Ruby 1.9.3p327(2012-11-10revision37606)
|
00001 /* 00002 * yaml2byte.c 00003 * 00004 * $Author: nobu $ 00005 * 00006 * Copyright (C) 2003 why the lucky stiff, clark evans 00007 * 00008 * WARNING WARNING WARNING --- THIS IS *NOT JUST* PLAYING 00009 * ANYMORE! -- WHY HAS EMBRACED THIS AS THE REAL THING! 00010 */ 00011 #include "ruby/ruby.h" 00012 #include <syck.h> 00013 #include <assert.h> 00014 #define YAMLBYTE_UTF8 00015 #include "yamlbyte.h" 00016 00017 #include <stdio.h> 00018 #define TRACE0(a) \ 00019 do { printf(a); printf("\n"); fflush(stdout); } while(0) 00020 #define TRACE1(a,b) \ 00021 do { printf(a,b); printf("\n"); fflush(stdout); } while(0) 00022 #define TRACE2(a,b,c) \ 00023 do { printf(a,b,c); printf("\n"); fflush(stdout); } while(0) 00024 #define TRACE3(a,b,c,d) \ 00025 do { printf(a,b,c,d); printf("\n"); fflush(stdout); } while(0) 00026 00027 /* Reinvent the wheel... */ 00028 #define CHUNKSIZE 64 00029 #define HASH ((long)0xCAFECAFE) 00030 typedef struct { 00031 long hash; 00032 char *buffer; 00033 long length; 00034 long remaining; 00035 int printed; 00036 } bytestring_t; 00037 bytestring_t *bytestring_alloc(void) { 00038 bytestring_t *ret; 00039 /*TRACE0("bytestring_alloc()");*/ 00040 ret = S_ALLOC(bytestring_t); 00041 ret->hash = HASH; 00042 ret->length = CHUNKSIZE; 00043 ret->remaining = ret->length; 00044 ret->buffer = S_ALLOC_N(char, ret->length + 1 ); 00045 ret->buffer[0] = 0; 00046 ret->printed = 0; 00047 return ret; 00048 } 00049 void bytestring_append(bytestring_t *str, char code, 00050 char *start, char *finish) 00051 { 00052 long grow; 00053 long length = 2; /* CODE + LF */ 00054 char *curr; 00055 assert(str && HASH == str->hash); 00056 /*TRACE0("bytestring_append()");*/ 00057 if(start) { 00058 if(!finish) 00059 finish = start + strlen(start); 00060 length += (finish-start); 00061 } 00062 if(length > str->remaining) { 00063 grow = (length - str->remaining) + CHUNKSIZE; 00064 str->remaining += grow; 00065 str->length += grow; 00066 S_REALLOC_N( str->buffer, char, str->length + 1 ); 00067 assert(str->buffer); 00068 } 00069 curr = str->buffer + (str->length - str->remaining); 00070 *curr = code; 00071 curr += 1; 00072 if(start) 00073 while(start < finish) 00074 *curr ++ = *start ++; 00075 *curr = '\n'; 00076 curr += 1; 00077 *curr = 0; 00078 str->remaining = str->remaining - length; 00079 assert( (str->buffer + str->length) - str->remaining ); 00080 } 00081 void bytestring_extend(bytestring_t *str, bytestring_t *ext) 00082 { 00083 char *from; 00084 char *curr; 00085 char *stop; 00086 long grow; 00087 long length; 00088 assert(str && HASH == str->hash); 00089 assert(ext && HASH == ext->hash); 00090 if(ext->printed) { 00091 assert(ext->buffer[0] ==YAMLBYTE_ANCHOR); 00092 curr = ext->buffer; 00093 while( '\n' != *curr) 00094 curr++; 00095 bytestring_append(str, YAMLBYTE_ALIAS, ext->buffer + 1, curr); 00096 } else { 00097 ext->printed = 1; 00098 length = (ext->length - ext->remaining); 00099 if(length > str->remaining) { 00100 grow = (length - str->remaining) + CHUNKSIZE; 00101 str->remaining += grow; 00102 str->length += grow; 00103 S_REALLOC_N( str->buffer, char, str->length + 1 ); 00104 } 00105 curr = str->buffer + (str->length - str->remaining); 00106 from = ext->buffer; 00107 stop = ext->buffer + length; 00108 while( from < stop ) 00109 *curr ++ = *from ++; 00110 *curr = 0; 00111 str->remaining = str->remaining - length; 00112 assert( (str->buffer + str->length) - str->remaining ); 00113 } 00114 } 00115 00116 /* convert SyckNode into yamlbyte_buffer_t objects */ 00117 SYMID 00118 syck_yaml2byte_handler(p, n) 00119 SyckParser *p; 00120 SyckNode *n; 00121 { 00122 SYMID oid; 00123 long i; 00124 char ch; 00125 char nextcode; 00126 char *start; 00127 char *current; 00128 char *finish; 00129 bytestring_t *val = NULL; 00130 bytestring_t *sav = NULL; 00131 void *data; 00132 /*TRACE0("syck_yaml2byte_handler()");*/ 00133 val = bytestring_alloc(); 00134 if(n->anchor) bytestring_append(val,YAMLBYTE_ANCHOR, n->anchor, NULL); 00135 if ( n->type_id ) 00136 { 00137 if ( p->taguri_expansion ) 00138 { 00139 bytestring_append(val,YAMLBYTE_TRANSFER, n->type_id, NULL); 00140 } 00141 else 00142 { 00143 char *type_tag = S_ALLOC_N( char, strlen( n->type_id ) + 1 ); 00144 type_tag[0] = '\0'; 00145 strcat( type_tag, "!" ); 00146 strcat( type_tag, n->type_id ); 00147 bytestring_append( val, YAMLBYTE_TRANSFER, type_tag, NULL); 00148 S_FREE(type_tag); 00149 } 00150 } 00151 switch (n->kind) 00152 { 00153 case syck_str_kind: 00154 nextcode = YAMLBYTE_SCALAR; 00155 start = n->data.str->ptr; 00156 finish = start + n->data.str->len - 1; 00157 current = start; 00158 /*TRACE2("SCALAR: %s %d", start, n->data.str->len); */ 00159 while(1) { 00160 ch = *current; 00161 if('\n' == ch || 0 == ch || current > finish) { 00162 if(current >= start) { 00163 bytestring_append(val, nextcode, start, current); 00164 nextcode = YAMLBYTE_CONTINUE; 00165 } 00166 start = current + 1; 00167 if(current > finish) 00168 { 00169 break; 00170 } 00171 else if('\n' == ch ) 00172 { 00173 bytestring_append(val,YAMLBYTE_NEWLINE,NULL,NULL); 00174 } 00175 else if(0 == ch) 00176 { 00177 bytestring_append(val,YAMLBYTE_NULLCHAR,NULL,NULL); 00178 } 00179 else 00180 { 00181 assert("oops"); 00182 } 00183 } 00184 current += 1; 00185 } 00186 break; 00187 case syck_seq_kind: 00188 bytestring_append(val,YAMLBYTE_SEQUENCE,NULL,NULL); 00189 for ( i = 0; i < n->data.list->idx; i++ ) 00190 { 00191 oid = syck_seq_read( n, i ); 00192 if (syck_lookup_sym( p, oid, &data )) sav = data; 00193 bytestring_extend(val, sav); 00194 } 00195 bytestring_append(val,YAMLBYTE_END_BRANCH,NULL,NULL); 00196 break; 00197 case syck_map_kind: 00198 bytestring_append(val,YAMLBYTE_MAPPING,NULL,NULL); 00199 for ( i = 0; i < n->data.pairs->idx; i++ ) 00200 { 00201 oid = syck_map_read( n, map_key, i ); 00202 if (syck_lookup_sym( p, oid, &data )) sav = data; 00203 bytestring_extend(val, sav); 00204 oid = syck_map_read( n, map_value, i ); 00205 if (syck_lookup_sym( p, oid, &data )) sav = data; 00206 bytestring_extend(val, sav); 00207 } 00208 bytestring_append(val,YAMLBYTE_END_BRANCH,NULL,NULL); 00209 break; 00210 } 00211 oid = syck_add_sym( p, (char *) val ); 00212 /*TRACE1("Saving: %s", val->buffer );*/ 00213 return oid; 00214 } 00215 00216 char * 00217 syck_yaml2byte(char *yamlstr) 00218 { 00219 SYMID oid; 00220 char *ret; 00221 bytestring_t *sav; 00222 void *data; 00223 00224 SyckParser *parser = syck_new_parser(); 00225 syck_parser_str_auto( parser, yamlstr, NULL ); 00226 syck_parser_handler( parser, syck_yaml2byte_handler ); 00227 syck_parser_error_handler( parser, NULL ); 00228 syck_parser_implicit_typing( parser, 1 ); 00229 syck_parser_taguri_expansion( parser, 1 ); 00230 oid = syck_parse( parser ); 00231 00232 if ( syck_lookup_sym( parser, oid, &data ) ) { 00233 sav = data; 00234 ret = S_ALLOC_N( char, strlen( sav->buffer ) + 3 ); 00235 ret[0] = '\0'; 00236 strcat( ret, "D\n" ); 00237 strcat( ret, sav->buffer ); 00238 } 00239 else 00240 { 00241 ret = NULL; 00242 } 00243 00244 syck_free_parser( parser ); 00245 return ret; 00246 } 00247 00248 #ifdef TEST_YBEXT 00249 #include <stdio.h> 00250 int main() { 00251 char *yaml = "test: 1\nand: \"with new\\nline\\n\"\nalso: &3 three\nmore: *3"; 00252 printf("--- # YAML \n"); 00253 printf(yaml); 00254 printf("\n...\n"); 00255 printf(syck_yaml2byte(yaml)); 00256 return 0; 00257 } 00258 #endif 00259 00260