Ruby  2.0.0p247(2013-06-27revision41674)
ext/psych/yaml/writer.c
Go to the documentation of this file.
00001 
00002 #include "yaml_private.h"
00003 
00004 /*
00005  * Declarations.
00006  */
00007 
00008 static int
00009 yaml_emitter_set_writer_error(yaml_emitter_t *emitter, const char *problem);
00010 
00011 YAML_DECLARE(int)
00012 yaml_emitter_flush(yaml_emitter_t *emitter);
00013 
00014 /*
00015  * Set the writer error and return 0.
00016  */
00017 
00018 static int
00019 yaml_emitter_set_writer_error(yaml_emitter_t *emitter, const char *problem)
00020 {
00021     emitter->error = YAML_WRITER_ERROR;
00022     emitter->problem = problem;
00023 
00024     return 0;
00025 }
00026 
00027 /*
00028  * Flush the output buffer.
00029  */
00030 
00031 YAML_DECLARE(int)
00032 yaml_emitter_flush(yaml_emitter_t *emitter)
00033 {
00034     int low, high;
00035 
00036     assert(emitter);    /* Non-NULL emitter object is expected. */
00037     assert(emitter->write_handler); /* Write handler must be set. */
00038     assert(emitter->encoding);  /* Output encoding must be set. */
00039 
00040     emitter->buffer.last = emitter->buffer.pointer;
00041     emitter->buffer.pointer = emitter->buffer.start;
00042 
00043     /* Check if the buffer is empty. */
00044 
00045     if (emitter->buffer.start == emitter->buffer.last) {
00046         return 1;
00047     }
00048 
00049     /* If the output encoding is UTF-8, we don't need to recode the buffer. */
00050 
00051     if (emitter->encoding == YAML_UTF8_ENCODING)
00052     {
00053         if (emitter->write_handler(emitter->write_handler_data,
00054                     emitter->buffer.start,
00055                     emitter->buffer.last - emitter->buffer.start)) {
00056             emitter->buffer.last = emitter->buffer.start;
00057             emitter->buffer.pointer = emitter->buffer.start;
00058             return 1;
00059         }
00060         else {
00061             return yaml_emitter_set_writer_error(emitter, "write error");
00062         }
00063     }
00064 
00065     /* Recode the buffer into the raw buffer. */
00066 
00067     low = (emitter->encoding == YAML_UTF16LE_ENCODING ? 0 : 1);
00068     high = (emitter->encoding == YAML_UTF16LE_ENCODING ? 1 : 0);
00069 
00070     while (emitter->buffer.pointer != emitter->buffer.last)
00071     {
00072         unsigned char octet;
00073         unsigned int width;
00074         unsigned int value;
00075         size_t k;
00076 
00077         /*
00078          * See the "reader.c" code for more details on UTF-8 encoding.  Note
00079          * that we assume that the buffer contains a valid UTF-8 sequence.
00080          */
00081 
00082         /* Read the next UTF-8 character. */
00083 
00084         octet = emitter->buffer.pointer[0];
00085 
00086         width = (octet & 0x80) == 0x00 ? 1 :
00087                 (octet & 0xE0) == 0xC0 ? 2 :
00088                 (octet & 0xF0) == 0xE0 ? 3 :
00089                 (octet & 0xF8) == 0xF0 ? 4 : 0;
00090 
00091         value = (octet & 0x80) == 0x00 ? octet & 0x7F :
00092                 (octet & 0xE0) == 0xC0 ? octet & 0x1F :
00093                 (octet & 0xF0) == 0xE0 ? octet & 0x0F :
00094                 (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
00095 
00096         for (k = 1; k < width; k ++) {
00097             octet = emitter->buffer.pointer[k];
00098             value = (value << 6) + (octet & 0x3F);
00099         }
00100 
00101         emitter->buffer.pointer += width;
00102 
00103         /* Write the character. */
00104 
00105         if (value < 0x10000)
00106         {
00107             emitter->raw_buffer.last[high] = value >> 8;
00108             emitter->raw_buffer.last[low] = value & 0xFF;
00109 
00110             emitter->raw_buffer.last += 2;
00111         }
00112         else
00113         {
00114             /* Write the character using a surrogate pair (check "reader.c"). */
00115 
00116             value -= 0x10000;
00117             emitter->raw_buffer.last[high] = 0xD8 + (value >> 18);
00118             emitter->raw_buffer.last[low] = (value >> 10) & 0xFF;
00119             emitter->raw_buffer.last[high+2] = 0xDC + ((value >> 8) & 0xFF);
00120             emitter->raw_buffer.last[low+2] = value & 0xFF;
00121 
00122             emitter->raw_buffer.last += 4;
00123         }
00124     }
00125 
00126     /* Write the raw buffer. */
00127 
00128     if (emitter->write_handler(emitter->write_handler_data,
00129                 emitter->raw_buffer.start,
00130                 emitter->raw_buffer.last - emitter->raw_buffer.start)) {
00131         emitter->buffer.last = emitter->buffer.start;
00132         emitter->buffer.pointer = emitter->buffer.start;
00133         emitter->raw_buffer.last = emitter->raw_buffer.start;
00134         emitter->raw_buffer.pointer = emitter->raw_buffer.start;
00135         return 1;
00136     }
00137     else {
00138         return yaml_emitter_set_writer_error(emitter, "write error");
00139     }
00140 }
00141 
00142