ext/syck/yamlbyte.h

Go to the documentation of this file.
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 

Generated on Wed Aug 10 09:17:05 2011 for Ruby by  doxygen 1.4.7