blob: d91a2ee1a026da7b132ed8d2204293e21d0e7523 [file] [log] [blame]
#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<JAXBType>) 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<JAXBElement>) readXMLElement: (xmlTextReaderPtr) reader
{
return (id<JAXBElement>) [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) <JAXBType, JAXBElement>
@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<JAXBType>) 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<JAXBElement>) readXMLElement: (xmlTextReaderPtr) reader
{
return (id<JAXBElement>) [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) <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<JAXBType>) 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) <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<JAXBType>) 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) <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<JAXBType>) 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) <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<JAXBType>) 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) <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<JAXBType>) 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) <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<JAXBType>) 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) <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<JAXBType>) 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 */