Skip to content

Commit

Permalink
[JsonGen] Emit move ctors and move assignment ops
Browse files Browse the repository at this point in the history
  • Loading branch information
sebaszm committed Jul 4, 2024
1 parent 5bd3777 commit 120aff8
Showing 1 changed file with 122 additions and 81 deletions.
203 changes: 122 additions & 81 deletions JsonGenerator/source/class_emitter.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,112 +217,116 @@ def __EmitInit(json_obj):
if isinstance(prop, JsonString) and prop.schema.get("opaque"):
emit.Line("%s.SetQuoted(false);" % prop.cpp_name)

def __EmitAssignment(json_obj, other, optional_type=False, conv=False):
if optional_type:
def __EmitAssignment(json_obj, other, type, optional_type=False):
_move = (type == "move")

if optional_type and not _move:
emit.Line("if (%s.IsSet() == true) {" % other)
emit.Indent()

if optional_type:
other += ".Value()"

for prop in json_obj.properties:
optional_or_opaque = IsObjectOptionalOrOpaque(prop)
_prop_name = prop.actual_name if conv else prop.cpp_name
_prop_name = (prop.actual_name if type == "conv" else prop.cpp_name)

if (prop.optional and not prop.default_value):
emit.Line("if (%s.%s.IsSet() == true) {" % (other, prop.actual_name))
emit.Indent()
if _move:
emit.Line("%s = std::move(%s.%s);" % (prop.cpp_name, other, _prop_name + prop.convert_rhs))
else:
_optional_or_opaque = IsObjectOptionalOrOpaque(prop)

elif optional_or_opaque:
if isinstance(prop, JsonString):
emit.Line("if (%s.%s%s.empty() == false) {" % (other, _prop_name, ".Value()" if not conv else ""))
if (prop.optional and not prop.default_value):
emit.Line("if (%s.%s.IsSet() == true) {" % (other, prop.actual_name))
emit.Indent()
elif isinstance(prop, JsonInteger):
emit.Line("if (%s.%s != 0) {" % (other, _prop_name))
emit.Indent()
else:
optional_or_opaque = False # invalid @optional...

emit.Line("%s = %s.%s;" % (prop.cpp_name, other, _prop_name + prop.convert_rhs))
elif _optional_or_opaque:
if isinstance(prop, JsonString):
emit.Line("if (%s.%s%s.empty() == false) {" % (other, _prop_name, ".Value()" if type != "conv" else ""))
emit.Indent()
elif isinstance(prop, JsonInteger):
emit.Line("if (%s.%s != 0) {" % (other, _prop_name))
emit.Indent()
else:
_optional_or_opaque = False # invalid @optional...

if (prop.optional and not prop.default_value) or optional_or_opaque:
emit.Unindent()
emit.Line("}")
emit.Line("%s = %s.%s;" % (prop.cpp_name, other, _prop_name + prop.convert_rhs))

if optional_type:
if (prop.optional and not prop.default_value) or _optional_or_opaque:
emit.Unindent()
emit.Line("}")

if optional_type and not _move:
emit.Unindent()
emit.Line("}")

def __EmitCtor(json_obj, no_init_code=False, copy_ctor=False, conversion_ctor=False, optional_type=False):
_other = "_other"
def __EmitCtor(json_obj, type, no_init_code=False, optional_type=False, delete=False):
_other = " _other" if not delete else ""
_delete_str = " = delete;" if delete else ""

if copy_ctor:
if type == "copy":
assert not optional_type
emit.Line("%s(const %s&%s)%s" % (json_obj.cpp_class, json_obj.cpp_class, _other, _delete_str))
elif type == "move":
assert not optional_type
emit.Line("%s(const %s& %s)" % (json_obj.cpp_class, json_obj.cpp_class, _other))
elif conversion_ctor:
emit.Line("%s(const %s& %s)" % (json_obj.cpp_class, json_obj.cpp_native_type_opt_v(optional_type), _other))
emit.Line("%s(%s&&%s)%s" % (json_obj.cpp_class, json_obj.cpp_class, _other, _delete_str))
elif type == "conv":
assert not delete
emit.Line("%s(const %s&%s)" % (json_obj.cpp_class, json_obj.cpp_native_type_opt_v(optional_type), _other))
else:
assert not delete
assert not optional_type
emit.Line("%s()" % (json_obj.cpp_class))

emit.Indent()
emit.Line(": %s()" % CoreJson("Container"))

for prop in json_obj.properties:
if copy_ctor:
emit.Line(", %s(%s.%s)" % (prop.cpp_name, _other, prop.cpp_name))
elif prop.default_value:
emit.Line(", %s(%s)" % (prop.cpp_name, prop.default_value))

emit.Unindent()
emit.Line("{")
emit.Indent()

if conversion_ctor:
__EmitAssignment(json_obj, _other, optional_type, conv=True)
if not delete:
emit.Indent()
emit.Line(": %s()" % CoreJson("Container"))

if no_init_code:
emit.Line("_Init();")
else:
__EmitInit(json_obj)
for prop in json_obj.properties:
if type == "copy":
emit.Line(", %s(%s.%s)" % (prop.cpp_name, _other.strip(), prop.cpp_name))
elif type == "move":
emit.Line(", %s(std::move(%s.%s))" % (prop.cpp_name, _other.strip(), prop.cpp_name))
elif prop.default_value:
emit.Line(", %s(%s)" % (prop.cpp_name, prop.default_value))

emit.Unindent()
emit.Line("}")
emit.Unindent()
emit.Line("{")
emit.Indent()

def _EmitCtor(json_obj, no_init=False):
__EmitCtor(json_obj, no_init)
if type == "conv":
__EmitAssignment(json_obj, _other.strip(), type, optional_type)

def _EmitCopyCtor(json_obj, optional_type=False):
__EmitCtor(json_obj, True, True, False, optional_type)
if no_init_code:
emit.Line("_Init();")
else:
__EmitInit(json_obj)

def _EmitConvertCtor(json_obj, optional_type=False):
__EmitCtor(json_obj, True, False, True, optional_type)
emit.Unindent()
emit.Line("}")

def __EmitAssignmentOperator(json_obj, copy=False, conversion=False, optional_type=False):
_other = "_rhs"
def __EmitAssignmentOperator(json_obj, type, optional_type=False, delete=False):
_other = " _rhs" if not delete else ""
_delete_str = " = delete;" if delete else ""

if copy:
if type == "copy":
assert not optional_type
emit.Line("%s& operator=(const %s& %s)" % (json_obj.cpp_class, json_obj.cpp_class, _other))
elif conversion:
emit.Line("%s& operator=(const %s& %s)" % (json_obj.cpp_class, json_obj.cpp_native_type_opt_v(optional_type), _other))
emit.Line("%s& operator=(const %s&%s)%s" % (json_obj.cpp_class, json_obj.cpp_class, _other, _delete_str))
elif type == "move":
assert not optional_type
emit.Line("%s& operator=(%s&&%s)%s" % (json_obj.cpp_class, json_obj.cpp_class, _other, _delete_str))
elif type == "conv":
assert not delete
emit.Line("%s& operator=(const %s&%s)" % (json_obj.cpp_class, json_obj.cpp_native_type_opt_v(optional_type), _other))
else:
assert False

emit.Line("{")
emit.Indent()

__EmitAssignment(json_obj, _other, optional_type, conversion)

emit.Line("return (*this);")
emit.Unindent()
emit.Line("}")
if not delete:
emit.Line("{")
emit.Indent()

def _EmitCopyAssignmentOperator(json_obj, optional_type=False):
__EmitAssignmentOperator(json_obj, True, False, optional_type)
__EmitAssignment(json_obj, _other[1:], type, optional_type)

def _EmitConvertAssignmentOperator(json_obj, optional_type=False):
__EmitAssignmentOperator(json_obj, False, True, optional_type)
emit.Line("return (*this);")
emit.Unindent()
emit.Line("}")

def _EmitConversionOperator(json_obj):
emit.Line("operator %s() const" % (json_obj.cpp_native_type))
Expand All @@ -346,8 +350,32 @@ def _EmitConversionOperator(json_obj):
emit.Unindent()
emit.Line("}")

def _EmitCtor(json_obj, no_init=False):
__EmitCtor(json_obj, "default", no_init)

def _EmitCopyCtor(json_obj, optional_type=False, delete=False):
__EmitCtor(json_obj, "copy", True, optional_type, delete)

def _EmitMoveCtor(json_obj, optional_type=False, delete=False):
__EmitCtor(json_obj, "move", True, optional_type, delete)

def _EmitConvertCtor(json_obj, optional_type=False):
__EmitCtor(json_obj, "conv", True, optional_type)

def _EmitCopyAssignmentOperator(json_obj, optional_type=False, delete=False):
__EmitAssignmentOperator(json_obj, "copy", optional_type, delete)

def _EmitMoveAssignmentOperator(json_obj, optional_type=False, delete=False):
__EmitAssignmentOperator(json_obj, "move", optional_type, delete)

def _EmitConvertAssignmentOperator(json_obj, optional_type=False):
__EmitAssignmentOperator(json_obj, "conv", optional_type)

def _EmitValidator(json_obj):
emit.Line()
emit.Unindent()
emit.Line("public:")
emit.Indent()
emit.Line("bool IsDataValid() const")
emit.Line("{")
emit.Indent()
Expand Down Expand Up @@ -398,11 +426,15 @@ def _EmitValidator(json_obj):

_EmitCtor(json_obj, (json_obj.is_copy_ctor_needed or json_obj.original_type))

if json_obj.is_copy_ctor_needed:
if json_obj.is_copy_ctor_needed or json_obj.original_type:
emit.Line()
_EmitCopyCtor(json_obj)
emit.Line()
_EmitCopyAssignmentOperator(json_obj)
_EmitMoveCtor(json_obj)
else:
emit.Line()
_EmitCopyCtor(json_obj, delete=True)
_EmitMoveCtor(json_obj, delete=True)

if json_obj.original_type:
emit.Line()
Expand All @@ -412,6 +444,17 @@ def _EmitValidator(json_obj):
emit.Line()
_EmitConvertCtor(json_obj, optional_type=True)

if json_obj.is_copy_ctor_needed or json_obj.original_type:
emit.Line()
_EmitCopyAssignmentOperator(json_obj)
emit.Line()
_EmitMoveAssignmentOperator(json_obj)
else:
emit.Line()
_EmitCopyAssignmentOperator(json_obj, delete=True)
_EmitMoveAssignmentOperator(json_obj, delete=True)

if json_obj.original_type:
emit.Line()
_EmitConvertAssignmentOperator(json_obj)

Expand All @@ -422,6 +465,9 @@ def _EmitValidator(json_obj):
emit.Line()
_EmitConversionOperator(json_obj)

emit.Line()
emit.Line("~%s() = default;" % json_obj.cpp_class)

method = json_obj

while not isinstance(method, JsonMethod):
Expand All @@ -440,14 +486,9 @@ def _EmitValidator(json_obj):
__EmitInit(json_obj)
emit.Unindent()
emit.Line("}")
emit.Line()
else:
emit.Line()
emit.Line("%s(const %s&) = delete;" % (json_obj.cpp_class, json_obj.cpp_class))
emit.Line("%s& operator=(const %s&) = delete;" % (json_obj.cpp_class, json_obj.cpp_class))
emit.Line()

emit.Unindent()
emit.Line()
emit.Line("public:")
emit.Indent()

Expand Down

0 comments on commit 120aff8

Please sign in to comment.