![]() |
das2C
das core C utilities (v3)
|
Dynamic recursive ragged arrays. More...
#include <das2/array.h>
Public Member Functions | |
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. More... | |
DAS_API unsigned int | DasAry_setUsage (DasAry *pThis, unsigned int uFlags) |
Set usage flags to assist arbitrary consumers understand how to use this array. More... | |
DAS_API unsigned int | DasAry_getUsage (DasAry *pThis) |
Returns the usage flags for this array. | |
DAS_API int | inc_DasAry (DasAry *pThis) |
Increment the count of objects using this Das Array. More... | |
DAS_API int | ref_DasAry (const DasAry *pThis) |
Return the reference count of objects using this array. | |
DAS_API void | dec_DasAry (DasAry *pThis) |
Maybe remove the array. More... | |
DAS_API ubyte * | DasAry_disownElements (DasAry *pThis, size_t *pLen, size_t *pOffset) |
Take ownership of array element memory. More... | |
DAS_API bool | DasAry_ownsElements (const DasAry *pThis) |
Does this array own it's own memory? More... | |
DAS_API const char * | DasAry_id (const DasAry *pThis) |
Get the name of an array. More... | |
#define | DasAry_rank(pThis) pThis->nRank |
Get the number of dimensions in an array. More... | |
DAS_API das_units | DasAry_units (const DasAry *pThis) |
Get the units for the values in the array. | |
DAS_API das_val_type | DasAry_valType (const DasAry *pThis) |
Get the type of value stored in the array if knownh. More... | |
DAS_API const char * | DasAry_valTypeStr (const DasAry *pThis) |
Get the type of value stored in the array as a text string. | |
DAS_API char * | DasAry_toStr (const DasAry *pThis, char *sInfo, size_t uLen) |
Get a informational string representing the array. More... | |
DAS_API size_t | DasAry_size (const DasAry *pThis) |
Get the total number of data values in an array, regardless of it's shape. More... | |
DAS_API size_t | DasAry_valSize (const DasAry *pThis) |
Get the size in bytes of each element stored in the das array. More... | |
DAS_API size_t | DasAry_lengthIn (const DasAry *pThis, int nIdx, ptrdiff_t *pLoc) |
Return the current max value + 1 for any index. More... | |
DAS_API int | DasAry_shape (const DasAry *pThis, ptrdiff_t *pShape) |
Return current valid ranges for this array indices. More... | |
DAS_API int | DasAry_stride (const DasAry *pThis, ptrdiff_t *pShape, ptrdiff_t *pStride) |
Return the strides used for offest calculations. More... | |
DAS_API bool | DasAry_setFill (DasAry *pThis, das_val_type vt, const ubyte *pFill) |
Change the fill value for this array. More... | |
DAS_API bool | DasAry_validAt (const DasAry *pThis, ptrdiff_t *pLoc) |
Is a valid item located at a complete index. More... | |
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. More... | |
#define | DasAry_getFloatAt(pThis, pLoc) *((float*)(DasAry_getAt(pThis, vtFloat, pLoc))) |
Wrapper around DasAry_get for IEEE-754 binary32 (float) | |
#define | DasAry_getDoubleAt(pThis, pLoc) *((double*)(DasAry_getAt(pThis, vtDouble, pLoc))) |
Wrapper around DasAry_get for IEEE-754 binary64 (double) | |
#define | DasAry_getByteAt(pThis, pLoc) *((ubyte*)(DasAry_getAt(pThis, vtUByte, pLoc))) |
Wrapper around DasAry_get for unsigned bytes. | |
#define | DasAry_getUShortAt(pThis, pLoc) *((uint16_t*)(DasAry_getAt(pThis, etUint16, pLoc))) |
Wrapper around DasAry_get for unsigned 16-bit integers. | |
#define | DasAry_getShortAt(pThis, pLoc) *((int16_t*)(DasAry_getAt(pThis, etInt16, pLoc))) |
Wrapper around DasAry_get for signed 16-bit integers. | |
#define | DasAry_getIntAt(pThis, pLoc) *((int32_t*)(DasAry_getAt(pThis, etInt32, pLoc))) |
Wrapper around DasAry_get for 32-bit integers. | |
#define | DasAry_getLongAt(pThis, pLoc) *((int64_t*)(DasAry_getAt(pThis, etInt64, pLoc))) |
Wrapper around DasAry_get for signed 64-bit integers. | |
#define | DasAry_getTimeAt(pThis, pLoc) *((das_time*)(DasAry_getAt(pThis, vtTime, pLoc))) |
Wrapper around DasAry_get for das_time_t structures. | |
#define | DasAry_getTextAt(pThis, pLoc) *((char**)(DasAry_getAt(pThis, vtText, pLoc))) |
Wrapper around DasAry_get for pointers to null-terminated strings. | |
DAS_API bool | DasAry_putAt (DasAry *pThis, ptrdiff_t *pStart, const ubyte *pVals, size_t uVals) |
Set values starting at a complete index. More... | |
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. More... | |
#define | DasAry_getFloatsIn(T, ...) (const float*) DasAry_getIn(T, vtFloat, __VA_ARGS__) |
A wrapper around DasAry_getIn that casts the output and preforms type checking. | |
#define | DasAry_getDoublesIn(T, ...) (const double*) DasAry_getIn(T, vtDouble, __VA_ARGS__) |
A wrapper around DasAry_getIn that casts the output and preforms type checking. | |
#define | DasAry_getCharsIn(T, ...) (const char*) DasAry_getIn(T, vtUByte, __VA_ARGS__) |
A wrapper around DasAry_getIn that casts the output and preforms type checking. | |
#define | DasAry_getBytesIn(T, ...) (const ubyte*) DasAry_getIn(T, vtUByte, __VA_ARGS__) |
A wrapper around DasAry_getIn that casts the output and preforms type checking. | |
#define | DasAry_getUShortsIn(T, ...) (const uint16_t*) DasAry_getIn(T, vtUShort, __VA_ARGS__) |
A wrapper around DasAry_getIn that casts the output and preforms type checking. | |
#define | DasAry_getShortsIn(T, ...) (const int16_t*) DasAry_getIn(T, vtShort, __VA_ARGS__) |
A wrapper around DasAry_getIn that casts the output and preforms type checking. | |
#define | DasAry_getLongsIn(T, ...) (const int64_t*) DasAry_getIn(T, vtLong, __VA_ARGS__) |
A wrapper around DasAry_getIn that casts the output and preforms type checking. | |
#define | DasAry_getTimesIn(T, ...) (const das_time*) DasAry_getIn(T, vtTime, __VA_ARGS__) |
A wrapper around DasAry_getIn that casts the output and preforms type checking. | |
#define | DasAry_getTextIn(T, ...) (const char**) DasAry_getIn(T, vtText, __VA_ARGS__) |
A wrapper around DasAry_getIn that casts the output and preforms type checking. | |
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. More... | |
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. More... | |
DAS_API ubyte * | DasAry_append (DasAry *pThis, const ubyte *pVals, size_t uCount) |
Append some number of items to the end of the array. More... | |
DAS_API void | DasAry_markEnd (DasAry *pThis, int iDim) |
Mark a ragged dimension as finished. More... | |
DAS_API size_t | DasAry_clear (DasAry *pThis) |
Clear all values from the array. More... | |
DAS_API int | DasAry_cmp (DasAry *pThis, const ubyte *vpFirst, const ubyte *vpSecond) |
Compare two items of the type in the array. More... | |
DAS_API void | DasAry_setSrc (DasAry *pThis, int nPktId, size_t uStartItem, size_t uItems) |
Record which packets contain data destine for this array. More... | |
DAS_API size_t | DasDs_clearRagged0Arrays (DasDs *pThis) |
Clear any arrays that are ragged in index l. More... | |
Data Fields | |
void * | pUser |
User data pointer. More... | |
Dynamic recursive ragged arrays.
This class maps any number of indices, (i,j,k...) to elements stored into a continuous array. Any or all particular indexes of the array may be ragged if desired, though typically for fixed record size data streams, only the first index has an arbitrary length.
The backing buffers for the array grow as needed when new elements are appended. Individual elements may be arbitrary composite types, though extra capabilites are provided for a handful of known types.
Handling ragged data comes at a cost in that the length of each continuous run of elements must also be stored in an ancillary array since address strides are not necessarily constant. This cost is 8 to 16 bytes times the size of all indexes, except the last. For example, an array of shape (10,100,40) would use 10*100*16 extra bytes compared to a simple strideable array, though this is typically much smaller than the 10*100*40*element_size bytes used by the primary data buffer.
Handling ragged data also comes at a cost in terms of potential cache misses. For example to lookup a value in a rank 3 array requires accessing three dynamically allocated buffers. One for each dimension of the array. The first two are offset value buffers, the last is the actual data buffer.
Automatically switching to more efficent strided index calculations in cases where all records are of a constant size has yet to be implemented, though the DasAry_stride() function can be used to stride across the raw data buffer efficently if desired.
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.
id | A string token for this array. Must not be null, must not be more than 63 characaters long. In general it follows the rules for variable names in most languages. |
et | The element type, for arbitrary element storage use vtUnknown, specific types are provided in enum element_type. |
sz_each | The size of each element in the array in bytes. This parameter is only used when the element type is vtUnknown. |
fill | A pointer to the value for initializing all empty array records. The value should be size_each bytes long. These bytes are copied into the array and this pointer need not remain valid after the constructor call. For unknown types (et = etUnknown) this is a required, non NULL parameter. For known types you can use NULL to automatically set fill to the following values, based on the element_type: |
pFill can point to stack memory as the fill bytes are copied in.
rank | The number of dimensions in the array. This sets the number of arguments needed in the get() function call. To make your code easier to read, the defines RANK_1, RANK_2, ... RANK_8 are provided. |
shape | The initial shape of the array. One integer is needed here for each dimension in the array. Use the value 0 to set a dimension to be unbounded. Multi-dimension arrays used to hold an arbitrarily long set of records are typically only unbounded in the first index, though see the example in DasAry_markEnd for handling multiply ragged arrays. |
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 arrays can store co-opertive flags, these do not change the array API but do indicate how the array should be used. The following two usage flags are currently defined:
You can add your own flags as well so long as they have the value:
or higher they will be preserved through calls to setUsage and getUsage
pThis | |
uFlags | All the flag values to set at once. |
DAS_API int inc_DasAry | ( | DasAry * | pThis | ) |
Increment the count of objects using this Das Array.
DAS_API void dec_DasAry | ( | DasAry * | pThis | ) |
Maybe remove the array.
Calling this function decrements the reference count for the array. If the count reaches zero all backing buffers (owned by this array) are deleted.
DAS_API ubyte * DasAry_disownElements | ( | DasAry * | pThis, |
size_t * | pLen, | ||
size_t * | pOffset | ||
) |
Take ownership of array element memory.
Internally all Das Array elements are stored in a single continuous 1-D buffer. When the Das Array is deleted, this buffer is removed as well, if it's owned by the das array.
pThis | A pointer to a das array structure |
pLen | A pointer to a variable to hold the length of the element array in elements (not bytes). If the array had no values then length is set to 0 |
pOffset | Where to store the offset in elements (not bytes) to the start of valid values. Internally arrays may have invalid values in the memory buffer before valid values start. |
Return Notes: Buffer memory is not allocated until elements are inserted (lazy allocation) thus an empty array WILL NOT own any elements. So this this function will ALWAYS return NULL for an empty array. Use the value returned by pLen to see if the NULL return was because the array didn't own it's elements or if there were no elements to own.
Once elements are disowed, they can't be disowned again. Calling disownElements twice in succession in a single threaded program will always return NULL on the second call.
Implementation detail: The internal ragged index tracking arrays may still be owned by the DasAry object and will be deleted when the overall structure is deleted
DAS_API bool DasAry_ownsElements | ( | const DasAry * | pThis | ) |
Does this array own it's own memory?
If an array owns it's element memory then DasAry_disownElements will return a valid memory buffer if there are any valid values.
DAS_API const char * DasAry_id | ( | const DasAry * | pThis | ) |
Get the name of an array.
pThis | A constant pointer to this array structure |
DAS_API das_val_type DasAry_valType | ( | const DasAry * | pThis | ) |
Get the type of value stored in the array if knownh.
This function is used by dataset objects to know how to cast pointers to different data array values.
pThis | A constant pointer to this array structure |
DAS_API char * DasAry_toStr | ( | const DasAry * | pThis, |
char * | sInfo, | ||
size_t | uLen | ||
) |
Get a informational string representing the array.
pThis | The Array in question |
sInfo | pointer to the destination to hold the info string |
uLen | the length of the sInfo buffer |
DAS_API size_t DasAry_size | ( | const DasAry * | pThis | ) |
Get the total number of data values in an array, regardless of it's shape.
pThis | A constant pointer to this array structure |
DAS_API size_t DasAry_valSize | ( | const DasAry * | pThis | ) |
Get the size in bytes of each element stored in the das array.
pThis | The Array in question |
DAS_API size_t DasAry_lengthIn | ( | const DasAry * | pThis, |
int | nIdx, | ||
ptrdiff_t * | pLoc | ||
) |
Return the current max value + 1 for any index.
This is a more general version of DasAry_shape that works for both cubic arrays and those with ragged dimensions. For any index to be inspected, the value of all previous indices must be given. This is less confusing then it sounds, see the example below
pThis | A pointer to an array object |
nIdx | The number of location indices, should be less than the rank in order to get the length of a range of values. The macros DIM0, DIM1_AT, DIM2_AT, etc. are provided which combine this argument and the one below to make calling code more readable, see the example below. |
pLoc | A list of the values for previous indices. The macros DIM1, DIM2_AT, DIM3_AT etc. are provided which combine this argument with the one above to make calling code more readable, see the example below. |
DAS_API int DasAry_shape | ( | const DasAry * | pThis, |
ptrdiff_t * | pShape | ||
) |
Return current valid ranges for this array indices.
pThis | pointer to an array object | |
[out] | pShape | pointer to an array to received the current number of entries in each dimension, should be at least RANK in length. Each element of the output array will be one of the following. |
DAS_API int DasAry_stride | ( | const DasAry * | pThis, |
ptrdiff_t * | pShape, | ||
ptrdiff_t * | pStride | ||
) |
Return the strides used for offest calculations.
To support fast iteration over array data it's often useful to get a raw pointer and then stride across the 1-D array using an index calculation. Ragged arrays do not have a uniform stride, but many arrays are not ragged and sub-sections of ragged arrays may not be ragged. Use this function to get the stride coefficents.
pThis | pointer to an array object | |
[out] | pShape | The extent of the array in each index. The total number of elements is just the multiple of all values in this array up to the rank. |
[out] | pStride | pointer to an array to recive the number of elements to increment for each successive value of this index. Note that this is not the number of bytes to stride. Use DasAry_valSize() to get the size of each element. |
DAS_API bool DasAry_setFill | ( | DasAry * | pThis, |
das_val_type | vt, | ||
const ubyte * | pFill | ||
) |
Change the fill value for this array.
Set the fill value but don't re-write the data in the array. Any data locations in the array will still have the fill value. To change them iterate over the array looking for the old fill value an replace them in a loop.
pThis | The array to structure to alter |
pFill | Pointer to the relpacement fill value, use NULL to set this to the connonical fill value for this type. |
vt | The element type for the new fill value. This is used as a cross check. The element type of the new fill value must match the old one. |
DAS_API bool DasAry_validAt | ( | const DasAry * | pThis, |
ptrdiff_t * | pLoc | ||
) |
Is a valid item located at a complete index.
pThis | A pointer to the array |
pLoc | An array of indices of length RANK. A rank 1 Das Array requires two indices to access an element, a rank 2 requires three, etc. The macros LOC_1, LOC_2, etc have been provided to make code more readable. See the example below. |
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.
For type safety the macros DasAry_getFloat, DasAry_getDouble, etc have been provided and should be used instead of the base function here.
pThis | A pointer to the array |
et | The element type pointer expected at the given location, this is used by the type checking macros DasAry_getFloat and friends. |
pLoc | An array of indices of length RANK. A rank 2 Das Array requires two indices to access an element, a rank 3 requires three, etc. The macros IDX0, IDX1, IDX2, etc have been provided to make code more readable. See the example below. |
DAS_API bool DasAry_putAt | ( | DasAry * | pThis, |
ptrdiff_t * | pStart, | ||
const ubyte * | pVals, | ||
size_t | uVals | ||
) |
Set values starting at a complete index.
Note, this will not expand the size of the array. Use the function append() to automatically grow the array to store the desired number of items.
pThis | A pointer to the array |
pStart | The complete index to the starting point to write values, use the macros IDX1, IDX2, etc. to make calling code more readable |
pVals | The values to write |
uVals | The number of values to write |
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.
pThis | A Array containing the data of interest |
et | The expected type of element to be returned. This is used by the type safe macros DasAry_getDoubleAt, DasAry_getTextAt, etc. |
nDim | The number of location indices, should be less than the rank in order to get the length of a range of values. The macros DIM0, DIM1_AT, DIM2_AT, etc. are provided which combine this argument and the one below to make calling code more readable, see the example below. |
pLoc | An array of location indices, nDim long. Use the macros DIM0, DIM1_AT, DIM2_AT, etc. for cleaner code. |
pCount | A pointer to a variable to hold the number of elements under the given index. If nIndices is equal to the array rank the returned value will be at most 1. |
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.
For some given number of indices, produce a sub-array. This is similar to DasAry_getAt but produces a whole new Array object whose data are provided stored in a separate Array.
pThis | A pointer to the array to subset. It is not a constant pointer due to the need to increment the reference count. |
id | A identifying name for the new sub-array |
nIndices | The number of location indices, should be less than the rank in order to get a range of values. Use the macros DIM0, DIM1_AT, DIM2_AT, etc. for cleaner code. |
pLoc | An array of location indices, nIndices long. Use the macros DIM0, DIM1_AT, DIM2_AT, etc. for cleaner code. |
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.
pThis | the array |
iRecDim | The dimension to qube, typically the last dimension in the array, dimensions are numbered starting from 0. Use the macro's DIM1, DIM2, etc. to make the code more readable. Dimension 0 can't be marked as ended and the macro DIM0 will not work here. |
DAS_API ubyte * DasAry_append | ( | DasAry * | pThis, |
const ubyte * | pVals, | ||
size_t | uCount | ||
) |
Append some number of items to the end of the array.
This works as you would expect for all arrays that are only ragged in the 0th dimension.
pThis | The array which should copy in the new values. |
pVals | A constant pointer to values to add MAY BE NULL! If NULL uCount fill values are appended |
uCount | The number of values to add |
DAS_API void DasAry_markEnd | ( | DasAry * | pThis, |
int | iDim | ||
) |
Mark a ragged dimension as finished.
pThis | The das array |
iDim | The dimension which should have it's index rolled back to zero on the next insert. Marking the end of a low index (say 1) automatically marks the end of any higher indices (ex 2,3). // Read in lines of text into an array that stores data by page number,
// line number and the byte number. Input processing is simplistic in
// order to focus on Array calls.
byte fill = 0;
Array* pAry = new_Array("source", etByte, 0, &fill, RANK_3(0,0,0));
char sBuf[1024] = {'\0'};
size_t uLen = 0;
while(!eof(stdin)){
while(fgets(sBuf, 1024, stdin)){
uLen = strlen(sBuf);
DasAry_append(pAry, sBuf, uLen+1); // keep NULL terminators
}
}
DAS_API void DasAry_markEnd(DasAry *pThis, int iDim) Mark a ragged dimension as finished. |
DAS_API size_t DasAry_clear | ( | DasAry * | pThis | ) |
Clear all values from the array.
This operation internally just resets the count of items to 0 in all arrays it does not free memory. Dimensions above the 0th retain their shape.
pThis | The array to clear |
DAS_API int DasAry_cmp | ( | DasAry * | pThis, |
const ubyte * | vpFirst, | ||
const ubyte * | vpSecond | ||
) |
Compare two items of the type in the 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.
pThis | The array |
nPktId | The id of the Das packet which contains values that should be added to this array |
uStartItem | The location in the packet where this array's data starts |
uItems | The number of items to add from each packet |
DAS_API size_t DasDs_clearRagged0Arrays | ( | DasDs * | pThis | ) |
Clear any arrays that are ragged in index l.
This function is handy when reading data to insure that memory usage does not grow without limit. Any memory allocated is not freed, but the write points are reset so that the same buffers can be used over and over again.
pThis | A dataset |
void* pUser |
User data pointer.
The stream -> dataset -> array hierarchy provides a goood organizational structure for application data, especially applications that filter streams. It is initialized to NULL when a variable is created but otherwise the library dosen't deal with it.