#import "enunciate-common.h" /** * Enunciate-specific C functions. */ #ifndef ENUNCIATE_C_UTILITIES #define ENUNCIATE_C_UTILITIES /*******************xml utilities************************************/ int xmlTextReaderAdvanceToNextStartOrEndElement(xmlTextReaderPtr reader) { int status = xmlTextReaderRead(reader); while (status && xmlTextReaderNodeType(reader) != XML_READER_TYPE_ELEMENT && xmlTextReaderNodeType(reader) != XML_READER_TYPE_END_ELEMENT) { status = xmlTextReaderRead(reader); } return status; } int xmlTextReaderSkipElement(xmlTextReaderPtr reader) { int status = xmlTextReaderNext(reader); while (status && xmlTextReaderNodeType(reader) != XML_READER_TYPE_ELEMENT && xmlTextReaderNodeType(reader) != XML_READER_TYPE_END_ELEMENT) { status = xmlTextReaderRead(reader); } return status; } xmlChar *xmlTextReaderReadEntireNodeValue(xmlTextReaderPtr reader) { xmlChar *buffer = calloc(1, sizeof(xmlChar)); const xmlChar *snippet; int status; if (xmlTextReaderNodeType(reader) == XML_READER_TYPE_ATTRIBUTE) { return xmlTextReaderValue(reader); } else if (xmlTextReaderIsEmptyElement(reader) == 0) { status = xmlTextReaderRead(reader); while (status && (xmlTextReaderNodeType(reader) == XML_READER_TYPE_TEXT || xmlTextReaderNodeType(reader) == XML_READER_TYPE_CDATA || xmlTextReaderNodeType(reader) == XML_READER_TYPE_ENTITY_REFERENCE)) { snippet = xmlTextReaderConstValue(reader); buffer = realloc(buffer, (xmlStrlen(buffer) + xmlStrlen(snippet) + 1) * sizeof(xmlChar)); xmlStrcat(buffer, snippet); status = xmlTextReaderRead(reader); } } return buffer; } /*******************base 64 utilities************************************/ /* * Base64 Translation Table as described in RFC1113. * * This code was graciously ripped from http://base64.sourceforge.net */ const char cb64[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; /* * Base64 Translation Table to decode (created by author) * * This code was graciously ripped from http://base64.sourceforge.net */ const char cd64[]="|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW$$$$$$XYZ[\\]^_`abcdefghijklmnopq"; /* * encode 3 8-bit binary bytes as 4 '6-bit' characters * * This code was graciously ripped from http://base64.sourceforge.net * * @param in the block to encode * @param out the block to encode to * @param len the length of the 'in' block. */ void _encode_base64_block(unsigned char in[3], unsigned char out[4], int len) { out[0] = cb64[ in[0] >> 2 ]; out[1] = cb64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4) ]; out[2] = (unsigned char) (len > 1 ? cb64[ ((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6) ] : '='); out[3] = (unsigned char) (len > 2 ? cb64[ in[2] & 0x3f ] : '='); } /* * decode 4 '6-bit' characters into 3 8-bit binary bytes * * This code was graciously ripped from http://base64.sourceforge.net */ void _decode_base64_block( unsigned char in[4], unsigned char out[3] ) { out[ 0 ] = (unsigned char ) (in[0] << 2 | in[1] >> 4); out[ 1 ] = (unsigned char ) (in[1] << 4 | in[2] >> 2); out[ 2 ] = (unsigned char ) (((in[2] << 6) & 0xc0) | in[3]); } /* * base64 encode a stream adding padding and line breaks as per spec. * * This code was graciously ripped from http://base64.sourceforge.net * * @param instream The stream to encode. * @param insize The size of the stream to encode. * @return The encoded string. */ xmlChar *_encode_base64(unsigned char *instream, int insize) { unsigned char in[3]; unsigned char out[4]; xmlChar *encoded; int i, in_index = 0, out_index = 0, blocklen; if (insize == 0) { return BAD_CAST "\0"; } encoded = calloc(((insize / 3) * 4) + 10, sizeof(xmlChar)); while (in_index <= insize) { blocklen = 0; for (i = 0; i < 3; i++) { in[i] = instream[in_index++]; if (in_index <= insize) { blocklen++; } else { in[i] = 0; } } if (blocklen) { _encode_base64_block(in, out, blocklen); for( i = 0; i < 4; i++ ) { encoded[out_index++] = out[i]; } } } return encoded; } /* * Decode a base64 encoded stream discarding padding, line breaks and noise * * This code was graciously ripped from http://base64.sourceforge.net * * @param invalue The string to decode. * @param outsize Holder for the length of the returned data. * @return The decoded data. */ unsigned char *_decode_base64( const xmlChar *invalue, int *outsize ) { xmlChar in[4]; unsigned char out[3], v; int i, in_index = 0, out_index = 0, blocklen; unsigned char *outstream; if (invalue == NULL) { return NULL; } outstream = calloc(((xmlStrlen(invalue) / 4) * 3) + 1, sizeof(unsigned char)); while (invalue[in_index] != '\0') { for (blocklen = 0, i = 0; i < 4 && invalue[in_index]; i++) { v = 0; while (invalue[in_index] != '\0' && v == 0) { v = (unsigned char) invalue[in_index++]; v = (unsigned char) ((v < 43 || v > 122) ? 0 : cd64[ v - 43 ]); if (v) { v = (unsigned char) ((v == '$') ? 0 : v - 61); } } if (v) { blocklen++; in[i] = (unsigned char) (v - 1); } else { in[i] = 0; } } if (blocklen) { _decode_base64_block( in, out ); for( i = 0; i < blocklen - 1; i++ ) { outstream[out_index++] = out[i]; } } } if (outsize != NULL) { *outsize = out_index; } return outstream; } #endif /* ENUNCIATE_C_UTILITIES */ #ifndef ENUNCIATE_OBJC_CLASSES #define ENUNCIATE_OBJC_CLASSES /** * Implementation of the JAXB type, element, events for a base object. */ @implementation NSObject (JAXB) /** * Read the XML type from the reader; an instance of NSXMLElement. * * @param reader The reader. * @return An instance of NSXMLElement */ + (id) readXMLType: (xmlTextReaderPtr) reader { return [JAXBBasicXMLNode readXMLType: reader]; } /** * Read an XML type from an XML reader into an existing instance. * * @param reader The reader. * @param existing The existing instance into which to read values. */ - (id) initWithReader: (xmlTextReaderPtr) reader { int status, depth; if ((self = [self init])) { if (xmlTextReaderHasAttributes(reader)) { while (xmlTextReaderMoveToNextAttribute(reader)) { if ([self readJAXBAttribute: reader] == NO) { [self readUnknownJAXBAttribute: reader]; } } status = xmlTextReaderMoveToElement(reader); if (!status) { //panic: unable to return to the element node. [NSException raise: @"XMLReadError" format: @"Error moving back to element position from attributes."]; } } if ([self readJAXBValue: reader] == NO) { //no value handled; attempt to process child elements if (xmlTextReaderIsEmptyElement(reader) == 0) { depth = xmlTextReaderDepth(reader);//track the depth. status = xmlTextReaderAdvanceToNextStartOrEndElement(reader); while (xmlTextReaderDepth(reader) > depth) { if (status < 1) { //panic: XML read error. [NSException raise: @"XMLReadError" format: @"Error handling a child element."]; } else if ([self readJAXBChildElement: reader]) { status = xmlTextReaderAdvanceToNextStartOrEndElement(reader); } else { status = [self readUnknownJAXBChildElement: reader]; } } } } } return self; } /** * Write the XML type value of this object to the writer. * * @param writer The writer. */ - (void) writeXMLType: (xmlTextWriterPtr) writer { [self writeJAXBAttributes: writer]; [self writeJAXBValue: writer]; [self writeJAXBChildElements: writer]; } /** * Read the XML element from the reader; an instance of NSXMLElement. * * @param reader The reader. * @return An instance of NSXMLElement */ + (id) readXMLElement: (xmlTextReaderPtr) reader { return (id) [JAXBBasicXMLNode readXMLType: reader]; } /** * No op; root objects don't have an element name/namespace. Subclasses must override. * * @param writer The writer. */ - (void) writeXMLElement: (xmlTextWriterPtr) writer { //no-op } /** * No op; root objects don't have an element name/namespace. Subclasses must override. * * @param writer The writer. * @param writeNs Ignored. */ - (void) writeXMLElement: (xmlTextWriterPtr) writer writeNamespaces: (BOOL) writeNs { //no-op } /** * No-op; base objects do not handle any attributes. * * @param reader The reader pointing to the attribute. * @return NO */ - (BOOL) readJAXBAttribute: (xmlTextReaderPtr) reader { return NO; } /** * No-op; base objects do not handle any values. * * @param reader The reader pointing to the element containing a value. * @return NO */ - (BOOL) readJAXBValue: (xmlTextReaderPtr) reader { return NO; } /** * No-op; base objects do not handle any child elements. * * @param reader The reader pointing to the child element. * @return NO */ - (BOOL) readJAXBChildElement: (xmlTextReaderPtr) reader { return NO; } /** * No-op; base objects do not handle any attributes. * * @param reader The reader pointing to the unknown attribute. */ - (void) readUnknownJAXBAttribute: (xmlTextReaderPtr) reader { } /** * Just skips the unknown element; base objects do not handle any child elements. * * @param reader The reader pointing to the unknown child element. * @return The status of the reader after skipping the unknown child element. */ - (int) readUnknownJAXBChildElement: (xmlTextReaderPtr) reader { return xmlTextReaderSkipElement(reader); } /** * No-op; base objects have no attributes. * * @param writer The writer. */ - (void) writeJAXBAttributes: (xmlTextWriterPtr) writer { //no-op. } /** * No-op; base objects have no element value. * * @param writer The writer. */ - (void) writeJAXBValue: (xmlTextWriterPtr) writer { //no-op. } /** * No-op; base objects have no child elements. * * @param writer The writer. */ - (void) writeJAXBChildElements: (xmlTextWriterPtr) writer { //no-op. } @end /*NSObject (JAXB)*/ /** * Implementation of the JAXB type, element for an xml element. */ @implementation JAXBBasicXMLNode /** * Accessor for the (local) name of the XML node. * * @return The (local) name of the XML node. */ - (NSString *) name { return _name; } /** * Accessor for the (local) name of the XML node. * * @param newName The (local) name of the XML node. */ - (void) setName: (NSString *) newName { [newName retain]; [_name release]; _name = newName; } /** * Accessor for the namespace of the XML node. * * @return The namespace of the XML node. */ - (NSString *) ns { return _ns; } /** * Accessor for the namespace of the XML node. * * @param newNs The namespace of the XML node. */ - (void) setNs: (NSString *) newNs { [newNs retain]; [_ns release]; _ns = newNs; } /** * Accessor for the namespace prefix of the XML node. * * @return The namespace prefix of the XML node. */ - (NSString *) prefix { return _prefix; } /** * Accessor for the namespace prefix of the XML node. * * @param newPrefix The namespace prefix of the XML node. */ - (void) setPrefix: (NSString *) newPrefix { [newPrefix retain]; [_prefix release]; _prefix = newPrefix; } /** * Accessor for the value of the XML node. * * @return The value of the XML node. */ - (NSString *) value { return _value; } /** * Accessor for the value of the XML node. * * @param newValue The value of the XML node. */ - (void) setValue: (NSString *) newValue { [newValue retain]; [_value release]; _value = newValue; } /** * Accessor for the child elements of the XML node. * * @return The child elements of the XML node. */ - (NSArray *) childElements { return _childElements; } /** * Accessor for the child elements of the XML node. * * @param newValue The child elements of the XML node. */ - (void) setChildElements: (NSArray *) newChildElements { [newChildElements retain]; [_childElements release]; _childElements = newChildElements; } /** * Accessor for the attributes of the XML node. * * @return The attributes of the XML node. */ - (NSArray *) attributes { return _attributes; } /** * Accessor for the attributes of the XML node. * * @param newAttributes The attributes of the XML node. */ - (void) setAttributes: (NSArray *) newAttributes { [newAttributes retain]; [_attributes release]; _attributes = newAttributes; } - (void) dealloc { [_name release]; [_ns release]; [_prefix release]; [_value release]; [_childElements release]; [_attributes release]; [super dealloc]; } @end /*implementation JAXBBasicXMLNode*/ /** * Internal, private interface for JAXB reading and writing. */ @interface JAXBBasicXMLNode (JAXB) @end /*interface JAXBBasicXMLNode (JAXB)*/ @implementation JAXBBasicXMLNode (JAXB) /** * Read the XML type from the reader; an instance of JAXBBasicXMLNode. * * @param reader The reader. * @return An instance of JAXBBasicXMLNode */ + (id) readXMLType: (xmlTextReaderPtr) reader { JAXBBasicXMLNode *node = [[JAXBBasicXMLNode alloc] init]; NS_DURING { [node initWithReader: reader]; } NS_HANDLER { node = nil; [localException raise]; } NS_ENDHANDLER [node autorelease]; return node; } /** * Read an XML type from an XML reader into an existing instance of JAXBBasicXMLNode. * * @param reader The reader. * @param existing The existing instance into which to read values. */ - (id) initWithReader: (xmlTextReaderPtr) reader { int status, depth; JAXBBasicXMLNode *child; xmlChar *value = NULL; const xmlChar *text; NSMutableArray *children; if ((self = [self init])) { depth = xmlTextReaderDepth(reader); [self setName: [NSString stringWithUTF8String: (const char *) xmlTextReaderLocalName(reader)]]; [self setNs: [NSString stringWithUTF8String: (const char *) xmlTextReaderNamespaceUri(reader)]]; [self setPrefix: [NSString stringWithUTF8String: (const char *)xmlTextReaderPrefix(reader)]]; if (xmlTextReaderHasAttributes(reader)) { child = nil; children = [[NSMutableArray alloc] init]; while (xmlTextReaderMoveToNextAttribute(reader)) { child = [[JAXBBasicXMLNode alloc] init]; [child setName: [NSString stringWithUTF8String: (const char *) xmlTextReaderLocalName(reader)]]; [child setNs: [NSString stringWithUTF8String: (const char *)xmlTextReaderNamespaceUri(reader)]]; [child setPrefix: [NSString stringWithUTF8String: (const char *) xmlTextReaderPrefix(reader)]]; [child setValue: [NSString stringWithUTF8String: (const char *) xmlTextReaderValue(reader)]]; [children addObject: child]; [child release]; } [self setAttributes: children]; [children release]; status = xmlTextReaderMoveToElement(reader); if (status < 1) { //panic: unable to return to the element node. [NSException raise: @"XMLReadError" format: @"Error moving to element from attributes."]; } } if (xmlTextReaderIsEmptyElement(reader) == 0) { children = [[NSMutableArray alloc] init]; status = xmlTextReaderRead(reader); while (status == 1 && xmlTextReaderDepth(reader) > depth) { switch (xmlTextReaderNodeType(reader)) { case XML_READER_TYPE_ELEMENT: child = (JAXBBasicXMLNode *) [JAXBBasicXMLNode readXMLType: reader]; [children addObject: child]; break; case XML_READER_TYPE_TEXT: case XML_READER_TYPE_CDATA: text = xmlTextReaderConstValue(reader); value = xmlStrncat(value, text, xmlStrlen(text)); break; default: //skip anything else. break; } status = xmlTextReaderRead(reader); } if (status < 1) { //panic: xml read error [NSException raise: @"XMLReadError" format: @"Error reading child elements."]; } if ([children count] > 0) { [self setChildElements: children]; } if (value != NULL) { [self setValue: [NSString stringWithUTF8String: (const char *) value]]; } [children release]; } } return self; } /** * Read the XML element from the reader; an instance of NSXMLElement. * * @param reader The reader. * @return An instance of NSXMLElement */ + (id) readXMLElement: (xmlTextReaderPtr) reader { return (id) [JAXBBasicXMLNode readXMLType: reader]; } /** * Write the basic node to an xml writer. * * @param writer The writer. */ - (void) writeXMLType: (xmlTextWriterPtr) writer { int status; NSEnumerator *enumerator; JAXBBasicXMLNode *child; xmlChar *childns, *childname, *childprefix, *childvalue; status = xmlTextWriterStartElementNS(writer, _prefix ? BAD_CAST [_prefix UTF8String] : NULL, _name ? BAD_CAST [_name UTF8String] : NULL, _ns ? BAD_CAST [_ns UTF8String] : NULL); if (status < 0) { childns = BAD_CAST ""; if (_ns) { childns = BAD_CAST [_ns UTF8String]; } childname = BAD_CAST ""; if (_name) { childname = BAD_CAST [_name UTF8String]; } [NSException raise: @"XMLWriteError" format: @"Error writing start element {%s}%s for JAXBBasicXMLNode.", childns, childname]; } if (_attributes) { enumerator = [_attributes objectEnumerator]; while ( (child = (JAXBBasicXMLNode *)[enumerator nextObject]) ) { childns = NULL; if ([child ns]) { childns = BAD_CAST [[child ns] UTF8String]; } childprefix = NULL; if ([child prefix]) { childprefix = BAD_CAST [[child prefix] UTF8String]; } childname = NULL; if ([child name]) { childname = BAD_CAST [[child name] UTF8String]; } childvalue = NULL; if ([child value]) { childvalue = BAD_CAST [[child value] UTF8String]; } status = xmlTextWriterWriteAttributeNS(writer, childprefix, childname, childns, childvalue); if (status < 0) { [NSException raise: @"XMLWriteError" format: @"Error writing attribute {%s}%s for JAXBBasicXMLNode.", childns, childname]; } } } if (_value) { status = xmlTextWriterWriteString(writer, BAD_CAST [_value UTF8String]); if (status < 0) { [NSException raise: @"XMLWriteError" format: @"Error writing value of JAXBBasicXMLNode."]; } } if (_childElements) { enumerator = [_childElements objectEnumerator]; while ( (child = [enumerator nextObject]) ) { [child writeXMLType: writer]; } } status = xmlTextWriterEndElement(writer); if (status < 0) { childns = BAD_CAST ""; if (_ns) { childns = BAD_CAST [_ns UTF8String]; } childname = BAD_CAST ""; if (_name) { childname = BAD_CAST [_name UTF8String]; } [NSException raise: @"XMLWriteError" format: @"Error writing end element {%s}%s for JAXBBasicXMLNode.", childns, childname]; } } /** * Writes this node to a writer. * * @param writer The writer. */ - (void) writeXMLElement: (xmlTextWriterPtr) writer { [self writeXMLType: writer]; } /** * Writes this node to a writer. * * @param writer The writer. * @param writeNs Whether to write the namespaces for this element to the xml writer. */ - (void) writeXMLElement: (xmlTextWriterPtr) writer writeNamespaces: (BOOL) writeNs { [self writeXMLType: writer]; } @end /* implementation JAXBBasicXMLNode (JAXB) */ /** * Implementation of the QName */ @implementation QName /** * Accessor for the local part of the QName. * * @return The local part of the QName. */ - (NSString *) localPart { return _localPart; } /** * Accessor for the local part of the QName. * * @param newLocalPart The local part of the QName. */ - (void) setLocalPart: (NSString *) newLocalPart { [newLocalPart retain]; [_localPart release]; _localPart = newLocalPart; } /** * Accessor for the namespace URI of the QName. * * @return The namespace URI of the QName. */ - (NSString *) namespaceURI { return _namespaceURI; } /** * Accessor for the namespace URI of the QName. * * @param newNamespaceURI The namespace URI of the QName. */ - (void) setNamespaceURI: (NSString *) newNamespaceURI { [newNamespaceURI retain]; [_namespaceURI release]; _namespaceURI = newNamespaceURI; } /** * Accessor for the namespace prefix of the QName. * * @return The namespace prefix of the QName. */ - (NSString *) prefix { return _prefix; } /** * Accessor for the namespace prefix of the QName. * * @param newPrefix The namespace prefix of the QName. */ - (void) setPrefix: (NSString *) newPrefix { [newPrefix retain]; [_prefix release]; _prefix = newPrefix; } - (void) dealloc { [super dealloc]; } @end /*implementation QName*/ /** * Declaration of the JAXB type for a QName. */ @interface QName (JAXBType) @end /** * Implementation of the JAXB type for a QName. */ @implementation QName (JAXBType) /** * Read the XML type from the reader. * * @param reader The reader. * @return The QName that was read from the reader. */ + (id) readXMLType: (xmlTextReaderPtr) reader { QName *qname = [[QName alloc] init]; NS_DURING { [qname initWithReader: reader]; } NS_HANDLER { qname = nil; [localException raise]; } NS_ENDHANDLER [qname autorelease]; return qname; } /** * Read an XML type from an XML reader into an existing instance. * * @param reader The reader. * @param existing The existing instance into which to read values. */ - (id) initWithReader: (xmlTextReaderPtr) reader { xmlChar *value = xmlTextReaderReadEntireNodeValue(reader); int len = 0; xmlChar *prefix; if ((self = [self init])) { #if DEBUG_ENUNCIATE > 1 NSLog(@"Reading QName value %s...\n", value); #endif if (value[len] == 0) { [NSException raise: @"XMLReadError" format: @"Empty QName value"]; } else if (value[0] == ':') { #if DEBUG_ENUNCIATE > 1 NSLog(@"QName value that starts with ':'. Weird.\n"); #endif /* nasty but valid */ [self setLocalPart: [NSString stringWithUTF8String: (const char *) xmlStrsub(value, 1, xmlStrlen(value) - 1)]]; [self setNamespaceURI: @""]; } else { /* * look for the ':' */ while ((value[len] != 0) && (value[len] != ':')) { len++; } #if DEBUG_ENUNCIATE > 1 NSLog(@"QName ':' character found at %i.\n", len); #endif if (value[len] == 0) { [self setLocalPart: [NSString stringWithUTF8String: (const char *) xmlStrdup(value)]]; [self setNamespaceURI: @""]; } else { prefix = xmlStrsub(value, 0, len); [self setLocalPart: [NSString stringWithUTF8String: (const char *) xmlStrsub(value, len + 1, xmlStrlen(value) - len - 1)]]; [self setNamespaceURI: [NSString stringWithUTF8String: (const char *) xmlTextReaderLookupNamespace(reader, prefix)]]; free(prefix); } } } free(value); return self; } /** * Write the NSString to the writer. * * @param writer The writer. */ - (void) writeXMLType: (xmlTextWriterPtr) writer { if ([[self localPart] length] == 0) { [NSException raise: @"XMLWriteError" format: @"Attempt to write a QName with an empty local part."]; } if (([[self namespaceURI] length] == 0) || ([[self prefix] length] == 0)) { xmlTextWriterWriteString(writer, BAD_CAST [[self localPart] UTF8String]); } else { xmlTextWriterWriteFormatString(writer, "%s:%s", BAD_CAST [[self prefix] UTF8String], BAD_CAST [[self localPart] UTF8String]); } } @end /*QName (JAXBType)*/ /** * Declaration of the JAXB type for a string. */ @interface NSString (JAXBType) @end /** * Implementation of the JAXB type for a string. */ @implementation NSString (JAXBType) /** * Read the XML type from the reader. * * @param reader The reader. * @return The NSString that was read from the reader. */ + (id) readXMLType: (xmlTextReaderPtr) reader { return [NSString stringWithUTF8String: (const char *) xmlTextReaderReadEntireNodeValue(reader)]; } /** * Read an XML type from an XML reader into an existing instance. * * @param reader The reader. * @param existing The existing instance into which to read values. */ - (id) initWithReader: (xmlTextReaderPtr) reader { [NSException raise: @"XMLReadError" format: @"An existing string cannot be modified."]; return nil; } /** * Write the NSString to the writer. * * @param writer The writer. */ - (void) writeXMLType: (xmlTextWriterPtr) writer { xmlTextWriterWriteString(writer, BAD_CAST [self UTF8String]); } @end /*NSString (JAXBType)*/ /** * Declaration of the JAXB type for a big number. */ @interface NSNumber (JAXBType) @end /** * Implementation of the JAXB type for a big number. */ @implementation NSNumber (JAXBType) /** * Read the XML type from the reader. * * @param reader The reader. * @return The NSNumber that was read from the reader. */ + (id) readXMLType: (xmlTextReaderPtr) reader { return [NSNumber numberWithLongLong: [[NSString stringWithUTF8String: (const char *) xmlTextReaderReadEntireNodeValue(reader)] longLongValue]]; } /** * Read an XML type from an XML reader into an existing instance. * * @param reader The reader. * @param existing The existing instance into which to read values. */ - (id) initWithReader: (xmlTextReaderPtr) reader { [NSException raise: @"XMLReadError" format: @"An existing number cannot be modified."]; return nil; } /** * Write the NSNumber to the writer. * * @param writer The writer. */ - (void) writeXMLType: (xmlTextWriterPtr) writer { xmlTextWriterWriteString(writer, BAD_CAST [[self description] UTF8String]); } @end /*NSNumber (JAXBType)*/ /** * Declaration of the JAXB type for a big number. */ @interface NSDecimalNumber (JAXBType) @end /** * Implementation of the JAXB type for a big number. */ @implementation NSDecimalNumber (JAXBType) /** * Read the XML type from the reader. * * @param reader The reader. * @return The NSDecimalNumber that was read from the reader. */ + (id) readXMLType: (xmlTextReaderPtr) reader { return [NSDecimalNumber decimalNumberWithString: [NSString stringWithUTF8String: (const char *) xmlTextReaderReadEntireNodeValue(reader)]]; } /** * Read an XML type from an XML reader into an existing instance. * * @param reader The reader. * @param existing The existing instance into which to read values. */ - (id) initWithReader: (xmlTextReaderPtr) reader { [NSException raise: @"XMLReadError" format: @"An existing decimal number cannot be modified."]; return nil; } /** * Write the NSDecimalNumber to the writer. * * @param writer The writer. */ - (void) writeXMLType: (xmlTextWriterPtr) writer { xmlTextWriterWriteString(writer, BAD_CAST [[self description] UTF8String]); } @end /*NSDecimalNumber (JAXBType)*/ /** * Declaration of the JAXB type for a url. */ @interface NSURL (JAXBType) @end /** * Implementation of the JAXB type for a url. */ @implementation NSURL (JAXBType) /** * Read the XML type from the reader. * * @param reader The reader. * @return The NSURL that was read from the reader. */ + (id) readXMLType: (xmlTextReaderPtr) reader { return [NSURL URLWithString: [NSString stringWithUTF8String: (const char *) xmlTextReaderReadEntireNodeValue(reader)]]; } /** * Read an XML type from an XML reader into an existing instance. * * @param reader The reader. * @param existing The existing instance into which to read values. */ - (id) initWithReader: (xmlTextReaderPtr) reader { [NSException raise: @"XMLReadError" format: @"An existing url cannot be modified."]; return nil; } /** * Write the NSURL to the writer. * * @param writer The writer. */ - (void) writeXMLType: (xmlTextWriterPtr) writer { xmlTextWriterWriteString(writer, BAD_CAST [[self absoluteString] UTF8String]); } @end /*NSURL (JAXBType)*/ /** * Declaration of the JAXB type for binary data. */ @interface NSData (JAXBType) @end /** * Implementation of the JAXB type for a binary data. */ @implementation NSData (JAXBType) /** * Read the XML type from the reader. * * @param reader The reader. * @return The NSData that was read from the reader. */ + (id) readXMLType: (xmlTextReaderPtr) reader { xmlChar *base64data = xmlTextReaderReadEntireNodeValue(reader); int len; unsigned char *data = _decode_base64(base64data, &len); NSData *wrappedData = [NSData dataWithBytesNoCopy: data length: len]; free(base64data); return wrappedData; } /** * Read an XML type from an XML reader into an existing instance. * * @param reader The reader. * @param existing The existing instance into which to read values. */ - (id) initWithReader: (xmlTextReaderPtr) reader { [NSException raise: @"XMLReadError" format: @"An existing NSData cannot be modified."]; return nil; } /** * Write the NSData to the writer. * * @param writer The writer. */ - (void) writeXMLType: (xmlTextWriterPtr) writer { xmlChar *out = _encode_base64((unsigned char *)[self bytes], [self length]); xmlTextWriterWriteString(writer, out); free(out); } @end /*NSData (JAXBType)*/ /** * Declaration of the JAXB type for a big number. */ @interface NSDate (JAXBType) @end /** * Implementation of the JAXB type for a big number. */ @implementation NSDate (JAXBType) /** * Read the XML type from the reader. * * @param reader The reader. * @return The NSDate that was read from the reader. */ + (id) readXMLType: (xmlTextReaderPtr) reader { xmlChar *timevalue = xmlTextReaderReadEntireNodeValue(reader); NSInteger year = 0; NSUInteger month = 1, day = 1, hour = 0, minute = 0, second = 0; BOOL skip_time = NO; int index = 0, token_index = 0, len = xmlStrlen(timevalue), offset_hour = 0, offset_minute = 0; char token[len]; if (len > (index + 5) && timevalue[index + 4] == '-') { //assume we're at yyyy-MM-dd token_index = 0; while (index < len && timevalue[index] != '-') { token[token_index++] = timevalue[index++]; } token[token_index] = '\0'; if (token_index != 4) { [NSException raise: @"XMLReadError" format: @"Unable to read dateTime %s; invalid year: %s", timevalue, token]; } year = atoi(token); index++; //go to next '-' character. token_index = 0; while (index < len && timevalue[index] != '-') { token[token_index++] = timevalue[index++]; } token[token_index] = '\0'; if (token_index != 2) { [NSException raise: @"XMLReadError" format: @"Unable to read dateTime %s; invalid month: %s", timevalue, token]; } month = atoi(token); index++; //go to 'T', 'Z', '+', or '-' character. token_index = 0; while (index < len && timevalue[index] != 'T' && timevalue[index] != 'Z' && timevalue[index] != '-' && timevalue[index] != '+') { token[token_index++] = timevalue[index++]; } token[token_index] = '\0'; if (token_index != 2) { [NSException raise: @"XMLReadError" format: @"Unable to read dateTime %s; invalid day of month: %s", timevalue, token]; } day = atoi(token); if (timevalue[index] != 'T') { skip_time = YES; } if (timevalue[index] != '-') { index++; } } if (skip_time == NO || (len > (index + 3) && timevalue[index + 2] == ':')) { //assume we're at HH:mm:ss //go to ':' character. token_index = 0; while (index < len && timevalue[index] != ':') { token[token_index++] = timevalue[index++]; } token[token_index] = '\0'; if (token_index != 2) { [NSException raise: @"XMLReadError" format: @"Unable to read dateTime %s; invalid hour: %s", timevalue, token]; } hour = atoi(token); index++; //go to ':' character. token_index = 0; while (index < len && timevalue[index] != ':') { token[token_index++] = timevalue[index++]; } token[token_index] = '\0'; if (token_index != 2) { [NSException raise: @"XMLReadError" format: @"Unable to read dateTime %s; invalid minute: %s", timevalue, token]; } minute = atoi(token); index++; //go to '+' or '-' or 'Z' character. token_index = 0; while (index < len && timevalue[index] != '+' && timevalue[index] != '-' && timevalue[index] != 'Z') { token[token_index++] = timevalue[index++]; } token[token_index] = '\0'; if (token_index == 0) { [NSException raise: @"XMLReadError" format: @"Unable to read dateTime %s; invalid seconds: %s", timevalue, token]; } second = (NSUInteger) atof(token); if (timevalue[index] != '-') { index++; } } //go to ':' character. token_index = 0; while (index < len && timevalue[index] != ':') { token[token_index++] = timevalue[index++]; } token[token_index] = '\0'; offset_hour += atoi(token); index++; //go to end. token_index = 0; while (index < len) { token[token_index++] = timevalue[index++]; } token[token_index] = '\0'; offset_minute += atoi(token); //YYYY-MM-DD HH:MM:SS -HHHMM free(timevalue); NSString *dateString = [NSString stringWithFormat: @"%04i-%02i-%02i %02i:%02i:%02i %+03i%02i", (int) year, (int) month, (int) day, (int) hour, (int) minute, (int) second, (int) offset_hour, (int) offset_minute]; #ifdef GNUSTEP /* GNUstep code goes here ... */ return [NSDate dateWithString: dateString]; #else /* Cocoa/Cocoa Touch native code goes here ... */ // Create date formatter static NSDateFormatter *dateFormatter = nil; if (!dateFormatter) { [NSDateFormatter setDefaultFormatterBehavior:NSDateFormatterBehavior10_4]; NSLocale *enUSPOSIXLocale = [[[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"] autorelease]; dateFormatter = [[NSDateFormatter alloc] init]; [dateFormatter setLocale:enUSPOSIXLocale]; [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss ZZ"]; [dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]]; [enUSPOSIXLocale release]; } return [dateFormatter dateFromString: dateString]; #endif } /** * Read an XML type from an XML reader into an existing instance. * * @param reader The reader. * @param existing The existing instance into which to read values. */ - (id) initWithReader: (xmlTextReaderPtr) reader { [NSException raise: @"XMLReadError" format: @"An existing date cannot be modified."]; return nil; } /** * Write the NSDate to the writer. * * @param writer The writer. */ - (void) writeXMLType: (xmlTextWriterPtr) writer { #ifdef GNUSTEP /* GNUstep code goes here ... */ NSDateFormatter *formatter = [[NSDateFormatter alloc] initWithDateFormat: @"%Y-%m-%dT%H:%M:%S %z" allowNaturalLanguage: NO]; #else /* Cocoa/Cocoa Touch native code goes here ... */ NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; [formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss ZZ"]; #endif xmlChar *timevalue = BAD_CAST [[formatter stringForObjectValue: self] UTF8String]; timevalue[19] = timevalue[20]; timevalue[20] = timevalue[21]; timevalue[21] = timevalue[22]; timevalue[22] = ':'; xmlTextWriterWriteString(writer, timevalue); [formatter release]; } @end /*NSDate (JAXBType)*/ #endif /* ENUNCIATE_OBJC_CLASSES */ #ifndef ENUNCIATE_XML_OBJC_PRIMITIVE_FUNCTIONS #define ENUNCIATE_XML_OBJC_PRIMITIVE_FUNCTIONS /*******************boolean************************************/ /** * Read a boolean value from the reader. * * @param reader The reader (pointing at a node with a value). * @return YES if "true" was read. NO otherwise. */ BOOL *xmlTextReaderReadBooleanType(xmlTextReaderPtr reader) { xmlChar *nodeValue = xmlTextReaderReadEntireNodeValue(reader); BOOL *value = malloc(sizeof(BOOL)); *value = (xmlStrcmp(BAD_CAST "true", nodeValue) == 0) ? YES : NO; free(nodeValue); return value; } /** * Write a boolean value to the writer. * * @param writer The writer. * @param value The value to be written. * @return the bytes written (may be 0 because of buffering) or -1 in case of error. */ int xmlTextWriterWriteBooleanType(xmlTextWriterPtr writer, BOOL *value) { if (*value) { return xmlTextWriterWriteString(writer, BAD_CAST "true"); } else { return xmlTextWriterWriteString(writer, BAD_CAST "false"); } } /*******************byte************************************/ /** * Read a byte value from the reader. * * @param reader The reader (pointing at a node with a value). * @return the byte. */ unsigned char *xmlTextReaderReadByteType(xmlTextReaderPtr reader) { xmlChar *nodeValue = xmlTextReaderReadEntireNodeValue(reader); unsigned char *value = malloc(sizeof(unsigned char)); *value = (unsigned char) atoi((char *) nodeValue); free(nodeValue); return value; } /** * Write a byte value to the writer. * * @param writer The writer. * @param value The value to be written. * @return the bytes written (may be 0 because of buffering) or -1 in case of error. */ int xmlTextWriterWriteByteType(xmlTextWriterPtr writer, unsigned char *value) { return xmlTextWriterWriteFormatString(writer, "%i", *value); } /*******************double************************************/ /** * Read a double value from the reader. * * @param reader The reader (pointing at a node with a value). * @return the double. */ double *xmlTextReaderReadDoubleType(xmlTextReaderPtr reader) { xmlChar *nodeValue = xmlTextReaderReadEntireNodeValue(reader); double *value = malloc(sizeof(double)); *value = atof((char *) nodeValue); free(nodeValue); return value; } /** * Write a double value to the writer. * * @param writer The writer. * @param value The value to be written. * @return the bytes written (may be 0 because of buffering) or -1 in case of error. */ int xmlTextWriterWriteDoubleType(xmlTextWriterPtr writer, double *value) { return xmlTextWriterWriteFormatString(writer, "%f", *value); } /*******************float************************************/ /** * Read a float value from the reader. * * @param reader The reader (pointing at a node with a value). * @return the float. */ float *xmlTextReaderReadFloatType(xmlTextReaderPtr reader) { xmlChar *nodeValue = xmlTextReaderReadEntireNodeValue(reader); float *value = malloc(sizeof(float)); *value = atof((char *)nodeValue); free(nodeValue); return value; } /** * Write a float value to the writer. * * @param writer The writer. * @param value The value to be written. * @return the bytes written (may be 0 because of buffering) or -1 in case of error. */ int xmlTextWriterWriteFloatType(xmlTextWriterPtr writer, float *value) { return xmlTextWriterWriteFormatString(writer, "%f", *value); } /*******************int************************************/ /** * Read a int value from the reader. * * @param reader The reader (pointing at a node with a value). * @param value The value to be written. * @return the int. */ int *xmlTextReaderReadIntType(xmlTextReaderPtr reader) { xmlChar *nodeValue = xmlTextReaderReadEntireNodeValue(reader); int *value = malloc(sizeof(int)); *value = atoi((char *)nodeValue); free(nodeValue); return value; } /** * Write a int value to the writer. * * @param writer The writer. * @param value The value to be written. * @return the bytes written (may be 0 because of buffering) or -1 in case of error. */ int xmlTextWriterWriteIntType(xmlTextWriterPtr writer, int *value) { return xmlTextWriterWriteFormatString(writer, "%i", *value); } /*******************long************************************/ /** * Read a long value from the reader. * * @param reader The reader (pointing at a node with a value). * @return the long. */ long long *xmlTextReaderReadLongType(xmlTextReaderPtr reader) { xmlChar *nodeValue = xmlTextReaderReadEntireNodeValue(reader); long long *value = malloc(sizeof(long long)); *value = atoll((char *)nodeValue); free(nodeValue); return value; } /** * Write a long value to the writer. * * @param writer The writer. * @param value The value to be written. * @return the bytes written (may be 0 because of buffering) or -1 in case of error. */ int xmlTextWriterWriteLongType(xmlTextWriterPtr writer, long long *value) { return xmlTextWriterWriteFormatString(writer, "%lld", *value); } /*******************short************************************/ /** * Read a short value from the reader. * * @param reader The reader (pointing at a node with a value). * @return the short. */ short *xmlTextReaderReadShortType(xmlTextReaderPtr reader) { xmlChar *nodeValue = xmlTextReaderReadEntireNodeValue(reader); short *value = malloc(sizeof(short)); *value = atoi((char *)nodeValue); free(nodeValue); return value; } /** * Write a short value to the writer. * * @param writer The writer. * @param value The value to be written. * @return the bytes written (may be 0 because of buffering) or -1 in case of error. */ int xmlTextWriterWriteShortType(xmlTextWriterPtr writer, short *value) { return xmlTextWriterWriteFormatString(writer, "%hi", *value); } /*******************unsigned short***************************/ /** * Read an unsigned short value from the reader. * * @param reader The reader (pointing at a node with a value). * @return the unsigned short. */ unsigned short *xmlTextReaderReadUnsignedShortType(xmlTextReaderPtr reader) { xmlChar *nodeValue = xmlTextReaderReadEntireNodeValue(reader); unsigned short *value = malloc(sizeof(unsigned short)); *value = atoi((char *)nodeValue); free(nodeValue); return value; } /** * Write an unsigned short value to the writer. * * @param writer The writer. * @param value The value to be written. * @return the bytes written (may be 0 because of buffering) or -1 in case of error. */ int xmlTextWriterWriteUnsignedShortType(xmlTextWriterPtr writer, unsigned short *value) { return xmlTextWriterWriteFormatString(writer, "%hi", *value); } /*******************char************************************/ /** * Read a character value from the reader. * * @param reader The reader (pointing at a node with a value). * @return the character. */ xmlChar *xmlTextReaderReadCharacterType(xmlTextReaderPtr reader) { return xmlTextReaderReadEntireNodeValue(reader); } /** * Write a character value to the writer. * * @param writer The writer. * @param value The value to be written. * @return the bytes written (may be 0 because of buffering) or -1 in case of error. */ int xmlTextWriterWriteCharacterType(xmlTextWriterPtr writer, xmlChar *value) { return xmlTextWriterWriteString(writer, value); } #endif /* ENUNCIATE_XML_OBJC_PRIMITIVE_FUNCTIONS */