sstream.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. #include "pocketpy/common/sstream.h"
  2. #include "pocketpy/common/str.h"
  3. #include "pocketpy/common/utils.h"
  4. #include "pocketpy/pocketpy.h"
  5. #include <stdarg.h>
  6. #include <stdio.h>
  7. #include <assert.h>
  8. #include <ctype.h>
  9. #include <math.h>
  10. void c11_sbuf__ctor(c11_sbuf* self) {
  11. c11_vector__ctor(&self->data, sizeof(char));
  12. c11_vector__reserve(&self->data, sizeof(c11_string) + 100);
  13. self->data.length = sizeof(c11_string);
  14. }
  15. void c11_sbuf__dtor(c11_sbuf* self) { c11_vector__dtor(&self->data); }
  16. void c11_sbuf__write_char(c11_sbuf* self, char c) { c11_vector__push(char, &self->data, c); }
  17. void c11_sbuf__write_pad(c11_sbuf* self, int count, char pad) {
  18. for(int i = 0; i < count; i++) {
  19. c11_sbuf__write_char(self, pad);
  20. }
  21. }
  22. void c11_sbuf__write_int(c11_sbuf* self, int i) {
  23. // len('-2147483648') == 11
  24. c11_vector__reserve(&self->data, self->data.length + 11 + 1);
  25. char* p = (char*)self->data.data + self->data.length;
  26. int n = snprintf(p, 11 + 1, "%d", i);
  27. self->data.length += n;
  28. }
  29. void c11_sbuf__write_i64(c11_sbuf* self, int64_t val) {
  30. // len('-9223372036854775808') == 20
  31. c11_vector__reserve(&self->data, self->data.length + 20 + 1);
  32. char* p = (char*)self->data.data + self->data.length;
  33. int n = snprintf(p, 20 + 1, "%lld", (long long)val);
  34. self->data.length += n;
  35. }
  36. void c11_sbuf__write_f64(c11_sbuf* self, double val, int precision) {
  37. if(isinf(val)) {
  38. c11_sbuf__write_cstr(self, val > 0 ? "inf" : "-inf");
  39. return;
  40. }
  41. if(isnan(val)) {
  42. c11_sbuf__write_cstr(self, "nan");
  43. return;
  44. }
  45. char b[32];
  46. int size;
  47. if(precision < 0) {
  48. int prec = 17 - 1; // std::numeric_limits<double>::max_digits10 == 17
  49. size = snprintf(b, sizeof(b), "%.*g", prec, val);
  50. } else {
  51. int prec = precision;
  52. size = snprintf(b, sizeof(b), "%.*f", prec, val);
  53. }
  54. c11_sbuf__write_cstr(self, b);
  55. bool all_is_digit = true;
  56. for(int i = 1; i < size; i++) {
  57. if(!isdigit(b[i])) {
  58. all_is_digit = false;
  59. break;
  60. }
  61. }
  62. if(all_is_digit) c11_sbuf__write_cstr(self, ".0");
  63. }
  64. void c11_sbuf__write_sv(c11_sbuf* self, c11_sv sv) {
  65. c11_sbuf__write_cstrn(self, sv.data, sv.size);
  66. }
  67. void c11_sbuf__write_cstr(c11_sbuf* self, const char* str) {
  68. c11_sbuf__write_cstrn(self, str, strlen(str));
  69. }
  70. void c11_sbuf__write_cstrn(c11_sbuf* self, const char* str, int n) {
  71. c11_vector__extend(char, &self->data, str, n);
  72. }
  73. void c11_sbuf__write_quoted(c11_sbuf* self, c11_sv sv, char quote) {
  74. assert(quote == '"' || quote == '\'');
  75. c11_sbuf__write_char(self, quote);
  76. for(int i = 0; i < sv.size; i++) {
  77. char c = sv.data[i];
  78. switch(c) {
  79. case '"':
  80. case '\'':
  81. if(c == quote) c11_sbuf__write_char(self, '\\');
  82. c11_sbuf__write_char(self, c);
  83. break;
  84. case '\\': c11_sbuf__write_cstrn(self, "\\\\", 2); break;
  85. case '\n': c11_sbuf__write_cstrn(self, "\\n", 2); break;
  86. case '\r': c11_sbuf__write_cstrn(self, "\\r", 2); break;
  87. case '\t': c11_sbuf__write_cstrn(self, "\\t", 2); break;
  88. case '\b': c11_sbuf__write_cstrn(self, "\\b", 2); break;
  89. default:
  90. if('\x00' <= c && c <= '\x1f') {
  91. c11_sbuf__write_cstrn(self, "\\x", 2);
  92. c11_sbuf__write_char(self, PK_HEX_TABLE[c >> 4]);
  93. c11_sbuf__write_char(self, PK_HEX_TABLE[c & 0xf]);
  94. } else {
  95. c11_sbuf__write_char(self, c);
  96. }
  97. }
  98. }
  99. c11_sbuf__write_char(self, quote);
  100. }
  101. void c11_sbuf__write_hex(c11_sbuf* self, unsigned char c, bool non_zero) {
  102. unsigned char high = c >> 4;
  103. unsigned char low = c & 0xf;
  104. if(non_zero) {
  105. if(high) c11_sbuf__write_char(self, PK_HEX_TABLE[high]);
  106. if(high || low) c11_sbuf__write_char(self, PK_HEX_TABLE[low]);
  107. } else {
  108. c11_sbuf__write_char(self, PK_HEX_TABLE[high]);
  109. c11_sbuf__write_char(self, PK_HEX_TABLE[low]);
  110. }
  111. }
  112. void c11_sbuf__write_ptr(c11_sbuf* self, void* p) {
  113. if(p == NULL) {
  114. c11_sbuf__write_cstr(self, "0x0");
  115. return;
  116. }
  117. c11_sbuf__write_cstr(self, "0x");
  118. uintptr_t p_t = (uintptr_t)(p);
  119. bool non_zero = true;
  120. for(int i = sizeof(void*) - 1; i >= 0; i--) {
  121. unsigned char cpnt = (p_t >> (i * 8)) & 0xff;
  122. c11_sbuf__write_hex(self, cpnt, non_zero);
  123. if(cpnt != 0) non_zero = false;
  124. }
  125. }
  126. c11_string* c11_sbuf__submit(c11_sbuf* self) {
  127. c11_vector__push(char, &self->data, '\0');
  128. c11_array arr = c11_vector__submit(&self->data);
  129. c11_string* retval = arr.data;
  130. retval->size = arr.length - sizeof(c11_string) - 1;
  131. return retval;
  132. }
  133. void c11_sbuf__py_submit(c11_sbuf* self, py_Ref out) {
  134. c11_string* res = c11_sbuf__submit(self);
  135. py_newstrn(out, res->data, res->size);
  136. c11_string__delete(res);
  137. }
  138. void pk_vsprintf(c11_sbuf* ss, const char* fmt, va_list args) {
  139. while(*fmt) {
  140. char c = *fmt;
  141. if(c != '%') {
  142. c11_sbuf__write_char(ss, c);
  143. fmt++;
  144. continue;
  145. }
  146. fmt++;
  147. c = *fmt;
  148. switch(c) {
  149. case 'd': {
  150. int i = va_arg(args, int);
  151. c11_sbuf__write_int(ss, i);
  152. break;
  153. }
  154. case 'i': {
  155. int64_t i = va_arg(args, int64_t);
  156. c11_sbuf__write_i64(ss, i);
  157. break;
  158. }
  159. case 'f': {
  160. double d = va_arg(args, double);
  161. c11_sbuf__write_f64(ss, d, -1);
  162. break;
  163. }
  164. case 's': {
  165. const char* s = va_arg(args, const char*);
  166. c11_sbuf__write_cstr(ss, s);
  167. break;
  168. }
  169. case 'q': {
  170. c11_sv sv = va_arg(args, c11_sv);
  171. c11_sbuf__write_quoted(ss, sv, '\'');
  172. break;
  173. }
  174. case 'v': {
  175. c11_sv sv = va_arg(args, c11_sv);
  176. c11_sbuf__write_sv(ss, sv);
  177. break;
  178. }
  179. case 'c': {
  180. char c = va_arg(args, int);
  181. c11_sbuf__write_char(ss, c);
  182. break;
  183. }
  184. case 'p': {
  185. void* p = va_arg(args, void*);
  186. c11_sbuf__write_ptr(ss, p);
  187. break;
  188. }
  189. case 't': {
  190. py_Type t = va_arg(args, int);
  191. c11_sbuf__write_cstr(ss, py_tpname(t));
  192. break;
  193. }
  194. case 'n': {
  195. py_Name n = va_arg(args, int);
  196. c11_sbuf__write_cstr(ss, py_name2str(n));
  197. break;
  198. }
  199. case '%': c11_sbuf__write_char(ss, '%'); break;
  200. default:
  201. c11_sbuf__write_char(ss, c);
  202. assert(false); // invalid format
  203. break;
  204. }
  205. fmt++;
  206. }
  207. }
  208. void pk_sprintf(c11_sbuf* ss, const char* fmt, ...) {
  209. va_list args;
  210. va_start(args, fmt);
  211. pk_vsprintf(ss, fmt, args);
  212. va_end(args);
  213. }
  214. int py_replinput(char* buf, int max_size) {
  215. buf[0] = '\0'; // reset first char because we check '@' at the beginning
  216. int size = 0;
  217. bool multiline = false;
  218. printf(">>> ");
  219. while(true) {
  220. char c = getchar();
  221. if(c == EOF) break;
  222. if(c == '\n') {
  223. char last = '\0';
  224. if(size > 0) last = buf[size - 1];
  225. if(multiline) {
  226. if(last == '\n') {
  227. break; // 2 consecutive newlines to end multiline input
  228. } else {
  229. printf("... ");
  230. }
  231. } else {
  232. if(last == ':' || last == '(' || last == '[' || last == '{' || buf[0] == '@') {
  233. printf("... ");
  234. multiline = true;
  235. } else {
  236. break;
  237. }
  238. }
  239. }
  240. if(size == max_size - 1) {
  241. buf[size] = '\0';
  242. return size;
  243. }
  244. buf[size++] = c;
  245. }
  246. buf[size] = '\0';
  247. return size;
  248. }