read_type

Overview

Module with functions to read types from a text with a scanner.

Important
Check the err value of the scanner if a function returns false.

Functions

basic

read_bool_c

#define read_bool_c_( Sca, Bool )                                              \
   read_bool_c( (Sca), (Bool), "" )
bool read_bool_c( cScanner sca[static 1],
                  bool val[static 1],
                  char const fmt[static 1] );

Reads a bool value from a text with a scanner. The function supports the following formats:

Table 1. format

l

lower-case representation

true or false

U

upper-case representation

TRUE or FALSE

Cc

camel-case representation

True or False

*

all cases

The function will use \'*' as default format.

Example
#include "clingo/io/read_type.h"
#include "clingo/lang/expect.h"

TEMP_SLICE_C_(
   test,
   {
      char const* str;
      char const* fmt;
      bool expReturn;
      bool expVal;
   }
)
#define t_( ... ) ((test){__VA_ARGS__})

int main( void )
{
   init_tap_c_();

   testSlice tests = slice_c_( test,
   // default
      t_( "true", "", true, true ),
      t_( "False", "", true, false ),
      t_( "FALSE", "", true, false ),
      t_( "Yes", "", false, false ),
   // *
      t_( "true", "", true, true ),
      t_( "False", "", true, false ),
      t_( "FALSE", "", true, false ),
      t_( "NO", "", false, false ),
   // l
      t_( "true", "l", true, true ),
      t_( "false", "l", true, false ),
      t_( "True", "l", false, false ),
   // U
      t_( "TRUE", "U", true, true ),
      t_( "FALSE", "U", true, false ),
      t_( "false", "U", false, false ),
   // Cc
      t_( "True", "Cc", true, true ),
      t_( "False", "Cc", true, false ),
      t_( "TRUE", "Cc", false, false )
   );

   for ( int64_t i = 0; i < tests.s; ++i )
   {
      test t = tests.v[i];
      cScanner* sca = &cstr_scanner_c_( t.str );

      bool val = false;
      bool res = read_bool_c( sca, &val, t.fmt ) == t.expReturn;
      res &= val == t.expVal;

      tap_descf_c( res, "test at index %"PRIi64, i );
   }

   return finish_tap_c_();
}

read_byte_c

#define read_byte_c_( Sca, Byte )                                              \
   read_byte_c( (Sca), (Byte), "" )
bool read_byte_c( cScanner sca[static 1],
                  cByte byte[static 1],
                  char const fmt[static 1] );

Reads a byte value from a text with a scanner.

read_char_c

#define read_char_c_( Sca, Char )                                              \
   read_char_c( (Sca), (Char), "" )
bool read_char_c( cScanner sca[static 1],
                  char c[static 1],
                  char const fmt[static 1] );

Reads a char value from a text with a scanner.

read_range_c

#define read_range_c_( Sca, Rng )                                              \
   read_range_c( (Sca), (Rng), "" )
bool read_range_c( cScanner sca[static 1],
                   cRange rng[static 1],
                   char const fmt[static 1] );

Reads a range from a text with a scanner.

Example
#include "clingo/io/read_type.h"
#include "clingo/lang/expect.h"

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

int main( void )
{
   init_tap_c_();

   testSlice tests = slice_c_( test,
      t_( "[-213,-78]", closed_range_c_( -213, -78 ) ),
      t_( "[0..1984)", closed_open_range_c_( 0, 1984 ) ),
      t_( "(-56;56]", open_closed_range_c_( -56, 56 ) ),
      t_( "(64..256)", open_range_c_( 64, 256 ) )
   );

   for_each_c_( test const*, t, tests )
   {
      cScanner* sca = &cstr_scanner_c_( t->str );

      cRange dst;
      bool res = read_range_c( sca, &dst, "" );
      res &= eq_range_c( dst, t->exp );

      tap_descf_c( res, "test %s", t->str );
   }

   return finish_tap_c_();
}

read_rune_c

#define read_rune_c_( Sca, Rune )                                              \
   read_rune_c( (Sca), (Rune), "" )
bool read_rune_c( cScanner sca[static 1],
                  cRune rune[static 1],
                  char const fmt[static 1] );

Reads a rune value from a text with a scanner. The function supports the following formats:

Table 2. format

s

just the rune

n

unicode number

U+2658

u8

the UTF-8 hex values

e29998

html

decimal HTML-code

htmlx

hex HTML-code

Example
#include "clingo/io/read_type.h"
#include "clingo/lang/expect.h"

#include "clingo/io/print.h"
#define pln_( ... ) pjotln_c_( xyz, 1024, __VA_ARGS__ )

TEMP_SLICE_C_(
   test,
   {
      char const* inp;
      char const* fmt;
      char const* exp;
      char const* unscanned;
   }
)
#define t_( ... ) ((test){__VA_ARGS__})

int main( void )
{
   init_tap_c_();

   testSlice tests = slice_c_( test,
   // "" / "s"
      t_( "abc", "", "a", "bc" ),
      t_( "🪓♘", "", "🪓", "" ),
   // "n"
      t_( "U+005A,", "n", "Z", ","  ),
      t_( "U+2658,", "n", "", "," ),
      t_( "U+1FA93,", "n", "🪓", "," ),
   // "u8"
      t_( "5aaf", "u8", "Z", "af" ),
      t_( "e2999800", "u8", "", "00" ),
      t_( "f09faa9312", "u8", "🪓", "12" ),
   // "html"
      t_( "&#90;foo", "html", "Z", "foo" ),
      t_( "&#9816;bar", "html", "", "bar" ),
      t_( "&#129683;tar", "html", "🪓" , "tar" ),
   // "htmlx"
      t_( "&#x5A;bla", "htmlx", "Z", "bla" ),
      t_( "&#x2658;blo", "htmlx", "", "blo" ),
      t_( "&#x1FA93;blub", "htmlx", "🪓", "blub" )
   );

   for_each_c_( test const*, t, tests )
   {
      cScanner* sca = &cstr_scanner_c_( t->inp );

      cRune r = null_rune_c();
      bool res = read_rune_c( sca, &r, t->fmt );
      res &= rune_is_c( r, t->exp );
      res &= unscanned_is_c( sca,  t->unscanned );

      tap_descf_c( res, "test '%s' + '%s' -> '%s'", t->inp, t->fmt, t->exp );
   }

   return finish_tap_c_();
}

float

read_double_c

#define read_double_c_( Sca, Double )                                          \
   read_double_c( (Sca), (Double), "" )
bool read_double_c( cScanner sca[static 1],
                    double d[static 1],
                    char const fmt[static 1] );

Reads a double value from a text with a scanner.

Example
#include "clingo/io/read_type.h"
#include "clingo/lang/expect.h"
#include "clingo/lang/locale.h"

TEMP_SLICE_C_(
   test,
   {
      char const* str;
      char const* fmt;
      double exp;
      double diff;
   }
)
#define t_( ... ) ((test){__VA_ARGS__})

int main( void )
{
   init_tap_c_();

   set_locale_c( LC_ALL, "C" );

   testSlice tests = slice_c_( test,
      t_( "129038.213", "", 129038.213, 0.00001 )
   );

   for_each_c_( test const*, t, tests )
   {
      cScanner* sca = &cstr_scanner_c_( t->str );
      double d = 0.0;
      bool res = true;
      res &= read_double_c( sca, &d, t->fmt );
      res &= eq_double_c( d, t->exp, t->diff );

      tap_descf_c( res, "%s + \"%s\" -> %f", t->str, t->fmt, d );
   }

   return finish_tap_c_();
}

read_float_c

#define read_float_c_( Sca, Float )                                            \
   read_float_c( (Sca), (Float), "" )
bool read_float_c( cScanner sca[static 1],
                   float f[static 1],
                   char const format[static 1] );

Reads a float value from a text with a scanner.

Example
#include "clingo/io/read_type.h"
#include "clingo/lang/expect.h"
#include "clingo/lang/locale.h"

TEMP_SLICE_C_(
   test,
   {
      char const* str;
      char const* fmt;
      float exp;
   }
)
#define t_( ... ) ((test){__VA_ARGS__})

int main( void )
{
   init_tap_c_();

   set_locale_c( LC_ALL, "C" );

   testSlice tests = slice_c_( test,
      t_( "9038.213", "", 9038.213f )
   );

   for_each_c_( test const*, t, tests )
   {
      cScanner* sca = &cstr_scanner_c_( t->str );
      float f = 0.0f;
      bool res = true;
      res &= read_float_c( sca, &f, t->fmt );
      res &= eq_float_c_( f, t->exp );

      tap_descf_c( res, "%s + \"%s\" -> %f", t->str, t->fmt, f );
   }

   return finish_tap_c_();
}

signed

The format for all signed integers is:

Table 3. format

d

decimal value

x

lower- and upper-case hexadecimal value

X

lower- and upper-case hexadecimal value

o

octal-value

read_int16_c

#define read_int16_c_( Sca, Int16 )                                            \
   read_int16_c( (Sca), (Int16), "" )
bool read_int16_c( cScanner sca[static 1],
                   int16_t i16[static 1],
                   char const fmt[static 1] );
// > C_ReadError

Reads a int16_t value from a text with a scanner.

Example
#include "clingo/io/read_type.h"
#include "clingo/lang/expect.h"

TEMP_SLICE_C_(
   test,
   {
      char const* str;
      char const* fmt;
      int16_t exp;
   }
)
#define t_( ... ) ((test){__VA_ARGS__})

int main( void )
{
   init_tap_c_();

   testSlice tests = slice_c_( test,
   // general
      t_( "18", "", 18 ),
      t_( "30df", "x", 12511 ),
      t_( "-4E3", "X", -1251 ),
      t_( "7561", "o", 3953 ),
   // boundaries
      t_( "-32768", "", -32768 ),
      t_( "32767", "", 32767 ),
      t_( "32768", "", 3276 ),
   // ignore other data at the end
      t_( "345wxyz", "", 345 )
   );

   for ( int64_t i = 0; i < tests.s; ++i )
   {
      test t = tests.v[i];
      cScanner* sca = &cstr_scanner_c_( t.str );

      int16_t val;
      bool res = read_int16_c( sca, &val, t.fmt );
      res &= val == t.exp;

      tap_descf_c( res, "test at index %"PRIi64, i );
   }

   return finish_tap_c_();
}

read_int32_c

#define read_int32_c_( Sca, Int32 )                                            \
   read_int32_c( (Sca), (Int32), "" )
bool read_int32_c( cScanner sca[static 1],
                   int32_t i32[static 1],
                   char const fmt[static 1] );

Reads a int32_t value from a text with a scanner.

Example
#include "clingo/io/read_type.h"
#include "clingo/lang/expect.h"

TEMP_SLICE_C_(
   test,
   {
      char const* str;
      char const* fmt;
      int32_t exp;
   }
)
#define t_( ... ) ((test){__VA_ARGS__})

int main( void )
{
   init_tap_c_();

   testSlice tests = slice_c_( test,
   // general
      t_( "18", "", 18 ),
      t_( "30df", "x", 12511 ),
      t_( "-4E3", "X", -1251 ),
      t_( "7561", "o", 3953 ),
   // boundaries
      t_( "-2147483648", "", -2147483648 ),
      t_( "2147483647", "", 2147483647 ),
      t_( "-2147483649", "", -214748364 ),
   // ignore other data at the end
      t_( "345wxyz", "", 345 )
   );

   for ( int64_t i = 0; i < tests.s; ++i )
   {
      test t = tests.v[i];
      cScanner* sca = &cstr_scanner_c_( t.str );

      int32_t val;
      bool res = read_int32_c( sca, &val, t.fmt );
      res &= val == t.exp;

      tap_descf_c( res, "test at index %"PRIi64, i );
   }

   return finish_tap_c_();
}

read_int64_c

#define read_int64_c_( Sca, Int64 )                                            \
   read_int64_c( (Sca), (Int64), "" )
bool read_int64_c( cScanner sca[static 1],
                   int64_t i64[static 1],
                   char const fmt[static 1] );

Reads a int64_t value from a text with a scanner.

Example
#include "clingo/io/read_type.h"
#include "clingo/lang/expect.h"

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

int main( void )
{
   init_tap_c_();

   testSlice tests = slice_c_( test,
   // general
      t_( "42", "", 42 ),
      t_( "aBcD", "x", 43981 ),
      t_( "-4a3F", "X", -19007 ),
      t_( "7561", "o", 3953 ),
   // boundaries
      t_( "-9223372036854775808", "", int64_c_( -9223372036854775807 - 1 ) ),
      t_( "9223372036854775807", "", int64_c_( 9223372036854775807 ) ),
      t_( "9223372036854775808", "", int64_c_( 922337203685477580 ) ),
   // ignore other data at the end
      t_( "777 oth", "", 777 )
   );

   for ( int64_t i = 0; i < tests.s; ++i )
   {
      test t = tests.v[i];
      cScanner* sca = &cstr_scanner_c_( t.str );

      int64_t val;
      bool res = read_int64_c( sca, &val, t.fmt );
      res &= val == t.exp;

      tap_descf_c( res, "test at index %"PRIi64, i );
   }

   return finish_tap_c_();
}

read_int8_c

#define read_int8_c_( Sca, Int8 )                                              \
   read_int8_c( (Sca), (Int8), "" )
bool read_int8_c( cScanner sca[static 1],
                  int8_t i8[static 1],
                  char const fmt[static 1] );

Reads a int8_t value from a text with a scanner.

Example
#include "clingo/io/read_type.h"
#include "clingo/lang/expect.h"

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

int main( void )
{
   init_tap_c_();

   testSlice tests = slice_c_( test,
   // general
      t_( "22", "", 22 ),
      t_( "1c", "x", 28 ),
      t_( "0", "X", 0 ),
      t_( "-70", "o", -56 ),
   // boundaries
      t_( "-128", "", -128 ),
      t_( "127", "", 127 ),
      t_( "-2345", "", -23 ),
      t_( "128", "", 12 ),
   // with leading zeros
      t_( "-0046", "", -46 ),
   // ignore other data at the end
      t_( "32-blocks", "", 32 )
   );

   for ( int64_t i = 0; i < tests.s; ++i )
   {
      test t = tests.v[i];
      cScanner* sca = &cstr_scanner_c_( t.str );

      int8_t val;
      bool res = read_int8_c( sca, &val, t.fmt );
      res &= val == t.exp;

      tap_descf_c( res, "test at index %"PRIi64, i );
   }

   return finish_tap_c_();
}

unsigned

The format for all unsigned integers is:

Table 4. format

d

decimal value

x

lower- and upper-case hexadecimal value

X

lower- and upper-case hexadecimal value

o

octal-value

read_uint16_c

#define read_uint16_c_( Sca, Uint16 )                                          \
   read_uint16_c( (Sca), (Uint16), "" )
bool read_uint16_c( cScanner sca[static 1],
                    uint16_t u16[static 1],
                    char const fmt[static 1] );

Reads a uint16_t value from a text with a scanner.

Example
#include "clingo/io/read_type.h"
#include "clingo/lang/expect.h"

TEMP_SLICE_C_(
   test,
   {
      char const* str;
      char const* fmt;
      uint16_t exp;
   }
)
#define t_( ... ) ((test){__VA_ARGS__})

int main( void )
{
   init_tap_c_();

   testSlice tests = slice_c_( test,
   // general
      t_( "1834", "", 1834 ),
      t_( "30df", "x", 12511 ),
      t_( "4E3", "X", 1251 ),
      t_( "7561", "o", 3953 ),
   // boundaries
      t_( "0", "", 0 ),
      t_( "65535", "", 65535 ),
      t_( "65536", "", 6553 ),
   // ignore other data at the end
      t_( "8761hgfa", "", 8761 )
   );

   for ( int64_t i = 0; i < tests.s; ++i )
   {
      test t = tests.v[i];
      cScanner* sca = &cstr_scanner_c_( t.str );

      uint16_t val;
      bool res = read_uint16_c( sca, &val, t.fmt );
      res &= val == t.exp;

      tap_descf_c( res, "test at index %"PRIi64, i );
   }

   return finish_tap_c_();
}

read_uint32_c

#define read_uint32_c_( Sca, Uint32 )                                          \
   read_uint32_c( (Sca), (Uint32), "" )
bool read_uint32_c( cScanner sca[static 1],
                    uint32_t u32[static 1],
                    char const fmt[static 1] );

Reads a uint32_t value from a text with a scanner.

Example
#include "clingo/io/read_type.h"
#include "clingo/lang/expect.h"

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

int main( void )
{
   init_tap_c_();

   testSlice tests = slice_c_( test,
   // general
      t_( "18", "", 18 ),
      t_( "30df", "x", 12511 ),
      t_( "4E3", "X", 1251 ),
      t_( "7561", "o", 3953 ),
   // boundaries
      t_( "0", "", 0 ),
      t_( "4294967295", "", 4294967295 ),
      t_( "4294967296", "", 429496729 ),
   // ignore other data at the end
      t_( "345junk", "", 345 )
   );

   for ( int64_t i = 0; i < tests.s; ++i )
   {
      test t = tests.v[i];
      cScanner* sca = &cstr_scanner_c_( t.str );

      uint32_t val;
      bool res = read_uint32_c( sca, &val, t.fmt );
      res &= val == t.exp;

      tap_descf_c( res, "test at index %"PRIi64, i );
   }

   return finish_tap_c_();
}

read_uint64_c

#define read_uint64_c_( Sca, Uint64 )                                          \
   read_uint64_c( (Sca), (Uint64), "" )
bool read_uint64_c( cScanner sca[static 1],
                    uint64_t u64[static 1],
                    char const fmt[static 1] );

Reads a uint64_t value from a text with a scanner.

Example
#include "clingo/io/read_type.h"
#include "clingo/lang/expect.h"

TEMP_SLICE_C_(
   test,
   {
      char const* str;
      char const* fmt;
      uint64_t exp;
   }
)
#define t_( ... ) ((test){__VA_ARGS__})

int main( void )
{
   init_tap_c_();

   testSlice tests = slice_c_( test,
   // general
      t_( "18", "", 18 ),
      t_( "30df", "x", 12511 ),
      t_( "4E3", "X", 1251 ),
      t_( "7561", "o", 3953 ),
   // boundaries
      t_( "0", "", 0 ),
      t_( "18446744073709551615", "", 18446744073709551615ULL ),
      t_( "18446744073709551616", "", 1844674407370955161ULL ),
   // ignore other data at the end
      t_( "1170343number", "", 1170343 )
   );

   for ( int64_t i = 0; i < tests.s; ++i )
   {
      test t = tests.v[i];
      cScanner* sca = &cstr_scanner_c_( t.str );

      uint64_t val;
      bool res = read_uint64_c( sca, &val, t.fmt );
      res &= val == t.exp;

      tap_descf_c( res, "test at index %"PRIi64, i );
   }

   return finish_tap_c_();
}

read_uint8_c

#define read_uint8_c_( Sca, Uint8 )                                            \
   read_uint8_c( (Sca), (Uint8), "" )
bool read_uint8_c( cScanner sca[static 1],
                   uint8_t u8[static 1],
                   char const fmt[static 1] );

Reads a uint8_t value from a text with a scanner.

Example
#include "clingo/io/read_type.h"
#include "clingo/lang/expect.h"

TEMP_SLICE_C_(
   test,
   {
      char const* str;
      char const* fmt;
      uint8_t exp;
   }
)
#define t_( ... ) ((test){__VA_ARGS__})

int main( void )
{
   init_tap_c_();

   testSlice tests = slice_c_( test,
   // general
      t_( "18", "", 18 ),
      t_( "1c", "x", 28 ),
      t_( "F0", "X", 240 ),
      t_( "70", "o", 56 ),
   // boundaries
      t_( "0", "", 0 ),
      t_( "255", "", 255 ),
      t_( "2345", "", 234 ),
      t_( "256", "", 25 ),
   // with leading zeros
      t_( "0046", "", 46 ),

   // ignore other data at the end
      t_( "34test", "", 34 )
   );

   for ( int64_t i = 0; i < tests.s; ++i )
   {
      test t = tests.v[i];
      cScanner* sca = &cstr_scanner_c_( t.str );

      uint8_t val;
      bool res = read_uint8_c( sca, &val, t.fmt );
      res &= val == t.exp;

      tap_descf_c( res, "test at index %"PRIi64, i );
   }

   return finish_tap_c_();
}

slice

read_chars_c

#define read_chars_c_( Sca, Chars )                                            \
   read_chars_c( (Sca), (Chars), "" )
bool read_chars_c( cScanner sca[static 1],
                   cChars chars[static 1],
                   char const fmt[static 1] );

Reads the scanner and tracks the read chars in the chars value. The fmt C-string can have the same commands and specifier like the read_c function.

Example
#include "clingo/io/read_type.h"
#include "clingo/lang/expect.h"

TEMP_SLICE_C_(
   test,
   {
      char const* str;
      char const* fmt;
      char const* expChars;
      char const* expUnscanned;
   }
)
#define t_( ... ) ((test){__VA_ARGS__})

int main( void )
{
   init_tap_c_();

   testSlice tests = slice_c_( test,
      // any
      t_( "'key': 'value'", "{>:}", "'key'", ": 'value'" ),
      // func
      t_( "123456", "{/?d}", "1", "23456" ),
      t_( "123456", "{/*d}", "123456", "" ),
      // range
      t_( "I am müller", "{[*0000-007F}", "I am m", "üller" ),
      t_( "I am müller", "{[+0-7f}", "I am m", "üller" ),
      t_( "I am müller", "{[+ z}", "I am m", "üller" )
   );

   for_each_c_( test const*, t, tests )
   {
      cScanner* sca = &cstr_scanner_c_( t->str );
      cChars chars = (cChars)empty_c_();
      bool res = read_chars_c( sca, &chars, t->fmt );
      res &= chars_is_c( chars, t->expChars );
      res &= unscanned_is_c( sca, t->expUnscanned );

      tap_descf_c( res, "%s on %s", t->fmt, t->str );
   }

   return finish_tap_c_();
}