src/printf.c

Tue, 16 Jan 2024 23:16:15 +0100

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

fix unnecessary printf retry when printed string is empty

     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 (ret < 0 || ((unsigned)ret) < len) {
   148         va_end(ap2);
   149         return ret;
   150     } else {
   151         unsigned newlen = ret + 1;
   152         char *ptr = cxRealloc(alloc, *str, newlen);
   153         if (ptr) {
   154             int newret = vsnprintf(ptr, newlen, fmt, ap2);
   155             va_end(ap2);
   156             if (newret < 0) {
   157                 cxFree(alloc, ptr);
   158                 return ret;
   159             } else {
   160                 *str = ptr;
   161                 return newret;
   162             }
   163         } else {
   164             va_end(ap2);
   165             return ret;
   166         }
   167     }
   168 }
   170 int cx_sprintf_sa(CxAllocator *alloc, char *buf, size_t len, char **str, const char *fmt, ... ) {
   171     va_list ap;
   172     va_start(ap, fmt);
   173     int ret = cx_vsprintf_sa(alloc, buf, len, str, fmt, ap);
   174     va_end(ap);
   175     return ret;
   176 }
   178 int cx_vsprintf_sa(CxAllocator *alloc, char *buf, size_t len, char **str, const char *fmt, va_list ap) {
   179     va_list ap2;
   180     va_copy(ap2, ap);
   181     int ret = vsnprintf(buf, len, fmt, ap);
   182     *str = buf;
   183     if (ret < 0 || ((unsigned)ret) < len) {
   184         va_end(ap2);
   185         return ret;
   186     } else {
   187         unsigned newlen = ret + 1;
   188         char *ptr = cxMalloc(alloc, newlen);
   189         if (ptr) {
   190             int newret = vsnprintf(ptr, newlen, fmt, ap2);
   191             va_end(ap2);
   192             if (newret < 0) {
   193                 cxFree(alloc, ptr);
   194                 return ret;
   195             } else {
   196                 *str = ptr;
   197                 return newret;
   198             }
   199         } else {
   200             va_end(ap2);
   201             return ret;
   202         }
   203     }
   204 }

mercurial