das2C
das core C utilities (v3)
Loading...
Searching...
No Matches
array.h
Go to the documentation of this file.
1/* Copyright (C) 2017-2024 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
20/* I'm sure this kind of buffer has been done many times before, but I haven't
21 * seen an implementation that handles arbitrarily ragged arrays. Thanks to
22 * Larry Granroth, and Matt Leifert for helping me talk through the issues
23 * around this class.
24 * -cwp
25 */
26
27#ifndef _das_array_h_
28#define _das_array_h_
29
30#include <stdarg.h>
31#include <stddef.h>
32#include <stdint.h>
33#include <stdbool.h>
34
35#include <das3/value.h>
36#include <das3/units.h>
37
38#ifdef __cplusplus
39extern "C" {
40#endif
41
43#define ARYIDX_MAX 8
44
46#define ARYIDX_LAST {-1,-1,-1,-1,-1,-1,-1,-1}
47
52#define ARYIDX_UNBOUND 0
53
55#define VARIDX_RAGGED -1
56
59DAS_API extern const char g_sIdxLower[ARYIDX_MAX];
60DAS_API extern const char g_sIdxUpper[ARYIDX_MAX];
61
62#define RANK_1(I) 1, (size_t[1]){I}
63#define RANK_2(I, J) 2, (size_t[2]){I, J}
64#define RANK_3(I, J, K) 3, (size_t[3]){I, J, K}
65#define RANK_4(I, J, K, L) 4, (size_t[4]){I, J, K, L}
66#define RANK_5(I, J, K, L, M) 5, (size_t[5]){I, J, K, L, M}
67#define RANK_6(I, J, K, L, M, N) 6, (size_t[6]){I, J, K, L, M, N}
68#define RANK_7(I, J, K, L, M, N, O) 7, (size_t[7]){I, J, K, L, M, N, O}
69#define RANK_8(I, J, K, L, M, N, O, P) 8, (size_t[8]){I, J, K, L, M, N, O, P}
70
71#define DIM0 0, (NULL)
72#define DIM1_AT(I) 1, (ptrdiff_t[1]){I}
73#define DIM2_AT(I,J) 2, (ptrdiff_t[2]){I,J}
74#define DIM3_AT(I,J,K) 3, (ptrdiff_t[3]){I,J,K}
75#define DIM4_AT(I,J,K,L) 4, (ptrdiff_t[4]){I,J,K,L}
76#define DIM5_AT(I,J,K,L,M) 5, (ptrdiff_t[5]){I,J,K,L,M}
77#define DIM6_AT(I,J,K,L,M,N) 6, (ptrdiff_t[6]){I,J,K,L,M,N}
78#define DIM7_AT(I,J,K,L,M,N,O) 7, (ptrdiff_t[7]){I,J,K,L,M,N,O}
79
80#define IDX0(I) (ptrdiff_t[1]){I}
81#define IDX1(I,J) (ptrdiff_t[2]){I,J}
82#define IDX2(I,J,K) (ptrdiff_t[3]){I,J,K}
83#define IDX3(I,J,K,L) (ptrdiff_t[4]){I,J,K,L}
84#define IDX4(I,J,K,L,M) (ptrdiff_t[5]){I,J,K,L,M}
85#define IDX5(I,J,K,L,M,N) (ptrdiff_t[6]){I,J,K,L,M,N}
86#define IDX6(I,J,K,L,M,N,O) (ptrdiff_t[7]){I,J,K,L,M,N,O}
87#define IDX7(I,J,K,L,M,N,O,P) (ptrdiff_t[8]){I,J,K,L,M,N,O,P}
88
89#define DIM1 1
90#define DIM2 2
91#define DIM3 3
92#define DIM4 4
93#define DIM5 5
94#define DIM6 6
95#define DIM7 7
96
97#define RNG_1(i,I) 1, (ptrdiff_t[1]){i}, (ptrdiff_t[1]){I}
98#define RNG_2(i,I,j,J) 2, (ptrdiff_t[2]){i,j}, (ptrdiff_t[2]){I,J}
99#define RNG_3(i,I,j,J,k,K) 3, (ptrdiff_t[3]){i,j,k}, (ptrdiff_t[3]){I,J,K}
100#define RNG_4(i,I,j,J,k,K,l,L) 4, (ptrdiff_t[4]){i,j,k,l}, (ptrdiff_t[4]){I,J,K,L}
101#define RNG_5(i,I,j,J,k,K,l,L,m,M) 5, (ptrdiff_t[5]){i,j,k,l,m}, (ptrdiff_t[5]){I,J,K,L,M}
102#define RNG_6(i,I,j,J,k,K,l,L,m,M,n,N) 6, (ptrdiff_t[6]){i,j,k,l,m,n}, (ptrdiff_t[6]){I,J,K,L,M,N}
103#define RNG_7(i,I,j,J,k,K,l,L,m,M,n,N,o,O) 7, (ptrdiff_t[7]){i,j,k,l,m,n,o}, (ptrdiff_t[7]){I,J,K,L,M,N,O}
104
131DAS_API int das_rng2shape(
132 int nRngRank, const ptrdiff_t* pMin, const ptrdiff_t* pMax, size_t* pShape
133);
134
137/* Higher dimensions are handled by index buffers. These are the elements for
138 * the index buffers */
139typedef struct child_info_t{
140 ptrdiff_t nOffset; /* Start of child elements data in child buffer */
141 size_t uCount; /* The count child elements in child buffer */
142}das_idx_info;
143
144typedef struct dyna_buf{
145
146 ubyte* pBuf; /* The beginning a continuous buffer uSize long */
147 ubyte* pHead; /* The beginning of valid values in the buffer */
148 /*ubyte* pWrite;*/ /* The beginning of the append point for the buffer */
149 size_t uSize; /* The amount of space in the backing buffer */
150 size_t uValid; /* The number of valid elements in this buffer */
151 size_t uElemSz; /* The number of bytes occupied by each element */
152
153 ubyte* pFill; /* Pointer to fill value buffer */
154 ubyte fillBuf[sizeof(das_idx_info)]; /* Storage for short fill items */
155
156 size_t uChunkSz; /* Alloc helper, if set, allocate in even chunks
157 * of this size. */
158 size_t uShape; /* Qube helper, how many items in this array per
159 * parent item, 0 means ragged */
160 das_val_type etype; /* The element type */
161
162 bool bRollParent; /* The end mark. If set, adding data to the array
163 * will clear the end mark and trigger creation of
164 * a new parent. If this is set on all indexes
165 * attempting to add data will fail */
166
167 bool bKeepMem; /* If true memory will not be deleted when the
168 * buffer is deleted */
169
170} DynaBuf;
171
243typedef struct das_array {
244 char sId[DAS_MAX_ID_BUFSZ]; /* A text identifier of this instance of the array */
245 int nRank; /* The number of index dimensions for the array */
246 das_idx_info* pIdx0; /* top lever container, may not point here */
247
248 /* bool bTopOwned;*/ /* Same as pIdx0 == &index0 */
249 das_idx_info index0; /* Storage for element 0 of buffer 0, if needed */
250
251 /* Pointers to item arrays. One array is needed for each dimension,
252 * these may point to internal locations if the array is owned */
253 DynaBuf* pBufs[ARYIDX_MAX];
254
255 /* bool bOwned[16]; */ /* Same as pBufs[i] == &(bufs[i]) */
256 DynaBuf bufs[ARYIDX_MAX]; /* Storage for dynamic buffers, if needed */
257
258 /* Current compare function, set automatically if a known type is used,
259 * otherwise user needs to supply their own */
260 int (*compare)(const ubyte* vpFirst, const ubyte* vpSecond);
261
262 /* Where to send/read data when streaming */
263 int nSrcPktId;
264 size_t uStartItem;
265 size_t uItems;
266
267 /* Since so many datasets and functions can reference the same array,
268 * a reference count is needed to make sure they aren't deleted if
269 * still in use. */
270 int refcount;
271
272 /* Used to notify the owner of my memory that I'm not using it anymore. */
273 struct das_array* pMemOwner;
274
275 unsigned int uFlags; /* Store flags indicating intended use */
276
277 das_units units;
278
286 void* pUser;
287
288} DasAry;
289
366 const char* id, das_val_type et, size_t sz_each, const ubyte* fill,
367 int rank, size_t* shape, das_units units
368);
369
370
376DAS_API bool DasAry_init(
377 DasAry* pThis, const char* id, das_val_type et, size_t sz_each,
378 const ubyte* fill, int rank, size_t* shape, das_units units
379);
380
402DAS_API DasAry* new_DasPtrAry(const char* sType, int rank, size_t* shape);
403
407#define D2ARY_AS_SUBSEQ 0x00000001
408
413#define D2ARY_FILL_TERM 0x00000003
414
419#define D2ARY_AS_STRING 0x00000007
420
446DAS_API unsigned int DasAry_setUsage(DasAry* pThis, unsigned int uFlags);
447
451DAS_API unsigned int DasAry_getUsage(DasAry* pThis);
452
460DAS_API int inc_DasAry(DasAry* pThis);
461
465DAS_API int ref_DasAry(const DasAry* pThis);
466
476DAS_API void dec_DasAry(DasAry* pThis);
477
480DAS_API void DasAry_deInit(DasAry* pThis);
481
482
522 DasAry* pThis, size_t* pLen, size_t* pOffset
523);
524
533DAS_API bool DasAry_ownsElements(const DasAry* pThis);
534
541DAS_API const char* DasAry_id(const DasAry* pThis);
542
549DAS_API void DasAry_setId(DasAry* pThis, const char* sId);
550
557#define DasAry_rank(pThis) pThis->nRank
558
559/* DAS_API int DasAry_rank(const DasAry* pThis); */
560
564DAS_API das_units DasAry_units(const DasAry* pThis);
565
576DAS_API das_val_type DasAry_valType(const DasAry* pThis);
577
581DAS_API const char* DasAry_valTypeStr(const DasAry* pThis);
582
592DAS_API char* DasAry_toStr(const DasAry* pThis, char* sInfo, size_t uLen);
593
601DAS_API size_t DasAry_size(const DasAry* pThis);
602
609DAS_API size_t DasAry_valSize(const DasAry* pThis);
610
611
632DAS_API size_t DasAry_memUsed(const DasAry* pThis);
633
649DAS_API size_t DasAry_memOwned(const DasAry* pThis);
650
651
664DAS_API size_t DasAry_memIndexed(const DasAry* pThis);
665
666
708DAS_API size_t DasAry_lengthIn(const DasAry* pThis, int nIdx, ptrdiff_t* pLoc);
709
727DAS_API size_t DasAry_itemsIn(const DasAry* pThis, int nIdx, ptrdiff_t* pLoc);
728
748DAS_API int DasAry_shape(const DasAry* pThis, ptrdiff_t* pShape);
749
750
774DAS_API int DasAry_stride(
775 const DasAry* pThis, ptrdiff_t* pShape, ptrdiff_t* pStride
776);
777
782DAS_API const ubyte* DasAry_getFill(const DasAry* pThis);
783
800DAS_API bool DasAry_setFill(DasAry* pThis, das_val_type vt, const ubyte* pFill);
801
802
825DAS_API bool DasAry_validAt(const DasAry* pThis, ptrdiff_t* pLoc);
826
858DAS_API const ubyte* DasAry_getAt(const DasAry* pThis, das_val_type et, ptrdiff_t* pLoc);
859
862#define DasAry_getFloatAt(pThis, pLoc) *((float*)(DasAry_getAt(pThis, vtFloat, pLoc)))
865#define DasAry_getDoubleAt(pThis, pLoc) *((double*)(DasAry_getAt(pThis, vtDouble, pLoc)))
868#define DasAry_getByteAt(pThis, pLoc) *((ubyte*)(DasAry_getAt(pThis, vtUByte, pLoc)))
871#define DasAry_getUShortAt(pThis, pLoc) *((uint16_t*)(DasAry_getAt(pThis, etUint16, pLoc)))
874#define DasAry_getShortAt(pThis, pLoc) *((int16_t*)(DasAry_getAt(pThis, etInt16, pLoc)))
877#define DasAry_getIntAt(pThis, pLoc) *((int32_t*)(DasAry_getAt(pThis, etInt32, pLoc)))
880#define DasAry_getLongAt(pThis, pLoc) *((int64_t*)(DasAry_getAt(pThis, etInt64, pLoc)))
883#define DasAry_getTimeAt(pThis, pLoc) *((das_time*)(DasAry_getAt(pThis, vtTime, pLoc)))
886#define DasAry_getTextAt(pThis, pLoc) *((char**)(DasAry_getAt(pThis, vtText, pLoc)))
887
889#define DasAry_getPtrAt(pThis, pLoc) *((void**)(DasAry_getAt(pThis, vtUnknown, pLoc)))
890
891
907DAS_API bool DasAry_putAt(DasAry* pThis, ptrdiff_t* pStart, const ubyte* pVals, size_t uVals);
908
951DAS_API const ubyte* DasAry_getIn(
952 const DasAry* pThis, das_val_type et, int nDim, ptrdiff_t* pLoc, size_t* pCount
953);
954
962DAS_API ubyte* DasAry_getBuf(
963 DasAry* pThis, das_val_type et, int nDim, ptrdiff_t* pLoc, size_t* pCount
964);
965
968#define DasAry_getFloatsIn(T, ...) (const float*) DasAry_getIn(T, vtFloat, __VA_ARGS__)
969
972#define DasAry_getDoublesIn(T, ...) (const double*) DasAry_getIn(T, vtDouble, __VA_ARGS__)
973
976#define DasAry_getCharsIn(T, ...) (const char*) DasAry_getIn(T, vtUByte, __VA_ARGS__)
977
980#define DasAry_getBytesIn(T, ...) (const ubyte*) DasAry_getIn(T, vtUByte, __VA_ARGS__)
981
984#define DasAry_getUShortsIn(T, ...) (const uint16_t*) DasAry_getIn(T, vtUShort, __VA_ARGS__)
985
988#define DasAry_getShortsIn(T, ...) (const int16_t*) DasAry_getIn(T, vtShort, __VA_ARGS__)
989
992#define DasAry_getIntsIn(T, ...) (const int32_t*) DasAry_getIn(T, vtInt, __VA_ARGS__)
993
996#define DasAry_getLongsIn(T, ...) (const int64_t*) DasAry_getIn(T, vtLong, __VA_ARGS__)
997
1000#define DasAry_getTimesIn(T, ...) (const das_time*) DasAry_getIn(T, vtTime, __VA_ARGS__)
1001
1004#define DasAry_getTextIn(T, ...) (const char**) DasAry_getIn(T, vtText, __VA_ARGS__)
1005
1026DAS_API const ubyte* DasAry_getAllVals(
1027 const DasAry* pThis, size_t* pElSize, size_t* pElements
1028);
1029
1064 DasAry* pThis, const char* id, int nIndices, ptrdiff_t* pLoc
1065);
1066
1098DAS_API size_t DasAry_qubeIn(DasAry* pThis, int iRecDim);
1099
1121DAS_API ubyte* DasAry_append(DasAry* pThis, const ubyte* pVals, size_t uCount);
1122
1150DAS_API void DasAry_markEnd(DasAry* pThis, int iDim);
1151
1152/* Remove some number of records in a given index.
1153 *
1154 * This does not actually delete any data it just removes references to it.
1155 * Thus any subsets of this array will still reference the existing values.
1156 *
1157 * @see rmLastRec() for the definition of a record
1158 */
1159/* size_t DasAry_rmHead(Array* pThis, size_t uCount, int nIndex);*/
1160
1161/* Remove N records from the end of the array
1162 *
1163 * For rank 1 arrays, a 'record' is just a single value, for higher rank
1164 * arrays a record is the number of values represented by a change in the
1165 * first index. For example, for the array:
1166 * @code
1167 * a[][10][4]
1168 * @endcode
1169 * calling
1170 * @code
1171 * rmTail(pArray, 2)
1172 * @endcode
1173 * will result in 80 individual values being remove from the array.
1174 *
1175 * @param pThis the array to change
1176 * @param uRecs the number of records to remove. If uRecs is greater than
1177 * the shape of the first index, everything is removed and an error
1178 * is thrown.
1179 * @returns The new size of the array
1180 * @memberof DasAry
1181 */
1182/* size_t DasAry_rmTail(Array* pThis, size_t uRecs); */
1183
1194DAS_API size_t DasAry_clear(DasAry* pThis);
1195
1204DAS_API int DasAry_cmp(DasAry* pThis, const ubyte* vpFirst, const ubyte* vpSecond );
1205
1216DAS_API void DasAry_setSrc(DasAry* pThis, int nPktId, size_t uStartItem, size_t uItems);
1217
1218
1219#ifdef __cplusplus
1220}
1221#endif
1222
1223#endif /* _das_array_h_ */
DAS_API const ubyte * DasAry_getFill(const DasAry *pThis)
Return the fill value for this array.
DAS_API void DasAry_deInit(DasAry *pThis)
Similar to dec_dasAry, but for stack objects.
DAS_API const char g_sIdxLower[ARYIDX_MAX]
Index letters i,j,k,... for printing external index positions, and I,J,K,... for internal (item) inde...
DAS_API size_t DasAry_memUsed(const DasAry *pThis)
Get number of bytes currently used for data values and associated indexes by this dynamic array.
DAS_API ubyte * DasAry_getBuf(DasAry *pThis, das_val_type et, int nDim, ptrdiff_t *pLoc, size_t *pCount)
This is the writable pointer version of DasAry_getIn.
DAS_API DasAry * new_DasPtrAry(const char *sType, int rank, size_t *shape)
A convenience wrapper for storing arrays of pointers.
DAS_API size_t DasAry_memOwned(const DasAry *pThis)
Get the number of bytes currently owned for use in storing data values and indexes.
DAS_API bool DasAry_init(DasAry *pThis, const char *id, das_val_type et, size_t sz_each, const ubyte *fill, int rank, size_t *shape, das_units units)
Same as new_DasAry, but for initializing stack objects instead of making new heap objects.
DAS_API const ubyte * DasAry_getAllVals(const DasAry *pThis, size_t *pElSize, size_t *pElements)
Forget all the fancy indexing, just get a pointer to all the elements.
#define ARYIDX_MAX
The maximum number of array indices in das3.
Definition array.h:43
DAS_API size_t DasAry_memIndexed(const DasAry *pThis)
Get the number of bytes needed to store these values and their associated indexes.
DAS_API int das_rng2shape(int nRngRank, const ptrdiff_t *pMin, const ptrdiff_t *pMax, size_t *pShape)
Calculate a strided array shape from a min/max range.
const char * das_units
Handle SI and other units, with accommodations for Epoch systems, from units.h.
Definition units.h:141
das_val_type
Enumeration of value classes: what one whole externally indexable thing is – a number,...
Definition value.h:82
Dynamic recursive ragged arrays.
Definition array.h:243
DAS_API int inc_DasAry(DasAry *pThis)
Increment the count of objects using this Das Array.
DAS_API bool DasAry_ownsElements(const DasAry *pThis)
Does this array own it's own memory?
DAS_API char * DasAry_toStr(const DasAry *pThis, char *sInfo, size_t uLen)
Get a informational string representing the array.
DAS_API const char * DasAry_valTypeStr(const DasAry *pThis)
Get the type of value stored in the array as a text string.
DAS_API size_t DasAry_valSize(const DasAry *pThis)
Get the size in bytes of each element stored in the das array.
DAS_API int DasAry_shape(const DasAry *pThis, ptrdiff_t *pShape)
Return current valid ranges for this array indices.
DAS_API bool DasAry_putAt(DasAry *pThis, ptrdiff_t *pStart, const ubyte *pVals, size_t uVals)
Set values starting at a complete index.
DAS_API unsigned int DasAry_setUsage(DasAry *pThis, unsigned int uFlags)
Set usage flags to assist arbitrary consumers understand how to use this array.
DAS_API void DasAry_setSrc(DasAry *pThis, int nPktId, size_t uStartItem, size_t uItems)
Record which packets contain data destine for this array.
DAS_API int DasAry_stride(const DasAry *pThis, ptrdiff_t *pShape, ptrdiff_t *pStride)
Return the strides used for offset calculations.
DAS_API const ubyte * DasAry_getIn(const DasAry *pThis, das_val_type et, int nDim, ptrdiff_t *pLoc, size_t *pCount)
Get a pointer to the elements contained by a partial index.
DAS_API const char * DasAry_id(const DasAry *pThis)
Get the name of an array.
DAS_API size_t DasAry_itemsIn(const DasAry *pThis, int nIdx, ptrdiff_t *pLoc)
Count the logical items in a subset of the array.
DAS_API size_t DasAry_size(const DasAry *pThis)
Get the total number of data values in an array, regardless of it's shape.
DAS_API int DasAry_cmp(DasAry *pThis, const ubyte *vpFirst, const ubyte *vpSecond)
Compare two items of the type in the array.
DAS_API das_val_type DasAry_valType(const DasAry *pThis)
Get the type of value stored in the array if knownh.
DAS_API size_t DasAry_clear(DasAry *pThis)
Clear all values from the array.
DAS_API ubyte * DasAry_disownElements(DasAry *pThis, size_t *pLen, size_t *pOffset)
Take ownership of array element memory.
DAS_API ubyte * DasAry_append(DasAry *pThis, const ubyte *pVals, size_t uCount)
Append some number of items to the end of the array.
DAS_API void DasAry_markEnd(DasAry *pThis, int iDim)
Mark a ragged dimension as finished.
DAS_API bool DasAry_validAt(const DasAry *pThis, ptrdiff_t *pLoc)
Is a valid item located at a complete index.
DAS_API size_t DasAry_lengthIn(const DasAry *pThis, int nIdx, ptrdiff_t *pLoc)
Return the current max value + 1 for any index.
DAS_API const ubyte * DasAry_getAt(const DasAry *pThis, das_val_type et, ptrdiff_t *pLoc)
Get a pointer to an element at a complete index.
DAS_API das_units DasAry_units(const DasAry *pThis)
Get the units for the values in the array.
DAS_API size_t DasAry_qubeIn(DasAry *pThis, int iRecDim)
Use fill values to make sure the last subset in a dimension is a QUBE.
DAS_API DasAry * new_DasAry(const char *id, das_val_type et, size_t sz_each, const ubyte *fill, int rank, size_t *shape, das_units units)
Creates a new dynamic array buffer.
DAS_API unsigned int DasAry_getUsage(DasAry *pThis)
Returns the usage flags for this array.
DAS_API bool DasAry_setFill(DasAry *pThis, das_val_type vt, const ubyte *pFill)
Change the fill value for this array.
DAS_API void dec_DasAry(DasAry *pThis)
Maybe remove the array.
DAS_API int ref_DasAry(const DasAry *pThis)
Return the reference count of objects using this array.
DAS_API void DasAry_setId(DasAry *pThis, const char *sId)
Set the name of an array.
DAS_API DasAry * DasAry_subSetIn(DasAry *pThis, const char *id, int nIndices, ptrdiff_t *pLoc)
Get a lower rank array that is a sub-set of the current array.
void * pUser
User data pointer.
Definition array.h:286
Defines units used for items in the stream, most notably time units that reference an epoch and a ste...
#define DAS_MAX_ID_BUFSZ
The size of an char buffer large enough to hold valid object IDs.
Definition util.h:348
A generic value type for use in arrays, datums and variables.