libdas2
das2 core C utilities
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
array.h
Go to the documentation of this file.
1 /* Copyright (C) 2017-2018 Chris Piker <chris-piker@uiowa.edu>
2  *
3  * This file is part of libdas2, the Core Das2 C Library.
4  *
5  * Libdas2 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  * Libdas2 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 libdas2; 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 <das2/value.h>
36 #include <das2/units.h>
37 
38 #ifdef __cplusplus
39 extern "C" {
40 #endif
41 
42 
43 #define DASIDX_MAX 16
44 
45 /* WARNING! If the values below change, update das_varindex_merge */
46 /* and update das_varlength_merge */
47 
48 #define DASIDX_RAGGED -1
49 #define DASIDX_FUNC -2
50 #define DASIDX_UNUSED -3
51 
52 #define DASIDX_INIT_UNUSED {-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3}
53 #define DASIDX_INIT_BEGIN { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
54 
68 char* das_shape_prnRng(
69  ptrdiff_t* pShape, int iFirstInternal, int nShapeLen, char* sBuf, int nBufLen
70 );
71 
72 
73 #define RANK_1(I) 1, (size_t[1]){I}
74 #define RANK_2(I, J) 2, (size_t[2]){I, J}
75 #define RANK_3(I, J, K) 3, (size_t[3]){I, J, K}
76 #define RANK_4(I, J, K, L) 4, (size_t[4]){I, J, K, L}
77 #define RANK_5(I, J, K, L, M) 5, (size_t[5]){I, J, K, L, M}
78 #define RANK_6(I, J, K, L, M, N) 6, (size_t[6]){I, J, K, L, M, N}
79 #define RANK_7(I, J, K, L, M, N, O) 7, (size_t[7]){I, J, K, L, M, N, O}
80 #define RANK_8(I, J, K, L, M, N, O, P) 8, (size_t[8]){I, J, K, L, M, N, O, P}
81 
82 #define DIM0 0, (NULL)
83 #define DIM1_AT(I) 1, (ptrdiff_t[1]){I}
84 #define DIM2_AT(I,J) 2, (ptrdiff_t[2]){I,J}
85 #define DIM3_AT(I,J,K) 3, (ptrdiff_t[3]){I,J,K}
86 #define DIM4_AT(I,J,K,L) 4, (ptrdiff_t[4]){I,J,K,L}
87 #define DIM5_AT(I,J,K,L,M) 5, (ptrdiff_t[5]){I,J,K,L,M}
88 #define DIM6_AT(I,J,K,L,M,N) 6, (ptrdiff_t[6]){I,J,K,L,M,N}
89 #define DIM7_AT(I,J,K,L,M,N,O) 7, (ptrdiff_t[7]){I,J,K,L,M,N,O}
90 
91 #define IDX0(I) (ptrdiff_t[1]){I}
92 #define IDX1(I,J) (ptrdiff_t[2]){I,J}
93 #define IDX2(I,J,K) (ptrdiff_t[3]){I,J,K}
94 #define IDX3(I,J,K,L) (ptrdiff_t[4]){I,J,K,L}
95 #define IDX4(I,J,K,L,M) (ptrdiff_t[5]){I,J,K,L,M}
96 #define IDX5(I,J,K,L,M,N) (ptrdiff_t[6]){I,J,K,L,M,N}
97 #define IDX6(I,J,K,L,M,N,O) (ptrdiff_t[7]){I,J,K,L,M,N,O}
98 #define IDX7(I,J,K,L,M,N,O,P) (ptrdiff_t[8]){I,J,K,L,M,N,O,P}
99 
100 #define DIM1 1
101 #define DIM2 2
102 #define DIM3 3
103 #define DIM4 4
104 #define DIM5 5
105 #define DIM6 6
106 #define DIM7 7
107 
110 /* Higher dimensions are handled by index buffers. These are the elements for
111  * the index buffers */
112 typedef struct child_info_t{
113  ptrdiff_t nOffset; /* Start of child elements data in child buffer */
114  size_t uCount; /* The count child elements in child buffer */
115 }das_idx_info;
116 
117 typedef struct dyna_buf{
118  /* Stores the fill value as a hidden item below the first index */
119  byte* pBuf; /* The beginning a continuous buffer uSize long */
120  byte* pHead; /* The beginning of valid values in the buffer */
121  /*byte* pWrite;*/ /* The beginning of the append point for the buffer */
122  size_t uSize; /* The amount of space in the backing buffer */
123  size_t uValid; /* The number of valid elements in this buffer */
124  size_t uElemSz; /* The number of bytes occupied by each element */
125  byte* pFill; /* Pointer to fill value buffer */
126  byte fillBuf[sizeof(das_idx_info)]; /* Storage for short fill items */
127 
128  size_t uChunkSz; /* Alloc helper, if set, allocate in even chunks
129  * of this size. */
130  size_t uShape; /* Qube helper, how many items in this array per
131  * parent item, 0 means ragged */
132  das_val_type etype; /* The element type */
133 
134  bool bRollParent; /* The end mark. If set, adding data to the array
135  * will clear the end mark and trigger creation of
136  * a new parent. If this is set on all indexes
137  * attempting to add data will fail */
138 
139  bool bKeepMem; /* If true memory will not be deleted when the
140  * buffer is deleted */
141 } DynaBuf;
142 
193 typedef struct das_array {
194  char sId[64]; /* A text identifier of this instance of the array */
195  int nRank; /* The number of index dimensions for the array */
196  das_idx_info* pIdx0; /* top lever container, may not point here */
197 
198  /* bool bTopOwned;*/ /* Same as pIdx0 == &index0 */
199  das_idx_info index0; /* Storage for element 0 of buffer 0, if needed */
200 
201  /* Pointers to item arrays. One array is needed for each dimension,
202  * these may point to internal locations if the array is owned */
203  DynaBuf* pBufs[DASIDX_MAX];
204 
205  /* bool bOwned[16]; */ /* Same as pBufs[i] == bufs + i */
206  DynaBuf bufs[DASIDX_MAX]; /* Storage for dynamic buffers, if needed */
207 
208  /* Current compare function, set automatically if a known type is used,
209  * otherwise user needs to supply their own */
210  int (*compare)(const void* vpFirst, const void* vpSecond);
211 
212  /* Where to send/read data when streaming */
213  int nSrcPktId;
214  size_t uStartItem;
215  size_t uItems;
216 
217  /* Since so many datasets and functions can reference the same array,
218  * a reference count is needed to make sure they aren't deleted if
219  * still in use. */
220  int refcount;
221 
222  unsigned int uFlags; /* Store flags indicating intended use */
223 
224  das_units units;
225 
226 } DasAry;
227 
228 
300  const char* id, das_val_type et, size_t sz_each, const void* fill,
301  int rank, size_t* shape, das_units units
302 );
303 
307 #define D2ARY_AS_SUBSEQ 0x00000001
308 
313 #define D2ARY_FILL_TERM 0x00000003
314 
319 #define D2ARY_AS_STRING 0x00000007
320 
337 unsigned int DasAry_setUsage(DasAry* pThis, unsigned int uFlags);
338 
342 unsigned int DasAry_getUsage(DasAry* pThis);
343 
348 int inc_DasAry(DasAry* pThis);
349 
353 int ref_DasAry(const DasAry* pThis);
354 
362 void dec_DasAry(DasAry* pThis);
363 
364 
390 byte* DasAry_disownElements(DasAry* pThis, size_t* pLen);
391 
398 const char* DasAry_id(const DasAry* pThis);
399 
406 int DasAry_rank(const DasAry* pThis);
407 
411 das_units DasAry_units(const DasAry* pThis);
412 
423 enum das_val_type DasAry_valType(const DasAry* pThis);
424 
428 const char* DasAry_valTypeStr(const DasAry* pThis);
429 
438 char* DasAry_toStr(const DasAry* pThis, char* sInfo, size_t uLen);
439 
447 size_t DasAry_size(const DasAry* pThis);
448 
455 size_t DasAry_valSize(const DasAry* pThis);
456 
457 
499 size_t DasAry_lengthIn(const DasAry* pThis, int nIdx, ptrdiff_t* pLoc);
500 
520 int DasAry_shape(const DasAry* pThis, ptrdiff_t* pShape);
521 
522 
527 const void* DasAry_getFill(const DasAry* pThis);
528 
529 
552 bool DasAry_validAt(const DasAry* pThis, ptrdiff_t* pLoc);
553 
585 const void* DasAry_getAt(const DasAry* pThis, das_val_type et, ptrdiff_t* pLoc);
586 
589 #define DasAry_getFloatAt(pThis, pLoc) *((float*)(DasAry_getAt(pThis, vtFloat, pLoc)))
590 
592 #define DasAry_getDoubleAt(pThis, pLoc) *((double*)(DasAry_getAt(pThis, vtDouble, pLoc)))
593 
595 #define DasAry_getByteAt(pThis, pLoc) *((byte*)(DasAry_getAt(pThis, vtByte, pLoc)))
596 
598 #define DasAry_getUShortAt(pThis, pLoc) *((uint16_t*)(DasAry_getAt(pThis, etUint16, pLoc)))
599 
601 #define DasAry_getShortAt(pThis, pLoc) *((int16_t*)(DasAry_getAt(pThis, etInt16, pLoc)))
602 
604 #define DasAry_getIntAt(pThis, pLoc) *((int32_t*)(DasAry_getAt(pThis, etInt32, pLoc)))
605 
607 #define DasAry_getLongAt(pThis, pLoc) *((int64_t*)(DasAry_getAt(pThis, etInt64, pLoc)))
608 
610 #define DasAry_getTimeAt(pThis, pLoc) *((das_time*)(DasAry_getAt(pThis, vtTime, pLoc)))
611 
613 #define DasAry_getTextAt(pThis, pLoc) *((char**)(DasAry_getAt(pThis, vtText, pLoc)))
614 
615 
631 bool DasAry_putAt(DasAry* pThis, ptrdiff_t* pStart, const void* pVals, size_t uVals);
632 
675 const void* DasAry_getIn(
676  const DasAry* pThis, das_val_type et, int nDim, ptrdiff_t* pLoc, size_t* pCount
677 );
678 
681 #define DasAry_getFloatsIn(T, ...) (const float*) DasAry_getIn(T, vtFloat, __VA_ARGS__)
682 
685 #define DasAry_getDoublesIn(T, ...) (const double*) DasAry_getIn(T, vtDouble, __VA_ARGS__)
686 
689 #define DasAry_getBytesIn(T, ...) (const byte*) DasAry_getIn(T, vtByte, __VA_ARGS__)
690 
693 #define DasAry_getUShortsIn(T, ...) (const uint16_t*) DasAry_getIn(T, vtUShort, __VA_ARGS__)
694 
697 #define DasAry_getShortsIn(T, ...) (const int16_t*) DasAry_getIn(T, vtShort, __VA_ARGS__)
698 
701 #define DasAry_getIntsIn(T, ...) (const int32_t*) DasAry_getIn(T, vtInt, __VA_ARGS__)
702 
705 #define DasAry_getLongsIn(T, ...) (const int64_t*) DasAry_getIn(T, vtLong, __VA_ARGS__)
706 
709 #define DasAry_getTimesIn(T, ...) (const das_time*) DasAry_getIn(T, vtTime, __VA_ARGS__)
710 
713 #define DasAry_getTextIn(T, ...) (const char**) DasAry_getIn(T, vtText, __VA_ARGS__)
714 
748  const DasAry* pThis, const char* id, int nIndices, ptrdiff_t* pLoc
749 );
750 
782 size_t DasAry_qubeIn(DasAry* pThis, int iRecDim);
783 
799 bool DasAry_append(DasAry* pThis, const void* pVals, size_t uCount);
800 
828 void DasAry_markEnd(DasAry* pThis, int iDim);
829 
830 /* Remove some number of records in a given index.
831  *
832  * This does not actually delete any data it just removes references to it.
833  * Thus any subsets of this array will still reference the existing values.
834  *
835  * @see rmLastRec() for the definition of a record
836  */
837 /* size_t Array_rmHead(Array* pThis, size_t uCount, int nIndex);*/
838 
839 /* Remove N records from the end of the array
840  *
841  * For rank 1 arrays, a 'record' is just a single value, for higher rank
842  * arrays a record is the number of values represented by a change in the
843  * first index. For example, for the array:
844  * @code
845  * a[][10][4]
846  * @endcode
847  * calling
848  * @code
849  * rmTail(pArray, 2)
850  * @endcode
851  * will result in 80 individual values being remove from the array.
852  *
853  * @param pThis the array to change
854  * @param uRecs the number of records to remove. If uRecs is greater than
855  * the shape of the first index, everything is removed and an error
856  * is thrown.
857  * @returns The new size of the array
858  * @memberof DasAry
859  */
860 /* size_t Array_rmTail(Array* pThis, size_t uRecs); */
861 
872 size_t DasAry_clear(DasAry* pThis);
873 
882 int DasAry_cmp(DasAry* pThis, const void* vpFirst, const void* vpSecond );
883 
894 void DasAry_setSrc(DasAry* pThis, int nPktId, size_t uStartItem, size_t uItems);
895 
896 
897 #ifdef __cplusplus
898 }
899 #endif
900 
901 #endif /* _das_array_h_ */
int DasAry_cmp(DasAry *pThis, const void *vpFirst, const void *vpSecond)
Compare two items of the type in the array.
int DasAry_rank(const DasAry *pThis)
Get the number of dimensions in an array.
const void * DasAry_getAt(const DasAry *pThis, das_val_type et, ptrdiff_t *pLoc)
Get a pointer to an element at a complete index.
unsigned int DasAry_setUsage(DasAry *pThis, unsigned int uFlags)
Set usage flags to assist arbitrary consumers understand how to use this array.
int DasAry_shape(const DasAry *pThis, ptrdiff_t *pShape)
Return current valid ranges for this array indices.
size_t DasAry_qubeIn(DasAry *pThis, int iRecDim)
Use fill values to make sure the last subset in a dimension is a QUBE.
bool DasAry_append(DasAry *pThis, const void *pVals, size_t uCount)
Append some number of items to the end of the array.
das_val_type
Enumeration of types stored in Das Array (DasAry) objects Not that any kind of value may be stored in...
Definition: value.h:51
const char * DasAry_valTypeStr(const DasAry *pThis)
Get the type of value stored in the array as a text string.
const void * 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.
const char * DasAry_id(const DasAry *pThis)
Get the name of an array.
int inc_DasAry(DasAry *pThis)
Increment the count of objects using this Das Array.
int ref_DasAry(const DasAry *pThis)
Return the reference count of objects using this array.
size_t DasAry_clear(DasAry *pThis)
Clear all values from the array.
DasAry * new_DasAry(const char *id, das_val_type et, size_t sz_each, const void *fill, int rank, size_t *shape, das_units units)
Creates a new dynamic array buffer.
enum das_val_type DasAry_valType(const DasAry *pThis)
Get the type of value stored in the array if known.
byte * DasAry_disownElements(DasAry *pThis, size_t *pLen)
Remove ownership of the underlying element array from this DasArray.
Defines units used for items in the stream, most notably time units that reference an epoch and a ste...
void DasAry_markEnd(DasAry *pThis, int iDim)
Mark a ragged dimension as finished.
char * DasAry_toStr(const DasAry *pThis, char *sInfo, size_t uLen)
Get a informational string representing the array.
char * das_shape_prnRng(ptrdiff_t *pShape, int iFirstInternal, int nShapeLen, char *sBuf, int nBufLen)
Print shape information using symbols i,j,k etc for index positions.
bool DasAry_validAt(const DasAry *pThis, ptrdiff_t *pLoc)
Is a valid item located at a complete index.
size_t DasAry_size(const DasAry *pThis)
Get the total number of data values in an array, regardless of it&#39;s shape.
const void * DasAry_getFill(const DasAry *pThis)
Return the fill value for this array.
das_units DasAry_units(const DasAry *pThis)
Get the units for the values in the array.
bool DasAry_putAt(DasAry *pThis, ptrdiff_t *pStart, const void *pVals, size_t uVals)
Set values starting at a complete index.
A generic value type for use in arrays, datums and variables.
unsigned int DasAry_getUsage(DasAry *pThis)
Returns the usage flags for this array.
size_t DasAry_lengthIn(const DasAry *pThis, int nIdx, ptrdiff_t *pLoc)
Return the current max value + 1 for any index.
size_t DasAry_valSize(const DasAry *pThis)
Get the size in bytes of each element stored in the das array.
void dec_DasAry(DasAry *pThis)
Maybe remove the array.
DasAry * DasAry_subSetIn(const 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 DasAry_setSrc(DasAry *pThis, int nPktId, size_t uStartItem, size_t uItems)
Record which packets contain data destine for this array.
const char * das_units
Enumeration of unit types, that correspond to physical unit types.
Definition: units.h:135
Dynamic recursive ragged arrays.
Definition: array.h:193