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.

slice pineapple

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.

Example
#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.

Example
#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.

Example
#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.

Example
#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.

Example
#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.

Example
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.

Example
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.

Example
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.

Example
include::{xmpldir}/sub.c

check

is_empty_c_

#define is_empty_c_( Slice )

Returns true if the Slice is empty, otherwise false.

Example
#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.

Example
#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.

Example
#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.

Example
#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.

Example
#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.

Example
#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.

Example
#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.

Example
#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.

Example
#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.

Example
#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.

Example
#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.

Example
#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.

Example
#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.

Example
#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.

Example
#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.

Example
#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_();
}