-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Description
This idea is analogue to the c++ span type:
open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0122r1.pdf
The origin of this idea is, that I have written several C language wrappers and a repeating pattern to store a variable length array in a struct, is with the pointer/size pair. I use the following struct to solve the problem locally:
type
UncheckedArray {.unchecked.} [t] = array[0,t]
DataView*[T] = object
data: ptr UncheckedArray[T]
size: int
This is mostly for interfacing with C libraries. For example there is the C library that publishes the following api:
struct MyChildStructA {
char someData[8];
};
struct MyChildStructB {
char someData[16];
};
struct MyMotherStruct {
char headerData[64];
long numA;
struct MyChildStructA* childrenA;
long numB;
struct MyChildStructB* childrenB;
};
I would provide a wrapper like the following:
type
UncheckedArray {.unchecked.} [t] = array[0,t]
DataView*[T] = object
data: ptr UncheckedArray[T]
size: int
proc dataView[T](data: ptr T; size: int): DataView[T] =
result.data = cast[ptr UncheckedArray[T]](data)
result.size = size
type
MyChildStructA* = object
someData*: array[8, char]
MyChildStructB* = object
someData*: array[16, char]
MyMotherStruct* = object
headerData*: array[64, char]
numA: clong
childrenAptr: ptr MyChildStructA
numB: clong
childrenBptr: ptr MyChildStructBcontiguous
proc childrenA*(arg: MyMotherStruct): DataView[MyChildStructA] =
dataView(arg.childrenAptr, arg.numA)
proc childrenB*(arg: MyMotherStruct): DataView[MyChildStructB] =
dataView(arg.childrenBptr, arg.numB)
With proper Nim integration, this struct could provide iterators, index operators, conversion to openArray
, so that it feels just like a Nim data structure.
The reasone why a seq
does not do the job, is because the seq has quite a different memory layout. The seq has two integers, len
and reserved
, then the data follows directly without another pointer indirection. This mains, that I can't fill the seq
header with just the right values, so that the seq sees the exact same data as the C library does (apart from that, I also don't know how well that would work together with garbage collection). And I also can't just copy the data. Copying the data would destroy the idea of the thin wrapper, and sometimes it is necessary to have write access the the members of the DataView
. Even though I am not entirely happy with the name, I still like the View
part of that name, because it implies, that one has only a view access to data. One is not responsible for freeing that memory, or able to keeping it alive over the owners lifetime. Other possible Names might be DataSlice
, DataWindow
or just openArray
because it is semantically the same, just extended to be also be usable as values, not just function parameters.
Further possibilities:
It could be used for slicing:
proc dataView[T](arg: seq[T]; elements: Slice[int]): DataView[T] =
result.data = cast[ptr UncheckedArray[T]](arg[elements.a])
result.size = elements.b + 1 - elements.a
var s = @[7,5,6,4,8,1,2,9,0]
echo sorted(s[2..6], cmp)
var s1 = s.dataView(2..6)
#s1.sort(cmp) ## fails, because I can't provide a converter to openArray
#echo s
##
## should print @[7,5,1,2,4,6,8,9,0]
## |<sorted >|
When DataView
either becomes convertable to openArray
, or becomes openArray
, Then all algorithms that provide an interface to operate on openArray
then automatically also become able to operate on any sub array of arrays and seqs.