Index: src/OFXMLFactory.h ================================================================== --- src/OFXMLFactory.h +++ src/OFXMLFactory.h @@ -26,10 +26,39 @@ */ + (char*)escapeCString: (const char*)s; /** * Creates an XML stanza. + * + * \param name The name of the tag as a C string + * \param ... Field / value pairs for the tag in the form "field", "value" as + * C strings. + * Last element must be NULL. + * Example: "field1", "value1", "field2", "value2", NULL + * \return The created XML stanza as a C string. + * You need to free it manually! + */ ++ (char*)createStanza: (const char*)name, ...; + +/** + * Creates an XML stanza. + * + * \param name The name of the tag as a C string + * \param data Data that should be inside the tag as a C string. + * It will NOT be escaped, so you can also include other stanzas. + * \param ... Field / value pairs for the tag in the form "field", "value" as + * C strings. + * Last element must be NULL. + * Example: "field1", "value1", "field2", "value2", NULL + * \return The created XML stanza as a C string. + * You need to free it manually! + */ ++ (char*)createStanza: (const char*)name + withData: (const char*)data, ...; + +/** + * Creates an XML stanza. * * \param name The name of the tag as a C string * \param close A boolean whether the tag should be closed * \param data Data that should be inside the tag as a C string. * It will NOT be escaped, so you can also include other stanzas. @@ -42,10 +71,29 @@ */ + (char*)createStanza: (const char*)name withCloseTag: (BOOL)close andData: (const char*)data, ...; +/** + * Creates an XML stanza. + * + * \param name The name of the tag as a C string + * \param close A boolean whether the tag should be closed + * \param attrs Field / value pairs for the tag in the form "field", "value" as + * C strings inside a va_list. + * Last element must be NULL. + * Example: "field1", "value1", "field2", "value2", NULL in a va_list + * \param data Data that should be inside the tag as a C string. + * It will NOT be escaped, so you can also include other stanzas. + * \return The created XML stanza as a C string. + * You need to free it manually! + */ ++ (char*)createStanza: (const char*)name + withCloseTag: (BOOL)close + andAttributes: (va_list)attrs + andData: (const char*)data; + /** * Concats an array of C strings into one C string and frees the array of C * strings. * * \param strs An array of C strings Index: src/OFXMLFactory.m ================================================================== --- src/OFXMLFactory.m +++ src/OFXMLFactory.m @@ -108,18 +108,66 @@ } ret[i] = 0; return ret; } + ++ (char*)createStanza: (const char*)name, ... +{ + char *ret; + va_list attrs; + + va_start(attrs, name); + ret = [self createStanza: name + withCloseTag: YES + andAttributes: attrs + andData: NULL]; + va_end(attrs); + + return ret; +} + ++ (char*)createStanza: (const char*)name + withData: (const char*)data, ... +{ + char *ret; + va_list attrs; + + va_start(attrs, data); + ret = [self createStanza: name + withCloseTag: YES + andAttributes: attrs + andData: data]; + va_end(attrs); + + return ret; +} + (char*)createStanza: (const char*)name withCloseTag: (BOOL)close andData: (const char*)data, ... { + char *ret; + va_list attrs; + + va_start(attrs, data); + ret = [self createStanza: name + withCloseTag: close + andAttributes: attrs + andData: data]; + va_end(attrs); + + return ret; +} + ++ (char*)createStanza: (const char*)name + withCloseTag: (BOOL)close + andAttributes: (va_list)attrs + andData: (const char*)data +{ char *arg, *val, *xml, *esc_val = NULL; size_t i, len; - va_list args; /* Start of tag */ len = strlen(name); if (SIZE_MAX - len < 3) @throw [OFOutOfRangeException newWithClass: self]; @@ -132,21 +180,13 @@ i = 0; xml[i++] = '<'; memcpy(xml + i, name, strlen(name)); i += strlen(name); - /* - * Arguments - * - * va_start / va_end need to be INSIDE the @try block due to a bug in - * gcc 4.0.1. (Only in Apple gcc?) - */ @try { - va_start(args, data); - - while ((arg = va_arg(args, char*)) != NULL && - (val = va_arg(args, char*)) != NULL) { + while ((arg = va_arg(attrs, char*)) != NULL && + (val = va_arg(attrs, char*)) != NULL) { esc_val = NULL; /* Needed for our @catch */ esc_val = [self escapeCString: val]; resize(&xml, &len, 1 + strlen(arg) + 2 + strlen(esc_val) + 1, self); @@ -161,12 +201,10 @@ xml[i++] = '\''; free(esc_val); } - va_end(args); - /* End of tag */ if (close) { if (data == NULL) { resize(&xml, &len, 2 - 1, self); Index: tests/OFXMLFactory/OFXMLFactory.m ================================================================== --- tests/OFXMLFactory/OFXMLFactory.m +++ tests/OFXMLFactory/OFXMLFactory.m @@ -38,10 +38,11 @@ fflush(stdout); } else { printf("\r\033[K\033[1;31mTest %" ZD "/%d failed!\033[0m\n", i, NUM_TESTS); printf("%s is NOT expected result!\n", result); + printf("Should have been: %s\n", result); exit(1); } free(result); } @@ -85,42 +86,31 @@ andData: NULL, "bar", "baz", "blub", "asd", NULL], ""); - check_result([OFXMLFactory createStanza: "foo" - withCloseTag: YES - andData: NULL, - NULL], - ""); - check_result([OFXMLFactory createStanza: "foo" - withCloseTag: YES - andData: "bar", + check_result([OFXMLFactory createStanza: "foo", NULL], ""); + check_result([OFXMLFactory createStanza: "foo" + withData: "bar", NULL], "bar"); - check_result([OFXMLFactory createStanza: "foo" - withCloseTag: YES - andData: NULL, + check_result([OFXMLFactory createStanza: "foo", "bar", "b&az", NULL], ""); check_result([OFXMLFactory createStanza: "foo" - withCloseTag: YES - andData: "bar", + withData: "bar", "bar", "b'az", NULL], "bar"); - check_result([OFXMLFactory createStanza: "foo" - withCloseTag: YES - andData: NULL, + check_result([OFXMLFactory createStanza: "foo", "bar", "b&az", "x", "asd\"", NULL], ""); check_result([OFXMLFactory createStanza: "foo" - withCloseTag: YES - andData: "bar", + withData: "bar", "bar", "b'az", "x", "y", "a", "b", NULL], "bar");