Ruby 1.9.3p327(2012-11-10revision37606)
|
00001 /* yamlbyte.h 00002 * 00003 * The YAML bytecode "C" interface header file. See the YAML bytecode 00004 * reference for bytecode sequence rules and for the meaning of each 00005 * bytecode. 00006 */ 00007 00008 #ifndef YAMLBYTE_H 00009 #define YAMLBYTE_H 00010 #include <stddef.h> 00011 00012 /* define what a character is */ 00013 typedef unsigned char yamlbyte_utf8_t; 00014 typedef unsigned short yamlbyte_utf16_t; 00015 #ifdef YAMLBYTE_UTF8 00016 #ifdef YAMLBYTE_UTF16 00017 #error Must only define YAMLBYTE_UTF8 or YAMLBYTE_UTF16 00018 #endif 00019 typedef yamlbyte_utf8_t yamlbyte_char_t; 00020 #else 00021 #ifdef YAMLBYTE_UTF16 00022 typedef yamlbyte_utf16_t yamlbyte_char_t; 00023 #else 00024 #error Must define YAMLBYTE_UTF8 or YAMLBYTE_UTF16 00025 #endif 00026 #endif 00027 00028 /* specify list of bytecodes */ 00029 #define YAMLBYTE_FINISH ((yamlbyte_char_t) 0) 00030 #define YAMLBYTE_DOCUMENT ((yamlbyte_char_t)'D') 00031 #define YAMLBYTE_DIRECTIVE ((yamlbyte_char_t)'V') 00032 #define YAMLBYTE_PAUSE ((yamlbyte_char_t)'P') 00033 #define YAMLBYTE_MAPPING ((yamlbyte_char_t)'M') 00034 #define YAMLBYTE_SEQUENCE ((yamlbyte_char_t)'Q') 00035 #define YAMLBYTE_END_BRANCH ((yamlbyte_char_t)'E') 00036 #define YAMLBYTE_SCALAR ((yamlbyte_char_t)'S') 00037 #define YAMLBYTE_CONTINUE ((yamlbyte_char_t)'C') 00038 #define YAMLBYTE_NEWLINE ((yamlbyte_char_t)'N') 00039 #define YAMLBYTE_NULLCHAR ((yamlbyte_char_t)'Z') 00040 #define YAMLBYTE_ANCHOR ((yamlbyte_char_t)'A') 00041 #define YAMLBYTE_ALIAS ((yamlbyte_char_t)'R') 00042 #define YAMLBYTE_TRANSFER ((yamlbyte_char_t)'T') 00043 /* formatting bytecodes */ 00044 #define YAMLBYTE_COMMENT ((yamlbyte_char_t)'c') 00045 #define YAMLBYTE_INDENT ((yamlbyte_char_t)'i') 00046 #define YAMLBYTE_STYLE ((yamlbyte_char_t)'s') 00047 /* other bytecodes */ 00048 #define YAMLBYTE_LINE_NUMBER ((yamlbyte_char_t)'#') 00049 #define YAMLBYTE_WHOLE_SCALAR ((yamlbyte_char_t)'<') 00050 #define YAMLBYTE_NOTICE ((yamlbyte_char_t)'!') 00051 #define YAMLBYTE_SPAN ((yamlbyte_char_t)')') 00052 #define YAMLBYTE_ALLOC ((yamlbyte_char_t)'@') 00053 00054 /* second level style bytecodes, ie "s>" */ 00055 #define YAMLBYTE_FLOW ((yamlbyte_char_t)'>') 00056 #define YAMLBYTE_LITERAL ((yamlbyte_char_t)'|') 00057 #define YAMLBYTE_BLOCK ((yamlbyte_char_t)'b') 00058 #define YAMLBYTE_PLAIN ((yamlbyte_char_t)'p') 00059 #define YAMLBYTE_INLINE_MAPPING ((yamlbyte_char_t)'{') 00060 #define YAMLBYTE_INLINE_SEQUENCE ((yamlbyte_char_t)'[') 00061 #define YAMLBYTE_SINGLE_QUOTED ((yamlbyte_char_t)39) 00062 #define YAMLBYTE_DOUBLE_QUOTED ((yamlbyte_char_t)'"') 00063 00064 /* 00065 * The "C" API has two variants, one based on instructions, 00066 * with events delivered via pointers; and the other one 00067 * is character based where one or more instructions are 00068 * serialized into a buffer. 00069 * 00070 * Note: In the instruction based API, WHOLE_SCALAR does 00071 * not have the '<here' marshalling stuff. 00072 */ 00073 00074 typedef void * yamlbyte_consumer_t; 00075 typedef void * yamlbyte_producer_t; 00076 00077 /* push and pull APIs need a way to communicate results */ 00078 typedef enum { 00079 YAMLBYTE_OK = 0, /* proceed */ 00080 YAMLBYTE_E_MEMORY = 'M', /* could not allocate memory */ 00081 YAMLBYTE_E_READ = 'R', /* input stream read error */ 00082 YAMLBYTE_E_WRITE = 'W', /* output stream write error */ 00083 YAMLBYTE_E_OTHER = '?', /* some other error condition */ 00084 YAMLBYTE_E_PARSE = 'P', /* parse error, check bytecodes */ 00085 YAMLBYTE_MAX 00086 } yamlbyte_result_t; 00087 00088 typedef const yamlbyte_char_t *yamlbyte_buff_t; 00089 00090 /* 00091 * The "Instruction" API 00092 */ 00093 00094 typedef struct yaml_instruction { 00095 yamlbyte_char_t bytecode; 00096 yamlbyte_buff_t start; 00097 yamlbyte_buff_t finish; /* open range, *finish is _not_ part */ 00098 } *yamlbyte_inst_t; 00099 00100 /* producer pushes the instruction with one bytecode event to the 00101 * consumer; if the consumer's result is not YAMLBYTE_OK, then 00102 * the producer should stop */ 00103 typedef 00104 yamlbyte_result_t 00105 (*yamlbyte_push_t)( 00106 yamlbyte_consumer_t self, 00107 yamlbyte_inst_t inst 00108 ); 00109 00110 /* consumer pulls a bytecode instruction from the producer; in this 00111 * case the instruction (and is buffer) are owned by the producer and 00112 * will remain valid till the pull function is called once again; 00113 * if the instruction is NULL, then there are no more results; and 00114 * it is important to call the pull function till it returns NULL so 00115 * that the producer can clean up its memory allocations */ 00116 typedef 00117 yamlbyte_result_t 00118 (*yamlbyte_pull_t)( 00119 yamlbyte_producer_t self, 00120 yamlbyte_inst_t *inst /* to be filled in by the producer */ 00121 ); 00122 00123 /* 00124 * Buffer based API 00125 */ 00126 00127 /* producer pushes a null terminated buffer filled with one or more 00128 * bytecode events to the consumer; if the consumer's result is not 00129 * YAMLBYTE_OK, then the producer should stop */ 00130 typedef 00131 yamlbyte_result_t 00132 (*yamlbyte_pushbuff_t)( 00133 yamlbyte_consumer_t self, 00134 yamlbyte_buff_t buff 00135 ); 00136 00137 /* consumer pulls bytecode events from the producer; in this case 00138 * the buffer is owned by the producer, and will remain valid till 00139 * the pull function is called once again; if the buffer pointer 00140 * is set to NULL, then there are no more results; it is important 00141 * to call the pull function till it returns NULL so that the 00142 * producer can clean up its memory allocations */ 00143 typedef 00144 yamlbyte_result_t 00145 (*yamlbyte_pullbuff_t)( 00146 yamlbyte_producer_t self, 00147 yamlbyte_buff_t *buff /* to be filled in by the producer */ 00148 ); 00149 00150 /* convert a pull interface to a push interface; the reverse process 00151 * requires threads and thus is language dependent */ 00152 #define YAMLBYTE_PULL2PUSH(pull,producer,push,consumer,result) \ 00153 do { \ 00154 yamlbyte_pullbuff_t _pull = (pull); \ 00155 yamlbyte_pushbuff_t _push = (push); \ 00156 yamlbyte_result_t _result = YAMLBYTE_OK; \ 00157 yamlbyte_producer_t _producer = (producer); \ 00158 yamlbyte_consumer_t _consumer = (consumer); \ 00159 while(1) { \ 00160 yamlbyte_buff_t buff = NULL; \ 00161 _result = _pull(_producer,&buff); \ 00162 if(YAMLBYTE_OK != result || NULL == buff) \ 00163 break; \ 00164 _result = _push(_consumer,buff); \ 00165 if(YAMLBYTE_OK != result) \ 00166 break; \ 00167 } \ 00168 (result) = _result; \ 00169 } while(0) 00170 00171 #endif 00172