vstr.c 7.4 KB

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