00001
00002
00003
00004
00005
00006
00007
00008
00009
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
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
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;
00054 char *curr;
00055 assert(str && HASH == str->hash);
00056
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
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
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
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
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