cRune

Overview

Module with functions and types to work with cRune values.

Types and Definitions

cRune

struct cRune
{
   union
   {
      uint32_t ctrl;
      cByte b[4];
      char c[4];
   };
};
typedef struct cRune cRune;

A cRune is a type that can hold a single Unicode code point. The Unicode code point is encoded in UTF-8 inside a cRune.

c_check_rune

typedef bool ( *c_check_rune )( cRune r )

c_check_rune is the signature of a function to check a rune value.

Generated

cRuneSlice

struct cRuneSlice
{
   int64_t s;
   cRune const* v;
};
typedef struct cRuneSlice cRuneSlice;

Via the macro SLICES_C_ generated struct.

cVarRuneSlice

struct cVarRuneSlice
{
   int64_t s;
   cRune* v;
};
typedef struct cVarRuneSlice cVarRuneSlice;

Via the macro SLICES_C_ generated struct.

Functions

utf8

is_utf8_head_c

bool is_utf8_head_c( char c );

Returns true if c is a valid first byte of a UTF-8 encoded code point, otherwise false.

Example
#include "clingo/lang/expect.h"
#include "clingo/type/cRune.h"

int main( void )
{
   init_tap_c_();

   char const* cs1 = "®"; // size 2
   expect_c_(  is_utf8_head_c( cs1[0] ) );
   expect_c_( !is_utf8_head_c( cs1[1] ) );

   char const* cs2 = ""; // size 3
   expect_c_(  is_utf8_head_c( cs2[0] ) );
   expect_c_( !is_utf8_head_c( cs2[1] ) );
   expect_c_( !is_utf8_head_c( cs2[2] ) );

   char const* cs3 = "𝄞"; // size 4
   expect_c_(  is_utf8_head_c( cs3[0] ) );
   expect_c_( !is_utf8_head_c( cs3[1] ) );
   expect_c_( !is_utf8_head_c( cs3[2] ) );
   expect_c_( !is_utf8_head_c( cs3[3] ) );

   return finish_tap_c_();
}

is_utf8_tail_c

bool is_utf8_tail_c( char c );

Returns true if c is a valid byte in the tail of a UTF-8 encoded code point, otherwise false.

Example
#include "clingo/lang/expect.h"
#include "clingo/type/cRune.h"

int main( void )
{
   init_tap_c_();

   char const* cs1 = "®"; // size 2
   expect_c_( !is_utf8_tail_c( cs1[0] ) );
   expect_c_(  is_utf8_tail_c( cs1[1] ) );

   char const* cs2 = ""; // size 3
   expect_c_( !is_utf8_tail_c( cs2[0] ) );
   expect_c_(  is_utf8_tail_c( cs2[1] ) );
   expect_c_(  is_utf8_tail_c( cs2[2] ) );

   char const* cs3 = "𝄞"; // size 4
   expect_c_( !is_utf8_tail_c( cs3[0] ) );
   expect_c_(  is_utf8_tail_c( cs3[1] ) );
   expect_c_(  is_utf8_tail_c( cs3[2] ) );
   expect_c_(  is_utf8_tail_c( cs3[3] ) );

   return finish_tap_c_();
}

utf8_length_c

int8_t utf8_length_c( char c );

Returns number of bytes of the UTF-8 encoded code point. An invalid c value leads to the result 0.

Example
#include "clingo/lang/expect.h"
#include "clingo/type/cRune.h"

int main( void )
{
   init_tap_c_();

   char const* cs1 = "y";
   expect_c_( utf8_length_c( cs1[0] ) == 1 );

   char const* cs2 = "®";
   expect_c_( utf8_length_c( cs2[0] ) == 2 );

   char const* cs3 = "";
   expect_c_( utf8_length_c( cs3[0] ) == 3 );

   char const* cs4 = "𝄞";
   expect_c_( utf8_length_c( cs4[0] ) == 4 );

   expect_c_( utf8_length_c( char_c_( 0xff ) ) == 0 );

   return finish_tap_c_();
}

utf16

is_high_utf16_surrogate_c

bool is_high_utf16_surrogate_c( uint16_t val );

Returns true if the value represents a UTF-16 high surrogate value.

is_low_utf16_surrogate_c

bool is_low_utf16_surrogate_c( uint16_t val );

Returns true if the value represents a UTF-16 low surrogate value.

utf16_to_utf32_c

uint32_t utf16_to_utf32_c( uint16_t high, uint16_t low );

Converts a UTF-16 surrogate pair to an UTF-32 value.

Example
#include "clingo/lang/expect.h"
#include "clingo/type/cRune.h"

TEMP_SLICE_C_(
   test,
   {
      uint16_t h;
      uint16_t l;
      uint32_t exp;
   }
)
#define t_( ... ) ((test){__VA_ARGS__})

int main( void )
{
   init_tap_c_();

   testSlice tests = slice_c_( test,
      t_( 0xd834, 0xdd1e, 0x1d11e ),
      t_( 0xd83d, 0xde03, 0x1f603 ),
      t_( 0x2605, 0x0, 0x2605 )
   );

   for_each_c_( test const*, t, tests )
   {
      uint32_t val = utf16_to_utf32_c( t->h, t->l );
      expect_c_( val == t->exp );
   }

   return finish_tap_c_();
}

utf32_to_utf16_c

uint16_t utf32_to_utf16_c( uint32_t val, uint16_t low[static 1] );

Converts a UTF-32 in to a UTF-16 surrogate pair. The function returns the high surrogate and writes the low surrogate into low.

Example
#include "clingo/lang/expect.h"
#include "clingo/type/cRune.h"

TEMP_SLICE_C_(
   test,
   {
      uint32_t inp;
      uint16_t val;
      uint16_t low;
   }
)
#define t_( ... ) ((test){__VA_ARGS__})

int main( void )
{
   init_tap_c_();

   testSlice tests = slice_c_( test,
      t_( 0x1d11e, 0xd834, 0xdd1e ),
      t_( 0x1f603, 0xd83d, 0xde03 ),
      t_( 0x2605, 0x2605, 0x0 )
   );

   for_each_c_( test const*, t, tests )
   {
      uint16_t low = 0;
      uint16_t high = utf32_to_utf16_c( t->inp, &low );
      expect_c_( t->val == high );
      expect_c_( t->low == low );
   }

   return finish_tap_c_();
}

init

build_rune_c_

#define build_rune_c_( A, B, C, D )

Creates a cRune with the byte values A, B, C and D.

Example
#include "clingo/lang/expect.h"
#include "clingo/type/cRune.h"

int main( void )
{
   init_tap_c_();

   cRune dollar = build_rune_c_( 0x24, 0, 0, 0 );
   expect_c_( rune_is_c( dollar, "$" ) );
   expect_c_( not rune_is_c( dollar, "" ) );

   cRune euro = build_rune_c_( 0xe2, 0x82, 0xac, 0 );
   expect_c_( rune_is_c( euro, "" ) );
   expect_c_( not rune_is_c( euro, "$" ) );

   return finish_tap_c_();
}

make_rune_c

cRune make_rune_c( cChars chars );

Creates a cRune from the UTF-8 encoded code point at the front.

Example
#include "clingo/lang/expect.h"
#include "clingo/type/cRune.h"

int main( void )
{
   init_tap_c_();

   cChars euroChars = c_c( "" );
   cRune euro = make_rune_c( euroChars );
   expect_c_( rune_is_c( euro, "" ) );

   cRune invalidEuro = make_rune_c( left_c_( cChars, euroChars ,2 ) );
   expect_c_( not rune_is_valid_c( invalidEuro ) );

   return finish_tap_c_();
}

null_rune_c

cRune null_rune_c();

Creates a invalid cRune.

Example
#include "clingo/lang/expect.h"
#include "clingo/type/cRune.h"

int main( void )
{
   init_tap_c_();

   cRune r = null_rune_c();
   expect_c_( not rune_is_valid_c( r ) );

   return finish_tap_c_();
}

rune_c

cRune rune_c( char const cstr[static 1] );

Creates a cRune from the UTF-8 encoded code point at the front.

Example
#include "clingo/lang/expect.h"
#include "clingo/type/cRune.h"

int main( void )
{
   init_tap_c_();

   cRune x = rune_c( "x" );
   expect_c_( rune_is_c( x, "x" ) );

   cRune y = rune_c( "yz" );
   expect_c_( rune_is_c( y, "y" ) );

   cRune snowman = rune_c( "☃ needs an ☂" );
   expect_c_( rune_is_c( snowman, "" ) );

   return finish_tap_c_();
}

utf16_rune_c

cRune utf16_rune_c( uint16_t val );

Creates a cRune from a UTF-16 encoded code point.

Example
#include "clingo/lang/expect.h"
#include "clingo/type/cRune.h"

#define expect_( Rune, Exp )                                                   \
   expect_c_(                                                                  \
      rune_is_c( (Rune), (Exp) )                                               \
   )

int main( void )
{
   init_tap_c_();

   expect_( utf16_rune_c( 0x56 ), "V" );
   expect_( utf16_rune_c( 0xe9 ), "é" );
   expect_( utf16_rune_c( 0x2602 ), "" );

   return finish_tap_c_();
}

utf32_rune_c

cRune utf32_rune_c( uint32_t val );

Creates a rune from a UTF-32 encoded code point.

Example
#include "clingo/lang/expect.h"
#include "clingo/type/cRune.h"

#define expect_( Rune, Exp )                                                   \
   expect_c_(                                                                  \
      rune_is_c( (Rune), (Exp) )                                               \
   )

int main( void )
{
   init_tap_c_();

   expect_( utf32_rune_c( 0x56 ), "V" ); // 56
   expect_( utf32_rune_c( 0xe9 ), "é" ); // c3 a9
   expect_( utf32_rune_c( 0x0f3c ), "" ); // e0 bc bc
   expect_( utf32_rune_c( 0x0103ab ), "𐎫" ); // f0 90 8e ab

   return finish_tap_c_();
}

overall

cmp_rune_c

int cmp_rune_c( cRune a, cRune b );

Compares the cRune values and returns the three possible results:

<0

means that a is less compared to b

0

means that a and b are equal

>0

means that a is greater compared to b

Example
#include "clingo/lang/expect.h"
#include "clingo/type/cRune.h"

int main( void )
{
   init_tap_c_();

   // ascii
   cRune x = rune_c( "x" );
   cRune y = rune_c( "y" );
   cRune z = rune_c( "z" );

   expect_eq_c_( cmp_rune_c( x, x ) );
   expect_eq_c_( cmp_rune_c( y, y ) );
   expect_eq_c_( cmp_rune_c( z, z ) );

   expect_lt_c_( cmp_rune_c( x, y ) );
   expect_lt_c_( cmp_rune_c( x, z ) );
   expect_lt_c_( cmp_rune_c( y, z ) );

   expect_gt_c_( cmp_rune_c( y, x ) );
   expect_gt_c_( cmp_rune_c( z, x ) );
   expect_gt_c_( cmp_rune_c( z, y ) );

   // unicode
   cRune umbrella  = rune_c( "" ); // U+2602
   expect_eq_c_( cmp_rune_c( umbrella, utf16_rune_c( 0x2602 ) ) );

   cRune snowman = rune_c( "" ); // U+2603
   expect_eq_c_( cmp_rune_c( snowman, utf16_rune_c( 0x2603 ) ) );

   expect_lt_c_( cmp_rune_c( umbrella, snowman ) );
   expect_gt_c_( cmp_rune_c( snowman, umbrella ) );


   return finish_tap_c_();
}

eq_rune_c

bool eq_rune_c( cRune a, cRune b );

Checks if a and b are equal.

Example
#include "clingo/lang/expect.h"
#include "clingo/type/cRune.h"

int main( void )
{
   init_tap_c_();

   cRune x = rune_c( "x" );
   cRune snowman = rune_c( "" ); // U+2603

   expect_c_(  eq_rune_c( x, x ) );
   expect_c_(  eq_rune_c( snowman, snowman ) );
   expect_c_( !eq_rune_c( x, snowman ) );

   return finish_tap_c_();
}

rune_code_c

uint32_t rune_code_c( cRune r );

Converts a rune into a UTF-32 encoded code point.

Example
#include "clingo/lang/expect.h"
#include "clingo/type/cRune.h"

TEMP_SLICE_C_(
   test,
   {
      char const* input;
      uint32_t exp;
   }
)
#define t_( ... ) ((test){__VA_ARGS__})

int main( void )
{
   init_tap_c_();

   testSlice tests = slice_c_( test,
      t_( "A", 0x41 ),
      t_( "ö", 0xf6 ),
      t_( "Ж", 0x0416 ),
      t_( "", 0x20ac ),
      t_( "𝄞", 0x1d11e ),
      t_( "α", 0x03b1 ),
      t_( "😎", 0x01f60e )
   );

   for ( int64_t i = 0; i < tests.s; ++i )
   {
      test t = tests.v[i];
      cRune r = rune_c( t.input );
      uint32_t res = rune_code_c( r );
      tap_descf_c( res == t.exp, "test at index %"PRIi64, i );
   }

   return finish_tap_c_();
}

rune_is_c

bool rune_is_c( cRune r, char const cstr[static 1] );

Checks if r and the first UTF-8 encoded code point in the C string are equal.

Example
#include "clingo/lang/expect.h"
#include "clingo/type/cRune.h"

int main( void )
{
   init_tap_c_();

   cRune umbrella = rune_c( "" );

   expect_c_(  rune_is_c( umbrella, "" ) );
   expect_c_( !rune_is_c( umbrella, "y" ) );

   return finish_tap_c_();
}

rune_is_valid_c

bool rune_is_valid_c( cRune r );

Checks if r contains a valid byte sequence.

Example
#include "clingo/lang/expect.h"
#include "clingo/type/cRune.h"

int main( void )
{
   init_tap_c_();

   cRune valid = rune_c( "a" );
   expect_c_( rune_is_valid_c( valid ) );

   cRune invalid = { .ctrl=0xffffffff };
   expect_c_( not rune_is_valid_c( invalid ) );

   // € = e2 82 ac
   cRune euro = build_rune_c_( 0xe2, 0x82, 0, 0 );
   expect_c_( not rune_is_valid_c( euro ) );

   return finish_tap_c_();
}

rune_size_c

int8_t rune_size_c( cRune r );

Returns how much bytes are used to store the UTF-8 encoded code point.

Example
#include "clingo/lang/expect.h"
#include "clingo/type/cRune.h"

TEMP_SLICE_C_(
   test,
   {
      char const* input;
      int8_t exp;
   }
)
#define t_( ... ) ((test){__VA_ARGS__})

int main( void )
{
   init_tap_c_();

   testSlice tests = slice_c_( test,
      t_( "", 3 ),
      t_( "y", 1 ),
      t_( "®", 2 ),
      t_( "", 3 ),
      t_( "𝄞", 4 ),
      t_( "yes", 1 )
   );

   for ( int64_t i = 0; i < tests.s; ++i )
   {
      test t = tests.v[i];
      cRune r = rune_c( t.input );
      int8_t res = rune_size_c( r );
      tap_descf_c( res == t.exp, "test at index %"PRIi64, i );
   }

   return finish_tap_c_();
}

access

ceil_to_rune_c

char const* ceil_to_rune_c( cChars chars, int64_t index );

Returns a pointer to the first char of a UTF-8 encoded code point at the byte index. If the char at index is a UTF-8 tail goes the function forward to the next UTF-8 head.

Example
#include "clingo/lang/expect.h"
#include "clingo/type/cRune.h"

int main( void )
{
   init_tap_c_();

   // rune/size -> ®/2 =/1 ☂/3
   cChars chars = c_c( "®=☂" );
   expect_c_( ceil_to_rune_c( chars, 1 ) == ptr_for_c_( chars,  2 ) );
   expect_c_( ceil_to_rune_c( chars, 2 ) == ptr_for_c_( chars,  2 ) );
   expect_c_( ceil_to_rune_c( chars, 3 ) == ptr_for_c_( chars,  3 ) );
   expect_c_( ceil_to_rune_c( chars, 4 ) == ptr_for_c_( chars, -1 ) );



   return finish_tap_c_();
}

first_rune_c

char const* first_rune_c( cChars chars );

Returns a pointer to the first rune in chars.

floor_to_rune_c

char const* floor_to_rune_c( cChars chars, int64_t index );

Returns a pointer to the first char of a UTF-8 encoded code point at the byte index. If the char at index is a UTF-8 tail goes the function back to the beginning of the UTF8- encoded code point.

Example
#include "clingo/lang/expect.h"
#include "clingo/type/cRune.h"

int main( void )
{
   init_tap_c_();

   // rune/size -> ®/2 =/1 ☂/3
   cChars chars = c_c( "®=☂" );
   expect_c_( floor_to_rune_c( chars, 1 ) == ptr_for_c_( chars, 0 ) );
   expect_c_( floor_to_rune_c( chars, 2 ) == ptr_for_c_( chars, 2 ) );
   expect_c_( floor_to_rune_c( chars, 3 ) == ptr_for_c_( chars, 3 ) );
   expect_c_( floor_to_rune_c( chars, 4 ) == ptr_for_c_( chars, 3 ) );

   return finish_tap_c_();
}

last_rune_c

char const* last_rune_c( cChars chars );

Returns a pointer to the last rune in chars.

nth_rune_c

char const* nth_rune_c( cChars chars, int64_t n );

Returns a pointer to the nth UTF-8 encoded code point in the chars. The n value can be nagtive to access the chars backwards. If n is out of range returns the function NULL.

Example
#include "clingo/lang/expect.h"
#include "clingo/type/cRune.h"

#define expect_( Rune, Exp )                                                   \
   expect_c_(                                                                  \
      rune_is_c( rune_c( Rune ), (Exp) )                                       \
   )

int main( void )
{
   init_tap_c_();

   cChars chars = c_c( "abcd€f®!" );

   expect_( nth_rune_c( chars, 0 ), "a" );
   expect_( nth_rune_c( chars, 4 ), "" );
   expect_( nth_rune_c( chars, 5 ), "f" );
   expect_( nth_rune_c( chars, 6 ), "®" );
   expect_( nth_rune_c( chars, 7 ), "!" );
   expect_c_( nth_rune_c( chars, 8 ) == NULL );

   expect_( nth_rune_c( chars, -1 ), "!" );
   expect_( nth_rune_c( chars, -2 ), "®" );
   expect_( nth_rune_c( chars, -3 ), "f" );
   expect_( nth_rune_c( chars, -4 ), "" );
   expect_( nth_rune_c( chars, -8 ), "a" );
   expect_c_( nth_rune_c( chars, -9 ) == NULL );

   return finish_tap_c_();
}

iterate

iterate_runes_c_

#define iterate_runes_c_( Itr, Rune, Chars )

Macro function to define a for statement to iterate over all runes in chars.

Example
#include "clingo/io/cRecorder.h"
#include "clingo/lang/expect.h"
#include "clingo/type/cRune.h"

int main( void )
{
   init_tap_c_();

   cRecorder* ascii = &recorder_c_( 128 );
   cRecorder* unicode = &recorder_c_( 128 );

   cChars chars = c_c( "® yes this is a 𝄞 and €!" );
   cRune r;
   iterate_runes_c_( itr, r, chars )
   {
      cRecorder* rec = rune_size_c( r) == 1 ? ascii : unicode;
      record_rune_c( rec, r );
   }

   expect_c_( recorded_is_c( ascii, " yes this is a  and !" ));
   println_recorded_c( ascii );
   expect_c_( recorded_is_c( unicode, "®𝄞€" ));

   return finish_tap_c_();
}

next_rune_c

char const* next_rune_c( cChars chars, char const* itr, cRune r[static 1] )

Navigates a to the next UTF-8 encoded code point in a C string. The returned iterator is invalid if no next value exist.

Example
#include "clingo/lang/expect.h"
#include "clingo/type/cRune.h"

int main( void )
{
   init_tap_c_();

   cChars chars = c_c( "® yes this is a 𝄞 and €!" );
   cRune r;
   char const* itr;

   itr = next_rune_c( chars, NULL, &r );
   expect_c_( rune_is_c( r, "®" ) );

   itr = next_rune_c( chars, itr, &r );
   expect_c_( rune_is_c( r, " " ) );
   expect_eq_c_( strcmp( " yes this is a 𝄞 and €!", itr ) );

   itr = next_rune_c( chars, itr, &r );
   expect_c_( rune_is_c( r, "y" ) );
   expect_eq_c_( strcmp( "yes this is a 𝄞 and €!", itr ) );

   return finish_tap_c_();
}

char slice

count_runes_c

int64_t count_runes_c( cChars chars );

Counts the number of runes of the chars. Returns -1 for chars with incomplete runes.

Example
#include "clingo/lang/expect.h"
#include "clingo/type/cRune.h"

int main( void )
{
   init_tap_c_();

   // ®=2 / 𝄞=4 / €=3
   cChars chars1 = c_c( "® yes this is a 𝄞 and €!" );
   expect_c_( chars1.s == 30 );
   expect_c_( count_runes_c( chars1 ) == 24 );

   cChars chars2 = c_c( "abcdefgh" );
   expect_c_( chars2.s == 8 );
   expect_c_( count_runes_c( chars2 ) == 8 );

   cChars empty = (cChars)empty_c_();
   expect_c_( count_runes_c( empty ) == 0 );

   cChars euroSign = (cChars){ 7, "euro:€" }; // wrong size
   expect_c_( count_runes_c( euroSign ) == -1 );
   euroSign.s = 8;
   expect_c_( count_runes_c( euroSign ) == 6 );

   return finish_tap_c_();
}

fill_rune_slice_c

cVarRuneSlice fill_rune_slice_c( cVarRuneSlice dst, cChars src );

Fills dst with the complete runes in src.

Example
#include "clingo/lang/expect.h"
#include "clingo/type/cRune.h"

int main( void )
{
   init_tap_c_();

   cChars src = c_c( "My € makes 𝄞®!" );

   {
      cVarRuneSlice dst = structs_c_( 20, cRune );
      cVarRuneSlice res = fill_rune_slice_c( dst, src );

      expect_c_( res.s == 14 );
      expect_c_( rune_is_c( res.v[  0 ], "M" ) );
      expect_c_( rune_is_c( res.v[  1 ], "y" ) );
      expect_c_( rune_is_c( res.v[  2 ], " " ) );
      expect_c_( rune_is_c( res.v[  3 ], "" ) );
      expect_c_( rune_is_c( res.v[  4 ], " " ) );
      expect_c_( rune_is_c( res.v[  5 ], "m" ) );
      expect_c_( rune_is_c( res.v[  6 ], "a" ) );
      expect_c_( rune_is_c( res.v[  7 ], "k" ) );
      expect_c_( rune_is_c( res.v[  8 ], "e" ) );
      expect_c_( rune_is_c( res.v[  9 ], "s" ) );
      expect_c_( rune_is_c( res.v[ 10 ], " " ) );
      expect_c_( rune_is_c( res.v[ 11 ], "𝄞" ) );
      expect_c_( rune_is_c( res.v[ 12 ], "®" ) );
      expect_c_( rune_is_c( res.v[ 13 ], "!" ) );
   }

   {
      cVarRuneSlice dst = structs_c_( 10, cRune );
      cVarRuneSlice res = fill_rune_slice_c( dst, src );

      expect_c_( res.s == 10 );
      expect_c_( rune_is_c( res.v[  0 ], "M" ) );
      expect_c_( rune_is_c( res.v[  1 ], "y" ) );
      expect_c_( rune_is_c( res.v[  2 ], " " ) );
      expect_c_( rune_is_c( res.v[  3 ], "" ) );
      expect_c_( rune_is_c( res.v[  4 ], " " ) );
      expect_c_( rune_is_c( res.v[  5 ], "m" ) );
      expect_c_( rune_is_c( res.v[  6 ], "a" ) );
      expect_c_( rune_is_c( res.v[  7 ], "k" ) );
      expect_c_( rune_is_c( res.v[  8 ], "e" ) );
      expect_c_( rune_is_c( res.v[  9 ], "s" ) );
   }

   return finish_tap_c_();
}

find_any_rune_c

#define find_any_rune_c_( Chars, Cstr )                                        \
   find_any_rune_c( (Chars), c_c( Cstr ) )
char const* find_any_rune_c( cChars chars, cChars set );

Returns a pointer to the first char that matches any of the runes in the set and NULL if non of the runes exist in the chars.

Example
#include "clingo/lang/expect.h"
#include "clingo/type/cRune.h"

#define expect_rune_( Res, Exp )                                               \
   expect_c_( eq_rune_c( rune_c( Res ), rune_c( Exp ) ) );


int main( void )
{
   init_tap_c_();

   cChars base = c_c( "with 𐤠 and 𐤹, from the Lydian set" );
   cChars chars = base;
   cChars set = c_c( "𐤹,𐤠L" );

   char const* ptr = NULL;
   int64_t idx = -1;

   ptr = find_any_rune_c( chars, set ); // --------------------------------- '𐤠'
   idx = index_of_c_( base, ptr );
   expect_rune_( ptr, "𐤠" );
   expect_c_( idx == 5 );
   chars = mid_runes_c( base, 6 );

   ptr = find_any_rune_c( chars, set ); // --------------------------------- '𐤹'
   idx = index_of_c_( base, ptr );
   expect_rune_( ptr, "𐤹" );
   expect_c_( idx == 14 );
   chars = mid_runes_c( base, 12 );

   ptr = find_any_rune_c( chars, set ); // --------------------------------- ','
   idx = index_of_c_( base, ptr );
   expect_rune_( ptr, "," );
   expect_c_( idx == 18 );
   chars = mid_runes_c( base, 13 );

   ptr = find_any_rune_c( chars, set ); // --------------------------------- 'L'
   idx = index_of_c_( base, ptr );
   expect_rune_( ptr, "L" );
   expect_c_( idx == 29 );
   chars = mid_runes_c( base, 24 );

   return finish_tap_c_();
}

find_rune_c

#define find_rune_c_( Chars, Cstr )                                            \
   find_rune_c( (Chars), rune_c( Cstr ) )
char const* find_rune_c( cChars chars, cRune r );

Returns a pointer to the first char of a UTF-8 encoded code point in a chars that equals r.

Example
#include "clingo/lang/expect.h"
#include "clingo/type/cRune.h"

int main( void )
{
   init_tap_c_();

   // ®=2 / 𝄞=4 / €=3
   cChars chars = c_c( "® yes 𝄞 and €!" );

   char const* res = find_rune_c( chars, rune_c( "𝄞" ) );
   expect_c_( index_of_c_( chars, res ) == 7 );
   expect_c_( rune_is_c( rune_c( res ), "𝄞" ) );

   res = find_rune_c_( chars, "" );
   expect_c_( index_of_c_( chars, res ) == 16 );
   expect_c_( rune_is_c( rune_c( res ), "" ) );

   res = find_rune_c_( chars, "x" );
   expect_c_( index_of_c_( chars, res ) == -1 );
   expect_c_( res == NULL );

   chars.s = 17; // ends in the middle of '€'
   res = find_rune_c_( chars, "" );
   expect_c_( index_of_c_( chars, res ) == -1 );
   expect_c_( res == NULL );

   return finish_tap_c_();
}

left_runes_c

cChars left_runes_c( cChars chars, int64_t maxLen );

Returns the leftmost runes in a chars. If maxLen is greater or equal the number of runes in the chars returns the function the whole chars.

Example
#include "clingo/lang/expect.h"
#include "clingo/type/cRune.h"

TEMP_SLICE_C_(
   test,
   {
      char const* input;
      int64_t maxLen;
      char const* exp;
   }
)
#define t_( ... ) ((test){__VA_ARGS__})

int main( void )
{
   init_tap_c_();

   testSlice tests = slice_c_( test,
      t_( "ананас", 6, "ананас" ),
      t_( "ананас", 4, "анан" ),
      t_( "ананас", 0, "" )
   );

   for_each_c_( test const*, t, tests )
   {
      cChars chars = c_c( t->input );
      cChars left = left_runes_c( chars, t->maxLen );
      bool res = chars_is_c( left, t->exp );
      tap_descf_c( res, "test '%s' -> '%s'", t->input, t->exp );
   }

   return finish_tap_c_();
}

mid_runes_c

cChars mid_runes_c( cChars chars, int64_t index );

Returns chars starting(including) at a given rune index. If index does not point into the chars returns the function an empty slice.

Example
#include "clingo/lang/expect.h"
#include "clingo/type/cRune.h"

TEMP_SLICE_C_(
   test,
   {
      char const* input;
      int64_t index;
      char const* exp;
   }
)
#define t_( ... ) ((test){__VA_ARGS__})

int main( void )
{
   init_tap_c_();

   testSlice tests = slice_c_( test,
      t_( "ананас", 0, "ананас" ),
      t_( "ананас", 4, "ас" ),
      t_( "ананас", 6, "" )
   );

   for_each_c_( test const*, t, tests )
   {
      cChars chars = c_c( t->input );
      cChars mid = mid_runes_c( chars, t->index );
      bool res = chars_is_c( mid, t->exp );
      tap_descf_c( res, "test '%s' -> '%s'", t->input, t->exp );
   }

   return finish_tap_c_();
}

right_runes_c

cChars right_runes_c( cChars chars, int64_t maxLen );

Returns the rightmost runes in chars. If maxLen is greater or equal the number of runes in the chars returns the function the whole chars.

Example
#include "clingo/lang/expect.h"
#include "clingo/type/cRune.h"

TEMP_SLICE_C_(
   test,
   {
      char const* input;
      int64_t maxLen;
      char const* exp;
   }
)
#define t_( ... ) ((test){__VA_ARGS__})

int main( void )
{
   init_tap_c_();

   testSlice tests = slice_c_( test,
      t_( "ананас", 6, "ананас" ),
      t_( "ананас", 4, "анас" ),
      t_( "ананас", 0, "" )
   );

   for_each_c_( test const*, t, tests )
   {
      cChars chars = c_c( t->input );
      cChars right = right_runes_c( chars, t->maxLen );
      bool res = chars_is_c( right, t->exp );
      tap_descf_c( res, "test '%s' -> '%s'", t->input, t->exp );
   }

   return finish_tap_c_();
}

sub_runes_c

cChars sub_runes_c( cChars chars, int64_t begIdx, int64_t endIdx );

The returned chars includes the rune at begIdx(begin index) as first value and the rune at endIdx-1 as last value. If begIdx or endIdx are not valid rune indices returns the function a empty slice.

Example
#include "clingo/lang/expect.h"
#include "clingo/type/cRune.h"

TEMP_SLICE_C_(
   test,
   {
      char const* input;
      int64_t begIdx;
      int64_t endIdx;
      char const* exp;
   }
)
#define t_( ... ) ((test){__VA_ARGS__})

int main( void )
{
   init_tap_c_();

   testSlice tests = slice_c_( test,
      t_( "ананас", 0, 3, "ана" ),
      t_( "ананас", 2, 6, "анас" ),
      t_( "ананас", 3, 4, "н" ),
      t_( "ананас", 6, 2, "" ),
      t_( "ананас", 0, 7, "" )
   );

   for_each_c_( test const*, t, tests )
   {
      cChars chars = c_c( t->input );
      cChars sub = sub_runes_c( chars, t->begIdx, t->endIdx );
      bool res = chars_is_c( sub, t->exp );
      tap_descf_c( res, "test '%s' -> '%s'", t->input, t->exp );
   }

   return finish_tap_c_();
}