| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276 |
- #include "pocketpy/common/sstream.h"
- #include "pocketpy/common/str.h"
- #include "pocketpy/common/utils.h"
- #include "pocketpy/pocketpy.h"
- #include <stdarg.h>
- #include <stdio.h>
- #include <assert.h>
- #include <ctype.h>
- #include <math.h>
- void c11_sbuf__ctor(c11_sbuf* self) {
- c11_vector__ctor(&self->data, sizeof(char));
- c11_vector__reserve(&self->data, sizeof(c11_string) + 100);
- self->data.length = sizeof(c11_string);
- }
- void c11_sbuf__dtor(c11_sbuf* self) { c11_vector__dtor(&self->data); }
- void c11_sbuf__write_char(c11_sbuf* self, char c) { c11_vector__push(char, &self->data, c); }
- void c11_sbuf__write_pad(c11_sbuf* self, int count, char pad) {
- for(int i = 0; i < count; i++) {
- c11_sbuf__write_char(self, pad);
- }
- }
- void c11_sbuf__write_int(c11_sbuf* self, int i) {
- // len('-2147483648') == 11
- c11_vector__reserve(&self->data, self->data.length + 11 + 1);
- char* p = (char*)self->data.data + self->data.length;
- int n = snprintf(p, 11 + 1, "%d", i);
- self->data.length += n;
- }
- void c11_sbuf__write_i64(c11_sbuf* self, int64_t val) {
- // len('-9223372036854775808') == 20
- c11_vector__reserve(&self->data, self->data.length + 20 + 1);
- char* p = (char*)self->data.data + self->data.length;
- int n = snprintf(p, 20 + 1, "%lld", (long long)val);
- self->data.length += n;
- }
- void c11_sbuf__write_f64(c11_sbuf* self, double val, int precision) {
- if(isinf(val)) {
- c11_sbuf__write_cstr(self, val > 0 ? "inf" : "-inf");
- return;
- }
- if(isnan(val)) {
- c11_sbuf__write_cstr(self, "nan");
- return;
- }
- char b[32];
- int size;
- if(precision < 0) {
- int prec = 17 - 1; // std::numeric_limits<double>::max_digits10 == 17
- size = snprintf(b, sizeof(b), "%.*g", prec, val);
- } else {
- int prec = precision;
- size = snprintf(b, sizeof(b), "%.*f", prec, val);
- }
- c11_sbuf__write_cstr(self, b);
- bool all_is_digit = true;
- for(int i = 1; i < size; i++) {
- if(!isdigit(b[i])) {
- all_is_digit = false;
- break;
- }
- }
- if(all_is_digit) c11_sbuf__write_cstr(self, ".0");
- }
- void c11_sbuf__write_sv(c11_sbuf* self, c11_sv sv) {
- c11_sbuf__write_cstrn(self, sv.data, sv.size);
- }
- void c11_sbuf__write_cstr(c11_sbuf* self, const char* str) {
- c11_sbuf__write_cstrn(self, str, strlen(str));
- }
- void c11_sbuf__write_cstrn(c11_sbuf* self, const char* str, int n) {
- c11_vector__extend(char, &self->data, str, n);
- }
- void c11_sbuf__write_quoted(c11_sbuf* self, c11_sv sv, char quote) {
- assert(quote == '"' || quote == '\'');
- c11_sbuf__write_char(self, quote);
- for(int i = 0; i < sv.size; i++) {
- char c = sv.data[i];
- switch(c) {
- case '"':
- case '\'':
- if(c == quote) c11_sbuf__write_char(self, '\\');
- c11_sbuf__write_char(self, c);
- break;
- case '\\': c11_sbuf__write_cstrn(self, "\\\\", 2); break;
- case '\n': c11_sbuf__write_cstrn(self, "\\n", 2); break;
- case '\r': c11_sbuf__write_cstrn(self, "\\r", 2); break;
- case '\t': c11_sbuf__write_cstrn(self, "\\t", 2); break;
- case '\b': c11_sbuf__write_cstrn(self, "\\b", 2); break;
- default:
- if(!isprint(c)) {
- unsigned char uc = (unsigned char)c;
- c11_sbuf__write_cstrn(self, "\\x", 2);
- c11_sbuf__write_char(self, PK_HEX_TABLE[uc >> 4]);
- c11_sbuf__write_char(self, PK_HEX_TABLE[uc & 0xf]);
- } else {
- c11_sbuf__write_char(self, c);
- }
- }
- }
- c11_sbuf__write_char(self, quote);
- }
- void c11_sbuf__write_hex(c11_sbuf* self, unsigned char c, bool non_zero) {
- unsigned char high = c >> 4;
- unsigned char low = c & 0xf;
- if(non_zero) {
- if(high) c11_sbuf__write_char(self, PK_HEX_TABLE[high]);
- if(high || low) c11_sbuf__write_char(self, PK_HEX_TABLE[low]);
- } else {
- c11_sbuf__write_char(self, PK_HEX_TABLE[high]);
- c11_sbuf__write_char(self, PK_HEX_TABLE[low]);
- }
- }
- void c11_sbuf__write_ptr(c11_sbuf* self, void* p) {
- if(p == NULL) {
- c11_sbuf__write_cstr(self, "0x0");
- return;
- }
- c11_sbuf__write_cstr(self, "0x");
- uintptr_t p_t = (uintptr_t)(p);
- bool non_zero = true;
- for(int i = sizeof(void*) - 1; i >= 0; i--) {
- unsigned char cpnt = (p_t >> (i * 8)) & 0xff;
- c11_sbuf__write_hex(self, cpnt, non_zero);
- if(cpnt != 0) non_zero = false;
- }
- }
- c11_string* c11_sbuf__submit(c11_sbuf* self) {
- c11_vector__push(char, &self->data, '\0');
- int arr_length;
- c11_string* retval = c11_vector__submit(&self->data, &arr_length);
- retval->size = arr_length - sizeof(c11_string) - 1;
- return retval;
- }
- void c11_sbuf__py_submit(c11_sbuf* self, py_Ref out) {
- c11_string* res = c11_sbuf__submit(self);
- py_newstrv(out, (c11_sv){res->data, res->size});
- c11_string__delete(res);
- }
- void pk_vsprintf(c11_sbuf* ss, const char* fmt, va_list args) {
- while(*fmt) {
- char c = *fmt;
- if(c != '%') {
- c11_sbuf__write_char(ss, c);
- fmt++;
- continue;
- }
- fmt++;
- c = *fmt;
- switch(c) {
- case 'd': {
- int i = va_arg(args, int);
- c11_sbuf__write_int(ss, i);
- break;
- }
- case 'i': {
- int64_t i = va_arg(args, int64_t);
- c11_sbuf__write_i64(ss, i);
- break;
- }
- case 'f': {
- double d = va_arg(args, double);
- c11_sbuf__write_f64(ss, d, -1);
- break;
- }
- case 's': {
- const char* s = va_arg(args, const char*);
- c11_sbuf__write_cstr(ss, s);
- break;
- }
- case 'q': {
- c11_sv sv = va_arg(args, c11_sv);
- c11_sbuf__write_quoted(ss, sv, '\'');
- break;
- }
- case 'v': {
- c11_sv sv = va_arg(args, c11_sv);
- c11_sbuf__write_sv(ss, sv);
- break;
- }
- case 'c': {
- char c = va_arg(args, int);
- c11_sbuf__write_char(ss, c);
- break;
- }
- case 'p': {
- void* p = va_arg(args, void*);
- c11_sbuf__write_ptr(ss, p);
- break;
- }
- case 't': {
- py_Type t = va_arg(args, int);
- c11_sbuf__write_cstr(ss, py_tpname(t));
- break;
- }
- case 'n': {
- py_Name n = va_arg(args, int);
- c11_sbuf__write_cstr(ss, py_name2str(n));
- break;
- }
- case '%': c11_sbuf__write_char(ss, '%'); break;
- default:
- c11_sbuf__write_char(ss, c);
- assert(false); // invalid format
- break;
- }
- fmt++;
- }
- }
- void pk_sprintf(c11_sbuf* ss, const char* fmt, ...) {
- va_list args;
- va_start(args, fmt);
- pk_vsprintf(ss, fmt, args);
- va_end(args);
- }
- int py_replinput(char* buf, int max_size) {
- buf[0] = '\0'; // reset first char because we check '@' at the beginning
- int size = 0;
- bool multiline = false;
- printf(">>> ");
- while(true) {
- char c = getchar();
- if(c == EOF) break;
- if(c == '\n') {
- char last = '\0';
- if(size > 0) last = buf[size - 1];
- if(multiline) {
- if(last == '\n') {
- break; // 2 consecutive newlines to end multiline input
- } else {
- printf("... ");
- }
- } else {
- if(last == ':' || last == '(' || last == '[' || last == '{' || buf[0] == '@') {
- printf("... ");
- multiline = true;
- } else {
- break;
- }
- }
- }
- if(size == max_size - 1) {
- buf[size] = '\0';
- return size;
- }
- buf[size++] = c;
- }
- buf[size] = '\0';
- return size;
- }
|