vstr.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. /*
  2. * This file is part of the MicroPython project, http://micropython.org/
  3. *
  4. * The MIT License (MIT)
  5. *
  6. * Copyright (c) 2013, 2014 Damien P. George
  7. *
  8. * Permission is hereby granted, free of charge, to any person obtaining a copy
  9. * of this software and associated documentation files (the "Software"), to deal
  10. * in the Software without restriction, including without limitation the rights
  11. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. * copies of the Software, and to permit persons to whom the Software is
  13. * furnished to do so, subject to the following conditions:
  14. *
  15. * The above copyright notice and this permission notice shall be included in
  16. * all copies or substantial portions of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  24. * THE SOFTWARE.
  25. */
  26. #include <stdio.h>
  27. #include <stdarg.h>
  28. #include <string.h>
  29. #include <assert.h>
  30. #include "py/mpconfig.h"
  31. #include "py/runtime.h"
  32. #include "py/mpprint.h"
  33. // returned value is always at least 1 greater than argument
  34. #define ROUND_ALLOC(a) (((a) & ((~0U) - 7)) + 8)
  35. // Init the vstr so it allocs exactly given number of bytes. Set length to zero.
  36. void vstr_init(vstr_t *vstr, size_t alloc) {
  37. if (alloc < 1) {
  38. alloc = 1;
  39. }
  40. vstr->alloc = alloc;
  41. vstr->len = 0;
  42. vstr->buf = m_new(char, vstr->alloc);
  43. vstr->fixed_buf = false;
  44. }
  45. // Init the vstr so it allocs exactly enough ram to hold a null-terminated
  46. // string of the given length, and set the length.
  47. void vstr_init_len(vstr_t *vstr, size_t len) {
  48. vstr_init(vstr, len + 1);
  49. vstr->len = len;
  50. }
  51. void vstr_init_fixed_buf(vstr_t *vstr, size_t alloc, char *buf) {
  52. vstr->alloc = alloc;
  53. vstr->len = 0;
  54. vstr->buf = buf;
  55. vstr->fixed_buf = true;
  56. }
  57. void vstr_init_print(vstr_t *vstr, size_t alloc, mp_print_t *print) {
  58. vstr_init(vstr, alloc);
  59. print->data = vstr;
  60. print->print_strn = (mp_print_strn_t)vstr_add_strn;
  61. }
  62. void vstr_clear(vstr_t *vstr) {
  63. if (!vstr->fixed_buf) {
  64. m_del(char, vstr->buf, vstr->alloc);
  65. }
  66. vstr->buf = NULL;
  67. }
  68. vstr_t *vstr_new(size_t alloc) {
  69. vstr_t *vstr = m_new_obj(vstr_t);
  70. vstr_init(vstr, alloc);
  71. return vstr;
  72. }
  73. void vstr_free(vstr_t *vstr) {
  74. if (vstr != NULL) {
  75. if (!vstr->fixed_buf) {
  76. m_del(char, vstr->buf, vstr->alloc);
  77. }
  78. m_del_obj(vstr_t, vstr);
  79. }
  80. }
  81. // Extend vstr strictly by requested size, return pointer to newly added chunk.
  82. char *vstr_extend(vstr_t *vstr, size_t size) {
  83. if (vstr->fixed_buf) {
  84. // We can't reallocate, and the caller is expecting the space to
  85. // be there, so the only safe option is to raise an exception.
  86. mp_raise_msg(&mp_type_RuntimeError, NULL);
  87. }
  88. char *new_buf = m_renew(char, vstr->buf, vstr->alloc, vstr->alloc + size);
  89. char *p = new_buf + vstr->alloc;
  90. vstr->alloc += size;
  91. vstr->buf = new_buf;
  92. return p;
  93. }
  94. STATIC void vstr_ensure_extra(vstr_t *vstr, size_t size) {
  95. if (vstr->len + size > vstr->alloc) {
  96. if (vstr->fixed_buf) {
  97. // We can't reallocate, and the caller is expecting the space to
  98. // be there, so the only safe option is to raise an exception.
  99. mp_raise_msg(&mp_type_RuntimeError, NULL);
  100. }
  101. size_t new_alloc = ROUND_ALLOC((vstr->len + size) + 16);
  102. char *new_buf = m_renew(char, vstr->buf, vstr->alloc, new_alloc);
  103. vstr->alloc = new_alloc;
  104. vstr->buf = new_buf;
  105. }
  106. }
  107. void vstr_hint_size(vstr_t *vstr, size_t size) {
  108. vstr_ensure_extra(vstr, size);
  109. }
  110. char *vstr_add_len(vstr_t *vstr, size_t len) {
  111. vstr_ensure_extra(vstr, len);
  112. char *buf = vstr->buf + vstr->len;
  113. vstr->len += len;
  114. return buf;
  115. }
  116. // Doesn't increase len, just makes sure there is a null byte at the end
  117. char *vstr_null_terminated_str(vstr_t *vstr) {
  118. // If there's no more room, add single byte
  119. if (vstr->alloc == vstr->len) {
  120. vstr_extend(vstr, 1);
  121. }
  122. vstr->buf[vstr->len] = '\0';
  123. return vstr->buf;
  124. }
  125. void vstr_add_byte(vstr_t *vstr, byte b) {
  126. byte *buf = (byte*)vstr_add_len(vstr, 1);
  127. buf[0] = b;
  128. }
  129. void vstr_add_char(vstr_t *vstr, unichar c) {
  130. #if MICROPY_PY_BUILTINS_STR_UNICODE
  131. // TODO: Can this be simplified and deduplicated?
  132. // Is it worth just calling vstr_add_len(vstr, 4)?
  133. if (c < 0x80) {
  134. byte *buf = (byte*)vstr_add_len(vstr, 1);
  135. *buf = (byte)c;
  136. } else if (c < 0x800) {
  137. byte *buf = (byte*)vstr_add_len(vstr, 2);
  138. buf[0] = (c >> 6) | 0xC0;
  139. buf[1] = (c & 0x3F) | 0x80;
  140. } else if (c < 0x10000) {
  141. byte *buf = (byte*)vstr_add_len(vstr, 3);
  142. buf[0] = (c >> 12) | 0xE0;
  143. buf[1] = ((c >> 6) & 0x3F) | 0x80;
  144. buf[2] = (c & 0x3F) | 0x80;
  145. } else {
  146. assert(c < 0x110000);
  147. byte *buf = (byte*)vstr_add_len(vstr, 4);
  148. buf[0] = (c >> 18) | 0xF0;
  149. buf[1] = ((c >> 12) & 0x3F) | 0x80;
  150. buf[2] = ((c >> 6) & 0x3F) | 0x80;
  151. buf[3] = (c & 0x3F) | 0x80;
  152. }
  153. #else
  154. vstr_add_byte(vstr, c);
  155. #endif
  156. }
  157. void vstr_add_str(vstr_t *vstr, const char *str) {
  158. vstr_add_strn(vstr, str, strlen(str));
  159. }
  160. void vstr_add_strn(vstr_t *vstr, const char *str, size_t len) {
  161. vstr_ensure_extra(vstr, len);
  162. memmove(vstr->buf + vstr->len, str, len);
  163. vstr->len += len;
  164. }
  165. STATIC char *vstr_ins_blank_bytes(vstr_t *vstr, size_t byte_pos, size_t byte_len) {
  166. size_t l = vstr->len;
  167. if (byte_pos > l) {
  168. byte_pos = l;
  169. }
  170. if (byte_len > 0) {
  171. // ensure room for the new bytes
  172. vstr_ensure_extra(vstr, byte_len);
  173. // copy up the string to make room for the new bytes
  174. memmove(vstr->buf + byte_pos + byte_len, vstr->buf + byte_pos, l - byte_pos);
  175. // increase the length
  176. vstr->len += byte_len;
  177. }
  178. return vstr->buf + byte_pos;
  179. }
  180. void vstr_ins_byte(vstr_t *vstr, size_t byte_pos, byte b) {
  181. char *s = vstr_ins_blank_bytes(vstr, byte_pos, 1);
  182. *s = b;
  183. }
  184. void vstr_ins_char(vstr_t *vstr, size_t char_pos, unichar chr) {
  185. // TODO UNICODE
  186. char *s = vstr_ins_blank_bytes(vstr, char_pos, 1);
  187. *s = chr;
  188. }
  189. void vstr_cut_head_bytes(vstr_t *vstr, size_t bytes_to_cut) {
  190. vstr_cut_out_bytes(vstr, 0, bytes_to_cut);
  191. }
  192. void vstr_cut_tail_bytes(vstr_t *vstr, size_t len) {
  193. if (len > vstr->len) {
  194. vstr->len = 0;
  195. } else {
  196. vstr->len -= len;
  197. }
  198. }
  199. void vstr_cut_out_bytes(vstr_t *vstr, size_t byte_pos, size_t bytes_to_cut) {
  200. if (byte_pos >= vstr->len) {
  201. return;
  202. } else if (byte_pos + bytes_to_cut >= vstr->len) {
  203. vstr->len = byte_pos;
  204. } else {
  205. memmove(vstr->buf + byte_pos, vstr->buf + byte_pos + bytes_to_cut, vstr->len - byte_pos - bytes_to_cut);
  206. vstr->len -= bytes_to_cut;
  207. }
  208. }
  209. void vstr_printf(vstr_t *vstr, const char *fmt, ...) {
  210. va_list ap;
  211. va_start(ap, fmt);
  212. vstr_vprintf(vstr, fmt, ap);
  213. va_end(ap);
  214. }
  215. void vstr_vprintf(vstr_t *vstr, const char *fmt, va_list ap) {
  216. mp_print_t print = {vstr, (mp_print_strn_t)vstr_add_strn};
  217. mp_vprintf(&print, fmt, ap);
  218. }