2024-04-02 03:09:14 +00:00
# pragma GCC push_options
2024-04-03 19:40:39 +00:00
# pragma GCC optimize("O0")
2024-03-21 16:30:37 +00:00
2024-03-30 02:43:46 +00:00
// OPTIONS to set before including sl.h
// ---------------------------------------------------------------------------
# define DEBUG
# define SKIPLIST_DIAGNOSTIC
/* Setting SKIPLIST_MAX_HEIGHT will do two things:
* 1 ) limit our max height across all instances of this data structure .
2024-03-20 18:33:08 +00:00
* 2 ) remove a heap allocation on frequently used paths , insert / remove / etc .
* so , use it when you need it .
*/
2024-03-30 02:43:46 +00:00
# define SKIPLIST_MAX_HEIGHT 12
2024-03-17 14:40:59 +00:00
2024-03-30 02:43:46 +00:00
// Include our monolithic ADT, the Skiplist!
// ---------------------------------------------------------------------------
# include "../include/sl.h"
2024-03-28 00:34:47 +00:00
2024-03-30 02:43:46 +00:00
// Local demo application OPTIONS:
// ---------------------------------------------------------------------------
2024-05-25 02:11:03 +00:00
# define TEST_ARRAY_SIZE 100
2024-03-30 02:43:46 +00:00
# define VALIDATE
2024-04-03 19:53:09 +00:00
//define SNAPSHOTS
2024-04-03 19:40:39 +00:00
//define TODO_RESTORE_SNAPSHOTS
2024-04-08 15:18:36 +00:00
# define STABLE_SEED
# define DOT
2024-04-01 21:14:04 +00:00
# ifdef DOT
size_t gen = 0 ;
FILE * of = 0 ;
# endif
2024-03-28 00:34:47 +00:00
2024-03-30 02:43:46 +00:00
// ---------------------------------------------------------------------------
# ifdef VALIDATE
2024-04-03 19:40:39 +00:00
# define CHECK __skip_integrity_check_ex(list, 0)
2024-03-30 02:43:46 +00:00
# else
# define CHECK ((void)0)
# endif
2024-03-17 14:40:59 +00:00
/*
* SKIPLIST EXAMPLE :
*
2024-04-08 15:18:36 +00:00
* This example creates an " ex " Skiplist where keys are integers , values are
* strings containing the roman numeral for the key allocated on the heap .
2024-03-17 14:40:59 +00:00
*/
2024-03-18 18:58:35 +00:00
/*
* To start , you must create a type node that will contain the
* fields you ' d like to maintain in your Skiplist . In this case
2024-03-29 23:48:11 +00:00
* we map int - > char [ ] on the heap , but what you put here is up
* to you . You don ' t even need a " key " , just a way to compare one
* node against another , logic you ' ll provide in SKIP_DECL as a
* block below .
2024-03-18 18:58:35 +00:00
*/
2024-04-03 19:40:39 +00:00
struct ex_node {
2024-03-20 19:23:27 +00:00
int key ;
2024-03-21 16:30:37 +00:00
char * value ;
2024-04-03 19:40:39 +00:00
SKIPLIST_ENTRY ( ex ) entries ;
2024-03-17 14:40:59 +00:00
} ;
2024-03-18 18:58:35 +00:00
/*
* Generate all the access functions for our type of Skiplist .
2024-03-19 13:41:36 +00:00
*/
2024-03-19 16:33:11 +00:00
SKIPLIST_DECL (
2024-04-03 19:40:39 +00:00
ex , api_ , entries ,
2024-03-30 02:43:46 +00:00
/* compare entries: list, a, b, aux */
{
( void ) list ;
( void ) aux ;
if ( a - > key < b - > key )
return - 1 ;
if ( a - > key > b - > key )
return 1 ;
return 0 ;
} ,
/* free entry: node */
2024-03-30 19:34:42 +00:00
{ free ( node - > value ) ; } ,
2024-03-31 20:37:14 +00:00
/* update entry: rc, node, value */
2024-03-30 02:43:46 +00:00
{
2024-04-03 13:50:31 +00:00
char * numeral = ( char * ) value ;
2024-03-31 20:37:14 +00:00
if ( node - > value )
2024-03-30 02:57:41 +00:00
free ( node - > value ) ;
2024-04-03 13:50:31 +00:00
node - > value = numeral ;
2024-03-30 02:43:46 +00:00
} ,
/* archive an entry: rc, src, dest */
2024-03-21 16:30:37 +00:00
{
2024-03-28 02:41:26 +00:00
dest - > key = src - > key ;
char * nv = calloc ( strlen ( src - > value ) + 1 , sizeof ( char ) ) ;
2024-03-21 18:43:10 +00:00
if ( nv = = NULL )
2024-03-24 13:32:47 +00:00
rc = ENOMEM ;
else {
2024-03-28 02:41:26 +00:00
strncpy ( nv , src - > value , strlen ( src - > value ) ) ;
dest - > value = nv ;
2024-03-24 13:32:47 +00:00
}
2024-03-21 16:30:37 +00:00
} ,
2024-03-30 02:43:46 +00:00
/* size in bytes of the content stored in an entry: bytes */
2024-03-30 19:34:42 +00:00
{ bytes = strlen ( node - > value ) + 1 ; } )
2024-03-19 13:41:36 +00:00
/*
2024-03-30 02:43:46 +00:00
* Skiplists are ordered , we need a way to compare entries .
2024-03-19 13:41:36 +00:00
* Let ' s create a function with four arguments :
2024-03-18 18:58:35 +00:00
* - a reference to the Skiplist , ` slist `
* - the two nodes to compare , ` a ` and ` b `
* - and ` aux ` , which you can use to pass into this function
* any additional information required to compare objects .
* ` aux ` is passed from the value in the Skiplist , you can
* modify that value at any time to suit your needs .
*
2024-03-19 13:41:36 +00:00
* Your function should result in a return statement :
2024-03-18 18:58:35 +00:00
* a < b : return - 1
* a = = b : return 0
* a > b : return 1
*
* This result provides the ordering within the Skiplist . Sometimes
2024-03-19 13:41:36 +00:00
* your function will not be used when comparing nodes . This will
* happen when ` a ` or ` b ` are references to the head or tail of the
2024-03-18 18:58:35 +00:00
* list or when ` a = = b ` . In those cases the comparison function
* returns before using the code in your block , don ' t panic . : )
2024-03-19 01:19:26 +00:00
int
2024-04-03 19:40:39 +00:00
__ex_key_compare ( ex_t * list , ex_node_t * a , ex_node_t * b , void * aux )
2024-03-19 01:19:26 +00:00
{
2024-03-20 19:23:27 +00:00
( void ) list ;
( void ) aux ;
if ( a - > key < b - > key )
return - 1 ;
if ( a - > key > b - > key )
return 1 ;
return 0 ;
2024-03-19 01:19:26 +00:00
}
2024-03-30 02:43:46 +00:00
*/
2024-03-17 14:40:59 +00:00
2024-03-30 02:43:46 +00:00
/*
* Optional : Getters and Setters
* - get , put , dup ( put ) , del , etc . functions
*
* It can be useful to have simple get / put - style API , but to
* do that you ' ll have to supply some blocks of code used to
* extract data from within your nodes .
*/
SKIPLIST_DECL_ACCESS (
2024-04-03 19:40:39 +00:00
ex , api_ , key , int , value , char * ,
2024-03-30 02:43:46 +00:00
/* query blk */ { query . key = key ; } ,
/* return blk */ { return node - > value ; } )
/*
* Optional : Snapshots
*
2024-03-31 00:36:27 +00:00
* Enable functions that enable returning to an earlier point in
* time when a snapshot was created .
2024-03-30 02:43:46 +00:00
*/
2024-04-03 19:40:39 +00:00
SKIPLIST_DECL_SNAPSHOTS ( ex , api_ , entries )
2024-03-30 02:43:46 +00:00
/*
* Optional : Archive to / from bytes
*
2024-03-31 00:36:27 +00:00
* Enable functions that can write / read the content of your Skiplist
* out / in to / from an array of bytes .
2024-03-30 02:43:46 +00:00
*/
2024-04-03 19:40:39 +00:00
// TODO SKIPLIST_DECL_ARCHIVE(ex, api_, entries)
2024-03-30 02:43:46 +00:00
/*
* Optional : As Hashtable
*
2024-03-31 00:36:27 +00:00
* Turn your Skiplist into a hash table .
2024-03-30 02:43:46 +00:00
*/
2024-04-03 19:40:39 +00:00
// TODO SKIPLIST_DECL_HASHTABLE(ex, api_, entries, snaps)
2024-03-30 02:43:46 +00:00
/*
* Optional : Check Skiplists at runtime
*
* Create a functions that validate the integrity of a Skiplist .
*/
2024-04-03 19:40:39 +00:00
SKIPLIST_DECL_VALIDATE ( ex , api_ , entries )
2024-03-30 02:43:46 +00:00
/* Optional: Visualize your Skiplist using DOT/Graphviz in PDF
*
* Create the functions used to annotate a visualization of a Skiplist .
*/
2024-04-03 19:40:39 +00:00
SKIPLIST_DECL_DOT ( ex , api_ , entries )
2024-03-30 02:43:46 +00:00
void
2024-04-03 19:40:39 +00:00
sprintf_ex_node ( ex_node_t * node , char * buf )
2024-03-30 02:43:46 +00:00
{
2024-04-03 19:40:39 +00:00
sprintf ( buf , " %d:%s " , node - > key , node - > value ) ;
2024-03-30 02:43:46 +00:00
}
// Function for this demo application.
// ---------------------------------------------------------------------------
2024-04-08 15:18:36 +00:00
int __xorshift32_state = 0 ;
// Xorshift algorithm for PRNG
uint32_t
xorshift32 ( )
{
uint32_t x = __xorshift32_state ;
if ( x = = 0 )
x = 123456789 ;
x ^ = x < < 13 ;
x ^ = x > > 17 ;
x ^ = x < < 5 ;
__xorshift32_state = x ;
return x ;
}
void
xorshift32_seed ( )
{
// Seed the PRNG
# ifdef STABLE_SEED
__xorshift32_state = 8675309 ;
# else
__xorshift32_state = ( unsigned int ) time ( NULL ) ^ getpid ( ) ;
# endif
}
2024-03-21 18:43:10 +00:00
static char *
to_lower ( char * str )
{
2024-03-21 16:30:37 +00:00
char * p = str ;
2024-03-21 18:43:10 +00:00
for ( ; * p ; + + p )
2024-03-26 13:52:24 +00:00
* p = ( char ) ( * p > = ' A ' & & * p < = ' Z ' ? * p | 0x60 : * p ) ;
2024-03-21 16:30:37 +00:00
return str ;
}
2024-03-21 18:43:10 +00:00
static char *
to_upper ( char * str )
{
2024-03-21 16:30:37 +00:00
char * p = str ;
2024-03-21 18:43:10 +00:00
for ( ; * p ; + + p )
2024-03-26 13:52:24 +00:00
* p = ( char ) ( * p > = ' a ' & & * p < = ' z ' ? * p & ~ 0x20 : * p ) ;
2024-03-21 16:30:37 +00:00
return str ;
}
2024-03-21 18:43:10 +00:00
static char *
int_to_roman_numeral ( int num )
{
int del [ ] = { 1000 , 900 , 500 , 400 , 100 , 90 , 50 , 40 , 10 , 9 , 5 , 4 , 1 } ; // Key value in Roman counting
char * sym [ ] = { " M " , " CM " , " D " , " CD " , " C " , " XC " , " L " , " XL " , " X " , " IX " , " V " , " IV " , " I " } ; // Symbols for key values
// The maximum length of the Roman numeral representation for the maximum signed 64-bit integer would be approximately 19 * 3 = 57 characters, assuming
// every digit is represented by its Roman numeral equivalent up to 3 repetitions. Therefore, 64 should be more than enough.
2024-03-28 01:37:38 +00:00
char * res = ( char * ) calloc ( 4096 , sizeof ( char ) ) ;
2024-03-21 16:30:37 +00:00
int i = 0 ;
if ( num < 0 ) {
res [ 0 ] = ' - ' ;
i + + ;
num = - num ;
}
if ( num = = 0 ) {
res [ 0 ] = ' 0 ' ;
return res ;
}
2024-04-02 17:18:07 +00:00
if ( num > 10000 ) {
sprintf ( res , " The person you were looking for is not here, their mailbox is full, good bye. " ) ;
return res ;
}
2024-03-21 18:43:10 +00:00
while ( num ) { // while input number is not zero
while ( num / del [ i ] ) { // while a number contains the largest key value possible
strcat ( res , sym [ i ] ) ; // append the symbol for this key value to res string
num - = del [ i ] ; // subtract the key value from number
2024-03-21 16:30:37 +00:00
}
2024-03-21 18:43:10 +00:00
i + + ; // proceed to the next key value
2024-03-21 16:30:37 +00:00
}
return res ;
}
2024-03-21 18:43:10 +00:00
void
shuffle ( int * array , size_t n )
{
2024-03-21 16:30:37 +00:00
if ( n > 1 ) {
size_t i ;
for ( i = n - 1 ; i > 0 ; i - - ) {
2024-04-08 15:18:36 +00:00
size_t j = ( unsigned int ) ( xorshift32 ( ) % ( i + 1 ) ) ; /* NOLINT(*-msc50-cpp) */
2024-03-21 16:30:37 +00:00
int t = array [ j ] ;
array [ j ] = array [ i ] ;
array [ i ] = t ;
}
}
}
2024-04-03 19:40:39 +00:00
# ifdef TODO_RESTORE_SNAPSHOTS
typedef struct {
size_t length ;
size_t key ;
size_t snap_id ;
} snap_info_t ;
# endif
2024-03-30 02:43:46 +00:00
// ---------------------------------------------------------------------------
2024-03-19 01:19:26 +00:00
int
main ( )
{
2024-03-26 13:52:24 +00:00
int rc ;
2024-04-03 19:40:39 +00:00
# ifdef TODO_RESTORE_SNAPSHOTS
size_t n_snaps = 0 ;
snap_info_t snaps [ TEST_ARRAY_SIZE * 2 + 1 ] ;
2024-03-30 02:43:46 +00:00
# endif
2024-03-22 03:09:16 +00:00
2024-04-08 15:18:36 +00:00
xorshift32_seed ( ) ;
2024-03-24 13:32:47 +00:00
# ifdef DOT
2024-04-08 15:18:36 +00:00
of = fopen ( " /tmp/ex1.dot " , " w " ) ;
2024-03-22 03:09:16 +00:00
if ( ! of ) {
2024-04-08 15:18:36 +00:00
perror ( " Failed to open file /tmp/ex1.dot " ) ;
2024-03-22 03:09:16 +00:00
return 1 ;
}
2024-03-24 13:32:47 +00:00
# endif
2024-03-21 16:30:37 +00:00
2024-03-20 19:23:27 +00:00
/* Allocate and initialize a Skiplist. */
2024-04-03 19:40:39 +00:00
ex_t * list = ( ex_t * ) malloc ( sizeof ( ex_t ) ) ;
2024-03-21 16:30:37 +00:00
if ( list = = NULL )
return ENOMEM ;
2024-04-08 15:18:36 +00:00
/* We set the max height here to 12, it's negative so that
the PRNG is seeded with this value as a testing trick for
predictable random sequences . */
2024-04-03 19:40:39 +00:00
rc = api_skip_init_ex ( list , - 12 ) ;
2024-03-19 13:41:36 +00:00
if ( rc )
2024-03-20 19:23:27 +00:00
return rc ;
2024-04-03 19:40:39 +00:00
api_skip_snapshots_init_ex ( list ) ;
2024-03-24 13:32:47 +00:00
# ifdef DOT
2024-04-03 19:40:39 +00:00
api_skip_dot_ex ( of , list , gen + + , " init " , sprintf_ex_node ) ;
2024-03-24 13:32:47 +00:00
# endif
2024-04-03 19:40:39 +00:00
if ( api_skip_get_ex ( list , 0 ) ! = NULL )
2024-03-28 00:34:47 +00:00
perror ( " found a non-existent item! " ) ;
2024-04-03 19:40:39 +00:00
api_skip_del_ex ( list , 0 ) ;
2024-03-30 02:43:46 +00:00
CHECK ;
2024-03-20 19:23:27 +00:00
2024-04-03 19:40:39 +00:00
/* Insert TEST_ARRAY_SIZE key/value pairs into the list. */
2024-03-26 13:52:24 +00:00
int i , j ;
2024-03-28 00:34:47 +00:00
char * numeral ;
# ifdef DOT
char msg [ 1024 ] ;
2024-03-30 22:00:06 +00:00
memset ( msg , 0 , 1024 ) ;
2024-03-28 00:34:47 +00:00
# endif
2024-03-21 16:30:37 +00:00
int amt = TEST_ARRAY_SIZE , asz = ( amt * 2 ) + 1 ;
int array [ ( TEST_ARRAY_SIZE * 2 ) + 1 ] ;
2024-03-26 13:52:24 +00:00
for ( j = 0 , i = - amt ; i < = amt ; i + + , j + + )
2024-03-21 16:30:37 +00:00
array [ j ] = i ;
shuffle ( array , asz ) ;
2024-03-24 13:32:47 +00:00
for ( i = 0 ; i < asz ; i + + ) {
2024-03-26 00:17:40 +00:00
# ifdef SNAPSHOTS
2024-04-03 19:40:39 +00:00
api_skip_snapshot_ex ( list ) ;
# elif defined(TODO_RESTORE_SNAPSHOTS)
/* Snapshot the first iteration, and then every 5th after that. */
if ( i % 5 = = 0 ) {
snaps [ i ] . length = api_skip_length_ex ( list ) ;
snaps [ i ] . key = array [ i ] ;
snaps [ i ] . snap_id = api_skip_snapshot_ex ( list ) ;
n_snaps + + ;
2024-03-30 02:43:46 +00:00
CHECK ;
2024-03-29 23:48:11 +00:00
}
2024-03-28 00:34:47 +00:00
# endif
2024-04-03 19:40:39 +00:00
numeral = to_lower ( int_to_roman_numeral ( array [ i ] ) ) ;
rc = api_skip_put_ex ( list , array [ i ] , numeral ) ;
CHECK ;
2024-03-24 13:32:47 +00:00
# ifdef DOT
2024-03-26 13:52:24 +00:00
sprintf ( msg , " put key: %d value: %s " , i , numeral ) ;
2024-04-03 19:40:39 +00:00
api_skip_dot_ex ( of , list , gen + + , msg , sprintf_ex_node ) ;
2024-03-24 13:32:47 +00:00
# endif
2024-04-03 19:40:39 +00:00
char * v = api_skip_get_ex ( list , array [ i ] ) ;
2024-03-30 02:43:46 +00:00
CHECK ;
2024-03-31 20:37:14 +00:00
char * upper_numeral = calloc ( 1 , strlen ( v ) + 1 ) ;
strncpy ( upper_numeral , v , strlen ( v ) ) ;
2024-04-03 19:40:39 +00:00
assert ( strncmp ( v , upper_numeral , strlen ( upper_numeral ) ) = = 0 ) ;
2024-03-31 20:37:14 +00:00
to_upper ( upper_numeral ) ;
2024-04-03 19:40:39 +00:00
api_skip_set_ex ( list , array [ i ] , upper_numeral ) ;
2024-03-30 02:43:46 +00:00
CHECK ;
2024-03-20 19:23:27 +00:00
}
2024-03-26 13:52:24 +00:00
numeral = int_to_roman_numeral ( - 1 ) ;
2024-04-03 19:40:39 +00:00
api_skip_dup_ex ( list , - 1 , numeral ) ;
2024-03-30 02:43:46 +00:00
CHECK ;
2024-03-24 13:32:47 +00:00
# ifdef DOT
2024-03-26 13:52:24 +00:00
sprintf ( msg , " put dup key: %d value: %s " , i , numeral ) ;
2024-04-03 19:40:39 +00:00
api_skip_dot_ex ( of , list , gen + + , msg , sprintf_ex_node ) ;
2024-03-24 13:32:47 +00:00
# endif
2024-03-26 13:52:24 +00:00
numeral = int_to_roman_numeral ( 1 ) ;
2024-04-03 19:40:39 +00:00
api_skip_dup_ex ( list , 1 , numeral ) ;
2024-03-30 02:43:46 +00:00
CHECK ;
2024-03-24 13:32:47 +00:00
# ifdef DOT
2024-03-26 13:52:24 +00:00
sprintf ( msg , " put dup key: %d value: %s " , i , numeral ) ;
2024-04-03 19:40:39 +00:00
api_skip_dot_ex ( of , list , gen + + , msg , sprintf_ex_node ) ;
2024-03-24 13:32:47 +00:00
# endif
2024-03-20 19:23:27 +00:00
2024-04-03 19:40:39 +00:00
api_skip_del_ex ( list , 0 ) ;
2024-03-30 02:43:46 +00:00
CHECK ;
2024-04-03 19:40:39 +00:00
if ( api_skip_get_ex ( list , 0 ) ! = NULL )
2024-03-28 00:34:47 +00:00
perror ( " found a deleted item! " ) ;
2024-04-03 19:40:39 +00:00
api_skip_del_ex ( list , 0 ) ;
2024-03-30 02:43:46 +00:00
CHECK ;
2024-04-03 19:40:39 +00:00
if ( api_skip_get_ex ( list , 0 ) ! = NULL )
2024-03-28 00:34:47 +00:00
perror ( " found a deleted item! " ) ;
2024-03-30 19:34:42 +00:00
int key = TEST_ARRAY_SIZE + 1 ;
2024-04-03 19:40:39 +00:00
api_skip_del_ex ( list , key ) ;
2024-03-30 19:34:42 +00:00
CHECK ;
key = - ( TEST_ARRAY_SIZE ) - 1 ;
2024-04-03 19:40:39 +00:00
api_skip_del_ex ( list , key ) ;
2024-03-30 19:34:42 +00:00
CHECK ;
2024-03-24 13:32:47 +00:00
# ifdef DOT
2024-03-26 13:52:24 +00:00
sprintf ( msg , " deleted key: %d, value: %s " , 0 , numeral ) ;
2024-04-03 19:40:39 +00:00
api_skip_dot_ex ( of , list , gen + + , msg , sprintf_ex_node ) ;
2024-03-26 00:17:40 +00:00
# endif
2024-03-21 20:35:18 +00:00
2024-04-03 13:50:31 +00:00
numeral = int_to_roman_numeral ( - ( TEST_ARRAY_SIZE ) ) ;
2024-04-03 19:40:39 +00:00
assert ( strcmp ( api_skip_pos_ex ( list , SKIP_GTE , - ( TEST_ARRAY_SIZE ) - 1 ) - > value , numeral ) = = 0 ) ;
2024-04-03 13:50:31 +00:00
free ( numeral ) ;
numeral = int_to_roman_numeral ( - 2 ) ;
2024-04-03 19:40:39 +00:00
assert ( strcmp ( api_skip_pos_ex ( list , SKIP_GTE , - 2 ) - > value , numeral ) = = 0 ) ;
2024-04-03 13:50:31 +00:00
free ( numeral ) ;
numeral = int_to_roman_numeral ( 1 ) ;
2024-04-03 19:40:39 +00:00
assert ( strcmp ( api_skip_pos_ex ( list , SKIP_GTE , 0 ) - > value , numeral ) = = 0 ) ;
2024-04-03 13:50:31 +00:00
free ( numeral ) ;
numeral = int_to_roman_numeral ( 2 ) ;
2024-04-03 19:40:39 +00:00
assert ( strcmp ( api_skip_pos_ex ( list , SKIP_GTE , 2 ) - > value , numeral ) = = 0 ) ;
2024-04-03 13:50:31 +00:00
free ( numeral ) ;
2024-04-03 19:40:39 +00:00
assert ( api_skip_pos_ex ( list , SKIP_GTE , ( TEST_ARRAY_SIZE + 1 ) ) = = NULL ) ;
2024-04-01 18:26:44 +00:00
2024-04-03 13:50:31 +00:00
numeral = int_to_roman_numeral ( - ( TEST_ARRAY_SIZE ) ) ;
2024-04-03 19:40:39 +00:00
assert ( strcmp ( api_skip_pos_ex ( list , SKIP_GT , - ( TEST_ARRAY_SIZE ) - 1 ) - > value , numeral ) = = 0 ) ;
2024-04-03 13:50:31 +00:00
free ( numeral ) ;
numeral = int_to_roman_numeral ( - 1 ) ;
2024-04-03 19:40:39 +00:00
assert ( strcmp ( api_skip_pos_ex ( list , SKIP_GT , - 2 ) - > value , numeral ) = = 0 ) ;
2024-04-03 13:50:31 +00:00
free ( numeral ) ;
numeral = int_to_roman_numeral ( 1 ) ;
2024-04-03 19:40:39 +00:00
assert ( strcmp ( api_skip_pos_ex ( list , SKIP_GT , 0 ) - > value , numeral ) = = 0 ) ;
2024-04-03 13:50:31 +00:00
free ( numeral ) ;
numeral = int_to_roman_numeral ( 2 ) ;
2024-04-03 19:40:39 +00:00
assert ( strcmp ( api_skip_pos_ex ( list , SKIP_GT , 1 ) - > value , numeral ) = = 0 ) ;
2024-04-03 13:50:31 +00:00
free ( numeral ) ;
2024-04-03 19:40:39 +00:00
assert ( api_skip_pos_ex ( list , SKIP_GT , TEST_ARRAY_SIZE ) = = NULL ) ;
2024-04-01 18:26:44 +00:00
2024-04-03 19:40:39 +00:00
assert ( api_skip_pos_ex ( list , SKIP_LT , - ( TEST_ARRAY_SIZE ) ) = = NULL ) ;
2024-04-03 13:50:31 +00:00
numeral = int_to_roman_numeral ( - 2 ) ;
2024-04-03 19:40:39 +00:00
assert ( strcmp ( api_skip_pos_ex ( list , SKIP_LT , - 1 ) - > value , numeral ) = = 0 ) ;
2024-04-03 13:50:31 +00:00
free ( numeral ) ;
numeral = int_to_roman_numeral ( - 1 ) ;
2024-04-03 19:40:39 +00:00
assert ( strcmp ( api_skip_pos_ex ( list , SKIP_LT , 0 ) - > value , numeral ) = = 0 ) ;
2024-04-03 13:50:31 +00:00
free ( numeral ) ;
numeral = int_to_roman_numeral ( 1 ) ;
2024-04-03 19:40:39 +00:00
assert ( strcmp ( api_skip_pos_ex ( list , SKIP_LT , 2 ) - > value , numeral ) = = 0 ) ;
2024-04-03 13:50:31 +00:00
free ( numeral ) ;
numeral = int_to_roman_numeral ( TEST_ARRAY_SIZE ) ;
2024-04-03 19:40:39 +00:00
assert ( strcmp ( api_skip_pos_ex ( list , SKIP_LT , ( TEST_ARRAY_SIZE + 1 ) ) - > value , numeral ) = = 0 ) ;
2024-04-03 13:50:31 +00:00
free ( numeral ) ;
2024-04-01 18:26:44 +00:00
2024-04-03 19:40:39 +00:00
assert ( api_skip_pos_ex ( list , SKIP_LTE , - ( TEST_ARRAY_SIZE ) - 1 ) = = NULL ) ;
2024-04-03 13:50:31 +00:00
numeral = int_to_roman_numeral ( - 2 ) ;
2024-04-03 19:40:39 +00:00
assert ( strcmp ( api_skip_pos_ex ( list , SKIP_LTE , - 2 ) - > value , numeral ) = = 0 ) ;
2024-04-03 13:50:31 +00:00
free ( numeral ) ;
numeral = int_to_roman_numeral ( - 1 ) ;
2024-04-03 19:40:39 +00:00
assert ( strcmp ( api_skip_pos_ex ( list , SKIP_LTE , 0 ) - > value , numeral ) = = 0 ) ;
2024-04-03 13:50:31 +00:00
free ( numeral ) ;
numeral = int_to_roman_numeral ( 2 ) ;
2024-04-03 19:40:39 +00:00
assert ( strcmp ( api_skip_pos_ex ( list , SKIP_LTE , 2 ) - > value , numeral ) = = 0 ) ;
2024-04-03 13:50:31 +00:00
free ( numeral ) ;
numeral = int_to_roman_numeral ( TEST_ARRAY_SIZE ) ;
2024-04-03 19:40:39 +00:00
assert ( strcmp ( api_skip_pos_ex ( list , SKIP_LTE , ( TEST_ARRAY_SIZE + 1 ) ) - > value , numeral ) = = 0 ) ;
2024-04-03 13:50:31 +00:00
free ( numeral ) ;
2024-04-01 18:26:44 +00:00
2024-04-03 19:40:39 +00:00
# ifdef TODO_RESTORE_SNAPSHOTS
// Walk backward by 2 and test snapshot restore.
for ( i = n_snaps ; i > 0 ; i - = 2 ) {
api_skip_restore_snapshot_ex ( list , snaps [ i ] . snap_id ) ;
CHECK ;
assert ( api_skip_length_ex ( list ) = = snaps [ i ] . length ) ;
numeral = int_to_roman_numeral ( snaps [ i ] . key ) ;
assert ( strncmp ( api_skip_get_ex ( list , snaps [ i ] . key ) , numeral , strlen ( numeral ) ) = = 0 ) ;
free ( numeral ) ;
}
api_skip_release_snapshots_ex ( list ) ;
# endif
2024-03-24 13:32:47 +00:00
# ifdef DOT
2024-04-03 19:40:39 +00:00
api_skip_dot_end_ex ( of , gen ) ;
2024-03-22 03:09:16 +00:00
fclose ( of ) ;
2024-03-24 13:32:47 +00:00
# endif
2024-04-03 19:40:39 +00:00
api_skip_free_ex ( list ) ;
2024-04-03 13:50:31 +00:00
free ( list ) ;
2024-03-20 19:23:27 +00:00
return rc ;
2024-03-17 14:40:59 +00:00
}
2024-04-02 03:09:14 +00:00
# pragma GCC pop_options