writer.c revision 296373
1 2#include "yaml_private.h" 3 4/* 5 * Declarations. 6 */ 7 8static int 9yaml_emitter_set_writer_error(yaml_emitter_t *emitter, const char *problem); 10 11YAML_DECLARE(int) 12yaml_emitter_flush(yaml_emitter_t *emitter); 13 14/* 15 * Set the writer error and return 0. 16 */ 17 18static int 19yaml_emitter_set_writer_error(yaml_emitter_t *emitter, const char *problem) 20{ 21 emitter->error = YAML_WRITER_ERROR; 22 emitter->problem = problem; 23 24 return 0; 25} 26 27/* 28 * Flush the output buffer. 29 */ 30 31YAML_DECLARE(int) 32yaml_emitter_flush(yaml_emitter_t *emitter) 33{ 34 int low, high; 35 36 assert(emitter); /* Non-NULL emitter object is expected. */ 37 assert(emitter->write_handler); /* Write handler must be set. */ 38 assert(emitter->encoding); /* Output encoding must be set. */ 39 40 emitter->buffer.last = emitter->buffer.pointer; 41 emitter->buffer.pointer = emitter->buffer.start; 42 43 /* Check if the buffer is empty. */ 44 45 if (emitter->buffer.start == emitter->buffer.last) { 46 return 1; 47 } 48 49 /* If the output encoding is UTF-8, we don't need to recode the buffer. */ 50 51 if (emitter->encoding == YAML_UTF8_ENCODING) 52 { 53 if (emitter->write_handler(emitter->write_handler_data, 54 emitter->buffer.start, 55 emitter->buffer.last - emitter->buffer.start)) { 56 emitter->buffer.last = emitter->buffer.start; 57 emitter->buffer.pointer = emitter->buffer.start; 58 return 1; 59 } 60 else { 61 return yaml_emitter_set_writer_error(emitter, "write error"); 62 } 63 } 64 65 /* Recode the buffer into the raw buffer. */ 66 67 low = (emitter->encoding == YAML_UTF16LE_ENCODING ? 0 : 1); 68 high = (emitter->encoding == YAML_UTF16LE_ENCODING ? 1 : 0); 69 70 while (emitter->buffer.pointer != emitter->buffer.last) 71 { 72 unsigned char octet; 73 unsigned int width; 74 unsigned int value; 75 size_t k; 76 77 /* 78 * See the "reader.c" code for more details on UTF-8 encoding. Note 79 * that we assume that the buffer contains a valid UTF-8 sequence. 80 */ 81 82 /* Read the next UTF-8 character. */ 83 84 octet = emitter->buffer.pointer[0]; 85 86 width = (octet & 0x80) == 0x00 ? 1 : 87 (octet & 0xE0) == 0xC0 ? 2 : 88 (octet & 0xF0) == 0xE0 ? 3 : 89 (octet & 0xF8) == 0xF0 ? 4 : 0; 90 91 value = (octet & 0x80) == 0x00 ? octet & 0x7F : 92 (octet & 0xE0) == 0xC0 ? octet & 0x1F : 93 (octet & 0xF0) == 0xE0 ? octet & 0x0F : 94 (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0; 95 96 for (k = 1; k < width; k ++) { 97 octet = emitter->buffer.pointer[k]; 98 value = (value << 6) + (octet & 0x3F); 99 } 100 101 emitter->buffer.pointer += width; 102 103 /* Write the character. */ 104 105 if (value < 0x10000) 106 { 107 emitter->raw_buffer.last[high] = value >> 8; 108 emitter->raw_buffer.last[low] = value & 0xFF; 109 110 emitter->raw_buffer.last += 2; 111 } 112 else 113 { 114 /* Write the character using a surrogate pair (check "reader.c"). */ 115 116 value -= 0x10000; 117 emitter->raw_buffer.last[high] = 0xD8 + (value >> 18); 118 emitter->raw_buffer.last[low] = (value >> 10) & 0xFF; 119 emitter->raw_buffer.last[high+2] = 0xDC + ((value >> 8) & 0xFF); 120 emitter->raw_buffer.last[low+2] = value & 0xFF; 121 122 emitter->raw_buffer.last += 4; 123 } 124 } 125 126 /* Write the raw buffer. */ 127 128 if (emitter->write_handler(emitter->write_handler_data, 129 emitter->raw_buffer.start, 130 emitter->raw_buffer.last - emitter->raw_buffer.start)) { 131 emitter->buffer.last = emitter->buffer.start; 132 emitter->buffer.pointer = emitter->buffer.start; 133 emitter->raw_buffer.last = emitter->raw_buffer.start; 134 emitter->raw_buffer.pointer = emitter->raw_buffer.start; 135 return 1; 136 } 137 else { 138 return yaml_emitter_set_writer_error(emitter, "write error"); 139 } 140} 141 142