mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	 6cdef2dc7e
			
		
	
	
		6cdef2dc7e
		
	
	
	
	
		
			
			string. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@14912 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
		
			
				
	
	
		
			256 lines
		
	
	
	
		
			7.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			256 lines
		
	
	
	
		
			7.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * yaml2byte.c
 | |
|  *
 | |
|  * $Author$
 | |
|  *
 | |
|  * Copyright (C) 2003 why the lucky stiff, clark evans
 | |
|  *
 | |
|  *   WARNING WARNING WARNING  --- THIS IS *NOT JUST* PLAYING
 | |
|  *   ANYMORE! -- WHY HAS EMBRACED THIS AS THE REAL THING!
 | |
|  */ 
 | |
| #include "ruby/ruby.h"
 | |
| #include <syck.h>
 | |
| #include <assert.h>
 | |
| #define YAMLBYTE_UTF8
 | |
| #include "yamlbyte.h"
 | |
| 
 | |
| #include <stdio.h>
 | |
| #define TRACE0(a)  \
 | |
|     do { printf(a); printf("\n"); fflush(stdout); } while(0)
 | |
| #define TRACE1(a,b) \
 | |
|     do { printf(a,b); printf("\n"); fflush(stdout); } while(0)
 | |
| #define TRACE2(a,b,c) \
 | |
|     do { printf(a,b,c); printf("\n"); fflush(stdout); } while(0)
 | |
| #define TRACE3(a,b,c,d) \
 | |
|     do { printf(a,b,c,d); printf("\n"); fflush(stdout); } while(0)
 | |
| 
 | |
| /* Reinvent the wheel... */
 | |
| #define CHUNKSIZE 64
 | |
| #define HASH ((long)0xCAFECAFE)
 | |
| typedef struct {
 | |
|    long hash;
 | |
|    char *buffer;
 | |
|    long length;
 | |
|    long remaining;
 | |
|    int  printed;
 | |
| } bytestring_t;
 | |
| bytestring_t *bytestring_alloc(void) {
 | |
|     bytestring_t *ret; 
 | |
|     /*TRACE0("bytestring_alloc()");*/
 | |
|     ret = S_ALLOC(bytestring_t);
 | |
|     ret->hash   = HASH;
 | |
|     ret->length = CHUNKSIZE;
 | |
|     ret->remaining = ret->length;
 | |
|     ret->buffer = S_ALLOC_N(char, ret->length + 1 );
 | |
|     ret->buffer[0] = 0;
 | |
|     ret->printed = 0;
 | |
|     return ret;
 | |
| }
 | |
| void bytestring_append(bytestring_t *str, char code, 
 | |
|                        char *start, char *finish) 
 | |
| {
 | |
|     long grow;
 | |
|     long length = 2;   /* CODE + LF */
 | |
|     char *curr;
 | |
|     assert(str && HASH == str->hash);
 | |
|     /*TRACE0("bytestring_append()");*/
 | |
|     if(start) {
 | |
|         if(!finish)
 | |
|             finish = start + strlen(start);
 | |
|         length += (finish-start);
 | |
|     }
 | |
|     if(length > str->remaining) {
 | |
|         grow = (length - str->remaining) + CHUNKSIZE;
 | |
|         str->remaining += grow;
 | |
|         str->length    += grow; 
 | |
|         str->buffer = S_REALLOC_N( str->buffer, char, str->length + 1 );
 | |
|         assert(str->buffer);
 | |
|     }
 | |
|     curr = str->buffer + (str->length - str->remaining);
 | |
|     *curr = code;
 | |
|     curr += 1;
 | |
|     if(start) 
 | |
|         while(start < finish)
 | |
|             *curr ++ = *start ++;
 | |
|     *curr = '\n';
 | |
|     curr += 1;
 | |
|     *curr = 0;
 | |
|     str->remaining = str->remaining - length;
 | |
|     assert( (str->buffer + str->length) - str->remaining );
 | |
| }
 | |
| void bytestring_extend(bytestring_t *str, bytestring_t *ext)
 | |
| {
 | |
|     char *from;
 | |
|     char *curr;
 | |
|     char *stop;
 | |
|     long grow;
 | |
|     long length;
 | |
|     assert(str && HASH == str->hash);
 | |
|     assert(ext && HASH == ext->hash);
 | |
|     if(ext->printed) {
 | |
|         assert(ext->buffer[0] ==YAMLBYTE_ANCHOR);
 | |
|         curr = ext->buffer;
 | |
|         while( '\n' != *curr)
 | |
|             curr++;
 | |
|         bytestring_append(str, YAMLBYTE_ALIAS, ext->buffer + 1, curr);
 | |
|     } else {
 | |
|         ext->printed = 1;
 | |
|         length  = (ext->length - ext->remaining);
 | |
|         if(length > str->remaining) {
 | |
|             grow = (length - str->remaining) + CHUNKSIZE;
 | |
|             str->remaining += grow;
 | |
|             str->length    += grow; 
 | |
|             str->buffer = S_REALLOC_N( str->buffer, char, str->length + 1 );
 | |
|         }
 | |
|         curr = str->buffer + (str->length - str->remaining);
 | |
|         from = ext->buffer;
 | |
|         stop = ext->buffer + length;
 | |
|         while( from < stop )
 | |
|             *curr ++ = *from ++;
 | |
|         *curr = 0;
 | |
|         str->remaining = str->remaining - length;
 | |
|         assert( (str->buffer + str->length) - str->remaining );
 | |
|     }
 | |
| }
 | |
| 
 | |
| /* convert SyckNode into yamlbyte_buffer_t objects */
 | |
| SYMID
 | |
| syck_yaml2byte_handler(p, n)
 | |
|     SyckParser *p;
 | |
|     SyckNode *n;
 | |
| {
 | |
|     SYMID oid;
 | |
|     long i;
 | |
|     char ch;
 | |
|     char nextcode;
 | |
|     char *start;
 | |
|     char *current;
 | |
|     char *finish;
 | |
|     bytestring_t *val = NULL;
 | |
|     bytestring_t *sav = NULL;
 | |
|     /*TRACE0("syck_yaml2byte_handler()");*/
 | |
|     val = bytestring_alloc();
 | |
|     if(n->anchor) bytestring_append(val,YAMLBYTE_ANCHOR, n->anchor, NULL);
 | |
|     if ( n->type_id )
 | |
|     {
 | |
|         if ( p->taguri_expansion )
 | |
|         {
 | |
|             bytestring_append(val,YAMLBYTE_TRANSFER, n->type_id, NULL);
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             char *type_tag = S_ALLOC_N( char, strlen( n->type_id ) + 1 );
 | |
|             type_tag[0] = '\0';
 | |
|             strcat( type_tag, "!" );
 | |
|             strcat( type_tag, n->type_id );
 | |
|             bytestring_append( val, YAMLBYTE_TRANSFER, type_tag, NULL);
 | |
| 	    S_FREE(type_tag);
 | |
|         }
 | |
|     }
 | |
|     switch (n->kind)
 | |
|     {
 | |
|         case syck_str_kind:
 | |
|             nextcode = YAMLBYTE_SCALAR;
 | |
|             start  = n->data.str->ptr;
 | |
|             finish = start + n->data.str->len - 1;
 | |
|             current = start;
 | |
|             /*TRACE2("SCALAR: %s %d", start, n->data.str->len); */
 | |
|             while(1) {
 | |
|                 ch = *current;
 | |
|                 if('\n' == ch || 0 == ch || current > finish) {
 | |
|                     if(current >= start) {
 | |
|                         bytestring_append(val, nextcode, start, current);
 | |
|                         nextcode = YAMLBYTE_CONTINUE;
 | |
|                     }
 | |
|                     start = current + 1;
 | |
|                     if(current > finish)
 | |
|                     {
 | |
|                         break;
 | |
|                     }
 | |
|                     else if('\n' == ch )
 | |
|                     {
 | |
|                         bytestring_append(val,YAMLBYTE_NEWLINE,NULL,NULL);
 | |
|                     }
 | |
|                     else if(0 == ch)
 | |
|                     {
 | |
|                         bytestring_append(val,YAMLBYTE_NULLCHAR,NULL,NULL);
 | |
|                     }
 | |
|                     else 
 | |
|                     {
 | |
|                         assert("oops");
 | |
|                     }
 | |
|                 }
 | |
|                 current += 1;
 | |
|             }
 | |
|         break;
 | |
|         case syck_seq_kind:
 | |
|             bytestring_append(val,YAMLBYTE_SEQUENCE,NULL,NULL);
 | |
|             for ( i = 0; i < n->data.list->idx; i++ )
 | |
|             {
 | |
|                 oid = syck_seq_read( n, i );
 | |
|                 syck_lookup_sym( p, oid, (char **)&sav );
 | |
|                 bytestring_extend(val, sav);
 | |
|             }
 | |
|             bytestring_append(val,YAMLBYTE_END_BRANCH,NULL,NULL);
 | |
|         break;
 | |
|         case syck_map_kind:
 | |
|             bytestring_append(val,YAMLBYTE_MAPPING,NULL,NULL);
 | |
|             for ( i = 0; i < n->data.pairs->idx; i++ )
 | |
|             {
 | |
|                 oid = syck_map_read( n, map_key, i );
 | |
|                 syck_lookup_sym( p, oid, (char **)&sav );
 | |
|                 bytestring_extend(val, sav);
 | |
|                 oid = syck_map_read( n, map_value, i );
 | |
|                 syck_lookup_sym( p, oid, (char **)&sav );
 | |
|                 bytestring_extend(val, sav);
 | |
|             }
 | |
|             bytestring_append(val,YAMLBYTE_END_BRANCH,NULL,NULL);
 | |
|         break;
 | |
|     }
 | |
|     oid = syck_add_sym( p, (char *) val );
 | |
|     /*TRACE1("Saving: %s", val->buffer );*/
 | |
|     return oid;
 | |
| }
 | |
| 
 | |
| char *
 | |
| syck_yaml2byte(char *yamlstr)
 | |
| {
 | |
|     SYMID oid;
 | |
|     char *ret;
 | |
|     bytestring_t *sav; 
 | |
| 
 | |
|     SyckParser *parser = syck_new_parser();
 | |
|     syck_parser_str_auto( parser, yamlstr, NULL );
 | |
|     syck_parser_handler( parser, syck_yaml2byte_handler );
 | |
|     syck_parser_error_handler( parser, NULL );
 | |
|     syck_parser_implicit_typing( parser, 1 );
 | |
|     syck_parser_taguri_expansion( parser, 1 );
 | |
|     oid = syck_parse( parser );
 | |
| 
 | |
|     if ( syck_lookup_sym( parser, oid, (char **)&sav ) == 1 ) {
 | |
|         ret = S_ALLOC_N( char, strlen( sav->buffer ) + 3 );
 | |
|         ret[0] = '\0';
 | |
|         strcat( ret, "D\n" );
 | |
|         strcat( ret, sav->buffer );
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         ret = NULL;
 | |
|     }
 | |
| 
 | |
|     syck_free_parser( parser );
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| #ifdef TEST_YBEXT
 | |
| #include <stdio.h>
 | |
| int main() {
 | |
|    char *yaml = "test: 1\nand: \"with new\\nline\\n\"\nalso: &3 three\nmore: *3";
 | |
|    printf("--- # YAML \n");
 | |
|    printf(yaml);
 | |
|    printf("\n...\n");
 | |
|    printf(syck_yaml2byte(yaml));
 | |
|    return 0;
 | |
| }
 | |
| #endif
 | |
| 
 |