1/* 2 * yaml2byte.c 3 * 4 * $Author: kojima1 $ 5 * $Date: 2007/03/09 23:41:58 $ 6 * 7 * Copyright (C) 2003 why the lucky stiff, clark evans 8 * 9 * WARNING WARNING WARNING --- THIS IS *NOT JUST* PLAYING 10 * ANYMORE! -- WHY HAS EMBRACED THIS AS THE REAL THING! 11 */ 12#include <syck.h> 13#include <assert.h> 14#define YAMLBYTE_UTF8 15#include "yamlbyte.h" 16 17#include <stdio.h> 18#define TRACE0(a) \ 19 do { printf(a); printf("\n"); fflush(stdout); } while(0) 20#define TRACE1(a,b) \ 21 do { printf(a,b); printf("\n"); fflush(stdout); } while(0) 22#define TRACE2(a,b,c) \ 23 do { printf(a,b,c); printf("\n"); fflush(stdout); } while(0) 24#define TRACE3(a,b,c,d) \ 25 do { printf(a,b,c,d); printf("\n"); fflush(stdout); } while(0) 26 27/* Reinvent the wheel... */ 28#define CHUNKSIZE 64 29#define HASH ((long)0xCAFECAFE) 30typedef struct { 31 long hash; 32 char *buffer; 33 long length; 34 long remaining; 35 int printed; 36} bytestring_t; 37bytestring_t *bytestring_alloc() { 38 bytestring_t *ret; 39 /*TRACE0("bytestring_alloc()");*/ 40 ret = S_ALLOC(bytestring_t); 41 ret->hash = HASH; 42 ret->length = CHUNKSIZE; 43 ret->remaining = ret->length; 44 ret->buffer = S_ALLOC_N(char, ret->length + 1 ); 45 ret->buffer[0] = 0; 46 ret->printed = 0; 47 return ret; 48} 49void bytestring_append(bytestring_t *str, char code, 50 char *start, char *finish) 51{ 52 long grow; 53 long length = 2; /* CODE + LF */ 54 char *curr; 55 assert(str && HASH == str->hash); 56 /*TRACE0("bytestring_append()");*/ 57 if(start) { 58 if(!finish) 59 finish = start + strlen(start); 60 length += (finish-start); 61 } 62 if(length > str->remaining) { 63 grow = (length - str->remaining) + CHUNKSIZE; 64 str->remaining += grow; 65 str->length += grow; 66 str->buffer = S_REALLOC_N( str->buffer, char, str->length + 1 ); 67 assert(str->buffer); 68 } 69 curr = str->buffer + (str->length - str->remaining); 70 *curr = code; 71 curr += 1; 72 if(start) 73 while(start < finish) 74 *curr ++ = *start ++; 75 *curr = '\n'; 76 curr += 1; 77 *curr = 0; 78 str->remaining = str->remaining - length; 79 assert( (str->buffer + str->length) - str->remaining ); 80} 81void bytestring_extend(bytestring_t *str, bytestring_t *ext) 82{ 83 char *from; 84 char *curr; 85 char *stop; 86 long grow; 87 long length; 88 assert(str && HASH == str->hash); 89 assert(ext && HASH == ext->hash); 90 if(ext->printed) { 91 assert(ext->buffer[0] ==YAMLBYTE_ANCHOR); 92 curr = ext->buffer; 93 while( '\n' != *curr) 94 curr++; 95 bytestring_append(str, YAMLBYTE_ALIAS, ext->buffer + 1, curr); 96 } else { 97 ext->printed = 1; 98 length = (ext->length - ext->remaining); 99 if(length > str->remaining) { 100 grow = (length - str->remaining) + CHUNKSIZE; 101 str->remaining += grow; 102 str->length += grow; 103 str->buffer = S_REALLOC_N( str->buffer, char, str->length + 1 ); 104 } 105 curr = str->buffer + (str->length - str->remaining); 106 from = ext->buffer; 107 stop = ext->buffer + length; 108 while( from < stop ) 109 *curr ++ = *from ++; 110 *curr = 0; 111 str->remaining = str->remaining - length; 112 assert( (str->buffer + str->length) - str->remaining ); 113 } 114} 115 116/* convert SyckNode into yamlbyte_buffer_t objects */ 117SYMID 118syck_yaml2byte_handler(p, n) 119 SyckParser *p; 120 SyckNode *n; 121{ 122 SYMID oid; 123 long i; 124 char ch; 125 char nextcode; 126 char *start; 127 char *current; 128 char *finish; 129 bytestring_t *val = NULL; 130 bytestring_t *sav = NULL; 131 /*TRACE0("syck_yaml2byte_handler()");*/ 132 val = bytestring_alloc(); 133 if(n->anchor) bytestring_append(val,YAMLBYTE_ANCHOR, n->anchor, NULL); 134 if ( n->type_id ) 135 { 136 if ( p->taguri_expansion ) 137 { 138 bytestring_append(val,YAMLBYTE_TRANSFER, n->type_id, NULL); 139 } 140 else 141 { 142 char *type_tag = S_ALLOC_N( char, strlen( n->type_id ) + 1 ); 143 type_tag[0] = '\0'; 144 strcat( type_tag, "!" ); 145 strcat( type_tag, n->type_id ); 146 bytestring_append( val, YAMLBYTE_TRANSFER, type_tag, NULL); 147 } 148 } 149 switch (n->kind) 150 { 151 case syck_str_kind: 152 nextcode = YAMLBYTE_SCALAR; 153 start = n->data.str->ptr; 154 finish = start + n->data.str->len - 1; 155 current = start; 156 /*TRACE2("SCALAR: %s %d", start, n->data.str->len); */ 157 while(1) { 158 ch = *current; 159 if('\n' == ch || 0 == ch || current > finish) { 160 if(current >= start) { 161 bytestring_append(val, nextcode, start, current); 162 nextcode = YAMLBYTE_CONTINUE; 163 } 164 start = current + 1; 165 if(current > finish) 166 { 167 break; 168 } 169 else if('\n' == ch ) 170 { 171 bytestring_append(val,YAMLBYTE_NEWLINE,NULL,NULL); 172 } 173 else if(0 == ch) 174 { 175 bytestring_append(val,YAMLBYTE_NULLCHAR,NULL,NULL); 176 } 177 else 178 { 179 assert("oops"); 180 } 181 } 182 current += 1; 183 } 184 break; 185 case syck_seq_kind: 186 bytestring_append(val,YAMLBYTE_SEQUENCE,NULL,NULL); 187 for ( i = 0; i < n->data.list->idx; i++ ) 188 { 189 oid = syck_seq_read( n, i ); 190 syck_lookup_sym( p, oid, (char **)&sav ); 191 bytestring_extend(val, sav); 192 } 193 bytestring_append(val,YAMLBYTE_END_BRANCH,NULL,NULL); 194 break; 195 case syck_map_kind: 196 bytestring_append(val,YAMLBYTE_MAPPING,NULL,NULL); 197 for ( i = 0; i < n->data.pairs->idx; i++ ) 198 { 199 oid = syck_map_read( n, map_key, i ); 200 syck_lookup_sym( p, oid, (char **)&sav ); 201 bytestring_extend(val, sav); 202 oid = syck_map_read( n, map_value, i ); 203 syck_lookup_sym( p, oid, (char **)&sav ); 204 bytestring_extend(val, sav); 205 } 206 bytestring_append(val,YAMLBYTE_END_BRANCH,NULL,NULL); 207 break; 208 } 209 oid = syck_add_sym( p, (char *) val ); 210 /*TRACE1("Saving: %s", val->buffer );*/ 211 return oid; 212} 213 214char * 215syck_yaml2byte(char *yamlstr) 216{ 217 SYMID oid; 218 char *ret; 219 bytestring_t *sav; 220 221 SyckParser *parser = syck_new_parser(); 222 syck_parser_str_auto( parser, yamlstr, NULL ); 223 syck_parser_handler( parser, syck_yaml2byte_handler ); 224 syck_parser_error_handler( parser, NULL ); 225 syck_parser_implicit_typing( parser, 1 ); 226 syck_parser_taguri_expansion( parser, 1 ); 227 oid = syck_parse( parser ); 228 229 if ( syck_lookup_sym( parser, oid, (char **)&sav ) == 1 ) { 230 ret = S_ALLOC_N( char, strlen( sav->buffer ) + 3 ); 231 ret[0] = '\0'; 232 strcat( ret, "D\n" ); 233 strcat( ret, sav->buffer ); 234 } 235 else 236 { 237 ret = NULL; 238 } 239 240 syck_free_parser( parser ); 241 return ret; 242} 243 244#ifdef TEST_YBEXT 245#include <stdio.h> 246int main() { 247 char *yaml = "test: 1\nand: \"with new\\nline\\n\"\nalso: &3 three\nmore: *3"; 248 printf("--- # YAML \n"); 249 printf(yaml); 250 printf("\n...\n"); 251 printf(syck_yaml2byte(yaml)); 252 return 0; 253} 254#endif 255 256