slice
Overview
A slice is a abstract struct that refers to a segment of an array. Each struct that has an attribute s (defines the sequence length) and v (points to the first value of the sequence) can be viewed as a slice.
A slice does not own the referenced sequence, this allows to point with different slices at the same array.
It is best practice to define slice structs that just have the s and the v attribute. It is also recommended to use two kind of slices for a type or struct. A slice type where v is a pointer to const data and a slice that points to variable data.
Data Type | Const Data Slice | Variable Data Slice |
---|---|---|
char |
cChars |
cVarChars |
int8_t |
cInt8Slice |
cVarInt8Slice |
This module defines code generation macros to generate typed slice structs. Also has this module macro functions that work with all structs that can be viewed as a slice.
Code Generation Macros
type
SLICES_C_
#define SLICES_C_( Type, SliceType, VarSliceType )
Generates two slices for sequences with Type values. The struct SliceType for const sequences and VarSliceType for variable sequences.
The following call can be used in a .h or .c file.
SLICES_C_(
int8_t, // Type
cInt8Slice, // SliceType
cVarInt8Slice // VarSliceType
)
type
TEMP_SLICE_C_
#define TEMP_SLICE_C_( Entry, EntryStruct )
Generates a struct with the name Entry and a slice with the composed name EntrySlice. The Entry struct will have the in EntryStruct defined structure.
#include "clingo/lang/expect.h"
#include "clingo/lang/slice.h"
TEMP_SLICE_C_(
test,
{
char const* input;
int exp;
}
)
#define t_( ... ) ((test){__VA_ARGS__})
int main( void )
{
init_tap_c_();
testSlice tests = slice_c_( test,
t_( "1234", 1234 ),
t_( "-78", -78 )
);
for ( int64_t i = 0; i < tests.s; ++i )
{
test t = tests.v[i];
int res = atoi( t.input );
tap_descf_c( res == t.exp, "test at index %"PRIi64, i );
}
return finish_tap_c_();
}
[id='TEMP_VAR_SLICE_C_ ==== TEMP_VAR_SLICE_C_
#define TEMP_VAR_SLICE_C_( Entry, EntryStruct )
Generates a struct with the name Entry and a var slice with the composed name EntrySlice. The Entry struct will have the in EntryStruct defined structure.
Functions
init
as_c_
#define as_c_( SliceType, Slice )
A macro function that converts a abstract slice to a slice with the SliceType.
atween_c_
#define atween_c_( Beg, End )
A macro function that returns a slice that is defined with a pointer at the first element and a pointer after the last element.
#include "clingo/lang/expect.h"
#include "clingo/lang/slice.h"
#include "clingo/type/cChars.h"
int main( void )
{
init_tap_c_();
cChars cs = c_c( "abcdef" );
char const* beg = begin_c_( cs );
char const* end = end_c_( cs );
cChars abcdef = atween_c_( beg, end );
expect_c_( chars_is_c( abcdef, "abcdef" ) );
++beg;
--end;
cChars bcde = atween_c_( beg, end );
expect_c_( chars_is_c( bcde, "bcde" ) );
return finish_tap_c_();
}
empty_c_
#define empty_c_()
A macro function to initialse an empty slice where s is 0 and v is NULL.
heap_slice_c_
#define heap_slice_c_( Size, Type )
A macro function for the initialization of a slice with a sequence that will be allocated on the heap. Size defines the length of the sequence. Type defines the data type of the values in the sequence.
invalid_c_
#define invalid_c_()
A macro function to initialse an invalid slice.
scalars_c_
#define scalars_c_( Size, Type )
A macro function for the initializaiton of a slice with a sequence of scalar values. Size defines the length of the sequence. Type defines the data type of the values in the sequence.
#include "clingo/lang/expect.h"
#include "clingo/lang/slice.h"
#include "clingo/type/int64.h" // for cInt64Slice
int main( void )
{
init_tap_c_();
cVarInt64Slice slice = scalars_c_( 3, int64_t );
slice.v[ 0 ] = -10;
slice.v[ 1 ] = 100;
slice.v[ 2 ] = 200;
expect_c_( slice.s == 3 );
expect_c_( slice.v[ 0 ] == -10 );
expect_c_( slice.v[ 1 ] == 100 );
expect_c_( slice.v[ 2 ] == 200 );
// wrong code we acces the memory outside the array
// slice.v[ 3 ] = 999;
return finish_tap_c_();
}
slice_c_
#define slice_c_( Type, ... )
A macro function for the initialization of a slice with a sequence. Type defines the data type of the values in the sequence. The additional arguments(…) represent the values that the sequence should have.
#include "clingo/lang/expect.h"
#include "clingo/lang/slice.h"
#include "clingo/type/cChars.h"
//************************************** example struct
struct Point
{
int32_t x;
int32_t y;
};
typedef struct Point Point;
SLICES_C_(
Point,
PointSlice,
VarPointSlice
)
//**************************************
static cChars abc = slice_c_( char, 'a', 'b', 'c' );
int main( void )
{
init_tap_c_();
// global static slice
expect_c_( abc.s == 3 );
expect_c_( abc.v[ 0 ] == 'a' );
expect_c_( abc.v[ 1 ] == 'b' );
expect_c_( abc.v[ 2 ] == 'c' );
// local slice
cVarChars def = slice_c_( char, 'd', 'e', 'f' );
expect_c_( def.s == 3 );
expect_c_( def.v[ 0 ] == 'd' );
expect_c_( def.v[ 1 ] == 'e' );
expect_c_( def.v[ 2 ] == 'f' );
def.v[ 1 ] = 'x';
expect_c_( def.v[ 1 ] == 'x' );
// with struct values
VarPointSlice points = slice_c_( Point, { .x=1, .y=2 }, { 3, 4 } );
expect_c_( points.v[ 0 ].x == 1 );
expect_c_( points.v[ 0 ].y == 2 );
expect_c_( points.v[ 1 ].x == 3 );
expect_c_( points.v[ 1 ].y == 4 );
return finish_tap_c_();
}
structs_c_
#define structs_c_( Size, Type )
A macro function for the initializaiton of a slice with a sequence of structs. Size defines the length of the sequence. Type defines the data type of the values in the sequence.
#include "clingo/lang/slice.h"
#include "clingo/lang/expect.h"
//************************************** example struct
struct Point
{
int64_t x;
int64_t y;
};
typedef struct Point Point;
SLICES_C_(
Point,
PointSlice,
VarPointSlice
)
//**************************************
int main( void )
{
init_tap_c_();
VarPointSlice slice = structs_c_( 3, Point );
slice.v[ 0 ] = (Point){ .x=1, .y=200 };
slice.v[ 1 ] = (Point){ 3000, 44 };
slice.v[ 2 ].x = -55;
slice.v[ 2 ].y = 666;
expect_c_( slice.s == 3 );
expect_c_( slice.v[ 0 ].x == 1 );
expect_c_( slice.v[ 0 ].y == 200 );
expect_c_( slice.v[ 1 ].x == 3000 );
expect_c_( slice.v[ 1 ].y == 44 );
expect_c_( slice.v[ 2 ].x == -55 );
expect_c_( slice.v[ 2 ].y == 666 );
// wrong code we acces the memory outside the array
// slice.v[ 3 ] = (Point){ .x=999 };
return finish_tap_c_();
}
sub
left_c_
#define left_c_( SliceType, Slice, MaxLen )
A macro function that returns a sub-slice that contains the leftmost values of a slice. If maxLen is greater or equal the s value of slice, contains the sub-slice all values from the slice.
include::{xmpldir}/left.c
mid_c_
#define mid_c_( SliceType, Slice, Idx )
A macro function that returns a sub-slice starting(including) at a given index. If index does not point into the slice returns the function an empty slice.
include::{xmpldir}/mid.c
right_c_
#define right_c_( SliceType, Slice, MaxLen )
A macro function that return a sub-slice that contains the rightmost values of a slice. If maxLen is greater or equal as the s value of slice, contains the sub-slice all values from the slice.
include::{xmpldir}/right.c
sub_c_
#define sub_c_( SliceType, Slice, BegIdx, EndIdx )
A macro function that returns a sub-slice of a given slice. The returned sub-slice includes the value at begIdx(begin index) as first value and the value at endIdx-1 as last value. If begIdx or endIdx are not valid indices returns the function a empty slice.
include::{xmpldir}/sub.c
check
is_empty_c_
#define is_empty_c_( Slice )
Returns true if the Slice is empty, otherwise false.
#include "clingo/lang/expect.h"
#include "clingo/lang/slice.h"
#include "clingo/type/cChars.h"
int main( void )
{
init_tap_c_();
expect_c_( is_empty_c_( (cChars)empty_c_() ) );
expect_c_( is_empty_c_( c_c( "" ) ) );
cChars abc = c_c( "abc" );
expect_c_( not is_empty_c_( abc ) );
abc.s = 0;
expect_c_( is_empty_c_( abc ) );
return finish_tap_c_();
}
is_empty_c_
#define is_invalid_c_( Slice )
Returns true if the Slice is invalid, otherwise false. A slice wiht a negative s value is invalid.
is_sub_c_
#define is_sub_c_( Main, Sub )
Returns true if Sub is a sub-slice from Main, otherwise false.
#include "clingo/lang/expect.h"
#include "clingo/lang/slice.h"
#include "clingo/type/cChars.h"
int main( void )
{
init_tap_c_();
// ------------------------------------------------------------------- cChars
cChars chars = c_c( "Earth, Wind and Fire" );
cChars earth = left_c_( cChars, chars, 5 );
cChars wind = sub_c_( cChars, chars, 7, 11 );
cChars fire = right_c_( cChars, chars, 4 );
cChars windAndFire = mid_c_( cChars, chars, 7 );
expect_c_( is_sub_c_( chars, earth ) );
expect_c_( is_sub_c_( chars, wind ) );
expect_c_( is_sub_c_( chars, fire ) );
expect_c_( is_sub_c_( chars, windAndFire ) );
return finish_tap_c_();
}
valid_index_c_
#define valid_index_c_( Slice, Index )
Checks if a Index is inside the size boundaries of the Slice.
#include "clingo/lang/expect.h"
#include "clingo/lang/slice.h"
#include "clingo/type/cChars.h"
int main( void )
{
init_tap_c_();
cChars empty = empty_c_();
expect_c_( !valid_index_c_( empty, 0 ) );
expect_c_( !valid_index_c_( empty, 1 ) );
cChars abc = c_c( "abc" );
expect_c_( !valid_index_c_( abc, -1 ) );
expect_c_( valid_index_c_( abc, 0 ) );
expect_c_( valid_index_c_( abc, 1 ) );
expect_c_( valid_index_c_( abc, 2 ) );
expect_c_( !valid_index_c_( abc, 3 ) );
return finish_tap_c_();
}
access
first_c_
#define first_c_( Slice )
Returns the first value in the Slice.
#include "clingo/lang/expect.h"
#include "clingo/lang/slice.h"
#include "clingo/type/cChars.h"
int main( void )
{
init_tap_c_();
cChars abc = c_c( "abc" );
expect_c_( first_c_( abc ) == 'a' );
cChars foo = c_c( "xyz" );
expect_c_( first_c_( foo ) == 'x' );
return finish_tap_c_();
}
get_if_c_
#define get_if_c_( Slice, Index, Def )
Returns the value at the Index position in the Slice. If the Index is invalid will the Def value returned.
#include "clingo/lang/expect.h"
#include "clingo/lang/slice.h"
#include "clingo/type/cChars.h"
int main( void )
{
init_tap_c_();
cChars abc = c_c( "abc" );
expect_c_( get_if_c_( abc, -1, 'x' ) == 'x' );
expect_c_( get_if_c_( abc, 0, 'x' ) == 'a' );
expect_c_( get_if_c_( abc, 1, 'x' ) == 'b' );
expect_c_( get_if_c_( abc, 2, 'x' ) == 'c' );
expect_c_( get_if_c_( abc, 3, 'x' ) == 'x' );
return finish_tap_c_();
}
last_c_
#define last_c_( Slice )
Returns the last value in the Slice.
#include "clingo/lang/expect.h"
#include "clingo/lang/slice.h"
#include "clingo/type/cChars.h"
int main( void )
{
init_tap_c_();
cChars abc = c_c( "abc" );
expect_c_( last_c_( abc ) == 'c' );
cChars bar = c_c( "bar" );
expect_c_( last_c_( bar ) == 'r' );
return finish_tap_c_();
}
set_if_c_
#define set_if_c_( Slice, Index, Value )
Updates the Value at the Index position in the Slice. If the Index is invalid will no value be replaced.
#include "clingo/lang/expect.h"
#include "clingo/lang/slice.h"
#include "clingo/type/int64.h" // for cInt64Slice
int main( void )
{
init_tap_c_();
cVarInt64Slice slice4 = slice_c_( int64_t, 11, 22, 33, 44 );
cVarInt64Slice slice3 = left_c_( cVarInt64Slice, slice4, 3 );
set_if_c_( slice3, 0, 10 );
set_if_c_( slice3, 1, 20 );
set_if_c_( slice3, 2, 30 );
set_if_c_( slice3, 3, 40 ); // out of slice range
expect_c_( slice4.v[ 0 ] == 10 );
expect_c_( slice4.v[ 1 ] == 20 );
expect_c_( slice4.v[ 2 ] == 30 );
expect_c_( slice4.v[ 3 ] == 44 ); // not set
return finish_tap_c_();
}
pointer access
begin_c_
#define begin_c_( Slice )
Returns a pointer to the firts element of the sequence.
#include "clingo/lang/expect.h"
#include "clingo/lang/slice.h"
#include "clingo/type/cChars.h"
int main( void )
{
init_tap_c_();
cChars abc = c_c( "abc" );
expect_c_( *begin_c_( abc ) == 'a' );
char const* iter = begin_c_( abc );
expect_c_( *iter == 'a' );
++iter;
expect_c_( *iter == 'b' );
++iter;
expect_c_( *iter == 'c' );
++iter;
expect_c_( iter == end_c_( abc ) );
return finish_tap_c_();
}
end_c_
#define end_c_( Slice )
Returns a pointer to the element past the last element of the sequence.
#include "clingo/lang/expect.h"
#include "clingo/lang/slice.h"
#include "clingo/type/cChars.h"
int main( void )
{
init_tap_c_();
cChars abc = c_c( "abcx" );
abc.s--;
expect_c_( *end_c_( abc ) == 'x' );
char const* iter = end_c_( abc );
expect_c_( *iter == 'x' );
--iter;
expect_c_( *iter == 'c' );
--iter;
expect_c_( *iter == 'b' );
--iter;
expect_c_( iter == begin_c_( abc ) );
return finish_tap_c_();
}
for_each_c_
#define for_each_c_( Type, Itr, Slice )
Macro function to define a for statement to iterate over all elements in Slice.
#include "clingo/lang/expect.h"
#include "clingo/lang/slice.h"
#include "clingo/type/cChars.h"
int main( void )
{
init_tap_c_();
cVarChars buf = scalars_c_( 8, char );
bool flag = true;
for_each_c_( char*, c, buf )
{
if ( flag )
{
*c = '+';
flag = false;
}
else
{
*c = '.';
flag = true;
}
}
cChars slc = as_c_( cChars, buf );
expect_c_( chars_is_c( slc, "+.+.+.+." ) );
return finish_tap_c_();
}
nth_c_
#define nth_c_( Slice, N )
Returns a pointer to value at the position N in the Slice. Th N value can be negative to access the Slice backwards. If the N value is out of range will NULL be returned.
#include "clingo/lang/expect.h"
#include "clingo/lang/slice.h"
#include "clingo/type/cChars.h"
int main( void )
{
init_tap_c_();
cChars abcdef = c_c( "abcdef" );
expect_c_( *nth_c_( abcdef, 0 ) == 'a' );
expect_c_( *nth_c_( abcdef, 5 ) == 'f' );
expect_c_( *nth_c_( abcdef, -1 ) == 'f' );
expect_c_( *nth_c_( abcdef, -6 ) == 'a' );
expect_c_( nth_c_( abcdef, 6 ) == NULL );
expect_c_( nth_c_( abcdef, -7 ) == NULL );
return finish_tap_c_();
}
index_of_c_
#define index_of_c_( Slice, Ptr )
Returns the index of the pointer Ptr. If the pointer does not point to a value of the sequence returns the macro function -1.
#include "clingo/lang/expect.h"
#include "clingo/lang/slice.h"
#include "clingo/type/cChars.h"
int main( void )
{
init_tap_c_();
cChars abc = c_c( "abc" );
char const* ptr = NULL;
expect_c_( index_of_c_( abc, ptr ) == -1 );
ptr = begin_c_( abc );
expect_c_( index_of_c_( abc, ptr ) == 0 );
ptr++;
expect_c_( index_of_c_( abc, ptr ) == 1 );
ptr = rbegin_c_( abc );
expect_c_( index_of_c_( abc, ptr ) == 2 );
ptr = end_c_( abc );
expect_c_( index_of_c_( abc, ptr ) == -1 );
ptr = rend_c_( abc );
expect_c_( index_of_c_( abc, ptr ) == -1 );
return finish_tap_c_();
}
points_into_c_
#define points_into_c_( Slice, Ptr )
Checks if the pointer Ptr points to a value in the sequence of the Slice.
#include "clingo/lang/expect.h"
#include "clingo/lang/slice.h"
#include "clingo/type/cChars.h"
int main( void )
{
init_tap_c_();
cChars abc = c_c( "abc" );
expect_c_( points_into_c_( abc, begin_c_( abc ) ) );
expect_c_( points_into_c_( abc, rbegin_c_( abc ) ) );
expect_c_( !points_into_c_( abc, end_c_( abc ) ) );
expect_c_( !points_into_c_( abc, rend_c_( abc ) ) );
char const* ptr = begin_c_( abc );
ptr++;
expect_c_( points_into_c_( abc, ptr ) );
ptr = NULL;
expect_c_( !points_into_c_( abc, ptr ) );
return finish_tap_c_();
}
ptr_for_c_
#define ptr_for_c_( Slice, Index )
Returns a pointer to value at the Index position in the Slice. If the Index is invalid will a null pointer returned.
#include "clingo/lang/expect.h"
#include "clingo/lang/slice.h"
#include "clingo/type/cChars.h"
int main( void )
{
init_tap_c_();
cChars abcdef = c_c( "abcdef" );
char const* ptr = NULL;
// ---------------------------------------------------- returns valid pointer
ptr = ptr_for_c_( abcdef, 0 );
expect_c_( *ptr == 'a' );
ptr = ptr_for_c_( abcdef, 2 );
expect_c_( *ptr == 'c' );
ptr = ptr_for_c_( abcdef, 5 );
expect_c_( *ptr == 'f' );
// ---------------------------------------------------- try to access outside
ptr = ptr_for_c_( abcdef, -1 );
expect_c_( ptr == NULL );
ptr = ptr_for_c_( abcdef, 6 );
expect_c_( ptr == NULL );
return finish_tap_c_();
}
rbegin_c_
#define rbegin_c_( Slice )
Returns a pointer to the last element of the sequence.
#include "clingo/lang/expect.h"
#include "clingo/lang/slice.h"
#include "clingo/type/cChars.h"
int main( void )
{
init_tap_c_();
cChars abc = c_c( "abc" );
expect_c_( *rbegin_c_( abc ) == 'c' );
char const* itr = rbegin_c_( abc );
expect_c_( *itr == 'c' );
itr--;
expect_c_( *itr == 'b' );
itr--;
expect_c_( *itr == 'a' );
itr--;
expect_c_( itr == rend_c_( abc ) );
return finish_tap_c_();
}
rend_c_
#define rend_c_( Slice )
Returns a pointer to the element before the first element of the sequence.
#include "clingo/lang/expect.h"
#include "clingo/lang/slice.h"
#include "clingo/type/cChars.h"
int main( void )
{
init_tap_c_();
cChars abc = c_c( "xabc" );
abc.v++;
abc.s--;
expect_c_( *rend_c_( abc ) == 'x' );
char const* itr = rend_c_( abc );
expect_c_( *itr == 'x' );
itr++;
expect_c_( *itr == 'a' );
itr++;
expect_c_( *itr == 'b' );
itr++;
expect_c_( itr == rbegin_c_( abc ) );
return finish_tap_c_();
}