Add constructor
The printConstructor function is added for generating Constructor. So
setter functions are removed and all getter functions are changed to
const functions.
Bug: 157957506
Test: m -j && ./xsdc-cpp-tests
Change-Id: I57f33badf6b37d6ec140a59084f37829fa89d365
diff --git a/src/com/android/xsdc/cpp/CppCodeGenerator.java b/src/com/android/xsdc/cpp/CppCodeGenerator.java
index 4553cad..4dd3c57 100644
--- a/src/com/android/xsdc/cpp/CppCodeGenerator.java
+++ b/src/com/android/xsdc/cpp/CppCodeGenerator.java
@@ -277,35 +277,35 @@
CppType type = elementTypes.get(i);
XsdElement element = elements.get(i);
XsdElement elementValue = resolveElement(element);
- String typeName = element.isMultiple() || type instanceof CppComplexType ?
- String.format("std::vector<%s>", type.getName()) :
- String.format("std::optional<%s>", type.getName());
- headerFile.printf("%s %s_;\n", typeName,
+ String typeName = Utils.elementTypeName(type.getName(),
+ element.isMultiple() || type instanceof CppComplexType);
+ headerFile.printf("const %s %s_;\n", typeName,
Utils.toVariableName(getElementName(elementValue)));
}
for (int i = 0; i < attributeTypes.size(); ++i) {
CppType type = attributeTypes.get(i);
XsdAttribute attribute = resolveAttribute(attributes.get(i));
+ String variableName = Utils.toVariableName(attribute.getName());
if (attribute.isRequired()) {
- headerFile.printf("%s %s_;\n", type.getName(),
- Utils.toVariableName(attribute.getName()));
+ headerFile.printf("const %s %s_;\n", type.getName(), variableName);
} else {
- headerFile.printf("std::optional<%s> %s_;\n", type.getName(),
- Utils.toVariableName(attribute.getName()));
+ headerFile.printf("const std::optional<%s> %s_;\n", type.getName(), variableName);
}
}
if (valueType != null) {
- headerFile.printf("std::optional<%s> _value;\n", valueType.getName());
+ headerFile.printf("const std::optional<%s> _value;\n", valueType.getName());
}
- // print getters and setters
-
headerFile.printf("public:\n");
+ String constructorArgs = printConstructor(name, nameScope, complexType, elements,
+ attributes, baseName);
+
+ // print getters and setters
for (int i = 0; i < elementTypes.size(); ++i) {
CppType type = elementTypes.get(i);
XsdElement element = elements.get(i);
XsdElement elementValue = resolveElement(element);
- printGetterAndSetter(nameScope + name, type,
+ printGetter(nameScope + name, type,
Utils.toVariableName(getElementName(elementValue)),
type instanceof CppComplexType ? true : element.isMultiple(),
type instanceof CppComplexType ? false : ((CppSimpleType)type).isList(),
@@ -314,14 +314,14 @@
for (int i = 0; i < attributeTypes.size(); ++i) {
CppType type = attributeTypes.get(i);
XsdAttribute attribute = resolveAttribute(attributes.get(i));
- printGetterAndSetter(nameScope + name, type, Utils.toVariableName(attribute.getName()),
+ printGetter(nameScope + name, type, Utils.toVariableName(attribute.getName()),
false, false, attribute.isRequired());
}
if (valueType != null) {
- printGetterAndSetter(nameScope + name, valueType, "value", false, false, false);
+ printGetter(nameScope + name, valueType, "value", false, false, false);
}
- printParser(name, nameScope, complexType);
+ printParser(name, nameScope, complexType, constructorArgs);
if (writer) {
printWriter(name, nameScope, complexType);
@@ -330,7 +330,7 @@
headerFile.println("};\n");
}
- private void printParser(String name, String nameScope, XsdComplexType complexType)
+ private void printParser(String name, String nameScope, XsdComplexType complexType, String args)
throws CppCodeGeneratorException {
CppSimpleType baseValueType = (complexType instanceof XsdSimpleContent) ?
getValueType((XsdSimpleContent) complexType, true) : null;
@@ -355,16 +355,28 @@
headerFile.printf("static %s read(xmlNode *root);\n", fullName, Utils.lowerize(name));
cppFile.printf("\n%s %s::read(xmlNode *root) {\n", fullName, fullName);
- cppFile.printf("%s instance;\n std::string raw;\n", fullName, fullName);
+ cppFile.print("std::string raw;\n");
for (int i = 0; i < allAttributes.size(); ++i) {
CppType type = allAttributeTypes.get(i);
XsdAttribute attribute = resolveAttribute(allAttributes.get(i));
String variableName = Utils.toVariableName(attribute.getName());
cppFile.printf("raw = getXmlAttribute(root, \"%s\");\n", attribute.getName());
+ if (attribute.isRequired()) {
+ if (type.getName().equals("bool")) {
+ cppFile.printf("%s %s = false;\n", type.getName(), variableName);
+ } else if (type.getName().equals("std::string")) {
+ cppFile.printf("%s %s;\n", type.getName(), variableName);
+ } else {
+ cppFile.printf("%s %s = 0;\n", type.getName(), variableName);
+ }
+ } else {
+ cppFile.printf("std::optional<%s> %s = std::nullopt;\n", type.getName(),
+ variableName);
+ }
cppFile.printf("if (raw != \"\") {\n");
cppFile.print(type.getParsingExpression());
- cppFile.printf("instance.set%s(value);\n}\n", Utils.capitalize(variableName));
+ cppFile.printf("%s = value;\n}\n", variableName);
}
if (baseValueType != null) {
@@ -377,6 +389,14 @@
cppFile.printf("instance.setValue(value);\n");
cppFile.printf("}\n");
} else if (!allElements.isEmpty()) {
+ for (int i = 0; i < allElements.size(); ++i) {
+ CppType type = allElementTypes.get(i);
+ XsdElement element = allElements.get(i);
+ XsdElement elementValue = resolveElement(element);
+ String variableName = Utils.toVariableName(getElementName(elementValue));
+ cppFile.printf("%s %s;\n", Utils.elementTypeName(type.getName(),
+ element.isMultiple() || type instanceof CppComplexType), variableName);
+ }
cppFile.print("for (xmlNode *child = root->xmlChildrenNode; child != nullptr;"
+ " child = child->next) {\n");
for (int i = 0; i < allElements.size(); ++i) {
@@ -384,30 +404,30 @@
XsdElement element = allElements.get(i);
XsdElement elementValue = resolveElement(element);
String variableName = Utils.toVariableName(getElementName(elementValue));
+
if (i != 0) cppFile.printf("} else ");
- cppFile.printf("if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>");
+ cppFile.print("if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>");
cppFile.printf("(\"%s\"))) {\n", elementValue.getName());
if (type instanceof CppSimpleType) {
- cppFile.printf("auto xmlValue = make_xmlUnique(xmlNodeListGetString(");
- cppFile.printf("child->doc, child->xmlChildrenNode, 1));\n");
- cppFile.printf("if (xmlValue == nullptr) {\nraw = \"\";\n} else {\n");
- cppFile.printf("raw = reinterpret_cast<const char*>(xmlValue.get());\n}\n");
+ cppFile.print("auto xmlValue = make_xmlUnique(xmlNodeListGetString(");
+ cppFile.print("child->doc, child->xmlChildrenNode, 1));\n");
+ cppFile.print("if (xmlValue == nullptr) {\nraw = \"\";\n} else {\n");
+ cppFile.print("raw = reinterpret_cast<const char*>(xmlValue.get());\n}\n");
}
cppFile.print(type.getParsingExpression());
if (element.isMultiple() || type instanceof CppComplexType) {
- cppFile.printf("instance.get%s().push_back(std::move(value));\n",
- Utils.capitalize(variableName));
+ cppFile.printf("%s.push_back(std::move(value));\n", variableName);
} else {
- cppFile.printf("instance.set%s(value);\n", Utils.capitalize(variableName));
+ cppFile.printf("%s = std::move(value);\n", variableName);
}
}
cppFile.printf("}\n}\n");
}
- cppFile.printf("return instance;\n"
- + "}\n");
+ cppFile.printf("%s instance%s;\n", fullName, args.length() > 0 ? "(" + args + ")" : "");
+ cppFile.print("return instance;\n}\n");
}
private void printWriter(String name, String nameScope, XsdComplexType complexType)
@@ -432,8 +452,9 @@
}
String fullName = nameScope + name;
- headerFile.printf("void write(std::ostream& out, const std::string& name);\n");
- cppFile.printf("\nvoid %s::write(std::ostream& out, const std::string& name) {\n", fullName);
+ headerFile.printf("void write(std::ostream& out, const std::string& name) const;\n");
+ cppFile.printf("\nvoid %s::write(std::ostream& out, const std::string& name) const {\n",
+ fullName);
cppFile.printf("out << printIndent() << \"<\" << name;\n");
for (int i = 0; i < allAttributes.size(); ++i) {
@@ -491,15 +512,15 @@
cppFile.printf("}\n");
}
- private void printGetterAndSetter(String name, CppType type, String variableName,
+ private void printGetter(String name, CppType type, String variableName,
boolean isMultiple, boolean isMultipleType, boolean isRequired) {
String typeName = isMultiple ? String.format("std::vector<%s>",
type.getName()) : type.getName();
- headerFile.printf("%s& get%s();\n", typeName, Utils.capitalize(variableName));
+ headerFile.printf("const %s& get%s() const;\n", typeName, Utils.capitalize(variableName));
cppFile.println();
- cppFile.printf("%s& %s::get%s() {\n"
+ cppFile.printf("const %s& %s::get%s() const {\n"
+ "return %s;\n}\n\n",
typeName, name, Utils.capitalize(variableName), isMultiple || isRequired ?
variableName + "_" : String.format("%s_.value()", variableName));
@@ -518,10 +539,10 @@
String elementTypeName = type instanceof CppComplexType ? type.getName() :
((CppSimpleType)type).getTypeName();
if (elementTypeName.equals("bool")) {
- headerFile.printf("%s getFirst%s();\n",
+ headerFile.printf("%s getFirst%s() const;\n",
elementTypeName, Utils.capitalize(variableName));
cppFile.println();
- cppFile.printf("%s %s::getFirst%s() {\n"
+ cppFile.printf("%s %s::getFirst%s() const {\n"
+ "if (%s_%sempty()) {\n"
+ "return false;\n"
+ "}\n"
@@ -532,10 +553,10 @@
isMultiple ? String.format("%s_[0]", variableName) :
String.format("%s_.value()[0]", variableName));
} else {
- headerFile.printf("%s* getFirst%s();\n",
+ headerFile.printf("const %s* getFirst%s() const;\n",
elementTypeName, Utils.capitalize(variableName));
cppFile.println();
- cppFile.printf("%s* %s::getFirst%s() {\n"
+ cppFile.printf("const %s* %s::getFirst%s() const {\n"
+ "if (%s_%sempty()) {\n"
+ "return nullptr;\n"
+ "}\n"
@@ -547,15 +568,87 @@
String.format("%s_.value()[0]", variableName));
}
}
+ }
- if (isMultiple) return;
- headerFile.printf("void set%s(%s);\n", Utils.capitalize(variableName), typeName);
- cppFile.println();
- cppFile.printf("void %s::set%s(%s %s) {\n"
- + "%s_ = %s;\n"
- + "}\n",
- name, Utils.capitalize(variableName), typeName, variableName,
- variableName, Utils.toAssignmentName(typeName, variableName, isMultipleType));
+ private String printConstructor(String name, String nameScope, XsdComplexType complexType,
+ List<XsdElement> elements, List<XsdAttribute> attributes, String baseName)
+ throws CppCodeGeneratorException {
+ String fullName = nameScope + name;
+ StringBuilder constructorArgs = new StringBuilder();
+ StringBuilder parentArgs = new StringBuilder();
+ StringBuilder constructor = new StringBuilder();
+ StringBuilder args = new StringBuilder();
+
+ List<XsdElement> allElements = new ArrayList<>();
+ List<XsdAttribute> allAttributes = new ArrayList<>();
+ stackComponents(complexType, allElements, allAttributes);
+
+ List<CppType> allElementTypes = new ArrayList<>();
+ for (XsdElement element : allElements) {
+ XsdElement elementValue = resolveElement(element);
+ CppType type = parseType(elementValue.getType(), elementValue.getName());
+ String variableName = Utils.toVariableName(getElementName(elementValue));
+ constructorArgs.append(String.format(", %s %s", Utils.elementTypeName(type.getName(),
+ element.isMultiple() || type instanceof CppComplexType), variableName));
+ args.append(String.format(", %s", variableName));
+ boolean isMultipleType;
+ if (type instanceof CppComplexType) {
+ isMultipleType = true;
+ } else if (((CppSimpleType)type).isList()) {
+ isMultipleType = true;
+ } else {
+ isMultipleType = false;
+ }
+
+ if (elements.contains(element)) {
+ constructor.append(String.format(", %s_(%s)", variableName,
+ Utils.toAssignmentName(type.getName(), variableName, isMultipleType)));
+ } else {
+ parentArgs.append(String.format(", %s", variableName));
+ }
+ }
+ List<CppSimpleType> allAttributeTypes = new ArrayList<>();
+ for (XsdAttribute attribute : allAttributes) {
+ CppType type = parseSimpleType(resolveAttribute(attribute).getType(), false);
+ String variableName = Utils.toVariableName(resolveAttribute(attribute).getName());
+ if (attribute.isRequired()) {
+ constructorArgs.append(String.format(", %s %s", type.getName(), variableName));
+ } else {
+ constructorArgs.append(String.format(", std::optional<%s> %s", type.getName(),
+ variableName));
+ }
+ args.append(String.format(", %s", variableName));
+ boolean isMultipleType = ((CppSimpleType)type).isList() ? true : false;
+ if (attributes.contains(attribute)) {
+ constructor.append(String.format(", %s_(%s)", variableName,
+ Utils.toAssignmentName(type.getName(), variableName, isMultipleType)));
+ } else {
+ parentArgs.append(String.format(", %s", variableName));
+ }
+ }
+
+ String constructorArgsString = constructorArgs.toString();
+ String constructorString = constructor.toString();
+ if (constructorArgsString.length() > 0) {
+ constructorArgsString = constructorArgsString.substring(2);
+ }
+ headerFile.printf("%s(%s);\n", name, constructorArgsString);
+ cppFile.printf("\n%s::%s(%s) : ", fullName, name, constructorArgsString);
+
+ String parentArgsString = parentArgs.toString();
+ if (parentArgsString.length() > 0) {
+ parentArgsString = parentArgsString.substring(2);
+ cppFile.printf("%s(%s)", baseName, parentArgsString);
+ } else {
+ constructorString = constructorString.substring(2);
+ }
+ cppFile.printf("%s {\n}\n", constructorString);
+
+ String argsString = args.toString();
+ if (argsString.length() > 0) {
+ argsString = argsString.substring(2);
+ }
+ return argsString;
}
private void printXmlParser() throws CppCodeGeneratorException {
diff --git a/src/com/android/xsdc/cpp/Utils.java b/src/com/android/xsdc/cpp/Utils.java
index 2f29e80..3f21ac4 100644
--- a/src/com/android/xsdc/cpp/Utils.java
+++ b/src/com/android/xsdc/cpp/Utils.java
@@ -90,4 +90,14 @@
}
return variableName;
}
+
+ static String elementTypeName(String name, boolean isMultipleType) {
+ String res;
+ if (isMultipleType) {
+ res = "std::vector<" + name + ">";
+ } else {
+ res = "std::optional<" + name + ">";
+ }
+ return res;
+ }
}