das2C
das core C utilities (v3)
Loading...
Searching...
No Matches
var_priv.h
Go to the documentation of this file.
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
34#ifndef _das_var_priv_h_
35#define _das_var_priv_h_
36
37#include <das3/form.h> /* das_operand */
38#include <das3/variable.h>
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44/* Naming inside this table follows what a caller can reach.
45 *
46 * A slot with a variable.h entry dispatching straight to it is a public
47 * virtual member in all but syntax -- were this C++ there would be no explicit
48 * table and no question -- so its implementations carry no underscore:
49 * DasVarBytes_get, DasVarComp_intrShape, DasVarGen_lengthIn. Changing one of
50 * those changes behavior a user of DasVar sees.
51 *
52 * itemElems, subsetView and subsetInto have no such entry. They exist for
53 * _DasVar_subset() to divide the work, so their implementations keep the
54 * underscore: _DasVarGen_subsetInto, _DasVarBin_itemElems. Nothing outside
55 * this layer can call them by any route. */
56typedef struct DasVar_VTbl {
57
58 /* Read one value at a full external index into a datum.
59 *
60 * work is caller scratch, used ONLY when there is no storage to point at.
61 * Returns 0 on success, the bytes of scratch needed if work is too small,
62 * and a negative error code otherwise. See DasVar_get(). */
63 int (*get)(
64 const DasVar* pThis, ptrdiff_t* pLoc, das_byte_seq work, das_datum* pOut
65 );
66
67 /* The wire element this class serializes as: "scalar", "composite",
68 "bytes". Axis C lives on the class, so the serializer asks the class
69 rather than deriving structure back out of a presentation vocabulary. */
70 const char* (*element)(const DasVar* pThis);
71
72 das_elem_type (*elemType)(const DasVar* pThis); /* asks the generator */
73
74 int (*shape)(const DasVar* pThis, ptrdiff_t* pShape); /* full shape */
75 int (*intrShape)(const DasVar* pThis, ptrdiff_t* pShape); /* internal only */
76
77 /* How many items exist along external index nIdx at the location pLoc.
78 *
79 * The question ragged data forces: record 5 may hold 1400 frequency bins
80 * and record 6 only 1380, so a shape cannot answer it and the caller has
81 * to name a place.
82 *
83 * A vtable slot rather than one shared implementation because the classes
84 * answer differently. Anything built on a generator just asks it. A
85 * DasVarBin has no generator -- its values are computed from two operands
86 * -- so it asks both and takes the SMALLER real length.
87 *
88 * That minimum is a rule about live reads, not a safety margin. Two
89 * variables fill in different-sized blocks as a stream arrives, so at any
90 * instant the range over which BOTH actually have data is the shorter one.
91 * Operands disagreeing about length is a normal mid-stream state, not an
92 * error. das_varlength_merge() is where that lives.
93 */
94 ptrdiff_t (*lengthIn)(const DasVar* pThis, int nIdx, ptrdiff_t* pLoc);
95
96 /* Elements per item: 1 for a scalar, 3 for a vector, 9 for a 3;3 matrix,
97 * 0 when the run is ragged and has no fixed width.
98 *
99 * A slot because the answer has two sources. Anything built on a
100 * generator asks it; a DasVarBin has none and takes the count from the
101 * recipe, since the math can change the item shape (3;3 times 3 gives 3). */
102 size_t (*itemElems)(const DasVar* pThis);
103
104 /* Hand back a VIEW onto existing storage for an external range, or NULL.
105 *
106 * NULL is a complete answer meaning "not me, allocate and call subsetInto"
107 * -- exactly what _DasGen_subsetViewNone says one layer down for every
108 * computed generator. Only array-backed storage can lend memory. */
109 DasAry* (*subsetView)(
110 const DasVar* pThis, int nExtRank, const ptrdiff_t* pMin,
111 const ptrdiff_t* pMax
112 );
113
114 /* Materialize an external range into a caller-supplied buffer.
115 *
116 * A slot for the same reason: the shared implementation reads bytes out of
117 * a generator, and a computed variable has none to read from. It walks
118 * its two operands instead and applies the recipe as it goes. */
119 int (*subsetInto)(
120 const DasVar* pThis, int nExtRank, const ptrdiff_t* pMin,
121 const ptrdiff_t* pMax, ubyte* pBuf, size_t uBufLen
122 );
123
124 /* The first section of DasVar_toStr(): where the values come from. A
125 bare array id with its index map, or a parenthesized expression for a
126 computed value. Element type, units, ranges and formalism are appended
127 by the base, since every class answers those the same way. */
128 char* (*prnGen)(const DasVar* pThis, char* sBuf, int nLen);
129
130 bool (*isNumeric)(const DasVar* pThis);
131
132 int (*incRef)(DasVar* pThis);
133 int (*decRef)(DasVar* pThis);
134 DasVar* (*copy)(const DasVar* pThis);
135
136} DasVar_VTbl;
137
138/* Snapshot this variable's facts for the formalism layer.
139 *
140 * A form never reaches up into a DasVar; it is handed one of these, built from
141 * live facts at the moment of the call. That is what keeps form_*.c free of
142 * variable.h and what makes a stale cached element type impossible.
143 *
144 * Only the variable layer builds one of these. A formalism RECEIVES a
145 * das_operand in binOpLeft/binOpRight and never has cause to make one, which
146 * is why this is not public even though das_operand is.
147 *
148 * @param pThis the variable to describe
149 * @param pOut receives the snapshot
150 * @returns false if the variable has no formalism (a byte run), which is also
151 * the answer to "may this participate in arithmetic".
152 */
153bool _DasVar_operand(const DasVar* pThis, das_operand* pOut);
154
155/* Bytes in ONE item of this variable, or 0 when the run is ragged and the
156 * width is a property of the location rather than the variable. */
157size_t _DasVar_itemBytes(const DasVar* pThis);
158
159/* Scratch bytes DasVar_get() needs to produce one item, 0 when every run
160 * involved can be pointed at in place. Recurses through operation operands,
161 * since a nested operation needs room for its own result too. */
162size_t _DasVar_runScratch(const DasVar* pThis);
163
164/* One item run at one location.
165 *
166 * Hands back a pointer to the run and the bytes in it. That pointer is the
167 * variable's OWN storage when it has any -- das2C lends rather than copies --
168 * and pScratch otherwise. Returns NULL having set *pNeed when the scratch is
169 * too small, or NULL with *pNeed 0 on a loud error. */
170const ubyte* _DasVar_runAt(
171 const DasVar* pThis, ptrdiff_t* pLoc, ubyte* pScratch, size_t uScratch,
172 size_t* pBytes, size_t* pNeed
173);
174
175/* One item run of a binary operation, the class with no generator to read
176 * from. _DasVar_runAt() dispatches here so a nested operation reads its
177 * operands through the same call. */
178const ubyte* _DasVarBin_runAt(
179 const DasVar* pBase, ptrdiff_t* pLoc, ubyte* pScratch, size_t uScratch,
180 size_t* pBytes, size_t* pNeed
181);
182
183#ifdef __cplusplus
184}
185#endif
186
187#endif /* _das_var_priv_h_ */
What a variable's values (i.e.
Dynamic recursive ragged arrays.
Definition array.h:271
The form layer's currency: a snapshot of the facts a formalism may need.
Definition form.h:139
The DasVar layer: named values with formalisms.