das2C
das core C utilities (v3)
Loading...
Searching...
No Matches
info_priv.h
1/* Copyright (C) 2026 Chris Piker <chris-piker@uiowa.edu>
2 *
3 * This file is part of das2C, the Core Das2 C Library.
4 *
5 * Das2C is free software; you can redistribute it and/or modify it under
6 * the terms of the GNU Lesser General Public License version 2.1 as published
7 * by the Free Software Foundation.
8 *
9 * Das2C is distributed in the hope that it will be useful, but WITHOUT ANY
10 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public License
15 * version 2.1 along with das2C; if not, see <http://www.gnu.org/licenses/>.
16 */
17
18/* Private helpers for the info and toStr printers. Not installed.
19 *
20 * nNeed is the running length the output would have with unlimited room.
21 * Text goes to sBuf + nNeed while it fits, the buffer is always left NUL
22 * terminated, and counting continues after it fills. So the final nNeed is
23 * exactly what an _info caller must allocate, less the NUL, and a toStr
24 * function knows it was cut off when nNeed >= uLen. A sub-printer can be
25 * composed in with:
26 *
27 * n += Sub_info(pSub, _prn_at(sBuf, uLen, n), _prn_rem(uLen, n));
28 *
29 * nNeed stays an int, as snprintf returns; uLen is a size_t, as snprintf
30 * takes. Comparisons never compute uLen - 1, which wraps when uLen is 0.
31 */
32
33#ifndef _das_info_priv_h_
34#define _das_info_priv_h_
35
36#include <stdarg.h>
37#include <stddef.h>
38#include <stdio.h>
39
40/* Where the next byte goes, or NULL once full; snprintf(NULL, 0, ...) is the
41 standard way to only count, and uLen may be 0 with sBuf NULL. */
42static inline char* _prn_at(char* sBuf, size_t uLen, int nNeed)
43{
44 return ((size_t)nNeed < uLen) ? sBuf + nNeed : NULL;
45}
46
47static inline size_t _prn_rem(size_t uLen, int nNeed)
48{
49 return ((size_t)nNeed < uLen) ? uLen - (size_t)nNeed : 0;
50}
51
52/* Append formatted text, returns the new nNeed */
53static inline int _prn_catf(char* sBuf, size_t uLen, int nNeed, const char* sFmt, ...)
54{
55 va_list ap;
56 va_start(ap, sFmt);
57 int n = vsnprintf(_prn_at(sBuf, uLen, nNeed), _prn_rem(uLen, nNeed), sFmt, ap);
58 va_end(ap);
59 return (n < 0) ? nNeed : nNeed + n;
60}
61
62/* Append sSrc with sIndent inserted after every newline, returns the new
63 nNeed. This is how a container nests a member's multi-line description
64 without the member needing to know its depth. */
65static inline int _prn_catIndent(
66 char* sBuf, size_t uLen, int nNeed, const char* sSrc, const char* sIndent
67){
68 for(const char* p = sSrc; *p != '\0'; ++p){
69 if((size_t)nNeed + 1 < uLen) sBuf[nNeed] = *p;
70 ++nNeed;
71 if(*p == '\n'){
72 for(const char* q = sIndent; *q != '\0'; ++q){
73 if((size_t)nNeed + 1 < uLen) sBuf[nNeed] = *q;
74 ++nNeed;
75 }
76 }
77 }
78 if(uLen > 0) sBuf[((size_t)nNeed < uLen) ? (size_t)nNeed : uLen - 1] = '\0';
79 return nNeed;
80}
81
82/* The toStr ending: sBuf if all nNeed bytes fit, NULL if it was cut off */
83static inline char* _prn_fit(char* sBuf, size_t uLen, int nNeed)
84{
85 return ((nNeed >= 0)&&((size_t)nNeed < uLen)) ? sBuf : NULL;
86}
87
88/* Index tuple printer for error messages, "(i, j, k)", see array.c. It
89 returns sBuf so it can sit inline in a das_error() argument list. */
90char* das_idx_prn(int nRank, ptrdiff_t* pIdx, size_t uLen, char* sBuf);
91
92#endif /* _das_info_priv_h_ */