src/printf.c

Tue, 16 Jan 2024 23:43:27 +0100

author
Mike Becker <universe@uap-core.de>
date
Tue, 16 Jan 2024 23:43:27 +0100
changeset 813
aba6d37b78bd
parent 812
fda0f1910d7e
child 849
edb9f875b7f9
permissions
-rw-r--r--

improve program flow - relates to #353

     1 /*
     2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     3  *
     4  * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved.
     5  *
     6  * Redistribution and use in source and binary forms, with or without
     7  * modification, are permitted provided that the following conditions are met:
     8  *
     9  *   1. Redistributions of source code must retain the above copyright
    10  *      notice, this list of conditions and the following disclaimer.
    11  *
    12  *   2. Redistributions in binary form must reproduce the above copyright
    13  *      notice, this list of conditions and the following disclaimer in the
    14  *      documentation and/or other materials provided with the distribution.
    15  *
    16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    19  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
    20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    26  * POSSIBILITY OF SUCH DAMAGE.
    27  */
    29 #include "cx/printf.h"
    31 #include <stdio.h>
    32 #include <string.h>
    34 #ifndef CX_PRINTF_SBO_SIZE
    35 #define CX_PRINTF_SBO_SIZE 512
    36 #endif
    37 unsigned const cx_printf_sbo_size = CX_PRINTF_SBO_SIZE;
    39 int cx_fprintf(
    40         void *stream,
    41         cx_write_func wfc,
    42         char const *fmt,
    43         ...
    44 ) {
    45     int ret;
    46     va_list ap;
    47     va_start(ap, fmt);
    48     ret = cx_vfprintf(stream, wfc, fmt, ap);
    49     va_end(ap);
    50     return ret;
    51 }
    53 int cx_vfprintf(
    54         void *stream,
    55         cx_write_func wfc,
    56         char const *fmt,
    57         va_list ap
    58 ) {
    59     char buf[CX_PRINTF_SBO_SIZE];
    60     va_list ap2;
    61     va_copy(ap2, ap);
    62     int ret = vsnprintf(buf, CX_PRINTF_SBO_SIZE, fmt, ap);
    63     if (ret < 0) {
    64         va_end(ap2);
    65         return ret;
    66     } else if (ret < CX_PRINTF_SBO_SIZE) {
    67         va_end(ap2);
    68         return (int) wfc(buf, 1, ret, stream);
    69     } else {
    70         int len = ret + 1;
    71         char *newbuf = malloc(len);
    72         if (!newbuf) {
    73             va_end(ap2);
    74             return -1;
    75         }
    77         ret = vsnprintf(newbuf, len, fmt, ap2);
    78         va_end(ap2);
    79         if (ret > 0) {
    80             ret = (int) wfc(newbuf, 1, ret, stream);
    81         }
    82         free(newbuf);
    83     }
    84     return ret;
    85 }
    87 cxmutstr cx_asprintf_a(
    88         CxAllocator const *allocator,
    89         char const *fmt,
    90         ...
    91 ) {
    92     va_list ap;
    93     va_start(ap, fmt);
    94     cxmutstr ret = cx_vasprintf_a(allocator, fmt, ap);
    95     va_end(ap);
    96     return ret;
    97 }
    99 cxmutstr cx_vasprintf_a(
   100         CxAllocator const *a,
   101         char const *fmt,
   102         va_list ap
   103 ) {
   104     cxmutstr s;
   105     s.ptr = NULL;
   106     s.length = 0;
   107     char buf[CX_PRINTF_SBO_SIZE];
   108     va_list ap2;
   109     va_copy(ap2, ap);
   110     int ret = vsnprintf(buf, CX_PRINTF_SBO_SIZE, fmt, ap);
   111     if (ret >= 0 && ret < CX_PRINTF_SBO_SIZE) {
   112         s.ptr = cxMalloc(a, ret + 1);
   113         if (s.ptr) {
   114             s.length = (size_t) ret;
   115             memcpy(s.ptr, buf, ret);
   116             s.ptr[s.length] = '\0';
   117         }
   118     } else {
   119         int len = ret + 1;
   120         s.ptr = cxMalloc(a, len);
   121         if (s.ptr) {
   122             ret = vsnprintf(s.ptr, len, fmt, ap2);
   123             if (ret < 0) {
   124                 free(s.ptr);
   125                 s.ptr = NULL;
   126             } else {
   127                 s.length = (size_t) ret;
   128             }
   129         }
   130     }
   131     va_end(ap2);
   132     return s;
   133 }
   135 int cx_sprintf_a(CxAllocator *alloc, char **str, size_t len, const char *fmt, ... ) {
   136     va_list ap;
   137     va_start(ap, fmt);
   138     int ret = cx_vsprintf_a(alloc, str, len, fmt, ap);
   139     va_end(ap);
   140     return ret;
   141 }
   143 int cx_vsprintf_a(CxAllocator *alloc, char **str, size_t len, const char *fmt, va_list ap) {
   144     va_list ap2;
   145     va_copy(ap2, ap);
   146     int ret = vsnprintf(*str, len, fmt, ap);
   147     if ((unsigned) ret >= len) {
   148         unsigned newlen = ret + 1;
   149         char *ptr = cxRealloc(alloc, *str, newlen);
   150         if (ptr) {
   151             int newret = vsnprintf(ptr, newlen, fmt, ap2);
   152             if (newret < 0) {
   153                 cxFree(alloc, ptr);
   154             } else {
   155                 *str = ptr;
   156                 ret = newret;
   157             }
   158         }
   159     }
   160     va_end(ap2);
   161     return ret;
   162 }
   164 int cx_sprintf_sa(CxAllocator *alloc, char *buf, size_t len, char **str, const char *fmt, ... ) {
   165     va_list ap;
   166     va_start(ap, fmt);
   167     int ret = cx_vsprintf_sa(alloc, buf, len, str, fmt, ap);
   168     va_end(ap);
   169     return ret;
   170 }
   172 int cx_vsprintf_sa(CxAllocator *alloc, char *buf, size_t len, char **str, const char *fmt, va_list ap) {
   173     va_list ap2;
   174     va_copy(ap2, ap);
   175     int ret = vsnprintf(buf, len, fmt, ap);
   176     *str = buf;
   177     if ((unsigned) ret >= len) {
   178         unsigned newlen = ret + 1;
   179         char *ptr = cxMalloc(alloc, newlen);
   180         if (ptr) {
   181             int newret = vsnprintf(ptr, newlen, fmt, ap2);
   182             if (newret < 0) {
   183                 cxFree(alloc, ptr);
   184             } else {
   185                 *str = ptr;
   186                 ret = newret;
   187             }
   188         }
   189     }
   190     va_end(ap2);
   191     return ret;
   192 }

mercurial