Skip to content
This repository
branch: master
Fetching contributors…

Cannot retrieve contributors at this time

file 110 lines (96 sloc) 3.512 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
//
// YKEmitter.m
// YAMLKit
//
// Created by Patrick Thomson on 12/29/08.
//

#import "YKEmitter.h"

@interface YKEmitter (YKEmitterPrivateMEthods)

- (int)_writeItem:(id)item toDocument:(yaml_document_t *)document;

@end

@implementation YKEmitter

@synthesize usesExplicitDelimiters, encoding;

- (id)init
{
    if((self = [super init])) {
        memset(&emitter, 0, sizeof(emitter));
        yaml_emitter_initialize(&emitter);
        
        buffer = [NSMutableData data];
        // Coincidentally, the order of arguments to CFDataAppendBytes are just right
        // such that if I pass the buffer as the data parameter, I can just use
        // a pointer to CFDataAppendBytes to tell the emitter to write to the NSMutableData.
        yaml_emitter_set_output(&emitter, (yaml_write_handler_t*)CFDataAppendBytes, buffer);
        [self setUsesExplicitDelimiters:NO];
    }
return self;
}

- (void)emitItem:(id)item
{
    // Create and initialize a document to hold this.
    yaml_document_t document;
    memset(&document, 0, sizeof(document));
    // The double usage of !usesExplicitDelimiters corresponds to explicitly
// delimiting the start and end of various documents.
    yaml_document_initialize(&document, NULL, NULL, NULL, !usesExplicitDelimiters, !usesExplicitDelimiters);
    // TODO: Make this into a proper private method.
    [self _writeItem:item toDocument:&document];
    yaml_emitter_dump(&emitter, &document);
    yaml_document_delete(&document);
}

- (int)_writeItem:(id)item toDocument:(yaml_document_t *)doc
{
int nodeID = 0;
// #keyEnumerator covers NSMapTable/NSHashTable/NSDictionary
if([item respondsToSelector:@selector(keyEnumerator)]) {
// Add a mapping node.
nodeID = yaml_document_add_mapping(doc, (yaml_char_t *)YAML_DEFAULT_MAPPING_TAG, YAML_ANY_MAPPING_STYLE);
for(id key in item) {
int keyID = [self _writeItem:key toDocument:doc];
int valueID = [self _writeItem:[item objectForKey:key] toDocument:doc];
yaml_document_append_mapping_pair(doc, nodeID, keyID, valueID);
}
// #objectEnumerator covers NSSet/NSArray.
} else if([item respondsToSelector:@selector(objectEnumerator)]) {
// emit beginning sequence
nodeID = yaml_document_add_sequence(doc, (yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG, YAML_ANY_SEQUENCE_STYLE);
for(id subitem in item) {
int newItem = [self _writeItem:subitem toDocument:doc];
yaml_document_append_sequence_item(doc, nodeID, newItem);
}
// Everything else is a scalar.
} else {
// TODO: Add optional support for tagging emitted items.
// TODO: Wrap long lines.
nodeID = yaml_document_add_scalar(doc, (yaml_char_t *)YAML_DEFAULT_SCALAR_TAG, (yaml_char_t*)[[item description] UTF8String], [[item description] length], YAML_ANY_SCALAR_STYLE);
}
return nodeID;
}

- (NSString *)emittedString
{
    return [[[NSString alloc] initWithData:buffer encoding:NSUTF8StringEncoding] autorelease];
}

- (NSData *)emittedData
{
return [NSData dataWithData:buffer];
}

- (void)setEncoding:(NSStringEncoding)newEnc
{
encoding = newEnc;
yaml_encoding_t converted = YAML_ANY_ENCODING;
switch(encoding) {
case NSUTF8StringEncoding:
converted = YAML_UTF8_ENCODING;
break;
case NSUTF16LittleEndianStringEncoding:
converted = YAML_UTF16LE_ENCODING;
break;
case NSUTF16BigEndianStringEncoding:
converted = YAML_UTF16BE_ENCODING;
break;
default:
NSLog(@"Unsupported encoding passed to YKEmitter#setEncoding:.");
break;
}
yaml_emitter_set_encoding(&emitter, converted);
}

@end
Something went wrong with that request. Please try again.