From fdc81fca90cb41977ba3f059f86563523698c5cd Mon Sep 17 00:00:00 2001 From: Tony Xiao Date: Sun, 7 Apr 2013 18:02:12 -0700 Subject: [PATCH 1/5] Primitive and incomplete support for parsing scalar as null, boolean, number and date --- YAMLSerialization.m | 374 ++++++++++++++++++++++++-------------------- 1 file changed, 205 insertions(+), 169 deletions(-) diff --git a/YAMLSerialization.m b/YAMLSerialization.m index 25927c6..a680db5 100644 --- a/YAMLSerialization.m +++ b/YAMLSerialization.m @@ -14,176 +14,214 @@ // Assumes NSError **error is in the current scope #define YAML_SET_ERROR(errorCode, description, recovery) \ - if (error) \ - *error = [NSError errorWithDomain: YAMLErrorDomain \ - code: errorCode \ - userInfo: [NSDictionary dictionaryWithObjectsAndKeys: \ - description, NSLocalizedDescriptionKey, \ - recovery, NSLocalizedRecoverySuggestionErrorKey, \ - nil]] + if (error) \ + *error = [NSError errorWithDomain: YAMLErrorDomain \ + code: errorCode \ + userInfo: [NSDictionary dictionaryWithObjectsAndKeys: \ + description, NSLocalizedDescriptionKey, \ + recovery, NSLocalizedRecoverySuggestionErrorKey, \ + nil]] @implementation YAMLSerialization +static NSNumber *ParseBoolean(NSString *str) { + for (NSString *s in @[@"y", @"yes", @"true", @"on"]) + if ([s isEqualToString:str.lowercaseString]) + return @YES; + for (NSString *s in @[@"n", @"no", @"false", @"off"]) + if ([s isEqualToString:str.lowercaseString]) + return @NO; + return nil; +} + +static NSNumber *ParseNumber(NSString *str) { + static dispatch_once_t numberFormatterOnceToken; + static NSNumberFormatter *numberFormatter = nil; + dispatch_once(&numberFormatterOnceToken, ^{ + numberFormatter = [[NSNumberFormatter alloc] init]; + }); + NSNumber *number = nil; + if ([numberFormatter getObjectValue:&number forString:str errorDescription:nil]) + return [number autorelease]; + return nil; +} + +static NSDate *ParseDate(NSString *str) { + static dispatch_once_t dateFormatterOnceToken; + static NSDateFormatter *dateFormatter = nil; + dispatch_once(&dateFormatterOnceToken, ^{ + dateFormatter = [[NSDateFormatter alloc] init]; + dateFormatter.dateFormat = @"yyyy-MM-dd"; + }); + NSDate *date; + if ([dateFormatter getObjectValue:&date forString:str errorDescription:nil]) + return [date autorelease]; + return nil; +} + +static NSNull *ParseNull(NSString *str) { + if (str.length == 0 || [str isEqualToString:@"~"] || [str.lowercaseString isEqualToString:@"null"]) + return [NSNull null]; + return nil; +} + #pragma mark Reading YAML static int __YAMLSerializationParserInputReadHandler (void *data, unsigned char *buffer, size_t size, size_t *size_read) { - NSInteger outcome = [(NSInputStream *) data read: (uint8_t *) buffer maxLength: size]; - if (outcome < 0) { - *size_read = 0; - return NO; - } else { - *size_read = outcome; - return YES; - } + NSInteger outcome = [(NSInputStream *)data read: (uint8_t *)buffer maxLength: size]; + if (outcome < 0) { + *size_read = 0; + return NO; + } else { + *size_read = outcome; + return YES; + } } // Serialize single, parsed document. Does not destroy the document. static id __YAMLSerializationObjectWithYAMLDocument (yaml_document_t *document, YAMLReadOptions opt, NSError **error) { - id root = nil; - id *objects = nil; - - // Mutability options - Class arrayClass = [NSMutableArray class]; // TODO: FIXME: - Class dictionaryClass = [NSMutableDictionary class]; // TODO: FIXME: - Class stringClass = [NSString class]; - if (opt & kYAMLReadOptionMutableContainers) { - arrayClass = [NSMutableArray class]; - dictionaryClass = [NSMutableDictionary class]; - if (opt & kYAMLReadOptionMutableContainersAndLeaves) { - stringClass = [NSMutableString class]; - } - } - - if (opt & kYAMLReadOptionStringScalars) { - // Supported - } else { - YAML_SET_ERROR(kYAMLErrorInvalidOptions, @"Currently only kYAMLReadOptionStringScalars is supported", @"Serialize with kYAMLReadOptionStringScalars option"); - return nil; + id root = nil; + id *objects = nil; + + // Mutability options + Class arrayClass = [NSMutableArray class]; // TODO: FIXME: + Class dictionaryClass = [NSMutableDictionary class]; // TODO: FIXME: + Class stringClass = [NSString class]; + if (opt & kYAMLReadOptionMutableContainers) { + arrayClass = [NSMutableArray class]; + dictionaryClass = [NSMutableDictionary class]; + if (opt & kYAMLReadOptionMutableContainersAndLeaves) { + stringClass = [NSMutableString class]; } - - yaml_node_t *node = NULL; - yaml_node_item_t *item = NULL; - yaml_node_pair_t *pair = NULL; - - int i = 0; - - objects = (id *) calloc(document->nodes.top - document->nodes.start, sizeof(id)); - if (objects == NULL) { - YAML_SET_ERROR(kYAMLErrorCodeOutOfMemory, @"Couldn't allocate memory", @"Please try to free memory and retry"); - return nil; - } - - // Create all objects, don't fill containers yet... - for (node = document->nodes.start, i = 0; node < document->nodes.top; node++, i++) { - switch (node->type) { - case YAML_SCALAR_NODE: - objects[i] = [[stringClass alloc] initWithUTF8String: (const char *)node->data.scalar.value]; - if (!root) root = objects[i]; - break; - - case YAML_SEQUENCE_NODE: - objects[i] = [[arrayClass alloc] initWithCapacity: node->data.sequence.items.top - node->data.sequence.items.start]; - if (!root) root = objects[i]; - break; - - case YAML_MAPPING_NODE: - objects[i] = [[dictionaryClass alloc] initWithCapacity: node->data.mapping.pairs.top - node->data.mapping.pairs.start]; - if (!root) root = objects[i]; - break; - - default: - break; + } + + yaml_node_t *node = NULL; + yaml_node_item_t *item = NULL; + yaml_node_pair_t *pair = NULL; + + int i = 0; + + objects = (id *) calloc(document->nodes.top - document->nodes.start, sizeof(id)); + if (objects == NULL) { + YAML_SET_ERROR(kYAMLErrorCodeOutOfMemory, @"Couldn't allocate memory", @"Please try to free memory and retry"); + return nil; + } + + // Create all objects, don't fill containers yet... + for (node = document->nodes.start, i = 0; node < document->nodes.top; node++, i++) { + switch (node->type) { + case YAML_SCALAR_NODE: { + id value = [[stringClass alloc] initWithUTF8String: (const char *)node->data.scalar.value]; + if (!(opt & kYAMLReadOptionStringScalars)) { + value = ParseNull(value) ?: ParseBoolean(value) ?: ParseNumber(value) ?: ParseDate(value) ?: value; } + objects[i] = value; + if (!root) root = objects[i]; + break; + } + case YAML_SEQUENCE_NODE: + objects[i] = [[arrayClass alloc] initWithCapacity: node->data.sequence.items.top - node->data.sequence.items.start]; + if (!root) root = objects[i]; + break; + + case YAML_MAPPING_NODE: + objects[i] = [[dictionaryClass alloc] initWithCapacity: node->data.mapping.pairs.top - node->data.mapping.pairs.start]; + if (!root) root = objects[i]; + break; + + default: + break; } - - // Fill in containers - for (node = document->nodes.start, i = 0; node < document->nodes.top; node++, i++) { - switch (node->type) { - case YAML_SEQUENCE_NODE: - for (item = node->data.sequence.items.start; item < node->data.sequence.items.top; item++) - [objects[i] addObject: objects[*item - 1]]; - break; - - case YAML_MAPPING_NODE: - for (pair = node->data.mapping.pairs.start; pair < node->data.mapping.pairs.top; pair++) - [objects[i] setObject: objects[pair->value - 1] - forKey: objects[pair->key - 1]]; - break; - - default: - break; - } - } - - // Retain the root object - if (root != nil) { - [root retain]; - } - - // Release all objects. The root object and all referenced (in containers) objects - // will have retain count > 0 - for (node = document->nodes.start, i = 0; node < document->nodes.top; node++, i++) { - [objects[i] release]; - } - - if (objects != NULL) { - free(objects); + } + + // Fill in containers + for (node = document->nodes.start, i = 0; node < document->nodes.top; node++, i++) { + switch (node->type) { + case YAML_SEQUENCE_NODE: + for (item = node->data.sequence.items.start; item < node->data.sequence.items.top; item++) + [objects[i] addObject: objects[*item - 1]]; + break; + + case YAML_MAPPING_NODE: + for (pair = node->data.mapping.pairs.start; pair < node->data.mapping.pairs.top; pair++) + [objects[i] setObject: objects[pair->value - 1] + forKey: objects[pair->key - 1]]; + break; + + default: + break; } - - return root; + } + + // Retain the root object + if (root != nil) { + [root retain]; + } + + // Release all objects. The root object and all referenced (in containers) objects + // will have retain count > 0 + for (node = document->nodes.start, i = 0; node < document->nodes.top; node++, i++) { + [objects[i] release]; + } + + if (objects != NULL) { + free(objects); + } + + return root; } + (NSMutableArray *) objectsWithYAMLStream: (NSInputStream *) stream - options: (YAMLReadOptions) opt - error: (NSError **) error + options: (YAMLReadOptions) opt + error: (NSError **) error { - NSMutableArray *documents = [NSMutableArray array]; - id documentObject = nil; - - yaml_parser_t parser; - yaml_document_t document; - BOOL done = NO; - - // Open input stream - [stream open]; - - memset(&parser, 0, sizeof(yaml_parser_t)); - if (!yaml_parser_initialize(&parser)) { - YAML_SET_ERROR(kYAMLErrorCodeParserInitializationFailed, @"Error in yaml_parser_initialize(&parser)", @"Internal error, please let us know about this error"); - return nil; + NSMutableArray *documents = [NSMutableArray array]; + id documentObject = nil; + + yaml_parser_t parser; + yaml_document_t document; + BOOL done = NO; + + // Open input stream + [stream open]; + + memset(&parser, 0, sizeof(yaml_parser_t)); + if (!yaml_parser_initialize(&parser)) { + YAML_SET_ERROR(kYAMLErrorCodeParserInitializationFailed, @"Error in yaml_parser_initialize(&parser)", @"Internal error, please let us know about this error"); + return nil; + } + + yaml_parser_set_input(&parser, __YAMLSerializationParserInputReadHandler, (void *)stream); + + while (!done) { + + if (!yaml_parser_load(&parser, &document)) { + YAML_SET_ERROR(kYAMLErrorCodeParseError, @"Parse error", @"Make sure YAML file is well formed"); + return nil; } - - yaml_parser_set_input(&parser, __YAMLSerializationParserInputReadHandler, (void *)stream); - - while (!done) { - - if (!yaml_parser_load(&parser, &document)) { - YAML_SET_ERROR(kYAMLErrorCodeParseError, @"Parse error", @"Make sure YAML file is well formed"); - return nil; - } - - done = !yaml_document_get_root_node(&document); - - if (!done) { - documentObject = __YAMLSerializationObjectWithYAMLDocument(&document, opt, error); - if (error && *error) { - yaml_document_delete(&document); - } else { - [documents addObject: documentObject]; - [documentObject release]; - } - } - - // TODO: Check if aliases to previous documents are allowed by the specs + + done = !yaml_document_get_root_node(&document); + + if (!done) { + documentObject = __YAMLSerializationObjectWithYAMLDocument(&document, opt, error); + if (error && *error) { yaml_document_delete(&document); + } else { + [documents addObject: documentObject]; + [documentObject release]; + } } - - yaml_parser_delete(&parser); - - return documents; + + // TODO: Check if aliases to previous documents are allowed by the specs + yaml_document_delete(&document); + } + + yaml_parser_delete(&parser); + + return documents; } + (id) objectWithYAMLStream: (NSInputStream *) stream options: (YAMLReadOptions) opt error: (NSError **) error { @@ -191,34 +229,34 @@ + (id) objectWithYAMLStream: (NSInputStream *) stream options: (YAMLReadOptions) } + (NSMutableArray *) objectsWithYAMLData: (NSData *) data - options: (YAMLReadOptions) opt - error: (NSError **) error; + options: (YAMLReadOptions) opt + error: (NSError **) error; { - NSMutableArray *result = nil; - if (data != nil) { - NSInputStream *stream = [[NSInputStream alloc] initWithData: data]; - result = [self objectsWithYAMLStream: stream options: opt error: error]; - [stream release]; - } - return result; + NSMutableArray *result = nil; + if (data != nil) { + NSInputStream *stream = [[NSInputStream alloc] initWithData: data]; + result = [self objectsWithYAMLStream: stream options: opt error: error]; + [stream release]; + } + return result; } + (id) objectWithYAMLData: (NSData *) data options: (YAMLReadOptions) opt error: (NSError **) error { - return [[self objectsWithYAMLData: data options: opt error: error] objectAtIndex: 0]; + return [[self objectsWithYAMLData: data options: opt error: error] objectAtIndex: 0]; } + (NSMutableArray *) objectsWithYAMLString: (NSString *) string options: (YAMLReadOptions) opt error: (NSError **) error; { - return [self objectsWithYAMLData: [string dataUsingEncoding: NSUTF8StringEncoding] - options: opt - error: error]; + return [self objectsWithYAMLData: [string dataUsingEncoding: NSUTF8StringEncoding] + options: opt + error: error]; } + (id) objectWithYAMLString: (NSString *) string options: (YAMLReadOptions) opt error: (NSError **) error { - return [[self objectsWithYAMLString: string options: opt error: error] objectAtIndex: 0]; -} + return [[self objectsWithYAMLString: string options: opt error: error] objectAtIndex: 0]; +} #pragma mark Writing YAML @@ -276,16 +314,16 @@ + (BOOL) __YAMLSerializationAddRootObjectAndEmit: (id) object emitter: (yaml_emi + (BOOL) writeObject: (id) object toYAMLStream: (NSOutputStream *) stream - options: (YAMLWriteOptions) opt - error: (NSError **) error + options: (YAMLWriteOptions) opt + error: (NSError **) error { BOOL result = YES; yaml_emitter_t emitter; memset(&emitter, 0, sizeof(yaml_emitter_t)); if (!yaml_emitter_initialize(&emitter)) { - YAML_SET_ERROR(kYAMLErrorCodeEmitterError, @"Error in yaml_emitter_initialize(&emitter)", @"Internal error, please let us know about this error"); - return NO; + YAML_SET_ERROR(kYAMLErrorCodeEmitterError, @"Error in yaml_emitter_initialize(&emitter)", @"Internal error, please let us know about this error"); + return NO; } yaml_emitter_set_encoding(&emitter, YAML_UTF8_ENCODING); @@ -298,13 +336,11 @@ + (BOOL) writeObject: (id) object // YAML is an array of documents. for (id child in object) { - // TODO: Check result code. [self __YAMLSerializationAddRootObjectAndEmit: child emitter: &emitter]; } } else { - // YAML is a single document. [self __YAMLSerializationAddRootObjectAndEmit: object emitter: &emitter]; } @@ -323,7 +359,7 @@ + (NSData *) createYAMLDataWithObject: (id) object options: (YAMLWriteOptions) o [stream release]; return result; } - + + (NSData *) YAMLDataWithObject: (id) object options: (YAMLWriteOptions) opt error: (NSError **) error { return [[self createYAMLDataWithObject: object options: opt error: error] autorelease]; } @@ -333,7 +369,7 @@ + (NSString *) createYAMLStringWithObject: (id) object options: (YAMLWriteOption encoding: NSUTF8StringEncoding]; } - + + (NSString *) YAMLStringWithObject: (id) object options: (YAMLWriteOptions) opt error: (NSError **) error { return [[self createYAMLStringWithObject: object options: opt error: error] autorelease]; } From 4538a9cabd0a7f45486284f81a2725fb2d0dec95 Mon Sep 17 00:00:00 2001 From: Vladimir Grichina Date: Thu, 13 Feb 2014 03:40:45 +0200 Subject: [PATCH 2/5] Indentation and other whitespace fixes after merge --- YAMLSerialization.h | 4 +- YAMLSerialization.m | 136 ++++++++++++++++++++++---------------------- test/test.m | 68 +++++++++++----------- 3 files changed, 104 insertions(+), 104 deletions(-) diff --git a/YAMLSerialization.h b/YAMLSerialization.h index 1612264..2783c84 100644 --- a/YAMLSerialization.h +++ b/YAMLSerialization.h @@ -1,10 +1,10 @@ // // YAMLSerialization.h // YAML Serialization support by Mirek Rusin based on C library LibYAML by Kirill Simonov -// Released under MIT License +// Released under MIT License // // Copyright 2010 Mirek Rusin -// Copyright 2010 Stanislav Yudin +// Copyright 2010 Stanislav Yudin // #import diff --git a/YAMLSerialization.m b/YAMLSerialization.m index a680db5..5c9fa74 100644 --- a/YAMLSerialization.m +++ b/YAMLSerialization.m @@ -69,7 +69,7 @@ @implementation YAMLSerialization static int __YAMLSerializationParserInputReadHandler (void *data, unsigned char *buffer, size_t size, size_t *size_read) { - NSInteger outcome = [(NSInputStream *)data read: (uint8_t *)buffer maxLength: size]; + NSInteger outcome = [(NSInputStream *) data read: (uint8_t *) buffer maxLength: size]; if (outcome < 0) { *size_read = 0; return NO; @@ -87,8 +87,8 @@ @implementation YAMLSerialization id *objects = nil; // Mutability options - Class arrayClass = [NSMutableArray class]; // TODO: FIXME: - Class dictionaryClass = [NSMutableDictionary class]; // TODO: FIXME: + Class arrayClass = [NSMutableArray class]; // TODO: FIXME: + Class dictionaryClass = [NSMutableDictionary class]; // TODO: FIXME: Class stringClass = [NSString class]; if (opt & kYAMLReadOptionMutableContainers) { arrayClass = [NSMutableArray class]; @@ -98,14 +98,14 @@ @implementation YAMLSerialization } } - yaml_node_t *node = NULL; - yaml_node_item_t *item = NULL; - yaml_node_pair_t *pair = NULL; + yaml_node_t *node = NULL; + yaml_node_item_t *item = NULL; + yaml_node_pair_t *pair = NULL; int i = 0; - objects = (id *) calloc(document->nodes.top - document->nodes.start, sizeof(id)); - if (objects == NULL) { + objects = (id *) calloc(document->nodes.top - document->nodes.start, sizeof(id)); + if (objects == NULL) { YAML_SET_ERROR(kYAMLErrorCodeOutOfMemory, @"Couldn't allocate memory", @"Please try to free memory and retry"); return nil; } @@ -123,17 +123,17 @@ @implementation YAMLSerialization break; } case YAML_SEQUENCE_NODE: - objects[i] = [[arrayClass alloc] initWithCapacity: node->data.sequence.items.top - node->data.sequence.items.start]; + objects[i] = [[arrayClass alloc] initWithCapacity: node->data.sequence.items.top - node->data.sequence.items.start]; if (!root) root = objects[i]; break; case YAML_MAPPING_NODE: - objects[i] = [[dictionaryClass alloc] initWithCapacity: node->data.mapping.pairs.top - node->data.mapping.pairs.start]; + objects[i] = [[dictionaryClass alloc] initWithCapacity: node->data.mapping.pairs.top - node->data.mapping.pairs.start]; if (!root) root = objects[i]; break; - default: - break; + default: + break; } } @@ -151,25 +151,25 @@ @implementation YAMLSerialization forKey: objects[pair->key - 1]]; break; - default: - break; + default: + break; } } // Retain the root object - if (root != nil) { + if (root != nil) { [root retain]; - } + } // Release all objects. The root object and all referenced (in containers) objects // will have retain count > 0 - for (node = document->nodes.start, i = 0; node < document->nodes.top; node++, i++) { + for (node = document->nodes.start, i = 0; node < document->nodes.top; node++, i++) { [objects[i] release]; - } + } - if (objects != NULL) { + if (objects != NULL) { free(objects); - } + } return root; } @@ -188,27 +188,27 @@ + (NSMutableArray *) objectsWithYAMLStream: (NSInputStream *) stream // Open input stream [stream open]; - memset(&parser, 0, sizeof(yaml_parser_t)); + memset(&parser, 0, sizeof(yaml_parser_t)); if (!yaml_parser_initialize(&parser)) { YAML_SET_ERROR(kYAMLErrorCodeParserInitializationFailed, @"Error in yaml_parser_initialize(&parser)", @"Internal error, please let us know about this error"); return nil; } - yaml_parser_set_input(&parser, __YAMLSerializationParserInputReadHandler, (void *)stream); + yaml_parser_set_input(&parser, __YAMLSerializationParserInputReadHandler, (void *)stream); while (!done) { if (!yaml_parser_load(&parser, &document)) { - YAML_SET_ERROR(kYAMLErrorCodeParseError, @"Parse error", @"Make sure YAML file is well formed"); - return nil; + YAML_SET_ERROR(kYAMLErrorCodeParseError, @"Parse error", @"Make sure YAML file is well formed"); + return nil; } done = !yaml_document_get_root_node(&document); if (!done) { - documentObject = __YAMLSerializationObjectWithYAMLDocument(&document, opt, error); + documentObject = __YAMLSerializationObjectWithYAMLDocument(&document, opt, error); if (error && *error) { - yaml_document_delete(&document); + yaml_document_delete(&document); } else { [documents addObject: documentObject]; [documentObject release]; @@ -219,9 +219,9 @@ + (NSMutableArray *) objectsWithYAMLStream: (NSInputStream *) stream yaml_document_delete(&document); } - yaml_parser_delete(&parser); + yaml_parser_delete(&parser); - return documents; + return documents; } + (id) objectWithYAMLStream: (NSInputStream *) stream options: (YAMLReadOptions) opt error: (NSError **) error { @@ -232,31 +232,31 @@ + (NSMutableArray *) objectsWithYAMLData: (NSData *) data options: (YAMLReadOptions) opt error: (NSError **) error; { - NSMutableArray *result = nil; - if (data != nil) { - NSInputStream *stream = [[NSInputStream alloc] initWithData: data]; - result = [self objectsWithYAMLStream: stream options: opt error: error]; - [stream release]; - } - return result; + NSMutableArray *result = nil; + if (data != nil) { + NSInputStream *stream = [[NSInputStream alloc] initWithData: data]; + result = [self objectsWithYAMLStream: stream options: opt error: error]; + [stream release]; + } + return result; } + (id) objectWithYAMLData: (NSData *) data options: (YAMLReadOptions) opt error: (NSError **) error { - return [[self objectsWithYAMLData: data options: opt error: error] objectAtIndex: 0]; + return [[self objectsWithYAMLData: data options: opt error: error] objectAtIndex: 0]; } + (NSMutableArray *) objectsWithYAMLString: (NSString *) string options: (YAMLReadOptions) opt error: (NSError **) error; { - return [self objectsWithYAMLData: [string dataUsingEncoding: NSUTF8StringEncoding] - options: opt - error: error]; + return [self objectsWithYAMLData: [string dataUsingEncoding: NSUTF8StringEncoding] + options: opt + error: error]; } + (id) objectWithYAMLString: (NSString *) string options: (YAMLReadOptions) opt error: (NSError **) error { - return [[self objectsWithYAMLString: string options: opt error: error] objectAtIndex: 0]; -} + return [[self objectsWithYAMLString: string options: opt error: error] objectAtIndex: 0]; +} #pragma mark Writing YAML @@ -275,7 +275,7 @@ + (id) objectWithYAMLString: (NSString *) string options: (YAMLReadOptions) opt int valueIndex = __YAMLSerializationAddObject(document, [value objectForKey: key]); yaml_document_append_mapping_pair(document, result, keyIndex, valueIndex); } - } + } else if ([value isKindOfClass: [NSArray class]]) { result = yaml_document_add_sequence(document, NULL, YAML_BLOCK_SEQUENCE_STYLE); for (id element in value) { @@ -283,7 +283,7 @@ + (id) objectWithYAMLString: (NSString *) string options: (YAMLReadOptions) opt yaml_document_append_sequence_item(document, result, elementIndex); } } - else { + else { NSString *string = nil; if ([value isKindOfClass: [NSString class]]) { string = value; @@ -291,7 +291,7 @@ + (id) objectWithYAMLString: (NSString *) string options: (YAMLReadOptions) opt string = [value stringValue]; } result = yaml_document_add_scalar(document, NULL, (yaml_char_t *)[string UTF8String], (int) [string length], YAML_PLAIN_SCALAR_STYLE); - } + } return (int) result; } @@ -314,39 +314,39 @@ + (BOOL) __YAMLSerializationAddRootObjectAndEmit: (id) object emitter: (yaml_emi + (BOOL) writeObject: (id) object toYAMLStream: (NSOutputStream *) stream - options: (YAMLWriteOptions) opt - error: (NSError **) error + options: (YAMLWriteOptions) opt + error: (NSError **) error { BOOL result = YES; - yaml_emitter_t emitter; + yaml_emitter_t emitter; memset(&emitter, 0, sizeof(yaml_emitter_t)); - if (!yaml_emitter_initialize(&emitter)) { - YAML_SET_ERROR(kYAMLErrorCodeEmitterError, @"Error in yaml_emitter_initialize(&emitter)", @"Internal error, please let us know about this error"); - return NO; - } - - yaml_emitter_set_encoding(&emitter, YAML_UTF8_ENCODING); + if (!yaml_emitter_initialize(&emitter)) { + YAML_SET_ERROR(kYAMLErrorCodeEmitterError, @"Error in yaml_emitter_initialize(&emitter)", @"Internal error, please let us know about this error"); + return NO; + } + + yaml_emitter_set_encoding(&emitter, YAML_UTF8_ENCODING); yaml_emitter_set_output(&emitter, __YAMLSerializationEmitterOutputWriteHandler, (void *)stream); - + // Open output stream. - [stream open]; - - if (kYAMLWriteOptionMultipleDocuments & opt) { - + [stream open]; + + if (kYAMLWriteOptionMultipleDocuments & opt) { + // YAML is an array of documents. for (id child in object) { // TODO: Check result code. [self __YAMLSerializationAddRootObjectAndEmit: child emitter: &emitter]; - } - } - else { + } + } + else { // YAML is a single document. [self __YAMLSerializationAddRootObjectAndEmit: object emitter: &emitter]; - } - - [stream close]; - yaml_emitter_delete(&emitter); + } + + [stream close]; + yaml_emitter_delete(&emitter); return result; } @@ -367,19 +367,19 @@ + (NSData *) YAMLDataWithObject: (id) object options: (YAMLWriteOptions) opt err + (NSString *) createYAMLStringWithObject: (id) object options: (YAMLWriteOptions) opt error: (NSError **) error { return [[NSString alloc] initWithData: [self YAMLDataWithObject: object options: opt error: error] encoding: NSUTF8StringEncoding]; - + } + (NSString *) YAMLStringWithObject: (id) object options: (YAMLWriteOptions) opt error: (NSError **) error { return [[self createYAMLStringWithObject: object options: opt error: error] autorelease]; } - + #pragma mark Deprecated + (NSMutableArray *) YAMLWithStream: (NSInputStream *) stream options: (YAMLReadOptions) opt error: (NSError **) error { return [self objectsWithYAMLStream: stream options: opt error: error]; } - + + (NSMutableArray *) YAMLWithData: (NSData *) data options: (YAMLReadOptions) opt error: (NSError **) error { return [self objectsWithYAMLData: data options: opt error: error]; } diff --git a/test/test.m b/test/test.m index 08b29db..bee3fae 100644 --- a/test/test.m +++ b/test/test.m @@ -1,8 +1,8 @@ // -// test.m -// YAML Serialization support by Mirek Rusin based on C library LibYAML by Kirill Simonov +// test.m +// YAML Serialization support by Mirek Rusin based on C library LibYAML by Kirill Simonov // -// Copyright 2010 Mirek Rusin, Released under MIT License +// Copyright 2010 Mirek Rusin, Released under MIT License // #import @@ -12,41 +12,41 @@ test (int argc, char *argv[]) { int result = 0; - NSLog(@"reading test file... "); - NSData *data = [NSData dataWithContentsOfFile: @"yaml/basic.yaml"]; - NSInputStream *stream = [[[NSInputStream alloc] initWithFileAtPath: @"yaml/basic.yaml"] autorelease]; - NSLog(@"done."); + NSLog(@"reading test file... "); + NSData *data = [NSData dataWithContentsOfFile: @"yaml/basic.yaml"]; + NSInputStream *stream = [[[NSInputStream alloc] initWithFileAtPath: @"yaml/basic.yaml"] autorelease]; + NSLog(@"done."); - NSTimeInterval before = [[NSDate date] timeIntervalSince1970]; - NSMutableArray *yaml = [YAMLSerialization objectsWithYAMLData: data options: kYAMLReadOptionStringScalars error: nil]; - NSLog(@"YAMLWithData took %f", ([[NSDate date] timeIntervalSince1970] - before)); - NSLog(@"%@", yaml); + NSTimeInterval before = [[NSDate date] timeIntervalSince1970]; + NSMutableArray *yaml = [YAMLSerialization objectsWithYAMLData: data options: kYAMLReadOptionStringScalars error: nil]; + NSLog(@"YAMLWithData took %f", ([[NSDate date] timeIntervalSince1970] - before)); + NSLog(@"%@", yaml); NSError *err = nil; - NSTimeInterval before2 = [[NSDate date] timeIntervalSince1970]; - NSMutableArray *yaml2 = [YAMLSerialization objectsWithYAMLStream: stream options: kYAMLReadOptionStringScalars error: &err]; - NSLog(@"YAMLWithStream took %f", ([[NSDate date] timeIntervalSince1970] - before2)); - NSLog(@"%@", yaml2); + NSTimeInterval before2 = [[NSDate date] timeIntervalSince1970]; + NSMutableArray *yaml2 = [YAMLSerialization objectsWithYAMLStream: stream options: kYAMLReadOptionStringScalars error: &err]; + NSLog(@"YAMLWithStream took %f", ([[NSDate date] timeIntervalSince1970] - before2)); + NSLog(@"%@", yaml2); err = nil; - NSTimeInterval before3 = [[NSDate date] timeIntervalSince1970]; - NSOutputStream *outStream = [NSOutputStream outputStreamToMemory]; - [YAMLSerialization writeObject: yaml toYAMLStream: outStream options: kYAMLWriteOptionMultipleDocuments error: &err]; - if (err) { - NSLog(@"Error: %@", err); - return -1; - } - NSLog(@"writeYAML took %f", (float) ([[NSDate date] timeIntervalSince1970] - before3)); - NSLog(@"out stream %@", outStream); - - NSTimeInterval before4 = [[NSDate date] timeIntervalSince1970]; - NSData *outData = [YAMLSerialization YAMLDataWithObject: yaml2 options: kYAMLWriteOptionMultipleDocuments error: &err]; - if (!outData) { - NSLog(@"Data is nil!"); - return -1; - } - NSLog(@"dataFromYAML took %f", ([[NSDate date] timeIntervalSince1970] - before4)); - NSLog(@"out data %@", outData); + NSTimeInterval before3 = [[NSDate date] timeIntervalSince1970]; + NSOutputStream *outStream = [NSOutputStream outputStreamToMemory]; + [YAMLSerialization writeObject: yaml toYAMLStream: outStream options: kYAMLWriteOptionMultipleDocuments error: &err]; + if (err) { + NSLog(@"Error: %@", err); + return -1; + } + NSLog(@"writeYAML took %f", (float) ([[NSDate date] timeIntervalSince1970] - before3)); + NSLog(@"out stream %@", outStream); + + NSTimeInterval before4 = [[NSDate date] timeIntervalSince1970]; + NSData *outData = [YAMLSerialization YAMLDataWithObject: yaml2 options: kYAMLWriteOptionMultipleDocuments error: &err]; + if (!outData) { + NSLog(@"Data is nil!"); + return -1; + } + NSLog(@"dataFromYAML took %f", ([[NSDate date] timeIntervalSince1970] - before4)); + NSLog(@"out data %@", outData); return result; } @@ -57,5 +57,5 @@ @autoreleasepool { result = test(argc, argv); } - return result; + return result; } \ No newline at end of file From dde457c79b6255f0fc81cceee3bf71fb97c8997c Mon Sep 17 00:00:00 2001 From: Vladimir Grichina Date: Thu, 13 Feb 2014 03:55:30 +0200 Subject: [PATCH 3/5] Added podspec --- YAML-Framework.podspec | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 YAML-Framework.podspec diff --git a/YAML-Framework.podspec b/YAML-Framework.podspec new file mode 100644 index 0000000..6226bde --- /dev/null +++ b/YAML-Framework.podspec @@ -0,0 +1,39 @@ +Pod::Spec.new do |s| + s.name = "YAML-Framework" + s.version = "0.0.2" + s.summary = "Proper YAML support for Objective-C. Based on recommended LibYAML." + s.description = "YAML.framework provides support for YAML (de)serialisation similarly to standard NSPropertyListSerialization. Based on C LibYAML library by Kirill Simonov." + s.homepage = "https://github.com/mirek/YAML.framework" + s.license = { + :type => 'MIT', + :text => <<-LICENSE + Copyright (c) 2010 Mirek Rusin (YAML.framework) + 2006 Kirill Simonov (LibYAML) + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal in + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + LICENSE + } + + s.authors = { "Mirek Rusin" => "mirek@me.com", "Kirill Simonov" => "kiril" } + s.source = { :git => "https://github.com/mirek/YAML.framework.git", :tag => 'v0.0.2' } + s.source_files = 'YAMLSerialization.{h,m}', 'yaml-0.1.4/config.h' + s.public_header_files = 'YAMLSerialization.h' + s.requires_arc = false + s.dependency 'LibYAML', '~> 0.1.4' +end From f30e9d6f170f3abd89153205b80d99d251a8c407 Mon Sep 17 00:00:00 2001 From: Vladimir Grichina Date: Mon, 3 Mar 2014 04:37:48 +0200 Subject: [PATCH 4/5] Fixed memory corruption problem --- YAMLSerialization.m | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/YAMLSerialization.m b/YAMLSerialization.m index 5c9fa74..bb99fbd 100644 --- a/YAMLSerialization.m +++ b/YAMLSerialization.m @@ -40,10 +40,7 @@ @implementation YAMLSerialization dispatch_once(&numberFormatterOnceToken, ^{ numberFormatter = [[NSNumberFormatter alloc] init]; }); - NSNumber *number = nil; - if ([numberFormatter getObjectValue:&number forString:str errorDescription:nil]) - return [number autorelease]; - return nil; + return [[numberFormatter numberFromString:str] retain]; } static NSDate *ParseDate(NSString *str) { @@ -53,10 +50,7 @@ @implementation YAMLSerialization dateFormatter = [[NSDateFormatter alloc] init]; dateFormatter.dateFormat = @"yyyy-MM-dd"; }); - NSDate *date; - if ([dateFormatter getObjectValue:&date forString:str errorDescription:nil]) - return [date autorelease]; - return nil; + return [[dateFormatter dateFromString:str] retain]; } static NSNull *ParseNull(NSString *str) { From 2a8fb366e5ebe09ea94e470a5700e19acf4ac9fe Mon Sep 17 00:00:00 2001 From: Adam Cohen-Rose Date: Mon, 15 Aug 2016 15:48:09 +0100 Subject: [PATCH 5/5] Fixed date parsing and memory leak --- YAMLSerialization.m | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/YAMLSerialization.m b/YAMLSerialization.m index bb99fbd..5ef5684 100644 --- a/YAMLSerialization.m +++ b/YAMLSerialization.m @@ -48,6 +48,10 @@ @implementation YAMLSerialization static NSDateFormatter *dateFormatter = nil; dispatch_once(&dateFormatterOnceToken, ^{ dateFormatter = [[NSDateFormatter alloc] init]; + // set dateformatter defaults (otherwise it picks up current settings) + dateFormatter.calendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian]; + dateFormatter.locale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]; + dateFormatter.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0]; dateFormatter.dateFormat = @"yyyy-MM-dd"; }); return [[dateFormatter dateFromString:str] retain]; @@ -110,7 +114,11 @@ @implementation YAMLSerialization case YAML_SCALAR_NODE: { id value = [[stringClass alloc] initWithUTF8String: (const char *)node->data.scalar.value]; if (!(opt & kYAMLReadOptionStringScalars)) { - value = ParseNull(value) ?: ParseBoolean(value) ?: ParseNumber(value) ?: ParseDate(value) ?: value; + id parsedValue = ParseNull(value) ?: ParseBoolean(value) ?: ParseNumber(value) ?: ParseDate(value) ?: nil; + if (parsedValue) { + [value release]; + value = parsedValue; + } } objects[i] = value; if (!root) root = objects[i];