Skip to content

Commit

Permalink
CppCompiler: refactor destructMember() by relying on "extra attrs"
Browse files Browse the repository at this point in the history
  • Loading branch information
generalmimon committed Oct 16, 2023
1 parent ae16dee commit e0c94b5
Showing 1 changed file with 21 additions and 65 deletions.
86 changes: 21 additions & 65 deletions shared/src/main/scala/io/kaitai/struct/languages/CppCompiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -387,87 +387,43 @@ class CppCompiler(
outSrc.inc
}

val needRaw = this.needRaw(attr.dataType)
val innerType = attr.dataType match {
case st: SwitchType => st.combinedType
case t => t
(ExtraAttrs.forAttr(attr, this) ++ List(attr)).foreach { (attr) =>
val innerType = attr.dataType match {
case st: SwitchType => combineSwitchType(st)
case t => t
}
destructMember(attr.id, innerType, attr.isArray)
}

destructMember(id, innerType, attr.isArray, needRaw)

if (checks.nonEmpty) {
outSrc.dec
outSrc.puts("}")
}
}

def destructMember(id: Identifier, innerType: DataType, isArray: Boolean, needRaw: NeedRaw): Unit = {
def destructWithSafeguardHeader(ptr: String): Unit = {
outSrc.puts(s"if ($ptr) {")
outSrc.inc
}
def destructWithSafeguardFooter(ptr: String): Unit = {
outSrc.puts(s"delete $ptr; $ptr = $nullPtr;")
outSrc.dec
outSrc.puts("}")
}
def destructWithSafeguardSimple(ptr: String): Unit = {
destructWithSafeguardHeader(ptr)
destructWithSafeguardFooter(ptr)
}
if (config.cppConfig.pointers == CppRuntimeConfig.RawPointers) {
if (isArray) {
// raw is std::vector<string>*, no need to delete its contents, but we
// need to clean up the vector pointer itself
if (needRaw.level >= 1) {
destructWithSafeguardSimple(privateMemberName(RawIdentifier(id)))

// IO is std::vector<kstream*>*, needs destruction of both members
// and the vector pointer itself
if (needRaw.hasIO) {
val ioVar = privateMemberName(IoStorageIdentifier(RawIdentifier(id)))
destructWithSafeguardHeader(ioVar)
destructVector(s"$kstreamName*", ioVar)
destructWithSafeguardFooter(ioVar)
}
}
if (needRaw.level >= 2) {
// m__raw__raw_* is also std::vector<string>*, we just clean up the vector pointer
destructWithSafeguardSimple(privateMemberName(RawIdentifier(RawIdentifier(id))))
}
def destructMember(id: Identifier, innerType: DataType, isArray: Boolean): Unit = {
if (config.cppConfig.pointers != CppRuntimeConfig.RawPointers)
return

val arrVar = privateMemberName(id)
destructWithSafeguardHeader(arrVar)
val ptr = privateMemberName(id)
val innerNeedsDestruct = needsDestruction(innerType)

// main member contents
if (needsDestruction(innerType)) {
// C++ specific substitution: AnyType results from generic struct + raw bytes
// so we would assume that only generic struct needs to be cleaned up
val realType = innerType match {
case AnyType => KaitaiStructType
case _ => innerType
}
if (!isArray && !innerNeedsDestruct)
return

destructVector(kaitaiType2NativeType(realType), arrVar)
}

// main member is a std::vector of something, always needs destruction
destructWithSafeguardFooter(arrVar)
} else {
// raw is just a string, no need to cleanup => we ignore `needRaw.hasRaw`
outSrc.puts(s"if ($ptr) {")
outSrc.inc

// but needRaw.hasIO is important
if (needRaw.hasIO)
destructWithSafeguardSimple(privateMemberName(IoStorageIdentifier(RawIdentifier(id))))
if (isArray && innerNeedsDestruct)
destructVector(kaitaiType2NativeType(innerType), ptr)

if (needsDestruction(innerType))
destructWithSafeguardSimple(privateMemberName(id))
}
}
outSrc.puts(s"delete $ptr; $ptr = $nullPtr;")
outSrc.dec
outSrc.puts("}")
}

def needsDestruction(t: DataType): Boolean = t match {
case _: UserType | _: ArrayTypeInStream | KaitaiStructType | AnyType => true
case _: UserType | _: ArrayTypeInStream | KaitaiStructType | AnyType | OwnedKaitaiStreamType => true
case _ => false
}

Expand Down

0 comments on commit e0c94b5

Please sign in to comment.