// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved. // Use of this source code is governed by an MIT license // that can be found in the LICENSE file. module gen fn (mut g Gen) write_str_fn_definitions() { // _STR function can't be defined in vlib g.writeln(" void _STR_PRINT_ARG(const char *fmt, char** refbufp, int *nbytes, int *memsize, int guess, ...) { va_list args; va_start(args, guess); // NB: (*memsize - *nbytes) === how much free space is left at the end of the current buffer refbufp // *memsize === total length of the buffer refbufp // *nbytes === already occupied bytes of buffer refbufp // guess === how many bytes were taken during the current vsnprintf run for(;;) { if (guess < *memsize - *nbytes) { guess = vsnprintf(*refbufp + *nbytes, *memsize - *nbytes, fmt, args); if (guess < *memsize - *nbytes) { // result did fit into buffer *nbytes += guess; return; } } // increase buffer (somewhat exponentially) *memsize += (*memsize + *memsize) / 3 + guess; *refbufp = realloc(*refbufp, *memsize); } } string _STR(const char *fmt, int nfmts, ...) { va_list argptr; int memsize = 128; int nbytes = 0; char* buf = malloc(memsize); va_start(argptr, nfmts); for (int i=0; i= 'E' && fup <= 'G') { // floating point _STR_PRINT_ARG(fmt, &buf, &nbytes, &memsize, k+10, va_arg(argptr, double)); } else if (f == 'p') { _STR_PRINT_ARG(fmt, &buf, &nbytes, &memsize, k+14, va_arg(argptr, void*)); } else if (f == 's') { // v string string s = va_arg(argptr, string); if (fmt[k-4] == '*') { // %*.*s int fwidth = va_arg(argptr, int); if (fwidth < 0) fwidth -= (s.len - utf8_str_visible_length(s)); else fwidth += (s.len - utf8_str_visible_length(s)); _STR_PRINT_ARG(fmt, &buf, &nbytes, &memsize, k+s.len-4, fwidth, s.len, s.str); } else { // %.*s _STR_PRINT_ARG(fmt, &buf, &nbytes, &memsize, k+s.len-4, s.len, s.str); } } else { //v_panic(tos3('Invaid format specifier')); } } else { _STR_PRINT_ARG(fmt, &buf, &nbytes, &memsize, k); } fmt += k+1; } va_end(argptr); buf[nbytes] = 0; buf = realloc(buf, nbytes+1); #ifdef DEBUG_ALLOC //puts('_STR:'); puts(buf); #endif return tos2(buf); } string _STR_TMP(const char *fmt, ...) { va_list argptr; va_start(argptr, fmt); //size_t len = vsnprintf(0, 0, fmt, argptr) + 1; va_end(argptr); va_start(argptr, fmt); vsprintf((char *)g_str_buf, fmt, argptr); va_end(argptr); #ifdef DEBUG_ALLOC //puts('_STR_TMP:'); //puts(g_str_buf); #endif return tos2(g_str_buf); } // endof _STR_TMP ") }