1 /* yamlbyte.h 2 * 3 * The YAML bytecode "C" interface header file. See the YAML bytecode 4 * reference for bytecode sequence rules and for the meaning of each 5 * bytecode. 6 */ 7 8 #ifndef YAMLBYTE_H 9 #define YAMLBYTE_H 10 #include <stddef.h> 11 12 /* define what a character is */ 13 typedef unsigned char yamlbyte_utf8_t; 14 typedef unsigned short yamlbyte_utf16_t; 15 #ifdef YAMLBYTE_UTF8 16 #ifdef YAMLBYTE_UTF16 17 #error Must only define YAMLBYTE_UTF8 or YAMLBYTE_UTF16 18 #endif 19 typedef yamlbyte_utf8_t yamlbyte_char_t; 20 #else 21 #ifdef YAMLBYTE_UTF16 22 typedef yamlbyte_utf16_t yamlbyte_char_t; 23 #else 24 #error Must define YAMLBYTE_UTF8 or YAMLBYTE_UTF16 25 #endif 26 #endif 27 28 /* specify list of bytecodes */ 29 #define YAMLBYTE_FINISH ((yamlbyte_char_t) 0) 30 #define YAMLBYTE_DOCUMENT ((yamlbyte_char_t)'D') 31 #define YAMLBYTE_DIRECTIVE ((yamlbyte_char_t)'V') 32 #define YAMLBYTE_PAUSE ((yamlbyte_char_t)'P') 33 #define YAMLBYTE_MAPPING ((yamlbyte_char_t)'M') 34 #define YAMLBYTE_SEQUENCE ((yamlbyte_char_t)'S') 35 #define YAMLBYTE_END_BRANCH ((yamlbyte_char_t)'E') 36 #define YAMLBYTE_SCALAR ((yamlbyte_char_t)'S') 37 #define YAMLBYTE_CONTINUE ((yamlbyte_char_t)'C') 38 #define YAMLBYTE_NEWLINE ((yamlbyte_char_t)'N') 39 #define YAMLBYTE_NULLCHAR ((yamlbyte_char_t)'Z') 40 #define YAMLBYTE_ANCHOR ((yamlbyte_char_t)'A') 41 #define YAMLBYTE_ALIAS ((yamlbyte_char_t)'R') 42 #define YAMLBYTE_TRANSFER ((yamlbyte_char_t)'T') 43 /* formatting bytecodes */ 44 #define YAMLBYTE_COMMENT ((yamlbyte_char_t)'c') 45 #define YAMLBYTE_INDENT ((yamlbyte_char_t)'i') 46 #define YAMLBYTE_STYLE ((yamlbyte_char_t)'s') 47 /* other bytecodes */ 48 #define YAMLBYTE_LINE_NUMBER ((yamlbyte_char_t)'#') 49 #define YAMLBYTE_WHOLE_SCALAR ((yamlbyte_char_t)'<') 50 #define YAMLBYTE_NOTICE ((yamlbyte_char_t)'!') 51 #define YAMLBYTE_SPAN ((yamlbyte_char_t)')') 52 #define YAMLBYTE_ALLOC ((yamlbyte_char_t)'@') 53 54 /* second level style bytecodes, ie "s>" */ 55 #define YAMLBYTE_FLOW ((yamlbyte_char_t)'>') 56 #define YAMLBYTE_LITERAL ((yamlbyte_char_t)'|') 57 #define YAMLBYTE_BLOCK ((yamlbyte_char_t)'b') 58 #define YAMLBYTE_PLAIN ((yamlbyte_char_t)'p') 59 #define YAMLBYTE_INLINE_MAPPING ((yamlbyte_char_t)'{') 60 #define YAMLBYTE_INLINE_SEQUENCE ((yamlbyte_char_t)'[') 61 #define YAMLBYTE_SINGLE_QUOTED ((yamlbyte_char_t)39) 62 #define YAMLBYTE_DOUBLE_QUOTED ((yamlbyte_char_t)'"') 63 64 /* 65 * The "C" API has two variants, one based on instructions, 66 * with events delivered via pointers; and the other one 67 * is character based where one or more instructions are 68 * serialized into a buffer. 69 * 70 * Note: In the instruction based API, WHOLE_SCALAR does 71 * not have the '<here' marshalling stuff. 72 */ 73 74 typedef void * yamlbyte_consumer_t; 75 typedef void * yamlbyte_producer_t; 76 77 /* push and pull APIs need a way to communicate results */ 78 typedef enum { 79 YAMLBYTE_OK = 0, /* proceed */ 80 YAMLBYTE_E_MEMORY = 'M', /* could not allocate memory */ 81 YAMLBYTE_E_READ = 'R', /* input stream read error */ 82 YAMLBYTE_E_WRITE = 'W', /* output stream write error */ 83 YAMLBYTE_E_OTHER = '?', /* some other error condition */ 84 YAMLBYTE_E_PARSE = 'P', /* parse error, check bytecodes */ 85 } yamlbyte_result_t; 86 87 typedef const yamlbyte_char_t *yamlbyte_buff_t; 88 89 /* 90 * The "Instruction" API 91 */ 92 93 typedef struct yaml_instruction { 94 yamlbyte_char_t bytecode; 95 yamlbyte_buff_t start; 96 yamlbyte_buff_t finish; /* open range, *finish is _not_ part */ 97 } *yamlbyte_inst_t; 98 99 /* producer pushes the instruction with one bytecode event to the 100 * consumer; if the consumer's result is not YAMLBYTE_OK, then 101 * the producer should stop */ 102 typedef 103 yamlbyte_result_t 104 (*yamlbyte_push_t)( 105 yamlbyte_consumer_t self, 106 yamlbyte_inst_t inst 107 ); 108 109 /* consumer pulls a bytecode instruction from the producer; in this 110 * case the instruction (and is buffer) are owned by the producer and 111 * will remain valid till the pull function is called once again; 112 * if the instruction is NULL, then there are no more results; and 113 * it is important to call the pull function till it returns NULL so 114 * that the producer can clean up its memory allocations */ 115 typedef 116 yamlbyte_result_t 117 (*yamlbyte_pull_t)( 118 yamlbyte_producer_t self, 119 yamlbyte_inst_t *inst /* to be filled in by the producer */ 120 ); 121 122 /* 123 * Buffer based API 124 */ 125 126 /* producer pushes a null terminated buffer filled with one or more 127 * bytecode events to the consumer; if the consumer's result is not 128 * YAMLBYTE_OK, then the producer should stop */ 129 typedef 130 yamlbyte_result_t 131 (*yamlbyte_pushbuff_t)( 132 yamlbyte_consumer_t self, 133 yamlbyte_buff_t buff 134 ); 135 136 /* consumer pulls bytecode events from the producer; in this case 137 * the buffer is owned by the producer, and will remain valid till 138 * the pull function is called once again; if the buffer pointer 139 * is set to NULL, then there are no more results; it is important 140 * to call the pull function till it returns NULL so that the 141 * producer can clean up its memory allocations */ 142 typedef 143 yamlbyte_result_t 144 (*yamlbyte_pullbuff_t)( 145 yamlbyte_producer_t self, 146 yamlbyte_buff_t *buff /* to be filled in by the producer */ 147 ); 148 149 /* convert a pull interface to a push interface; the reverse process 150 * requires threads and thus is language dependent */ 151 #define YAMLBYTE_PULL2PUSH(pull,producer,push,consumer,result) \ 152 do { \ 153 yamlbyte_pullbuff_t _pull = (pull); \ 154 yamlbyte_pushbuff_t _push = (push); \ 155 yamlbyte_result_t _result = YAMLBYTE_OK; \ 156 yamlbyte_producer_t _producer = (producer); \ 157 yamlbyte_consumer_t _consumer = (consumer); \ 158 while(1) { \ 159 yamlbyte_buff_t buff = NULL; \ 160 _result = _pull(_producer,&buff); \ 161 if(YAMLBYTE_OK != result || NULL == buff) \ 162 break; \ 163 _result = _push(_consumer,buff); \ 164 if(YAMLBYTE_OK != result) \ 165 break; \ 166 } \ 167 (result) = _result; \ 168 } while(0) 169 170 #endif 171