aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-02-01 11:12:28 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-02-01 11:12:28 +0000
commit7bbab3bb2ac75b7c0fc5fd9b363be52613af1912 (patch)
treeced07775acbb5aa250c8eb1380c1aade06745882
parentc83456f7f47ef75aed27d22c9b457ccbd8cb64f9 (diff)
parent1da17e8ed45748c16a5c2bade198ae22fb411949 (diff)
downloadxsdc-7bbab3bb2ac75b7c0fc5fd9b363be52613af1912.tar.gz
Snap for 9550355 from 1da17e8ed45748c16a5c2bade198ae22fb411949 to sdk-releaseplatform-tools-34.0.1platform-tools-34.0.0platform-tools-33.0.4
Change-Id: I03dc468b8c47c17733acd618dc9ef7295e1879d1
-rw-r--r--Android.bp16
-rw-r--r--build/xsdc.go37
-rw-r--r--src/main/java/com/android/xsdc/CodeWriter.java (renamed from src/com/android/xsdc/CodeWriter.java)0
-rw-r--r--src/main/java/com/android/xsdc/FileSystem.java (renamed from src/com/android/xsdc/FileSystem.java)0
-rw-r--r--src/main/java/com/android/xsdc/Main.java (renamed from src/com/android/xsdc/Main.java)57
-rw-r--r--src/main/java/com/android/xsdc/XmlSchema.java (renamed from src/com/android/xsdc/XmlSchema.java)0
-rw-r--r--src/main/java/com/android/xsdc/XsdConstants.java (renamed from src/com/android/xsdc/XsdConstants.java)0
-rw-r--r--src/main/java/com/android/xsdc/XsdHandler.java (renamed from src/com/android/xsdc/XsdHandler.java)0
-rw-r--r--src/main/java/com/android/xsdc/XsdParserException.java (renamed from src/com/android/xsdc/XsdParserException.java)0
-rw-r--r--src/main/java/com/android/xsdc/cpp/CppCodeGenerator.java (renamed from src/com/android/xsdc/cpp/CppCodeGenerator.java)397
-rw-r--r--src/main/java/com/android/xsdc/cpp/CppCodeGeneratorException.java (renamed from src/com/android/xsdc/cpp/CppCodeGeneratorException.java)0
-rw-r--r--src/main/java/com/android/xsdc/cpp/CppComplexType.java (renamed from src/com/android/xsdc/cpp/CppComplexType.java)4
-rw-r--r--src/main/java/com/android/xsdc/cpp/CppSimpleType.java (renamed from src/com/android/xsdc/cpp/CppSimpleType.java)40
-rw-r--r--src/main/java/com/android/xsdc/cpp/CppType.java (renamed from src/com/android/xsdc/cpp/CppType.java)7
-rw-r--r--src/main/java/com/android/xsdc/cpp/Utils.java (renamed from src/com/android/xsdc/cpp/Utils.java)0
-rw-r--r--src/main/java/com/android/xsdc/java/JavaCodeGenerator.java (renamed from src/com/android/xsdc/java/JavaCodeGenerator.java)154
-rw-r--r--src/main/java/com/android/xsdc/java/JavaCodeGeneratorException.java (renamed from src/com/android/xsdc/java/JavaCodeGeneratorException.java)0
-rw-r--r--src/main/java/com/android/xsdc/java/JavaComplexType.java (renamed from src/com/android/xsdc/java/JavaComplexType.java)4
-rw-r--r--src/main/java/com/android/xsdc/java/JavaSimpleType.java (renamed from src/com/android/xsdc/java/JavaSimpleType.java)24
-rw-r--r--src/main/java/com/android/xsdc/java/JavaType.java (renamed from src/com/android/xsdc/java/JavaType.java)0
-rw-r--r--src/main/java/com/android/xsdc/java/Utils.java (renamed from src/com/android/xsdc/java/Utils.java)0
-rw-r--r--src/main/java/com/android/xsdc/tag/Nullability.java (renamed from src/com/android/xsdc/tag/Nullability.java)0
-rw-r--r--src/main/java/com/android/xsdc/tag/XsdAll.java (renamed from src/com/android/xsdc/tag/XsdAll.java)0
-rw-r--r--src/main/java/com/android/xsdc/tag/XsdAttribute.java (renamed from src/com/android/xsdc/tag/XsdAttribute.java)0
-rw-r--r--src/main/java/com/android/xsdc/tag/XsdAttributeGroup.java (renamed from src/com/android/xsdc/tag/XsdAttributeGroup.java)0
-rw-r--r--src/main/java/com/android/xsdc/tag/XsdChoice.java (renamed from src/com/android/xsdc/tag/XsdChoice.java)0
-rw-r--r--src/main/java/com/android/xsdc/tag/XsdComplexContent.java (renamed from src/com/android/xsdc/tag/XsdComplexContent.java)0
-rw-r--r--src/main/java/com/android/xsdc/tag/XsdComplexType.java (renamed from src/com/android/xsdc/tag/XsdComplexType.java)0
-rw-r--r--src/main/java/com/android/xsdc/tag/XsdElement.java (renamed from src/com/android/xsdc/tag/XsdElement.java)0
-rw-r--r--src/main/java/com/android/xsdc/tag/XsdEnumRestriction.java (renamed from src/com/android/xsdc/tag/XsdEnumRestriction.java)0
-rw-r--r--src/main/java/com/android/xsdc/tag/XsdEnumeration.java (renamed from src/com/android/xsdc/tag/XsdEnumeration.java)0
-rw-r--r--src/main/java/com/android/xsdc/tag/XsdGeneralExtension.java (renamed from src/com/android/xsdc/tag/XsdGeneralExtension.java)0
-rw-r--r--src/main/java/com/android/xsdc/tag/XsdGeneralRestriction.java (renamed from src/com/android/xsdc/tag/XsdGeneralRestriction.java)0
-rw-r--r--src/main/java/com/android/xsdc/tag/XsdGroup.java (renamed from src/com/android/xsdc/tag/XsdGroup.java)0
-rw-r--r--src/main/java/com/android/xsdc/tag/XsdList.java (renamed from src/com/android/xsdc/tag/XsdList.java)0
-rw-r--r--src/main/java/com/android/xsdc/tag/XsdRestriction.java (renamed from src/com/android/xsdc/tag/XsdRestriction.java)0
-rw-r--r--src/main/java/com/android/xsdc/tag/XsdSimpleContent.java (renamed from src/com/android/xsdc/tag/XsdSimpleContent.java)0
-rw-r--r--src/main/java/com/android/xsdc/tag/XsdSimpleType.java (renamed from src/com/android/xsdc/tag/XsdSimpleType.java)0
-rw-r--r--src/main/java/com/android/xsdc/tag/XsdTag.java (renamed from src/com/android/xsdc/tag/XsdTag.java)0
-rw-r--r--src/main/java/com/android/xsdc/tag/XsdType.java (renamed from src/com/android/xsdc/tag/XsdType.java)0
-rw-r--r--src/main/java/com/android/xsdc/tag/XsdUnion.java (renamed from src/com/android/xsdc/tag/XsdUnion.java)0
-rw-r--r--src/test/java/com/android/xsdc/cpp/TestCppCodeGenerator.java150
-rw-r--r--tests/resources/simple_complex_content/api/current.txt6
-rw-r--r--tests/resources/simple_complex_content/simple_complex_content.xsd2
-rw-r--r--tests/resources/simple_type/api/current.txt6
-rw-r--r--tests/resources/simple_type/simple_type.xsd3
-rw-r--r--tests/resources/simple_type_root.xml2
-rw-r--r--tests/simple_type.cpp26
-rw-r--r--tests/src/com/android/xsdc/tests/XmlParserTest.java25
49 files changed, 737 insertions, 223 deletions
diff --git a/Android.bp b/Android.bp
index e731a13..345cf74 100644
--- a/Android.bp
+++ b/Android.bp
@@ -4,9 +4,23 @@ package {
java_binary_host {
name: "xsdc",
- srcs: ["src/**/*.java"],
+ srcs: [
+ "src/main/java/**/*.java",
+ ],
static_libs: [
"commons-cli-1.2",
],
manifest: "MANIFEST.MF"
}
+
+java_test_host {
+ name: "xsdc-unittest",
+ srcs: [
+ "src/test/java/**/*.java",
+ ],
+ static_libs: [
+ "commons-cli-1.2",
+ "junit",
+ "xsdc",
+ ],
+}
diff --git a/build/xsdc.go b/build/xsdc.go
index f92ba28..c5bc28d 100644
--- a/build/xsdc.go
+++ b/build/xsdc.go
@@ -40,16 +40,23 @@ var (
xsdc = pctx.HostBinToolVariable("xsdcCmd", "xsdc")
xsdcJavaRule = pctx.StaticRule("xsdcJavaRule", blueprint.RuleParams{
Command: `rm -rf "${out}.temp" && mkdir -p "${out}.temp" && ` +
- `${xsdcCmd} $in -p $pkgName -o ${out}.temp -j $args && ` +
+ `${xsdcCmd} $in -p $pkgName -o ${out}.temp -j $args -d ${out}.dep && ` +
+ `echo "${out} : \\" > ${out}.d && cat ${out}.dep >> ${out}.d && ` +
`${config.SoongZipCmd} -jar -o ${out} -C ${out}.temp -D ${out}.temp && ` +
- `rm -rf ${out}.temp`,
+ `rm -rf ${out}.temp && rm -rf ${out}.dep`,
+ Depfile: "${out}.d",
+ Deps: blueprint.DepsGCC,
CommandDeps: []string{"${xsdcCmd}", "${config.SoongZipCmd}"},
Description: "xsdc Java ${in} => ${out}",
}, "pkgName", "args")
xsdcCppRule = pctx.StaticRule("xsdcCppRule", blueprint.RuleParams{
Command: `rm -rf "${outDir}" && ` +
- `${xsdcCmd} $in -p $pkgName -o ${outDir} -c $args`,
+ `${xsdcCmd} $in -p $pkgName -o ${outDir} -c $args -d ${out}.dep && ` +
+ `echo "${out} : \\" > ${out}.d && cat ${out}.dep >> ${out}.d && ` +
+ `rm -rf ${out}.dep`,
+ Depfile: "${out}.d",
+ Deps: blueprint.DepsGCC,
CommandDeps: []string{"${xsdcCmd}", "${config.SoongZipCmd}"},
Description: "xsdc C++ ${in} => ${out}",
}, "pkgName", "outDir", "args")
@@ -86,6 +93,11 @@ type xsdConfigProperties struct {
// ENTITY_REFs.
// This can improve memory footprint. Default value is false.
Tinyxml *bool
+ // Specify root elements explicitly. If not set, XSDC generates parsers and
+ // writers for all elements which can be root element. When set, XSDC
+ // generates parsers and writers for specified root elements. This can be
+ // used to avoid unnecessary code.
+ Root_elements []string
}
type xsdConfig struct {
@@ -214,6 +226,10 @@ func (module *xsdConfig) GenerateAndroidBuildActions(ctx android.ModuleContext)
args = args + " -t "
}
+ for _, elem := range module.properties.Root_elements {
+ args = args + " -r " + elem
+ }
+
module.genOutputs_j = android.PathForModuleGen(ctx, "java", filenameStem+"_xsdcgen.srcjar")
ctx.Build(pctx, android.BuildParams{
@@ -246,6 +262,15 @@ func (module *xsdConfig) GenerateAndroidBuildActions(ctx android.ModuleContext)
android.PathForModuleGen(ctx, "cpp", "include/"+filenameStem+".h"),
android.PathForModuleGen(ctx, "cpp", "include/"+filenameStem+"_enums.h")}
}
+
+ output := module.genOutputs_c[0]
+ // Multiple outputs aren't supported by depslog.
+ // So ImplicitOutputs is used for additional generated code.
+ implicitOutputs := module.genOutputs_h
+ if len(module.genOutputs_c) > 1 {
+ implicitOutputs = append(implicitOutputs, module.genOutputs_c[1:]...)
+ }
+
module.genOutputDir = android.PathForModuleGen(ctx, "cpp", "include")
ctx.Build(pctx, android.BuildParams{
@@ -253,8 +278,8 @@ func (module *xsdConfig) GenerateAndroidBuildActions(ctx android.ModuleContext)
Description: "xsdc " + xsdFile.String(),
Input: xsdFile,
Implicit: module.docsPath,
- Outputs: module.genOutputs_c,
- ImplicitOutputs: module.genOutputs_h,
+ Output: output,
+ ImplicitOutputs: implicitOutputs,
Args: map[string]string{
"pkgName": pkgName,
"outDir": android.PathForModuleGen(ctx, "cpp").String(),
@@ -330,4 +355,4 @@ func (module *xsdConfig) OutputFiles(tag string) (android.Paths, error) {
}
}
-var _ android.OutputFileProducer = (*xsdConfig)(nil);
+var _ android.OutputFileProducer = (*xsdConfig)(nil)
diff --git a/src/com/android/xsdc/CodeWriter.java b/src/main/java/com/android/xsdc/CodeWriter.java
index 489ccdc..489ccdc 100644
--- a/src/com/android/xsdc/CodeWriter.java
+++ b/src/main/java/com/android/xsdc/CodeWriter.java
diff --git a/src/com/android/xsdc/FileSystem.java b/src/main/java/com/android/xsdc/FileSystem.java
index 2d746f3..2d746f3 100644
--- a/src/com/android/xsdc/FileSystem.java
+++ b/src/main/java/com/android/xsdc/FileSystem.java
diff --git a/src/com/android/xsdc/Main.java b/src/main/java/com/android/xsdc/Main.java
index 0f486d0..90e0719 100644
--- a/src/com/android/xsdc/Main.java
+++ b/src/main/java/com/android/xsdc/Main.java
@@ -18,7 +18,11 @@ package com.android.xsdc;
import java.io.File;
import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
import static java.lang.System.exit;
@@ -101,6 +105,18 @@ public class Main {
.withDescription("Only generate XML parser in Cpp code.")
.create("x");
options.addOption(genParserOnly);
+ Option genDepFile = OptionBuilder
+ .withLongOpt("depfile")
+ .hasArgs(1)
+ .withDescription("Generate depfile for ninja.")
+ .create("d");
+ options.addOption(genDepFile);
+ options.addOption(OptionBuilder
+ .withLongOpt("root")
+ .hasArgs(1)
+ .withDescription("Root element.")
+ .create("r"));
+
// "Only generate enums" and "Only generate parser" options are mutually exclusive.
OptionGroup genOnlyGroup = new OptionGroup();
genOnlyGroup.setRequired(false);
@@ -119,7 +135,6 @@ public class Main {
return;
}
- String[] xsdFile = cmd.getArgs();
String packageName = cmd.getOptionValue('p', null);
String outDir = cmd.getOptionValue('o', null);
boolean writer = cmd.hasOption('w');
@@ -129,8 +144,10 @@ public class Main {
boolean parserOnly = cmd.hasOption('x');
boolean booleanGetter = cmd.hasOption('b');
boolean useTinyXml = cmd.hasOption('t');
+ String depFile = cmd.getOptionValue('d', null);
+ String[] rootElements = cmd.getOptionValues('r');
- if (xsdFile.length != 1 || packageName == null) {
+ if (cmd.getArgs().length != 1 || packageName == null) {
System.err.println("Error: no xsd files or package name");
help(options);
}
@@ -139,7 +156,20 @@ public class Main {
outDir = ".";
}
- XmlSchema xmlSchema = parse(xsdFile[0]);
+ String xsdFile = cmd.getArgs()[0];
+ List<String> included = new ArrayList<>();
+ included.add(xsdFile);
+ XmlSchema xmlSchema = parse(xsdFile, included);
+
+ // When -r (root element) is specified, then validate if it's defined in schema.
+ if (rootElements != null) {
+ for (String rootElement : rootElements) {
+ if (!xmlSchema.getElementMap().containsKey(rootElement)) {
+ System.err.println("Invalid root element(-r): " + rootElement);
+ System.exit(1);
+ }
+ }
+ }
if (cmd.hasOption('j')) {
File packageDir = new File(Paths.get(outDir, packageName.replace(".", "/")).toString());
@@ -147,7 +177,7 @@ public class Main {
FileSystem fs = new FileSystem(packageDir);
JavaCodeGenerator javaCodeGenerator =
new JavaCodeGenerator(xmlSchema, packageName, writer, nullability, genHas,
- booleanGetter);
+ booleanGetter, rootElements);
javaCodeGenerator.print(fs);
} else if (cmd.hasOption('c')) {
File includeDir = new File(Paths.get(outDir, "include").toString());
@@ -158,12 +188,16 @@ public class Main {
CppCodeGenerator.GENERATE_ENUMS | CppCodeGenerator.GENERATE_PARSER);
CppCodeGenerator cppCodeGenerator =
new CppCodeGenerator(xmlSchema, packageName, writer, generators,
- booleanGetter, useTinyXml);
+ booleanGetter, useTinyXml, rootElements);
cppCodeGenerator.print(fs);
}
+
+ if (depFile != null) {
+ writeDepFile(depFile, included);
+ }
}
- private static XmlSchema parse(String xsdFile) throws Exception {
+ private static XmlSchema parse(String xsdFile, List<String> included) throws Exception {
XmlSchema xmlSchema;
try (FileInputStream in = new FileInputStream(xsdFile)) {
SAXParserFactory factory = SAXParserFactory.newInstance();
@@ -174,12 +208,21 @@ public class Main {
xmlSchema = xsdHandler.getSchema();
}
for (String file : xmlSchema.getIncludeList()) {
- XmlSchema temp = parse(Paths.get(xsdFile).resolveSibling(file).toString());
+ String filePath = Paths.get(xsdFile).resolveSibling(file).toString();
+ included.add(filePath);
+ XmlSchema temp = parse(filePath, included);
xmlSchema.include(temp);
}
return xmlSchema;
}
+ private static void writeDepFile(String depFile, List<String> files)
+ throws IOException {
+ try (PrintWriter out = new PrintWriter(new File(depFile))) {
+ out.println(String.format(" %s", String.join(" \\\n ", files)));
+ }
+ }
+
private static void help(Options options) {
new HelpFormatter().printHelp(
"xsdc path/to/xsd_file.xsd","", options, null, true);
diff --git a/src/com/android/xsdc/XmlSchema.java b/src/main/java/com/android/xsdc/XmlSchema.java
index 4bfa3fd..4bfa3fd 100644
--- a/src/com/android/xsdc/XmlSchema.java
+++ b/src/main/java/com/android/xsdc/XmlSchema.java
diff --git a/src/com/android/xsdc/XsdConstants.java b/src/main/java/com/android/xsdc/XsdConstants.java
index 6c79b9b..6c79b9b 100644
--- a/src/com/android/xsdc/XsdConstants.java
+++ b/src/main/java/com/android/xsdc/XsdConstants.java
diff --git a/src/com/android/xsdc/XsdHandler.java b/src/main/java/com/android/xsdc/XsdHandler.java
index f6a9492..f6a9492 100644
--- a/src/com/android/xsdc/XsdHandler.java
+++ b/src/main/java/com/android/xsdc/XsdHandler.java
diff --git a/src/com/android/xsdc/XsdParserException.java b/src/main/java/com/android/xsdc/XsdParserException.java
index aa755d5..aa755d5 100644
--- a/src/com/android/xsdc/XsdParserException.java
+++ b/src/main/java/com/android/xsdc/XsdParserException.java
diff --git a/src/com/android/xsdc/cpp/CppCodeGenerator.java b/src/main/java/com/android/xsdc/cpp/CppCodeGenerator.java
index e470216..9bfbe56 100644
--- a/src/com/android/xsdc/cpp/CppCodeGenerator.java
+++ b/src/main/java/com/android/xsdc/cpp/CppCodeGenerator.java
@@ -51,17 +51,20 @@ public class CppCodeGenerator {
private int generators;
private boolean booleanGetter;
private boolean useTinyXml;
+ private String[] rootElements;
private static final String UNKNOWN_ENUM = "UNKNOWN";
public CppCodeGenerator(XmlSchema xmlSchema, String pkgName, boolean writer, int generators,
- boolean booleanGetter, boolean useTinyXml) throws CppCodeGeneratorException {
+ boolean booleanGetter, boolean useTinyXml, String[] rootElements)
+ throws CppCodeGeneratorException {
this.xmlSchema = xmlSchema;
this.pkgName = pkgName;
this.writer = writer;
this.generators = generators;
this.booleanGetter = booleanGetter;
this.useTinyXml = useTinyXml;
+ this.rootElements = rootElements;
// class naming validation
{
@@ -178,6 +181,14 @@ public class CppCodeGenerator {
enumsCppFile.printf("#include \"%s\"\n\n", enumsHeaderFileName);
parserCppFile.printf("#define LOG_TAG \"%s\"\n", pkgName);
parserCppFile.printf("#include \"%s\"\n\n", parserHeaderFileName);
+ // define _xsdc_assert to abort with message regardless of NDEBUG
+ parserCppFile.println("#include <assert.h>\n"
+ + "#ifndef __BIONIC__\n"
+ + "#define __assert2(f,n,fun,e) do { fprintf(stderr, \"%s:%d: %s: Assertion `%s'"
+ + " failed\", (f), (n), (fun), (e)); abort(); } while (false)\n"
+ + "#endif\n"
+ + "#define _xsdc_assert(e) do if (!(e)) __assert2(__FILE__, __LINE__,"
+ + " __PRETTY_FUNCTION__, #e); while (false)\n");
List<String> namespace = new java.util.ArrayList<>();
for (String token : pkgName.split("\\.")) {
@@ -322,6 +333,14 @@ public class CppCodeGenerator {
enumsHeaderFile.printf("};\n");
}
+ /**
+ * Prints forward declarations for complex types.
+ *
+ * Foo.h:
+ *
+ * class Foo;
+ *
+ */
private void printPrototype() throws CppCodeGeneratorException {
for (XsdType type : xmlSchema.getTypeMap().values()) {
if (type instanceof XsdComplexType) {
@@ -338,6 +357,22 @@ public class CppCodeGenerator {
}
}
+ /**
+ * Prints class definitions for complex types.
+ *
+ * Foo.h:
+ *
+ * class Foo {
+ * printClass(<inner types>)
+ * <members>
+ * const optional<> value_;
+ * args = printConstructor()
+ * printGetter(<members>)
+ * printParser( args )
+ * printWriter()
+ * };
+ *
+ */
private void printClass(String name, String nameScope, XsdComplexType complexType)
throws CppCodeGeneratorException {
assert name != null;
@@ -379,7 +414,7 @@ public class CppCodeGenerator {
elementTypes.add(cppType);
}
List<CppSimpleType> attributeTypes = new ArrayList<>();
- List<XsdAttribute> attributes = new ArrayList();
+ List<XsdAttribute> attributes = new ArrayList<>();
for (XsdAttributeGroup attributeGroup : complexType.getAttributeGroups()) {
attributes.addAll(getAllAttributes(resolveAttributeGroup(attributeGroup)));
}
@@ -451,6 +486,27 @@ public class CppCodeGenerator {
parserHeaderFile.println("};\n");
}
+ /**
+ * Prints read() static member function for complex types.
+ * Note that read() is a non-validating parser.
+ *
+ * Foo.h:
+ *
+ * static Foo read(XmlNode* root);
+ *
+ * Foo.cpp:
+ *
+ * Foo Foo::read(XmlNode* root) {
+ * string _raw;
+ * for each member m
+ * _raw = ..
+ * parsing expressions for each member (read _raw, set _value)
+ * m = _value;
+ * Foo instance(args...);
+ * return instance;
+ * }
+ *
+ */
private void printParser(String name, String nameScope, XsdComplexType complexType, String args)
throws CppCodeGeneratorException {
CppSimpleType baseValueType = (complexType instanceof XsdSimpleContent) ?
@@ -477,13 +533,13 @@ public class CppCodeGenerator {
parserHeaderFile.printf("static %s read(%s *root);\n", fullName, nodeType);
parserCppFile.printf("\n%s %s::read(%s *root) {\n", fullName, fullName, nodeType);
- parserCppFile.print("std::string raw;\n");
+ parserCppFile.print("std::string _raw;\n");
for (int i = 0; i < allAttributes.size(); ++i) {
CppSimpleType type = allAttributeTypes.get(i);
XsdAttribute attribute = resolveAttribute(allAttributes.get(i));
String variableName = Utils.toVariableName(attribute.getName());
- parserCppFile.printf("raw = getXmlAttribute(root, \"%s\");\n", attribute.getName());
+ parserCppFile.printf("_raw = getXmlAttribute(root, \"%s\");\n", attribute.getName());
if (attribute.isRequired()) {
if (type.isEnum()) {
parserCppFile.printf("%s %s = %s::%s;\n",
@@ -495,15 +551,15 @@ public class CppCodeGenerator {
parserCppFile.printf("std::optional<%s> %s = std::nullopt;\n", type.getName(),
variableName);
}
- parserCppFile.printf("if (raw != \"\") {\n");
+ parserCppFile.printf("if (_raw != \"\") {\n");
parserCppFile.print(type.getParsingExpression());
- parserCppFile.printf("%s = value;\n}\n", variableName);
+ parserCppFile.printf("%s = _value;\n}\n", variableName);
}
if (baseValueType != null) {
- printNodeListGetString("root");
+ printSetRawWithElementText("root");
parserCppFile.print(baseValueType.getParsingExpression());
- parserCppFile.printf("instance.setValue(value);\n");
+ parserCppFile.printf("instance.setValue(_value);\n");
parserCppFile.printf("}\n");
} else if (!allElements.isEmpty()) {
for (int i = 0; i < allElements.size(); ++i) {
@@ -515,13 +571,13 @@ public class CppCodeGenerator {
element.isMultiple() || type instanceof CppComplexType), variableName);
}
if (useTinyXml) {
- parserCppFile.print("for (auto *child = root->FirstChildElement();"
- + " child != nullptr;"
- + " child = child->NextSiblingElement()) {\n");
+ parserCppFile.print("for (auto *_child = root->FirstChildElement();"
+ + " _child != nullptr;"
+ + " _child = _child->NextSiblingElement()) {\n");
} else {
- parserCppFile.print("for (auto *child = root->xmlChildrenNode;"
- + " child != nullptr;"
- + " child = child->next) {\n");
+ parserCppFile.print("for (auto *_child = root->xmlChildrenNode;"
+ + " _child != nullptr;"
+ + " _child = _child->next) {\n");
}
for (int i = 0; i < allElements.size(); ++i) {
CppType type = allElementTypes.get(i);
@@ -531,24 +587,24 @@ public class CppCodeGenerator {
if (i != 0) parserCppFile.printf("} else ");
if (useTinyXml) {
- parserCppFile.printf("if (!strcmp(child->Name(), \"%s\")) {\n",
+ parserCppFile.printf("if (!strcmp(_child->Name(), \"%s\")) {\n",
elementValue.getName());
} else {
- parserCppFile.printf("if (!xmlStrcmp(child->name,"
+ parserCppFile.printf("if (!xmlStrcmp(_child->name,"
+ " reinterpret_cast<const xmlChar*>(\"%s\"))) {\n",
elementValue.getName());
}
if (type instanceof CppSimpleType) {
- printNodeListGetString("child");
+ printSetRawWithElementText("_child");
}
parserCppFile.print(type.getParsingExpression());
if (element.isMultiple() || type instanceof CppComplexType) {
- parserCppFile.printf("%s.push_back(std::move(value));\n", variableName);
+ parserCppFile.printf("%s.push_back(std::move(_value));\n", variableName);
} else {
- parserCppFile.printf("%s = std::move(value);\n", variableName);
+ parserCppFile.printf("%s = std::move(_value);\n", variableName);
}
}
parserCppFile.printf("}\n}\n");
@@ -562,31 +618,45 @@ public class CppCodeGenerator {
return (useTinyXml ? "tinyxml2::XMLElement" : "xmlNode");
}
- private void printNodeListGetString(String varName) {
+ private void printSetRawWithElementText(String varName) {
if (useTinyXml) {
// The tinyxml version, in contrast to xmlNodeListGetString does not deal
// with ENTITY_REF nodes
- parserCppFile.printf("raw = \"\";\n");
+ parserCppFile.printf("_raw = \"\";\n");
parserCppFile.printf("for (auto *textNode = %s->FirstChild();"
+ " textNode != nullptr;"
+ " textNode = textNode->NextSibling()) {\n", varName);
parserCppFile.printf("if (textNode->ToText() != nullptr) {\n");
- parserCppFile.printf("raw.append(textNode->Value());\n");
+ parserCppFile.printf("_raw.append(textNode->Value());\n");
parserCppFile.printf("}\n");
parserCppFile.printf("}\n");
} else {
parserCppFile.printf("auto xmlValue = make_xmlUnique(xmlNodeListGetString(");
parserCppFile.printf("%s->doc, %s->xmlChildrenNode, 1));\n", varName, varName);
- parserCppFile.printf("if (xmlValue == nullptr) {\nraw = \"\";\n} else {\n");
- parserCppFile.printf("raw = reinterpret_cast<const char*>(xmlValue.get());\n}");
+ parserCppFile.printf("if (xmlValue == nullptr) {\n_raw = \"\";\n} else {\n");
+ parserCppFile.printf("_raw = reinterpret_cast<const char*>(xmlValue.get());\n}");
parserCppFile.printf("\n");
}
}
+ /**
+ * Prints write() member function for complex types.
+ *
+ * Foo.h:
+ *
+ * void write(ostream& _out, string name) const;
+ *
+ * Foo.cpp:
+ *
+ * void Foo::write(ostream& _out, string name) const {
+ * <FooElement attrs....>
+ * value_
+ * </Fooelement>
+ * }
+ *
+ */
private void printWriter(String name, String nameScope, XsdComplexType complexType)
throws CppCodeGeneratorException {
- CppSimpleType baseValueType = (complexType instanceof XsdSimpleContent) ?
- getValueType((XsdSimpleContent) complexType, true) : null;
List<XsdElement> allElements = new ArrayList<>();
List<XsdAttribute> allAttributes = new ArrayList<>();
stackComponents(complexType, allElements, allAttributes);
@@ -605,24 +675,24 @@ public class CppCodeGenerator {
}
String fullName = nameScope + name;
- parserHeaderFile.printf("void write(std::ostream& out, const std::string& name) const;\n");
+ parserHeaderFile.printf("void write(std::ostream& _out, const std::string& _name) const;\n");
parserCppFile.printf(
- "\nvoid %s::write(std::ostream& out, const std::string& name) const {\n",
+ "\nvoid %s::write(std::ostream& _out, const std::string& _name) const {\n",
fullName);
- parserCppFile.printf("out << printIndent() << \"<\" << name;\n");
+ parserCppFile.printf("_out << printIndent() << \"<\" << _name;\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());
parserCppFile.printf("if (has%s()) {\n", Utils.capitalize(variableName));
- parserCppFile.printf("out << \" %s=\\\"\";\n", attribute.getName());
+ parserCppFile.printf("_out << \" %s=\\\"\";\n", attribute.getName());
parserCppFile.print(type.getWritingExpression(String.format("%s%s()",
getterName(type.getName()), Utils.capitalize(variableName)),
attribute.getName()));
- parserCppFile.printf("out << \"\\\"\";\n}\n");
+ parserCppFile.printf("_out << \"\\\"\";\n}\n");
}
- parserCppFile.print("out << \">\" << std::endl;\n");
+ parserCppFile.print("_out << \">\" << std::endl;\n");
parserCppFile.print("++indentIndex;\n");
if (!allElements.isEmpty()) {
@@ -634,30 +704,30 @@ public class CppCodeGenerator {
String variableName = Utils.toVariableName(elementName);
if (type instanceof CppComplexType || element.isMultiple()) {
- parserCppFile.printf("for (auto& value : get%s()) {\n",
+ parserCppFile.printf("for (auto& _value : get%s()) {\n",
Utils.capitalize(variableName));
if (type instanceof CppSimpleType) {
- parserCppFile.printf("out << printIndent() << \"<%s>\";\n",
+ parserCppFile.printf("_out << printIndent() << \"<%s>\";\n",
elementValue.getName());
}
parserCppFile.printf(
- type.getWritingExpression("value", elementValue.getName()));
+ type.getWritingExpression("_value", elementValue.getName()));
if (type instanceof CppSimpleType) {
- parserCppFile.printf("out << \"</%s>\" << std::endl;\n",
+ parserCppFile.printf("_out << \"</%s>\" << std::endl;\n",
elementValue.getName());
}
parserCppFile.printf("}\n");
} else {
parserCppFile.printf("if (has%s()) {\n", Utils.capitalize(variableName));
if (type instanceof CppSimpleType) {
- parserCppFile.printf("out << printIndent() << \"<%s>\";\n",
+ parserCppFile.printf("_out << printIndent() << \"<%s>\";\n",
elementValue.getName());
}
parserCppFile.print(type.getWritingExpression(String.format("%s%s()",
getterName(type.getName()), Utils.capitalize(variableName)),
elementValue.getName()));
if (type instanceof CppSimpleType) {
- parserCppFile.printf("out << \"</%s>\" << std::endl;\n",
+ parserCppFile.printf("_out << \"</%s>\" << std::endl;\n",
elementValue.getName());
}
parserCppFile.print("}\n");
@@ -665,24 +735,56 @@ public class CppCodeGenerator {
}
}
parserCppFile.print("--indentIndex;\n");
- parserCppFile.printf("out << printIndent() << \"</\" << name << \">\" << std::endl;\n");
+ parserCppFile.printf("_out << printIndent() << \"</\" << _name << \">\" << std::endl;\n");
parserCppFile.printf("}\n");
}
+ /**
+ * Prints hasAttr() and getAttr() member functions for each member field.
+ *
+ * Foo.h:
+ *
+ * const Attr& getAttr() const;
+ * bool hasAttr() const;
+ * const Item* getFirstItem() const; // for multi-value member
+ *
+ * Foo.cpp:
+ *
+ * const Attr& Foo::getAttr() const {
+ * return attr_;
+ * }
+ * bool Foo::hasAttr() const {
+ * return true;
+ * }
+ * const Item* Foo::getFirstItem() const {
+ * if (item_.empty()) {
+ * return nullptr;
+ * }
+ * return &item_[0];
+ * }
+ *
+ */
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();
+ String assertHasValue = String.format("_xsdc_assert(has%s());\n",
+ Utils.capitalize(variableName));
parserHeaderFile.printf("const %s& %s%s() const;\n", typeName, getterName(typeName),
Utils.capitalize(variableName));
parserCppFile.println();
- parserCppFile.printf("const %s& %s::%s%s() const {\n"
- + "return %s;\n}\n\n",
- typeName, name, getterName(typeName), Utils.capitalize(variableName),
- isMultiple || isRequired ?
- variableName + "_" : String.format("%s_.value()", variableName));
+ parserCppFile.printf("const %s& %s::%s%s() const {\n", typeName, name,
+ getterName(typeName), Utils.capitalize(variableName));
+ if (isMultiple || isRequired) {
+ parserCppFile.printf("return %s_;\n", variableName);
+ } else {
+ // Before accessing an optional::value(), we need to ensure that it has a value.
+ parserCppFile.print(assertHasValue);
+ parserCppFile.printf("return %s_.value();\n", variableName);
+ }
+ parserCppFile.printf("}\n\n");
parserHeaderFile.printf("bool has%s() const;\n", Utils.capitalize(variableName));
parserCppFile.printf("bool %s::has%s() const {\n", name, Utils.capitalize(variableName));
@@ -694,6 +796,7 @@ public class CppCodeGenerator {
parserCppFile.printf("return %s_.has_value();\n}\n", variableName);
}
+ // For elements that may occur multiple types or have a list of simple types
if (isMultiple || isMultipleType) {
String elementTypeName = type instanceof CppComplexType ? type.getName() :
((CppSimpleType)type).getTypeName();
@@ -702,12 +805,15 @@ public class CppCodeGenerator {
elementTypeName, Utils.capitalize(variableName));
parserCppFile.println();
parserCppFile.printf("%s %s::getFirst%s() const {\n"
+ + "%s"
+ "if (%s_%sempty()) {\n"
+ "return false;\n"
+ "}\n"
+ "return %s;\n"
+ "}\n",
- elementTypeName, name, Utils.capitalize(variableName), variableName,
+ elementTypeName, name, Utils.capitalize(variableName),
+ isMultiple ? "" : assertHasValue,
+ variableName,
isMultiple ? "." : "->",
isMultiple ? String.format("%s_[0]", variableName) :
String.format("%s_.value()[0]", variableName));
@@ -716,12 +822,15 @@ public class CppCodeGenerator {
elementTypeName, Utils.capitalize(variableName));
parserCppFile.println();
parserCppFile.printf("const %s* %s::getFirst%s() const {\n"
+ + "%s"
+ "if (%s_%sempty()) {\n"
+ "return nullptr;\n"
+ "}\n"
+ "return &%s;\n"
+ "}\n",
- elementTypeName, name, Utils.capitalize(variableName), variableName,
+ elementTypeName, name, Utils.capitalize(variableName),
+ isMultiple ? "" : assertHasValue,
+ variableName,
isMultiple ? "." : "->",
isMultiple ? String.format("%s_[0]", variableName) :
String.format("%s_.value()[0]", variableName));
@@ -729,6 +838,18 @@ public class CppCodeGenerator {
}
}
+ /**
+ * Prints constructor for complex types
+ *
+ * Foo.h:
+ *
+ * Foo(args...);
+ *
+ * Foo.cpp:
+ *
+ * Foo::Foo(args...): initializer... {}
+ *
+ */
private String printConstructor(String name, String nameScope, XsdComplexType complexType,
List<XsdElement> elements, List<XsdAttribute> attributes, String baseName)
throws CppCodeGeneratorException {
@@ -742,7 +863,6 @@ public class CppCodeGenerator {
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());
@@ -766,7 +886,6 @@ public class CppCodeGenerator {
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());
@@ -817,6 +936,22 @@ public class CppCodeGenerator {
return argsString;
}
+ /**
+ * Prints reader functions for each top-level types.
+ *
+ * Foo.h:
+ *
+ * optional<Foo> readFoo(const char* filename);
+ *
+ * Foo.cpp:
+ *
+ * std::optional<Foo> readFoo(const char* filename) {
+ * ...
+ * Foo _value = Foo::read(root);
+ * return _value;
+ * }
+ *
+ */
private void printXmlParser() throws CppCodeGeneratorException {
if (useTinyXml) {
// Nothing to do for libtinyxml2
@@ -853,75 +988,122 @@ public class CppCodeGenerator {
parserCppFile.printf("}\n\n");
}
- String className = Utils.toClassName(pkgName);
-
boolean isMultiRootElement = xmlSchema.getElementMap().values().size() > 1;
for (XsdElement element : xmlSchema.getElementMap().values()) {
- CppType cppType = parseType(element.getType(), element.getName());
- String elementName = element.getName();
- String VariableName = Utils.toVariableName(elementName);
- String typeName = cppType instanceof CppSimpleType ? cppType.getName() :
- Utils.toClassName(cppType.getName());
-
- parserHeaderFile.printf("std::optional<%s> read%s(const char* configFile);\n\n",
- typeName, isMultiRootElement ? Utils.capitalize(typeName) : "");
- parserCppFile.printf("std::optional<%s> read%s(const char* configFile) {\n",
- typeName, isMultiRootElement ? Utils.capitalize(typeName) : "");
- if (useTinyXml) {
- parserCppFile.printf("tinyxml2::XMLDocument doc;\n"
- + "if (doc.LoadFile(configFile) != tinyxml2::XML_SUCCESS) {\n"
- + "return std::nullopt;\n"
- + "}\n"
- + "auto child = doc.FirstChildElement();\n"
- + "if (child == nullptr) {\n"
- + "return std::nullopt;\n"
- + "}\n\n"
- + "if (strcmp(child->Name(), \"%s\") == 0) {\n",
- elementName);
- } else {
- parserCppFile.printf("auto doc = make_xmlUnique(xmlParseFile(configFile));\n"
- + "if (doc == nullptr) {\n"
- + "return std::nullopt;\n"
- + "}\n"
- + "xmlNodePtr child = xmlDocGetRootElement(doc.get());\n"
- + "if (child == nullptr) {\n"
- + "return std::nullopt;\n"
- + "}\n"
- + "if (xmlXIncludeProcess(doc.get()) < 0) {\n"
- + "return std::nullopt;\n"
- + "}\n\n"
- + "if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>"
- + "(\"%s\"))) {\n",
- elementName);
- }
-
- if (cppType instanceof CppSimpleType) {
- parserCppFile.printf("%s value = getXmlAttribute(child, \"%s\");\n",
- elementName, elementName);
- } else {
- parserCppFile.printf(cppType.getParsingExpression());
- }
- parserCppFile.printf("return value;\n}\n");
- parserCppFile.printf("return std::nullopt;\n");
- parserCppFile.printf("}\n\n");
+ // Skip parser if not specified as root.
+ if (rootElements != null
+ && Arrays.asList(rootElements).indexOf(element.getName()) == -1) continue;
+ printXmlParserFor(element, /*loadFile=*/true, isMultiRootElement);
+ printXmlParserFor(element, /*loadFile=*/false, isMultiRootElement);
}
}
+ /**
+ * Prints readType(const char* configFile) if loadFile is true.
+ * Otherwise, prints parseType(const char* xml).
+ */
+ private void printXmlParserFor(XsdElement element, boolean loadFile, boolean isMultiRootElement)
+ throws CppCodeGeneratorException {
+ CppType cppType = parseType(element.getType(), element.getName());
+ String elementName = element.getName();
+ String typeName = cppType.getName();
+ String readerName =
+ cppType instanceof CppSimpleType ? Utils.toClassName(elementName) : typeName;
+ String methodName = loadFile ? "read" : "parse";
+ String argName = loadFile ? "configFile" : "xml";
+ parserHeaderFile.printf("std::optional<%s> %s%s(const char* %s);\n\n",
+ typeName,
+ methodName,
+ isMultiRootElement ? readerName : "",
+ argName);
+ parserCppFile.printf("std::optional<%s> %s%s(const char* %s) {\n",
+ typeName,
+ methodName,
+ isMultiRootElement ? readerName : "",
+ argName);
+ if (useTinyXml) {
+ String innerParser = loadFile ? "LoadFile(configFile)" : "Parse(xml)";
+ parserCppFile.printf("tinyxml2::XMLDocument doc;\n"
+ + "if (doc.%s != tinyxml2::XML_SUCCESS) {\n"
+ + "return std::nullopt;\n"
+ + "}\n"
+ + "auto _child = doc.FirstChildElement();\n"
+ + "if (_child == nullptr) {\n"
+ + "return std::nullopt;\n"
+ + "}\n\n"
+ + "if (strcmp(_child->Name(), \"%s\") == 0) {\n",
+ innerParser,
+ elementName);
+ } else {
+ String innerParser = loadFile
+ ? "xmlParseFile(configFile)"
+ : "xmlParseDoc(reinterpret_cast<const xmlChar*>(xml))";
+ parserCppFile.printf("auto doc = make_xmlUnique(%s);\n"
+ + "if (doc == nullptr) {\n"
+ + "return std::nullopt;\n"
+ + "}\n"
+ + "xmlNodePtr _child = xmlDocGetRootElement(doc.get());\n"
+ + "if (_child == nullptr) {\n"
+ + "return std::nullopt;\n"
+ + "}\n"
+ + "if (xmlXIncludeProcess(doc.get()) < 0) {\n"
+ + "return std::nullopt;\n"
+ + "}\n\n"
+ + "if (!xmlStrcmp(_child->name, reinterpret_cast<const xmlChar*>"
+ + "(\"%s\"))) {\n",
+ innerParser,
+ elementName);
+ }
+
+ if (cppType instanceof CppSimpleType) {
+ parserCppFile.print("std::string _raw;\n");
+ printSetRawWithElementText("_child");
+ }
+ parserCppFile.printf(cppType.getParsingExpression());
+ parserCppFile.printf("return _value;\n}\n");
+ parserCppFile.printf("return std::nullopt;\n");
+ parserCppFile.printf("}\n\n");
+ }
+
+ /**
+ * Prints writer functions for each top-level types
+ *
+ * Foo.h:
+ *
+ * void write(ostream&, const Foo& foo);
+ *
+ * Foo.cpp:
+ *
+ * void write(ostream& _out, const Foo& foo) {
+ * ... <?xml ... ?>
+ * foo.write(_out, "FooElementName");
+ * }
+ *
+ */
private void printXmlWriter() throws CppCodeGeneratorException {
for (XsdElement element : xmlSchema.getElementMap().values()) {
+ // Skip writer if not specified as root.
+ if (rootElements != null
+ && Arrays.asList(rootElements).indexOf(element.getName()) == -1) continue;
CppType cppType = parseType(element.getType(), element.getName());
String elementName = element.getName();
- String VariableName = Utils.toVariableName(elementName);
- String typeName = cppType instanceof CppSimpleType ? cppType.getName() :
- Utils.toClassName(cppType.getName());
- parserHeaderFile.printf("void write(std::ostream& out, %s& %s);\n\n",
- typeName, VariableName);
- parserCppFile.printf("void write(std::ostream& out, %s& %s) {\n",
- typeName, VariableName);
-
+ String variableName = Utils.toVariableName(elementName);
+ String typeName = cppType.getName();
+ String writerName =
+ cppType instanceof CppSimpleType ? Utils.toClassName(elementName) : "";
+ parserHeaderFile.printf("void write%s(std::ostream& _out, const %s& %s);\n\n",
+ writerName, typeName, variableName);
+ parserCppFile.printf("void write%s(std::ostream& _out, const %s& %s) {\n",
+ writerName, typeName, variableName);
parserCppFile.print(
- "out << \"<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\"?>\\n\";\n");
- parserCppFile.printf("%s.write(out, \"%s\");\n", VariableName, elementName);
+ "_out << \"<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\"?>\\n\";\n");
+ if (cppType instanceof CppSimpleType) {
+ parserCppFile.printf("_out << \"<%s>\";\n", elementName);
+ parserCppFile.print(cppType.getWritingExpression(variableName, ""));
+ parserCppFile.printf("_out << \"</%s>\" << std::endl;\n", elementName);
+ } else {
+ parserCppFile.printf("%s.write(_out, \"%s\");\n", variableName, elementName);
+ }
parserCppFile.printf("}\n\n");
}
@@ -1157,7 +1339,6 @@ public class CppCodeGenerator {
}
boolean results = false;
for (XsdElement element : complexType.getElements()) {
- XsdElement elementValue = resolveElement(element);
if (element.getRef() == null && element.getType().getRef() == null
&& element.getType() instanceof XsdComplexType) {
results = hasAttribute((XsdComplexType) element.getType());
diff --git a/src/com/android/xsdc/cpp/CppCodeGeneratorException.java b/src/main/java/com/android/xsdc/cpp/CppCodeGeneratorException.java
index a6ccf2a..a6ccf2a 100644
--- a/src/com/android/xsdc/cpp/CppCodeGeneratorException.java
+++ b/src/main/java/com/android/xsdc/cpp/CppCodeGeneratorException.java
diff --git a/src/com/android/xsdc/cpp/CppComplexType.java b/src/main/java/com/android/xsdc/cpp/CppComplexType.java
index 64d735d..4a87afa 100644
--- a/src/com/android/xsdc/cpp/CppComplexType.java
+++ b/src/main/java/com/android/xsdc/cpp/CppComplexType.java
@@ -30,11 +30,11 @@ class CppComplexType implements CppType {
@Override
public String getParsingExpression() {
- return String.format("%s value = %s::read(child);\n", name, name);
+ return String.format("%s _value = %s::read(_child);\n", name, name);
}
@Override
public String getWritingExpression(String getValue, String name) {
- return String.format("%s.write(out, \"%s\");\n", getValue, name);
+ return String.format("%s.write(_out, \"%s\");\n", getValue, name);
}
}
diff --git a/src/com/android/xsdc/cpp/CppSimpleType.java b/src/main/java/com/android/xsdc/cpp/CppSimpleType.java
index d063ebe..5168329 100644
--- a/src/com/android/xsdc/cpp/CppSimpleType.java
+++ b/src/main/java/com/android/xsdc/cpp/CppSimpleType.java
@@ -62,19 +62,19 @@ class CppSimpleType implements CppType {
StringBuilder expression = new StringBuilder();
if (list) {
expression.append(
- String.format("%s value;\n", getName()));
+ String.format("%s _value;\n", getName()));
expression.append(String.format("{\n"
- + "std::istringstream stream(raw);\n"
- + "for(std::string str; stream >> str; ) {\n"
- + " value.push_back(%s);\n"
+ + "std::istringstream _stream(_raw);\n"
+ + "for(std::string str; _stream >> str; ) {\n"
+ + " _value.push_back(%s);\n"
+ "}\n",
String.format(rawParsingExpression, "str")));
expression.append("}\n");
} else {
expression.append(
- String.format("%s %svalue = %s;\n", getName(),
+ String.format("%s %s_value = %s;\n", getName(),
this.name.equals("std::string") ? "&" : "",
- String.format(rawParsingExpression, "raw")));
+ String.format(rawParsingExpression, "_raw")));
}
return expression.toString();
}
@@ -83,31 +83,31 @@ class CppSimpleType implements CppType {
public String getWritingExpression(String getValue, String name) {
StringBuilder expression = new StringBuilder();
if (list) {
- expression.append("{\nint count = 0;\n");
- expression.append(String.format("for (const auto& v : %s) {\n", getValue));
+ expression.append("{\nint _count = 0;\n");
+ expression.append(String.format("for (const auto& _v : %s) {\n", getValue));
String value;
if (isEnum) {
- value = String.format("%sToString(v)", this.name);
+ value = String.format("%sToString(_v)", this.name);
} else if (this.name.equals("char") || this.name.equals("unsigned char")) {
- value = "(int)v";
+ value = "(int)_v";
} else if (this.name.equals("bool")) {
- value = "(v ? \"true\" : \"false\")";
+ value = "(_v ? \"true\" : \"false\")";
} else {
- value = "v";
+ value = "_v";
}
- expression.append("if (count != 0) {\n"
- + "out << \" \";\n}\n"
- + "++count;\n");
- expression.append(String.format("out << %s;\n}\n}\n", value));
+ expression.append("if (_count != 0) {\n"
+ + "_out << \" \";\n}\n"
+ + "++_count;\n");
+ expression.append(String.format("_out << %s;\n}\n}\n", value));
} else {
if (isEnum) {
- expression.append(String.format("out << toString(%s);\n", getValue));
+ expression.append(String.format("_out << toString(%s);\n", getValue));
} else if (this.name.equals("char") || this.name.equals("unsigned char")) {
- expression.append(String.format("out << (int)%s;\n", getValue));
+ expression.append(String.format("_out << (int)%s;\n", getValue));
} else if (this.name.equals("bool")) {
- expression.append(String.format("out << (%s ? \"true\" : \"false\");\n", getValue));
+ expression.append(String.format("_out << (%s ? \"true\" : \"false\");\n", getValue));
} else {
- expression.append(String.format("out << %s;\n", getValue));
+ expression.append(String.format("_out << %s;\n", getValue));
}
}
return expression.toString();
diff --git a/src/com/android/xsdc/cpp/CppType.java b/src/main/java/com/android/xsdc/cpp/CppType.java
index 05d4da9..1c72d3f 100644
--- a/src/com/android/xsdc/cpp/CppType.java
+++ b/src/main/java/com/android/xsdc/cpp/CppType.java
@@ -19,6 +19,13 @@ package com.android.xsdc.cpp;
interface CppType {
String getName();
+ /**
+ * Statements to parse the input to this type. For simple types,
+ * `_raw(std::string)` should be available. For complex types,
+ * `_child(T)` should be available.
+ *
+ * @return statements declaring `_value` for this type from input
+ */
String getParsingExpression();
public String getWritingExpression(String getValue, String name);
diff --git a/src/com/android/xsdc/cpp/Utils.java b/src/main/java/com/android/xsdc/cpp/Utils.java
index d54a9aa..d54a9aa 100644
--- a/src/com/android/xsdc/cpp/Utils.java
+++ b/src/main/java/com/android/xsdc/cpp/Utils.java
diff --git a/src/com/android/xsdc/java/JavaCodeGenerator.java b/src/main/java/com/android/xsdc/java/JavaCodeGenerator.java
index 0025896..0fc2b7c 100644
--- a/src/com/android/xsdc/java/JavaCodeGenerator.java
+++ b/src/main/java/com/android/xsdc/java/JavaCodeGenerator.java
@@ -23,6 +23,7 @@ import com.android.xsdc.XsdConstants;
import com.android.xsdc.tag.*;
import java.io.IOException;
+import java.util.Arrays;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
@@ -41,9 +42,11 @@ public class JavaCodeGenerator {
private boolean generateHasMethod;
private boolean useHexBinary;
private boolean booleanGetter;
+ private String[] rootElements;
public JavaCodeGenerator(XmlSchema xmlSchema, String packageName, boolean writer,
- boolean showNullability, boolean generateHasMethod, boolean booleanGetter)
+ boolean showNullability, boolean generateHasMethod, boolean booleanGetter,
+ String[] rootElements)
throws JavaCodeGeneratorException {
this.xmlSchema = xmlSchema;
this.packageName = packageName;
@@ -51,6 +54,7 @@ public class JavaCodeGenerator {
this.showNullability = showNullability;
this.generateHasMethod = generateHasMethod;
this.booleanGetter = booleanGetter;
+ this.rootElements = rootElements;
useHexBinary = false;
// class naming validation
@@ -306,69 +310,69 @@ public class JavaCodeGenerator {
allAttributeTypes.add(parseSimpleType(type, false));
}
- out.printf("static %s%s read(%sorg.xmlpull.v1.XmlPullParser parser) " +
+ out.printf("static %s%s read(%sorg.xmlpull.v1.XmlPullParser _parser) " +
"throws org.xmlpull.v1.XmlPullParserException, java.io.IOException, " +
"javax.xml.datatype.DatatypeConfigurationException {\n",
getDefaultNullability(Nullability.NON_NULL), name,
getDefaultNullability(Nullability.NON_NULL));
- out.printf("%s instance = new %s();\n"
- + "String raw = null;\n", name, name);
+ out.printf("%s _instance = new %s();\n"
+ + "String _raw = null;\n", name, name);
for (int i = 0; i < allAttributes.size(); ++i) {
JavaType type = allAttributeTypes.get(i);
XsdAttribute attribute = resolveAttribute(allAttributes.get(i));
String variableName = Utils.toVariableName(attribute.getName());
- out.printf("raw = parser.getAttributeValue(null, \"%s\");\n"
- + "if (raw != null) {\n", attribute.getName());
+ out.printf("_raw = _parser.getAttributeValue(null, \"%s\");\n"
+ + "if (_raw != null) {\n", attribute.getName());
out.print(type.getParsingExpression());
- out.printf("instance.set%s(value);\n"
+ out.printf("_instance.set%s(_value);\n"
+ "}\n", Utils.capitalize(variableName));
}
if (baseValueType != null) {
- out.print("raw = XmlParser.readText(parser);\n"
- + "if (raw != null) {\n");
+ out.print("_raw = XmlParser.readText(_parser);\n"
+ + "if (_raw != null) {\n");
out.print(baseValueType.getParsingExpression());
- out.print("instance.setValue(value);\n"
+ out.print("_instance.setValue(_value);\n"
+ "}\n");
} else if (!allElements.isEmpty()) {
- out.print("int outerDepth = parser.getDepth();\n"
+ out.print("int outerDepth = _parser.getDepth();\n"
+ "int type;\n"
- + "while ((type=parser.next()) != org.xmlpull.v1.XmlPullParser.END_DOCUMENT\n"
+ + "while ((type=_parser.next()) != org.xmlpull.v1.XmlPullParser.END_DOCUMENT\n"
+ " && type != org.xmlpull.v1.XmlPullParser.END_TAG) {\n"
- + "if (parser.getEventType() != org.xmlpull.v1.XmlPullParser.START_TAG) "
+ + "if (_parser.getEventType() != org.xmlpull.v1.XmlPullParser.START_TAG) "
+ "continue;\n"
- + "String tagName = parser.getName();\n");
+ + "String _tagName = _parser.getName();\n");
for (int i = 0; i < allElements.size(); ++i) {
JavaType type = allElementTypes.get(i);
XsdElement element = allElements.get(i);
XsdElement elementValue = resolveElement(element);
String variableName = Utils.toVariableName(getElementName(elementValue));
- out.printf("if (tagName.equals(\"%s\")) {\n", elementValue.getName());
+ out.printf("if (_tagName.equals(\"%s\")) {\n", elementValue.getName());
if (type instanceof JavaSimpleType) {
- out.print("raw = XmlParser.readText(parser);\n");
+ out.print("_raw = XmlParser.readText(_parser);\n");
}
out.print(type.getParsingExpression());
if (element.isMultiple()) {
- out.printf("instance.get%s().add(value);\n",
+ out.printf("_instance.get%s().add(_value);\n",
Utils.capitalize(variableName));
} else {
- out.printf("instance.set%s(value);\n",
+ out.printf("_instance.set%s(_value);\n",
Utils.capitalize(variableName));
}
out.printf("} else ");
}
out.print("{\n"
- + "XmlParser.skip(parser);\n"
+ + "XmlParser.skip(_parser);\n"
+ "}\n"
+ "}\n");
out.printf("if (type != org.xmlpull.v1.XmlPullParser.END_TAG) {\n"
+ "throw new javax.xml.datatype.DatatypeConfigurationException(\"%s is not closed\");\n"
+ "}\n", name);
} else {
- out.print("XmlParser.skip(parser);\n");
+ out.print("XmlParser.skip(_parser);\n");
}
- out.print("return instance;\n"
+ out.print("return _instance;\n"
+ "}\n");
}
@@ -393,27 +397,27 @@ public class JavaCodeGenerator {
allAttributeTypes.add(parseSimpleType(type, false));
}
- out.printf("\nvoid write(%sXmlWriter out, %sString name) " +
+ out.printf("\nvoid write(%sXmlWriter _out, %sString _name) " +
"throws java.io.IOException {\n", getDefaultNullability(Nullability.NON_NULL),
getDefaultNullability(Nullability.NON_NULL));
- out.print("out.print(\"<\" + name);\n");
+ out.print("_out.print(\"<\" + _name);\n");
for (int i = 0; i < allAttributes.size(); ++i) {
JavaType type = allAttributeTypes.get(i);
boolean isList = allAttributeTypes.get(i).isList();
XsdAttribute attribute = resolveAttribute(allAttributes.get(i));
String variableName = Utils.toVariableName(attribute.getName());
out.printf("if (has%s()) {\n", Utils.capitalize(variableName));
- out.printf("out.print(\" %s=\\\"\");\n", attribute.getName());
+ out.printf("_out.print(\" %s=\\\"\");\n", attribute.getName());
out.print(type.getWritingExpression(String.format("%s%s()",
getterName(type.getName()), Utils.capitalize(variableName)),
attribute.getName()));
- out.printf("out.print(\"\\\"\");\n}\n");
+ out.printf("_out.print(\"\\\"\");\n}\n");
}
- out.printf("out.print(\">\\n\");\n");
+ out.printf("_out.print(\">\\n\");\n");
if (!allElements.isEmpty()) {
- out.printf("out.increaseIndent();\n");
+ out.printf("_out.increaseIndent();\n");
for (int i = 0; i < allElements.size(); ++i) {
JavaType type = allElementTypes.get(i);
XsdElement element = allElements.get(i);
@@ -425,31 +429,31 @@ public class JavaCodeGenerator {
out.printf("for (%s value : get%s()) {\n", type.getName(),
Utils.capitalize(variableName));
if (type instanceof JavaSimpleType) {
- out.printf("out.print(\"<%s>\");\n", elementValue.getName());
+ out.printf("_out.print(\"<%s>\");\n", elementValue.getName());
}
out.print(type.getWritingExpression("value", elementValue.getName()));
if (type instanceof JavaSimpleType) {
- out.printf("out.print(\"</%s>\\n\");\n", elementValue.getName());
+ out.printf("_out.print(\"</%s>\\n\");\n", elementValue.getName());
}
out.print("}\n");
} else {
out.printf("if (has%s()) {\n", Utils.capitalize(variableName));
if (type instanceof JavaSimpleType) {
- out.printf("out.print(\"<%s>\");\n", elementValue.getName());
+ out.printf("_out.print(\"<%s>\");\n", elementValue.getName());
}
out.print(type.getWritingExpression(String.format("%s%s()",
getterName(type.getName()), Utils.capitalize(variableName)),
elementValue.getName()));
if (type instanceof JavaSimpleType) {
- out.printf("out.print(\"</%s>\\n\");\n", elementValue.getName());
+ out.printf("_out.print(\"</%s>\\n\");\n", elementValue.getName());
}
out.printf("}\n");
}
}
- out.printf("out.decreaseIndent();\n");
+ out.printf("_out.decreaseIndent();\n");
}
- out.print("out.print(\"</\" + name + \">\\n\");\n");
+ out.print("_out.print(\"</\" + _name + \">\\n\");\n");
out.print("}\n");
}
@@ -509,26 +513,33 @@ public class JavaCodeGenerator {
boolean isMultiRootElement = xmlSchema.getElementMap().values().size() > 1;
for (XsdElement element : xmlSchema.getElementMap().values()) {
+ // Skip parser if not specified as root.
+ if (rootElements != null
+ && Arrays.asList(rootElements).indexOf(element.getName()) == -1) continue;
JavaType javaType = parseType(element.getType(), element.getName());
+ String elementName = element.getName();
+ String typeName = javaType.getName();
+ String readerName =
+ javaType instanceof JavaSimpleType ? Utils.toClassName(elementName) : typeName;
out.printf("public static %s%s read%s(%sjava.io.InputStream in)"
- + " throws org.xmlpull.v1.XmlPullParserException, java.io.IOException, "
- + "javax.xml.datatype.DatatypeConfigurationException {\n"
- + "org.xmlpull.v1.XmlPullParser parser = org.xmlpull.v1.XmlPullParserFactory"
- + ".newInstance().newPullParser();\n"
- + "parser.setFeature(org.xmlpull.v1.XmlPullParser.FEATURE_PROCESS_NAMESPACES, "
- + "true);\n"
- + "parser.setInput(in, null);\n"
- + "parser.nextTag();\n"
- + "String tagName = parser.getName();\n"
- + "String raw = null;\n", getDefaultNullability(Nullability.NULLABLE),
- javaType.getName(), isMultiRootElement ? Utils.capitalize(javaType.getName()) : "",
- getDefaultNullability(Nullability.NON_NULL));
- out.printf("if (tagName.equals(\"%s\")) {\n", element.getName());
+ + " throws org.xmlpull.v1.XmlPullParserException, java.io.IOException, "
+ + "javax.xml.datatype.DatatypeConfigurationException {\n"
+ + "org.xmlpull.v1.XmlPullParser _parser = org.xmlpull.v1.XmlPullParserFactory"
+ + ".newInstance().newPullParser();\n"
+ + "_parser.setFeature(org.xmlpull.v1.XmlPullParser.FEATURE_PROCESS_NAMESPACES, "
+ + "true);\n"
+ + "_parser.setInput(in, null);\n"
+ + "_parser.nextTag();\n"
+ + "String _tagName = _parser.getName();\n"
+ + "String _raw = null;\n", getDefaultNullability(Nullability.NULLABLE),
+ typeName, isMultiRootElement ? readerName : "",
+ getDefaultNullability(Nullability.NON_NULL));
+ out.printf("if (_tagName.equals(\"%s\")) {\n", elementName);
if (javaType instanceof JavaSimpleType) {
- out.print("raw = XmlParser.readText(parser);\n");
+ out.print("_raw = XmlParser.readText(_parser);\n");
}
out.print(javaType.getParsingExpression());
- out.print("return value;\n"
+ out.print("return _value;\n"
+ "}\n"
+ "return null;\n"
+ "}\n");
@@ -536,12 +547,12 @@ public class JavaCodeGenerator {
}
out.printf(
- "public static %sjava.lang.String readText(%sorg.xmlpull.v1.XmlPullParser parser)"
+ "public static %sjava.lang.String readText(%sorg.xmlpull.v1.XmlPullParser _parser)"
+ " throws org.xmlpull.v1.XmlPullParserException, java.io.IOException {\n"
+ "String result = \"\";\n"
- + "if (parser.next() == org.xmlpull.v1.XmlPullParser.TEXT) {\n"
- + " result = parser.getText();\n"
- + " parser.nextTag();\n"
+ + "if (_parser.next() == org.xmlpull.v1.XmlPullParser.TEXT) {\n"
+ + " result = _parser.getText();\n"
+ + " _parser.nextTag();\n"
+ "}\n"
+ "return result;\n"
+ "}\n", getDefaultNullability(Nullability.NULLABLE),
@@ -549,14 +560,14 @@ public class JavaCodeGenerator {
out.println();
out.printf(
- "public static void skip(%sorg.xmlpull.v1.XmlPullParser parser)"
+ "public static void skip(%sorg.xmlpull.v1.XmlPullParser _parser)"
+ " throws org.xmlpull.v1.XmlPullParserException, java.io.IOException {\n"
- + "if (parser.getEventType() != org.xmlpull.v1.XmlPullParser.START_TAG) {\n"
+ + "if (_parser.getEventType() != org.xmlpull.v1.XmlPullParser.START_TAG) {\n"
+ " throw new IllegalStateException();\n"
+ "}\n"
+ "int depth = 1;\n"
+ "while (depth != 0) {\n"
- + " switch (parser.next()) {\n"
+ + " switch (_parser.next()) {\n"
+ " case org.xmlpull.v1.XmlPullParser.END_TAG:\n"
+ " depth--;\n"
+ " break;\n"
@@ -622,18 +633,31 @@ public class JavaCodeGenerator {
for (XsdElement element : xmlSchema.getElementMap().values()) {
+ // Skip writer if not specified as root.
+ if (rootElements != null
+ && Arrays.asList(rootElements).indexOf(element.getName()) == -1) continue;
JavaType javaType = parseType(element.getType(), element.getName());
String elementName = element.getName();
- String VariableName = Utils.toVariableName(elementName);
- String typeName = javaType instanceof JavaSimpleType ? javaType.getName() :
- Utils.toClassName(javaType.getName());
- out.printf("public static void write(%sXmlWriter out, %s%s %s) "
- + "throws java.io.IOException {", getDefaultNullability(Nullability.NON_NULL),
- getDefaultNullability(Nullability.NON_NULL), typeName, VariableName);
- out.print("\nout.print(\"<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\"?>\\n\");\n");
- out.printf("if (%s != null) {\n", VariableName);
- out.printf("%s.write(out, \"%s\");\n}\n", VariableName, elementName);
- out.print("out.printXml();\n}\n\n");
+ String variableName = Utils.toVariableName(elementName);
+ String typeName = javaType.getName();
+ String writerName
+ = javaType instanceof JavaSimpleType ? Utils.toClassName(elementName) : "";
+ out.printf("public static void write%s(%sXmlWriter _out, %s%s %s) "
+ + "throws java.io.IOException {",
+ writerName,
+ getDefaultNullability(Nullability.NON_NULL),
+ getDefaultNullability(Nullability.NON_NULL), typeName, variableName);
+ out.print("\n_out.print(\"<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\"?>\\n\");\n");
+ out.printf("if (%s != null) {\n", variableName);
+ if (javaType instanceof JavaSimpleType) {
+ out.printf("_out.print(\"<%s>\");\n", elementName);
+ out.print(javaType.getWritingExpression(variableName, ""));
+ out.printf("_out.print(\"</%s>\\n\");\n", elementName);
+ } else {
+ out.printf("%s.write(_out, \"%s\");\n", variableName, elementName);
+ }
+ out.print("}\n");
+ out.print("_out.printXml();\n}\n\n");
}
out.printf("}\n");
}
diff --git a/src/com/android/xsdc/java/JavaCodeGeneratorException.java b/src/main/java/com/android/xsdc/java/JavaCodeGeneratorException.java
index b37a284..b37a284 100644
--- a/src/com/android/xsdc/java/JavaCodeGeneratorException.java
+++ b/src/main/java/com/android/xsdc/java/JavaCodeGeneratorException.java
diff --git a/src/com/android/xsdc/java/JavaComplexType.java b/src/main/java/com/android/xsdc/java/JavaComplexType.java
index 1a66794..e25acd7 100644
--- a/src/com/android/xsdc/java/JavaComplexType.java
+++ b/src/main/java/com/android/xsdc/java/JavaComplexType.java
@@ -40,11 +40,11 @@ class JavaComplexType implements JavaType {
@Override
public String getParsingExpression() {
- return String.format("%s value = %s.read(parser);\n", name, name);
+ return String.format("%s _value = %s.read(_parser);\n", name, name);
}
@Override
public String getWritingExpression(String getValue, String name) {
- return String.format("%s.write(out, \"%s\");\n", getValue, name);
+ return String.format("%s.write(_out, \"%s\");\n", getValue, name);
}
}
diff --git a/src/com/android/xsdc/java/JavaSimpleType.java b/src/main/java/com/android/xsdc/java/JavaSimpleType.java
index 5c73466..5ad905f 100644
--- a/src/com/android/xsdc/java/JavaSimpleType.java
+++ b/src/main/java/com/android/xsdc/java/JavaSimpleType.java
@@ -74,15 +74,15 @@ class JavaSimpleType implements JavaType {
StringBuilder expression = new StringBuilder();
if (list) {
expression.append(
- String.format("%s value = new java.util.ArrayList<>();\n", getName()));
- expression.append("for (String token : raw.split(\"\\\\s+\")) {\n");
- expression.append(String.format("value.add(%s);\n",
- String.format(rawParsingExpression, "token")));
+ String.format("%s _value = new java.util.ArrayList<>();\n", getName()));
+ expression.append("for (String _token : _raw.split(\"\\\\s+\")) {\n");
+ expression.append(String.format("_value.add(%s);\n",
+ String.format(rawParsingExpression, "_token")));
expression.append("}\n");
} else {
expression.append(
- String.format("%s value = %s;\n", getName(),
- String.format(rawParsingExpression, "raw")));
+ String.format("%s _value = %s;\n", getName(),
+ String.format(rawParsingExpression, "_raw")));
}
return expression.toString();
}
@@ -91,16 +91,16 @@ class JavaSimpleType implements JavaType {
public String getWritingExpression(String getValue, String name) {
StringBuilder expression = new StringBuilder();
if (list) {
- expression.append("{\nint count = 0;\n");
+ expression.append("{\nint _count = 0;\n");
expression.append(String.format("for (%s v : %s) {\n", this.name, getValue));
- expression.append("if (count != 0) {\n"
- + "out.print(\" \");\n}\n"
- + "++count;\n");
- expression.append(String.format("out.print(%s);\n}\n",
+ expression.append("if (_count != 0) {\n"
+ + "_out.print(\" \");\n}\n"
+ + "++_count;\n");
+ expression.append(String.format("_out.print(%s);\n}\n",
String.format(rawWritingExpression, "v")));
expression.append("}\n");
} else {
- expression.append(String.format("out.print(%s);\n",
+ expression.append(String.format("_out.print(%s);\n",
String.format(rawWritingExpression, getValue)));
}
return expression.toString();
diff --git a/src/com/android/xsdc/java/JavaType.java b/src/main/java/com/android/xsdc/java/JavaType.java
index 8605f5d..8605f5d 100644
--- a/src/com/android/xsdc/java/JavaType.java
+++ b/src/main/java/com/android/xsdc/java/JavaType.java
diff --git a/src/com/android/xsdc/java/Utils.java b/src/main/java/com/android/xsdc/java/Utils.java
index 5a7a92a..5a7a92a 100644
--- a/src/com/android/xsdc/java/Utils.java
+++ b/src/main/java/com/android/xsdc/java/Utils.java
diff --git a/src/com/android/xsdc/tag/Nullability.java b/src/main/java/com/android/xsdc/tag/Nullability.java
index 9e81635..9e81635 100644
--- a/src/com/android/xsdc/tag/Nullability.java
+++ b/src/main/java/com/android/xsdc/tag/Nullability.java
diff --git a/src/com/android/xsdc/tag/XsdAll.java b/src/main/java/com/android/xsdc/tag/XsdAll.java
index 39c2562..39c2562 100644
--- a/src/com/android/xsdc/tag/XsdAll.java
+++ b/src/main/java/com/android/xsdc/tag/XsdAll.java
diff --git a/src/com/android/xsdc/tag/XsdAttribute.java b/src/main/java/com/android/xsdc/tag/XsdAttribute.java
index 0c46eb0..0c46eb0 100644
--- a/src/com/android/xsdc/tag/XsdAttribute.java
+++ b/src/main/java/com/android/xsdc/tag/XsdAttribute.java
diff --git a/src/com/android/xsdc/tag/XsdAttributeGroup.java b/src/main/java/com/android/xsdc/tag/XsdAttributeGroup.java
index 6c8f853..6c8f853 100644
--- a/src/com/android/xsdc/tag/XsdAttributeGroup.java
+++ b/src/main/java/com/android/xsdc/tag/XsdAttributeGroup.java
diff --git a/src/com/android/xsdc/tag/XsdChoice.java b/src/main/java/com/android/xsdc/tag/XsdChoice.java
index 223bb44..223bb44 100644
--- a/src/com/android/xsdc/tag/XsdChoice.java
+++ b/src/main/java/com/android/xsdc/tag/XsdChoice.java
diff --git a/src/com/android/xsdc/tag/XsdComplexContent.java b/src/main/java/com/android/xsdc/tag/XsdComplexContent.java
index aa9de87..aa9de87 100644
--- a/src/com/android/xsdc/tag/XsdComplexContent.java
+++ b/src/main/java/com/android/xsdc/tag/XsdComplexContent.java
diff --git a/src/com/android/xsdc/tag/XsdComplexType.java b/src/main/java/com/android/xsdc/tag/XsdComplexType.java
index a7e0311..a7e0311 100644
--- a/src/com/android/xsdc/tag/XsdComplexType.java
+++ b/src/main/java/com/android/xsdc/tag/XsdComplexType.java
diff --git a/src/com/android/xsdc/tag/XsdElement.java b/src/main/java/com/android/xsdc/tag/XsdElement.java
index 40a6695..40a6695 100644
--- a/src/com/android/xsdc/tag/XsdElement.java
+++ b/src/main/java/com/android/xsdc/tag/XsdElement.java
diff --git a/src/com/android/xsdc/tag/XsdEnumRestriction.java b/src/main/java/com/android/xsdc/tag/XsdEnumRestriction.java
index 3ae7ae0..3ae7ae0 100644
--- a/src/com/android/xsdc/tag/XsdEnumRestriction.java
+++ b/src/main/java/com/android/xsdc/tag/XsdEnumRestriction.java
diff --git a/src/com/android/xsdc/tag/XsdEnumeration.java b/src/main/java/com/android/xsdc/tag/XsdEnumeration.java
index 2f9fdc0..2f9fdc0 100644
--- a/src/com/android/xsdc/tag/XsdEnumeration.java
+++ b/src/main/java/com/android/xsdc/tag/XsdEnumeration.java
diff --git a/src/com/android/xsdc/tag/XsdGeneralExtension.java b/src/main/java/com/android/xsdc/tag/XsdGeneralExtension.java
index 24043e4..24043e4 100644
--- a/src/com/android/xsdc/tag/XsdGeneralExtension.java
+++ b/src/main/java/com/android/xsdc/tag/XsdGeneralExtension.java
diff --git a/src/com/android/xsdc/tag/XsdGeneralRestriction.java b/src/main/java/com/android/xsdc/tag/XsdGeneralRestriction.java
index 6583622..6583622 100644
--- a/src/com/android/xsdc/tag/XsdGeneralRestriction.java
+++ b/src/main/java/com/android/xsdc/tag/XsdGeneralRestriction.java
diff --git a/src/com/android/xsdc/tag/XsdGroup.java b/src/main/java/com/android/xsdc/tag/XsdGroup.java
index dd8f008..dd8f008 100644
--- a/src/com/android/xsdc/tag/XsdGroup.java
+++ b/src/main/java/com/android/xsdc/tag/XsdGroup.java
diff --git a/src/com/android/xsdc/tag/XsdList.java b/src/main/java/com/android/xsdc/tag/XsdList.java
index 70023c8..70023c8 100644
--- a/src/com/android/xsdc/tag/XsdList.java
+++ b/src/main/java/com/android/xsdc/tag/XsdList.java
diff --git a/src/com/android/xsdc/tag/XsdRestriction.java b/src/main/java/com/android/xsdc/tag/XsdRestriction.java
index 17dfdd5..17dfdd5 100644
--- a/src/com/android/xsdc/tag/XsdRestriction.java
+++ b/src/main/java/com/android/xsdc/tag/XsdRestriction.java
diff --git a/src/com/android/xsdc/tag/XsdSimpleContent.java b/src/main/java/com/android/xsdc/tag/XsdSimpleContent.java
index cefa60e..cefa60e 100644
--- a/src/com/android/xsdc/tag/XsdSimpleContent.java
+++ b/src/main/java/com/android/xsdc/tag/XsdSimpleContent.java
diff --git a/src/com/android/xsdc/tag/XsdSimpleType.java b/src/main/java/com/android/xsdc/tag/XsdSimpleType.java
index c7d7e37..c7d7e37 100644
--- a/src/com/android/xsdc/tag/XsdSimpleType.java
+++ b/src/main/java/com/android/xsdc/tag/XsdSimpleType.java
diff --git a/src/com/android/xsdc/tag/XsdTag.java b/src/main/java/com/android/xsdc/tag/XsdTag.java
index 3397267..3397267 100644
--- a/src/com/android/xsdc/tag/XsdTag.java
+++ b/src/main/java/com/android/xsdc/tag/XsdTag.java
diff --git a/src/com/android/xsdc/tag/XsdType.java b/src/main/java/com/android/xsdc/tag/XsdType.java
index a7e41a0..a7e41a0 100644
--- a/src/com/android/xsdc/tag/XsdType.java
+++ b/src/main/java/com/android/xsdc/tag/XsdType.java
diff --git a/src/com/android/xsdc/tag/XsdUnion.java b/src/main/java/com/android/xsdc/tag/XsdUnion.java
index f738330..f738330 100644
--- a/src/com/android/xsdc/tag/XsdUnion.java
+++ b/src/main/java/com/android/xsdc/tag/XsdUnion.java
diff --git a/src/test/java/com/android/xsdc/cpp/TestCppCodeGenerator.java b/src/test/java/com/android/xsdc/cpp/TestCppCodeGenerator.java
new file mode 100644
index 0000000..6106696
--- /dev/null
+++ b/src/test/java/com/android/xsdc/cpp/TestCppCodeGenerator.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2022, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.xsdc.cpp;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import com.android.xsdc.FileSystem;
+import com.android.xsdc.XmlSchema;
+import com.android.xsdc.XsdHandler;
+
+import org.junit.Test;
+
+import java.io.ByteArrayInputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+public class TestCppCodeGenerator {
+ public static final String SCHEMA = "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">\n"
+ + " <xs:element name=\"class\" type=\"xs:string\" />\n"
+ + "</xs:schema>";
+
+ @Test
+ public void testParseSchema() throws Exception {
+ XmlSchema schema = parseSchema(SCHEMA);
+ assertEquals(schema.getElementMap().keySet(), Set.of("class"));
+ }
+
+ @Test
+ public void testSimpleTypeRootParser() throws Exception {
+ // We need two root elements to generate reader with element name.
+ String schema = "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">\n"
+ + " <xs:element name=\"simple-type-element\" type=\"xs:string\" />\n"
+ + " <xs:element name=\"another-root\" type=\"xs:string\" />\n"
+ + "</xs:schema>";
+ Map<String, StringBuffer> files = new TreeMap<>();
+ CppCodeGenerator gen =
+ new CppCodeGenerator(
+ parseSchema(schema),
+ "com.abc",
+ /*writer=*/ true,
+ CppCodeGenerator.GENERATE_PARSER,
+ false,
+ false,
+ null);
+
+ FileSystem fs = new FileSystem(files);
+ gen.print(fs);
+ assertTrue(files.get("com_abc.cpp").toString().contains("readSimpleTypeElement"));
+ assertTrue(files.get("com_abc.cpp").toString().contains("writeSimpleTypeElement"));
+ }
+
+ @Test
+ public void testPrintWithoutEnumOutput() throws Exception {
+ Map<String, StringBuffer> files = new TreeMap<>();
+ CppCodeGenerator gen =
+ new CppCodeGenerator(
+ parseSchema(SCHEMA),
+ "com.abc",
+ false,
+ CppCodeGenerator.GENERATE_PARSER,
+ false,
+ false,
+ null);
+
+ FileSystem fs = new FileSystem(files);
+ gen.print(fs);
+
+ assertEquals(files.keySet(), Set.of("com_abc.cpp", "include/com_abc.h"));
+ }
+
+ @Test
+ public void printWithEnumOutput() throws Exception {
+ Map<String, StringBuffer> files = new TreeMap<>();
+
+ CppCodeGenerator gen =
+ new CppCodeGenerator(
+ parseSchema(SCHEMA),
+ "com.abc",
+ false,
+ CppCodeGenerator.GENERATE_PARSER | CppCodeGenerator.GENERATE_ENUMS,
+ false,
+ false,
+ null);
+
+ FileSystem fs = new FileSystem(files);
+ gen.print(fs);
+
+ assertEquals(
+ files.keySet(),
+ Set.of(
+ "com_abc.cpp",
+ "include/com_abc.h",
+ "com_abc_enums.cpp",
+ "include/com_abc_enums.h"));
+ }
+
+ private XmlSchema parseSchema(String contents) throws Exception {
+ byte[] bytes = contents.getBytes(StandardCharsets.UTF_8);
+ SAXParserFactory factory = SAXParserFactory.newInstance();
+ factory.setNamespaceAware(true);
+ SAXParser parser = factory.newSAXParser();
+ XsdHandler xsdHandler = new XsdHandler();
+ parser.parse(new ByteArrayInputStream(bytes), xsdHandler);
+ return xsdHandler.getSchema();
+ }
+
+ @Test
+ public void generateParsersForSpecifiedRoot() throws Exception {
+ Map<String, StringBuffer> files = new TreeMap<>();
+ String schema = "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">\n"
+ + " <xs:element name=\"root1\" type=\"xs:string\" />\n"
+ + " <xs:element name=\"root2\" type=\"xs:string\" />\n"
+ + "</xs:schema>";
+ CppCodeGenerator gen =
+ new CppCodeGenerator(
+ parseSchema(schema),
+ "com.abc",
+ false,
+ CppCodeGenerator.GENERATE_PARSER | CppCodeGenerator.GENERATE_ENUMS,
+ false,
+ false,
+ new String[]{"root1"});
+
+ FileSystem fs = new FileSystem(files);
+ gen.print(fs);
+ assertTrue(files.get("com_abc.cpp").toString().contains("readRoot1"));
+ assertFalse(files.get("com_abc.cpp").toString().contains("readRoot2"));
+ }
+}
diff --git a/tests/resources/simple_complex_content/api/current.txt b/tests/resources/simple_complex_content/api/current.txt
index 043fb50..785e014 100644
--- a/tests/resources/simple_complex_content/api/current.txt
+++ b/tests/resources/simple_complex_content/api/current.txt
@@ -24,14 +24,17 @@ package simple.complex.content {
method public String getName();
method public simple.complex.content.SubAddress getSubAddress();
method public simple.complex.content.USAddressP getUSAddressP();
+ method public simple.complex.content.KRAddress getValue();
method public boolean hasKRAddress();
method public boolean hasName();
method public boolean hasSubAddress();
method public boolean hasUSAddressP();
+ method public boolean hasValue();
method public void setKRAddress(simple.complex.content.KRAddress);
method public void setName(String);
method public void setSubAddress(simple.complex.content.SubAddress);
method public void setUSAddressP(simple.complex.content.USAddressP);
+ method public void setValue(simple.complex.content.KRAddress);
}
public class Person2 {
@@ -40,14 +43,17 @@ package simple.complex.content {
method public String getName();
method @NonNull public simple.complex.content.SubAddress getSubAddress();
method public simple.complex.content.USAddressP getUSAddressP();
+ method public String getValue();
method public boolean hasKRAddress();
method public boolean hasName();
method public boolean hasSubAddress();
method public boolean hasUSAddressP();
+ method public boolean hasValue();
method public void setKRAddress(simple.complex.content.KRAddress);
method public void setName(String);
method public void setSubAddress(@NonNull simple.complex.content.SubAddress);
method public void setUSAddressP(simple.complex.content.USAddressP);
+ method public void setValue(String);
}
public class SubAddress {
diff --git a/tests/resources/simple_complex_content/simple_complex_content.xsd b/tests/resources/simple_complex_content/simple_complex_content.xsd
index 62a6497..7bb57b5 100644
--- a/tests/resources/simple_complex_content/simple_complex_content.xsd
+++ b/tests/resources/simple_complex_content/simple_complex_content.xsd
@@ -50,6 +50,7 @@
<xs:element name="USAddressP" type="USAddressP"/>
<xs:element name="KRAddress" type="KRAddress"/>
<xs:element name="subAddress" type="subAddress"/>
+ <xs:element name="value" type="KRAddress" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:element>
@@ -62,6 +63,7 @@
<xs:element name="subAddress" type="subAddress">
<xs:annotation name="nonnull"/>
</xs:element>
+ <xs:element name="value" type="xs:string" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:element>
diff --git a/tests/resources/simple_type/api/current.txt b/tests/resources/simple_type/api/current.txt
index 0b163a5..8368c23 100644
--- a/tests/resources/simple_type/api/current.txt
+++ b/tests/resources/simple_type/api/current.txt
@@ -18,16 +18,20 @@ package simple.type {
public class SimpleTypes {
ctor public SimpleTypes();
method public java.util.List<java.lang.Integer> getListInt();
+ method public java.util.List<java.lang.Integer> getOptionalIntList();
method public java.util.List<java.lang.String> getUnionTest();
method public java.util.List<simple.type.EnumType> getYesOrNo();
method public boolean isExample1();
method public boolean isExample2();
method public boolean isExample3();
+ method public boolean isValue();
method public void setExample1(boolean);
method public void setExample2(boolean);
method public void setExample3(boolean);
method public void setListInt(java.util.List<java.lang.Integer>);
+ method public void setOptionalIntList(java.util.List<java.lang.Integer>);
method public void setUnionTest(java.util.List<java.lang.String>);
+ method public void setValue(boolean);
}
public class SingleChoice {
@@ -43,6 +47,7 @@ package simple.type {
public class XmlParser {
ctor public XmlParser();
method public static simple.type.MultiChoice readMultiChoice(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ method public static java.math.BigInteger readPercent(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public static simple.type.SimpleTypes readSimpleTypes(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public static simple.type.SingleChoice readSingleChoice(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public static String readText(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
@@ -55,6 +60,7 @@ package simple.type {
method public static void write(simple.type.XmlWriter, simple.type.SimpleTypes) throws java.io.IOException;
method public static void write(simple.type.XmlWriter, simple.type.MultiChoice) throws java.io.IOException;
method public static void write(simple.type.XmlWriter, simple.type.SingleChoice) throws java.io.IOException;
+ method public static void writePercent(simple.type.XmlWriter, java.math.BigInteger) throws java.io.IOException;
}
}
diff --git a/tests/resources/simple_type/simple_type.xsd b/tests/resources/simple_type/simple_type.xsd
index 481c476..9bbd283 100644
--- a/tests/resources/simple_type/simple_type.xsd
+++ b/tests/resources/simple_type/simple_type.xsd
@@ -33,8 +33,10 @@
<xs:element name="yesOrNo" type="enumType" maxOccurs="2"/>
<xs:element name="example1" type="xs:boolean"/>
<xs:element name="example2" type="xs:boolean"/>
+ <xs:element name="optional-int-list" maxOccurs="1" type="ints"/>
</xs:sequence>
<xs:attribute name="example3" type="xs:boolean"/>
+ <xs:attribute name="value" type="xs:boolean"/>
</xs:complexType>
</xs:element>
<xs:element name="multi-choice">
@@ -55,4 +57,5 @@
</xs:choice>
</xs:complexType>
</xs:element>
+ <xs:element name="percent" type="percent" />
</xs:schema>
diff --git a/tests/resources/simple_type_root.xml b/tests/resources/simple_type_root.xml
new file mode 100644
index 0000000..a6fed4f
--- /dev/null
+++ b/tests/resources/simple_type_root.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8"?>
+<percent>100</percent>
diff --git a/tests/simple_type.cpp b/tests/simple_type.cpp
index 5162c6d..3f1b2de 100644
--- a/tests/simple_type.cpp
+++ b/tests/simple_type.cpp
@@ -16,6 +16,7 @@
#include <iostream>
#include <fstream>
+#include <sstream>
#include <android-base/macros.h>
@@ -50,3 +51,28 @@ TEST_F(XmlTest, Simpletype) {
EXPECT_EQ(simple.getYesOrNo()[0], simple2.getYesOrNo()[0]);
EXPECT_EQ(simple.getYesOrNo()[1], simple2.getYesOrNo()[1]);
}
+
+TEST_F(XmlTest, Simpletype_AccessingEmptyOptionalAbortsWithMessage) {
+ using namespace simple::type;
+
+ string file_name = Resource("simple_type.xml");
+ SimpleTypes simple = *readSimpleTypes(file_name.c_str());
+
+ // trying to get the value for optional attribute
+ ASSERT_DEATH(simple.isExample3(), "hasExample3()");
+ // trying to get the value for optional element
+ ASSERT_DEATH(simple.getOptionalIntList(), "hasOptionalIntList()");
+ // trying to get the first value from optional element of list of simple values
+ ASSERT_DEATH(simple.getFirstOptionalIntList(), "hasOptionalIntList()");
+}
+
+TEST_F(XmlTest, SimpleTypeRoot) {
+ using namespace simple::type;
+
+ string file_name = Resource("simple_type_root.xml");
+ ASSERT_EQ(*readPercent(file_name.c_str()), 100);
+
+ ostringstream out;
+ writePercent(out, 100);
+ ASSERT_EQ(out.str(), "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<percent>100</percent>\n");
+}
diff --git a/tests/src/com/android/xsdc/tests/XmlParserTest.java b/tests/src/com/android/xsdc/tests/XmlParserTest.java
index f3b5eaf..bb54099 100644
--- a/tests/src/com/android/xsdc/tests/XmlParserTest.java
+++ b/tests/src/com/android/xsdc/tests/XmlParserTest.java
@@ -248,6 +248,31 @@ public class XmlParserTest {
}
@Test
+ public void testSimpleTypeRoot() throws Exception {
+ BigInteger percent;
+ try (InputStream str = this.getClass().getClassLoader().getResourceAsStream(
+ "simple_type_root.xml")) {
+ percent = simple.type.XmlParser.readPercent(str);
+ }
+
+ assertThat(percent, is(BigInteger.valueOf(100)));
+
+ String actualStr, expectedStr;
+ try (InputStream str = this.getClass().getClassLoader().getResourceAsStream(
+ "simple_type_root.xml")) {
+ expectedStr = new String(str.readAllBytes());
+ }
+ try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
+ try(simple.type.XmlWriter writer = new simple.type.XmlWriter(new PrintWriter(baos))) {
+ simple.type.XmlWriter.writePercent(writer, percent);
+ }
+ actualStr = new String(baos.toByteArray());
+ }
+
+ assertThat(new String(actualStr), is(expectedStr));
+ }
+
+ @Test
public void testReference() throws Exception {
reference.Class _class;
try (InputStream str = this.getClass().getClassLoader().getResourceAsStream(