X-Git-Url: http://nitlanguage.org diff --git a/lib/c.nit b/lib/c.nit index c0bd650..7db5945 100644 --- a/lib/c.nit +++ b/lib/c.nit @@ -14,23 +14,67 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Utilities and performant structure for the FFI with C +# Structures and services for compatibility with the C language module c +import core +intrude import core::collection::array + # A thin wrapper around a `NativeCArray` adding length information abstract class CArray[E] super AbstractArrayRead[E] - private init(length: Int) do self._length = length + # The corresponding C type + type NATIVE: NativeCArray + + # Pointer to the real C array + var native_array: NATIVE is noinit + + init(length: Int) is old_style_init do self._length = length + + redef fun [](index) + do + assert not destroyed + assert index >= 0 and index < length + return native_array[index] + end + + # Set `val` at `index`. + fun []=(index: Int, val: E) + do + assert not destroyed + assert index >= 0 and index < length + native_array[index] = val + end + + # Was this instance destroyed? + # + # See `CArray::destroy`. + var destroyed = false + + # Free used memory used by `native_array`. + # + # Also set `destroyed` to true. + fun destroy + do + if destroyed then return + + native_array.free + destroyed = true + end end # A native C array, as in a pointer to the first element of the array extern class NativeCArray `{ void * `} + + # Type of contained elements. type E: nullable Object - type SELF: NativeCArray - fun [](index: E): E is abstract - fun []=(index: E, val: E) is abstract + # Get element at `index`. + fun [](index: Int): E is abstract + + # Set `val` at `index`. + fun []=(index: Int, val: E) is abstract # Return pointer to the address to the second element of this array # @@ -41,55 +85,168 @@ end # Wrapper around an array of `int` in C (`int*`) with length and destroy state class CIntArray super CArray[Int] + redef type NATIVE: NativeCIntArray - var native_array: NativeCIntArray - init(size: Int) - do + # Initialize a new CIntArray of `size` elements. + init(size: Int) is old_style_init do native_array = new NativeCIntArray(size) super size end - redef fun [](index) + # Create from a `SequenceRead[Int]` + new from(array: SequenceRead[Int]) do - assert not destroyed - assert index >= 0 and index < length - return native_array[index] + var carray = new CIntArray(array.length) + for i in array.length.times do + carray[i] = array[i] + end + return carray + end +end + +# An array of `int` in C (`int*`) +extern class NativeCIntArray `{ int* `} + super NativeCArray + redef type E: Int + + # Initialize a new NativeCIntArray of `size` elements. + new(size: Int) `{ return calloc(size, sizeof(int)); `} + + redef fun [](index) `{ return self[index]; `} + redef fun []=(index, val) `{ self[index] = val; `} + + redef fun +(offset) `{ return self + offset; `} +end + +# Wrapper of a C array of type `uint16_t*` with length and destroy state +class CUInt16Array + super CArray[Int] + redef type NATIVE: NativeCUInt16Array + + # Initialize a new CIntArray of `size` elements. + init(size: Int) is old_style_init do + native_array = new NativeCUInt16Array(size) + super size end - fun []=(index: Int, val: Int) + # Create from a `SequenceRead[Int]` + new from(array: SequenceRead[Int]) do - assert not destroyed - assert index >= 0 and index < length - native_array[index] = val + var carray = new CUInt16Array(array.length) + for i in array.length.times do + carray[i] = array[i] + end + return carray end +end - var destroyed = false - fun destroy +# An array of `uint16_t` in C +extern class NativeCUInt16Array `{ uint16_t* `} + super NativeCArray + redef type E: Int + + # Initialize a new NativeCUInt16Array of `size` elements. + new(size: Int) `{ return calloc(size, sizeof(uint16_t)); `} + + redef fun [](index) `{ return self[index]; `} + redef fun []=(index, val) `{ self[index] = val; `} + + redef fun +(offset) `{ return self + offset; `} +end + +# Wrapper around an array of `unsigned char` in C (`unsigned char*`) with length and destroy state +class CByteArray + super CArray[Byte] + redef type NATIVE: NativeCByteArray + + # Allocate a new array of `size` + init(size: Int) is old_style_init do + native_array = new NativeCByteArray(size) + super size + end + + # Create from a `SequenceRead[Byte]` + new from(array: SequenceRead[Byte]) do - if destroyed then return + var carray = new CByteArray(array.length) + for i in array.length.times do + carray[i] = array[i] + end + return carray + end - native_array.free - destroyed = true + # Safely move `n` bytes from `dst_offset` to `src_offset`, inside this array + # + # Require: all arguments greater than 0 and ranges within `length` + fun move(dst_offset, src_offset, n: Int) + do + assert dst_offset >= 0 and src_offset >= 0 and n >= 0 + assert dst_offset + n <= length + assert src_offset + n <= length + + native_array.move(dst_offset, src_offset, n) end end -# An array of `int` in C (`int*`) -extern class NativeCIntArray `{ int* `} +# An array of `unsigned char` in C (`unsigned char*`) +extern class NativeCByteArray `{ unsigned char* `} super NativeCArray - redef type E: Int - redef type SELF: NativeCIntArray + redef type E: Byte - new(size: Int) `{ return calloc(size, sizeof(int)); `} - redef fun [](index) `{ return recv[index]; `} - redef fun []=(index, val) `{ recv[index] = val; `} + # Allocate a new array of `size` + new(size: Int) `{ return calloc(size, sizeof(unsigned char)); `} + + redef fun [](index) `{ return self[index]; `} + redef fun []=(index, val) `{ self[index] = val; `} + + redef fun +(offset) `{ return self + offset; `} + + # Move `n` bytes from `dst_offset` to `src_offset` + fun move(dst_offset, src_offset, n: Int) `{ + memmove(self+dst_offset, self+src_offset, n); + `} +end + +# Wrapper around an array of `CString` in C (`char**`) with length and destroy state. +class CCStringArray + super CArray[CString] + + redef type NATIVE: NativeCStringArray + + # Initialize a new NativeCStringArray of `size` elements. + init(size: Int) is old_style_init do + native_array = new NativeCStringArray(size) + super size + end + + # Create from an `SequenceRead[CString]` + new from(array: SequenceRead[CString]) + do + var carray = new CCStringArray(array.length) + for i in array.length.times do + carray[i] = array[i] + end + return carray + end +end + +# An array of `CString` in C (`char**`) +extern class NativeCStringArray `{ char** `} + super NativeCArray + + redef type E: CString + + # Initialize a new NativeCStringArray of `size` elements. + new(size: Int) `{ return calloc(size, sizeof(char*)); `} - redef fun +(offset) `{ return recv + offset; `} + redef fun [](index) `{ return self[index]; `} + redef fun []=(index, val) `{ self[index] = val; `} + redef fun +(offset) `{ return self + offset; `} end -redef class NativeString +redef class CString super NativeCArray redef type E: Char - redef type SELF: NativeString - redef fun +(offset) `{ return recv + offset; `} + redef fun +(offset) `{ return self + offset; `} end