**********************
xsd2cppsax Anleitung
**********************

1. Aufruf des Generators
************************
xsd2cppsax ist ein Code Generator, der aus einem XSD einen C++ SAX Parser generiert. Um die
Code Generierung zu starten kann folgende Kommandozeile verwendet werden:

java -cp xsd2cppsax.jar;xercesImpl.jar de.netallied.xsd2cppsax.Main -c < Pfad zur Config Datei >

Es wird Java mindestens in Version 5 bentigt.

Da der generierte Code Regulre Ausdrcke des XSDs mit vorkompilierten pcre Ausdrcken
validiert, muss sich pcre_compiler.exe im Working Directory befinden. 

Neben -c stehen noch zwei optionale Kommandozeilen Parameter zur Verfgung. Diese berschreiben
Optionen aus der Config Datei:
-i <input XSD>
-r <root element name>
Mittels dieser optionalen Parameter kann eine Config Datei mit mehreren XSDs verwendet werden.
Whrend des generierens wird auf optionale Attribute ohne Default-Wert hingewiesen. Bei spterer
integration des generierten parsers in eine Anwendung muss beachtet werden, dass diese Attribute
einen undefinierten Wert haben knnen.



2. ber den generierten Code
****************************
Grundstzlich werden zwei Klassen generiert: PublicParser und PrivateParser.
Der PrivateParser wird intern Verwendet. Er dient dazu die Text Daten des Eingabe 
Dokuments in binre Daten umzuwandeln (z.B. float oder URI). Auerdem ist er in
der Lage, das Eingabe Dokument zu validieren. Die Validierung ist zur Compile-Zeit
und zur Laufzeit abschaltbar. Nachdem der PrivateParser die Text Daten geparst hat
bergibt er sie an die Methoden des PublicParsers.

Der PublicParser ist dazu gedacht, von ihm abzuleiten. Fr jedes Element des XSDs
stellt er zwei oder drei Methoden zur Verfgung. Die beiden die immer Verfgbar sind,
sind eine "begin" und eine "end" Methode fr jedes Element. Die dritte Methode beginnt
mit "data". Durch sie werden die geparsten XML Text Daten an den Implementierer 
bergeben. Da nicht jedes Element Text Daten haben kann, ist diese Methode auch nicht
fr jedes Element verfgbar. Die "begin", "end" und "data" Methoden folgen dem SAX
Prinzip. Die Attribute eines Elements werden der "begin" Methode mit bergeben. Fr
die Attribute werden C++ structs generiert. Falls erforderlich enthalten diese structs
Bit-Felder um abzuprfen ob ein Attribut gesetzt ist oder nicht.

Fr den XSD Typ "anyURI" wird eine C++ URI Klasse verwendet. Diese stammt aus dem BaseUtils
Paket des OpenCOLLADA Projekts.

Fr XSD enums und unions werden auch C++ enums und unions generiert. Diese werden in
den Attribut structs und bei den "data" Methoden verwendet.

Eventuell auftretende Validierungs-Fehler werden an einen ErrorHandler bergeben. Dieser
sollte vom Anwendungs-Entwickler implementiert werden. Er kann entscheiden ob bei einem
Fehler abgebrochen wird oder nicht. Es wird eine Beispiel Implementierung mit geliefert,
welche alle Fehler ber die Standart-Ausgabe ausgibt und nie abbricht.

Dieser CoutErrorHandler befindet sich im Paket "GeneratedSaxParser" des OpenCOLLADA Projekts.
Dort befinden sich noch weitere Klassen die vom generierten Code verwendet werden. Dieses
Prjekt bietet die Mglichkeit zwei verschiedene XML Biblitheken als Basis fr den
generierten Parser zu verwenden. Dies sind libxml und expat. Mittels Prpozessor
Flag kann zwischen ihnen gewhlt werden:
- GENERATEDSAXPARSER_XMLPARSER_LIBXML
- GENERATEDSAXPARSER_XMLPARSER_EXPAT
Ein weiteres Prpozessor flag dient dazu, die Validierung zur Compile-Zeit einzuschalten:
- GENERATEDSAXPARSER_VALIDATION

Optional knnen zwei Implementierungen des PublicParsers generiert werden. Die eine,
ExampleParser, tut nichts. Sie dient als Beispiel wie ein eigener Parser implementiert
werden kann. Die andere, fprintf parser, schreibt die geparste Datei wieder in eine
andere Datei (mittles der C funktion fprinf). Sie kann fr Performance Messungen oder 
auch als Implementierungs Vorlage dienen.

Experimentell ist auch eine dritte PublicParser Implementierung verfgbar: CoherencyTestParser.
Er dient der berprfung von COLLADA Dokumenten, ist also spezifisch fr ein XSD. Da
er experimentell ist und kaum features bietet, wird von einer Generierung abgeraten.

Ein Groteil des generierten Codes wird durch Code Templates definiert. Diese Code 
Templates befinden sich in einer Datei welche von der Config Datei referenziert 
wird. Da nderungen hieran sehr leicht zu unkompilierbarem Code fhren knnen, wird 
empfohlen, die mitgelieferte Code Templates Datei unverndert zu verwenden.

Um eine hohe Performance zu erreichen wird innerhalb des PrivateParsers ein spezielles 
Memory Management verwendet. Wie anfangs beschrieben, parst der PrivateParser die
Text Daten des Dokuments. Um die binren Daten ablegen zu knnen ist Speicher erforderlich.
Da die C/C++ default Speicher Verwaltung mit einer Vielzahl an spezial Fllen zurecht
kommen muss, und evtl. das Betriebssystem sogar in den Kernel-Mode wechseln muss, kann
diese sehr langsam sein. Das Memory Management des PrivateParsers ist in der C++ Klasse
GeneratedSaxParser::StackMemoryManager gekapselt. Dieser Manager alloziert zu beginn
eine bestimmte Menge Speicher (per default 1 MB). Bei Bedarf wird in diesem Speicher
ein Objekt angelegt. Die gre des Objekts wird am seinem Ende mit abgelegt. Diese
Grenangabe dient spter dem korrekten freigeben des Objekts. Da der Manager nach dem
Stack Prinzip arbeitet, werden neuen Objekte immer am Ende des belegten Speichers angelegt
und es kann immer nur das letzte Objekt gelscht werden. Das Lschen ist enorm schnell, 
da nur ein paar interne Status Variablen des Managers gendert werden mssen. Da wrend
des Parsens nicht immer bekannt ist, wieviel Speicher bentigt wird, bietet der Manager 
die Mglichkeit, dass letzte Objekt auf dem Stack zu vergrern. Der Speicher des Managers
wird, anders als bei C++ new, nicht initialisiert, weshalb er sich nicht fr C++-Objekte
eignet (aber fr pointer auf solche).

Ein weiteres Detail um die Performance zu steigern liegt im parsen von Gleitkomma Zahlen.
Anstatt C Funktionen wie atof() oder scanf() zu verwenden, verfgt der generierte Parser
ber eine eigene Implementierung (GeneratedSaxParser::Utils::toFloatingPoint).

Whrend eines SAX-Parsing-Vorgangs mssen blicherweise viele Strings verglichen werden
(die Element Namen) um die richtigen Funktionen aufzurufen. Um dies zu vermeiden setzt
der generierte Parser auf String Hashes. Damit wird die Performance nocheinmal gesteigert.



3. Konfigurations Mglichkeiten
*******************************
In der angesprochenen Config Datei lassen sich eine Vielzahl von Optionen festlegen.
Es wird empfohlen die mitgelieferte Beispiel Datei als Vorlage zu nehmen.
Hier Eine Auswahl der Optionen:
- Ausgabe Pfade fr die generierten Dateien. Die Verzeichnisse mssen bereits existieren.
    outputHeaderFileNamePublic
    outputHeaderFileNamePrivate
    outputSourceFileNamePrivate
    outputExampleHeaderFileName
    outputExampleSourceFileName
    outputFPrintfHeaderFileName
    outputFPrintfSourceFileName
- Eingabe XSD
    inputFile
- Das Root Element des Eingabe XSDs
    rootElementName
- Klassennamen und Namespace des generierten Parsers
    namespace
    classNamePrivate
    classNamePublic
- Dateien die im generierten Code includiert werden
    includePrecompiledHeader
    includeFilesForEnumsHeader
    includeFilesForEnumsSource 
    includeFilesForImpl
    includeFilesForPrivateHeader
- Ein Header (z.B. mit Lizenz/Copyright informationen) fr den generierten Code
    outFileHeader
- Ob XSD float und double in C++ als float oder double verwendet werden sollen
  Damit kann der Anwender selbst zwischen Geschwindigkeit und Genauigkeit whlen
    treatXsFloatAsCppFloat
    treatXsDoubleAsCppDouble
- Elemente die unabhngig vom Rest eines Dokuments geparst werden sollen
  (Bei der OpenCOLLADA Bibliothek wird das fr die "Parser-Flags" verwendet)
    specialFunctionMapsStartElementNamesAllLevels
    specialFunctionMapsStartElementNamesOneLevel
- XSD Element Namen welche im Zusammenhang mit Complex Type Validation umbenannt werden mssen,
  da sie in C++ nicht erlaubt sind
    cppStructMemberNameMapping
- Generierte C++ Typnamen welche umbenannt werden sollen
  (z.B. fr Anonyme Enums des XSDs)
    userTypeNameMapping
- XML Namespaces welche abgekrzt werden sollen (um die Lesbarkeit zu erhhen)
    xsNamespaceMapping
- Ob eine Beispiel Parser Implementierung generiert werden soll
    generateExampleParser
- Ob der fprintf Parser generiert werden soll
  (dieser schreibt die geparste Datei sofort wieder in eine Datei)
    generateFprintfParser
- Klassennamen und Namespace von Beispiel- und fprintf-Parser
    exampleClassName
    exampleNamespace
    fPrintfParserClassName
    fPrintfParserNamespace
- Es stehen noch weitere Optionen zur Verfgung, die z.B. Typen und Namen 
  von Variablen im generierten Code ndern oder zu generierten Typ-Namen 
  oder Methoden suffixe/prefixe hinzufgen.
  nderungen hieran knnen dazu fhren, dass der generierte Code nicht mehr kompilierbar ist.
    convenienceDataMethodLengthParameterName
    simpleValidationFunctionLengthParameterType
    cppEnumTypePrefix
    attributeStructSuffix
    ...
