mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	 87af442f94
			
		
	
	
		87af442f94
		
	
	
	
	
		
			
			git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27944 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
		
			
				
	
	
		
			171 lines
		
	
	
	
		
			6.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			171 lines
		
	
	
	
		
			6.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*  yamlbyte.h
 | |
|  *
 | |
|  *  The YAML bytecode "C" interface header file.   See the YAML bytecode
 | |
|  *  reference for bytecode sequence rules and for the meaning of each
 | |
|  *  bytecode.
 | |
|  */
 | |
| 
 | |
| #ifndef YAMLBYTE_H
 | |
| #define YAMLBYTE_H
 | |
| #include <stddef.h>
 | |
| 
 | |
| /* define what a character is */
 | |
| typedef unsigned char yamlbyte_utf8_t;
 | |
| typedef unsigned short yamlbyte_utf16_t;
 | |
| #ifdef YAMLBYTE_UTF8
 | |
|   #ifdef YAMLBYTE_UTF16
 | |
|     #error Must only define YAMLBYTE_UTF8 or YAMLBYTE_UTF16
 | |
|   #endif
 | |
|   typedef yamlbyte_utf8_t yamlbyte_char_t;
 | |
| #else
 | |
|   #ifdef YAMLBYTE_UTF16
 | |
|     typedef yamlbyte_utf16_t yamlbyte_char_t;
 | |
|   #else
 | |
|     #error Must define YAMLBYTE_UTF8 or YAMLBYTE_UTF16
 | |
|   #endif
 | |
| #endif
 | |
| 
 | |
| /* specify list of bytecodes */
 | |
| #define YAMLBYTE_FINISH          ((yamlbyte_char_t) 0)
 | |
| #define YAMLBYTE_DOCUMENT        ((yamlbyte_char_t)'D')
 | |
| #define YAMLBYTE_DIRECTIVE       ((yamlbyte_char_t)'V')
 | |
| #define YAMLBYTE_PAUSE           ((yamlbyte_char_t)'P')
 | |
| #define YAMLBYTE_MAPPING         ((yamlbyte_char_t)'M')
 | |
| #define YAMLBYTE_SEQUENCE        ((yamlbyte_char_t)'Q')
 | |
| #define YAMLBYTE_END_BRANCH      ((yamlbyte_char_t)'E')
 | |
| #define YAMLBYTE_SCALAR          ((yamlbyte_char_t)'S')
 | |
| #define YAMLBYTE_CONTINUE        ((yamlbyte_char_t)'C')
 | |
| #define YAMLBYTE_NEWLINE         ((yamlbyte_char_t)'N')
 | |
| #define YAMLBYTE_NULLCHAR        ((yamlbyte_char_t)'Z')
 | |
| #define YAMLBYTE_ANCHOR          ((yamlbyte_char_t)'A')
 | |
| #define YAMLBYTE_ALIAS           ((yamlbyte_char_t)'R')
 | |
| #define YAMLBYTE_TRANSFER        ((yamlbyte_char_t)'T')
 | |
| /* formatting bytecodes */
 | |
| #define YAMLBYTE_COMMENT         ((yamlbyte_char_t)'c')
 | |
| #define YAMLBYTE_INDENT          ((yamlbyte_char_t)'i')
 | |
| #define YAMLBYTE_STYLE           ((yamlbyte_char_t)'s')
 | |
| /* other bytecodes */
 | |
| #define YAMLBYTE_LINE_NUMBER     ((yamlbyte_char_t)'#')
 | |
| #define YAMLBYTE_WHOLE_SCALAR    ((yamlbyte_char_t)'<')
 | |
| #define YAMLBYTE_NOTICE          ((yamlbyte_char_t)'!')
 | |
| #define YAMLBYTE_SPAN            ((yamlbyte_char_t)')')
 | |
| #define YAMLBYTE_ALLOC           ((yamlbyte_char_t)'@')
 | |
| 
 | |
| /* second level style bytecodes, ie "s>" */
 | |
| #define YAMLBYTE_FLOW            ((yamlbyte_char_t)'>')
 | |
| #define YAMLBYTE_LITERAL         ((yamlbyte_char_t)'|')
 | |
| #define YAMLBYTE_BLOCK           ((yamlbyte_char_t)'b')
 | |
| #define YAMLBYTE_PLAIN           ((yamlbyte_char_t)'p')
 | |
| #define YAMLBYTE_INLINE_MAPPING  ((yamlbyte_char_t)'{')
 | |
| #define YAMLBYTE_INLINE_SEQUENCE ((yamlbyte_char_t)'[')
 | |
| #define YAMLBYTE_SINGLE_QUOTED   ((yamlbyte_char_t)39)
 | |
| #define YAMLBYTE_DOUBLE_QUOTED   ((yamlbyte_char_t)'"')
 | |
| 
 | |
| /*
 | |
|  * The "C" API has two variants, one based on instructions,
 | |
|  * with events delivered via pointers; and the other one
 | |
|  * is character based where one or more instructions are
 | |
|  * serialized into a buffer.
 | |
|  *
 | |
|  * Note: In the instruction based API, WHOLE_SCALAR does
 | |
|  *       not have the '<here' marshalling stuff.
 | |
|  */
 | |
| 
 | |
| typedef void * yamlbyte_consumer_t;
 | |
| typedef void * yamlbyte_producer_t;
 | |
| 
 | |
| /* push and pull APIs need a way to communicate results */
 | |
| typedef enum {
 | |
|     YAMLBYTE_OK          = 0,     /* proceed                        */
 | |
|     YAMLBYTE_E_MEMORY    = 'M',   /* could not allocate memory      */
 | |
|     YAMLBYTE_E_READ      = 'R',   /* input stream read error        */
 | |
|     YAMLBYTE_E_WRITE     = 'W',   /* output stream write error      */
 | |
|     YAMLBYTE_E_OTHER     = '?',   /* some other error condition     */
 | |
|     YAMLBYTE_E_PARSE     = 'P',   /* parse error, check bytecodes   */
 | |
|     YAMLBYTE_MAX
 | |
| } yamlbyte_result_t;
 | |
| 
 | |
| typedef const yamlbyte_char_t *yamlbyte_buff_t;
 | |
| 
 | |
| /*
 | |
|  *  The "Instruction" API
 | |
|  */
 | |
| 
 | |
| typedef struct yaml_instruction {
 | |
|     yamlbyte_char_t bytecode;
 | |
|     yamlbyte_buff_t start;
 | |
|     yamlbyte_buff_t finish;  /* open range, *finish is _not_ part */
 | |
| } *yamlbyte_inst_t;
 | |
| 
 | |
| /* producer pushes the instruction with one bytecode event to the
 | |
|  * consumer; if the consumer's result is not YAMLBYTE_OK, then
 | |
|  * the producer should stop */
 | |
| typedef
 | |
|   yamlbyte_result_t
 | |
|    (*yamlbyte_push_t)(
 | |
|      yamlbyte_consumer_t self,
 | |
|      yamlbyte_inst_t  inst
 | |
|    );
 | |
| 
 | |
| /* consumer pulls a bytecode instruction from the producer; in this
 | |
|  * case the instruction (and is buffer) are owned by the producer and
 | |
|  * will remain valid till the pull function is called once again;
 | |
|  * if the instruction is NULL, then there are no more results; and
 | |
|  * it is important to call the pull function till it returns NULL so
 | |
|  * that the producer can clean up its memory allocations */
 | |
| typedef
 | |
|    yamlbyte_result_t
 | |
|     (*yamlbyte_pull_t)(
 | |
|       yamlbyte_producer_t self,
 | |
|       yamlbyte_inst_t *inst   /* to be filled in by the producer */
 | |
|     );
 | |
| 
 | |
| /*
 | |
|  *  Buffer based API
 | |
|  */
 | |
| 
 | |
| /* producer pushes a null terminated buffer filled with one or more
 | |
|  * bytecode events to the consumer; if the consumer's result is not
 | |
|  * YAMLBYTE_OK, then the producer should stop */
 | |
| typedef
 | |
|   yamlbyte_result_t
 | |
|    (*yamlbyte_pushbuff_t)(
 | |
|      yamlbyte_consumer_t self,
 | |
|      yamlbyte_buff_t  buff
 | |
|    );
 | |
| 
 | |
| /* consumer pulls bytecode events from the producer; in this case
 | |
|  * the buffer is owned by the producer, and will remain valid till
 | |
|  * the pull function is called once again; if the buffer pointer
 | |
|  * is set to NULL, then there are no more results; it is important
 | |
|  * to call the pull function till it returns NULL so that the
 | |
|  * producer can clean up its memory allocations */
 | |
| typedef
 | |
|    yamlbyte_result_t
 | |
|     (*yamlbyte_pullbuff_t)(
 | |
|       yamlbyte_producer_t self,
 | |
|       yamlbyte_buff_t *buff   /* to be filled in by the producer */
 | |
|     );
 | |
| 
 | |
| /* convert a pull interface to a push interface; the reverse process
 | |
|  * requires threads and thus is language dependent */
 | |
| #define YAMLBYTE_PULL2PUSH(pull,producer,push,consumer,result)       \
 | |
|     do {                                                         \
 | |
|         yamlbyte_pullbuff_t _pull = (pull);                              \
 | |
|         yamlbyte_pushbuff_t _push = (push);                              \
 | |
|         yamlbyte_result_t _result = YAMLBYTE_OK;                         \
 | |
|         yamlbyte_producer_t _producer = (producer);                  \
 | |
|         yamlbyte_consumer_t _consumer = (consumer);                  \
 | |
|         while(1) {                                               \
 | |
|             yamlbyte_buff_t buff = NULL;                           \
 | |
|             _result = _pull(_producer,&buff);                    \
 | |
|             if(YAMLBYTE_OK != result || NULL == buff)                \
 | |
|                 break;                                           \
 | |
|             _result = _push(_consumer,buff);                     \
 | |
|             if(YAMLBYTE_OK != result)                                \
 | |
|                 break;                                           \
 | |
|         }                                                        \
 | |
|         (result) = _result;                                      \
 | |
|     } while(0)
 | |
| 
 | |
| #endif
 |