ck_str_hash_lookup:
  146|  4.75k|const void *ck_str_hash_lookup(const char *key, ck_hash_table_t *table) {
  147|  4.75k|    size_t keylen = strlen(key);
  148|  4.75k|    return ck_str_n_hash_lookup(key, keylen, table);
  149|  4.75k|}
ck_str_n_hash_lookup:
  152|  4.75k|{
  153|  4.75k|	if (table->count == 0)
  ------------------
  |  Branch (153:6): [True: 1.09k, False: 3.65k]
  ------------------
  154|  1.09k|		return NULL;
  155|       |    	
  156|  3.65k|	if (keylen == 0)
  ------------------
  |  Branch (156:6): [True: 266, False: 3.39k]
  ------------------
  157|    266|		return NULL;
  158|       |	
  159|  3.39k|    uint64_t hash_key = ck_hash_str(key, keylen);
  160|  3.39k|	hash_key %= table->capacity;
  161|  3.39k|    uint64_t end = hash_key;
  162|  3.79k|    do {
  163|  3.79k|        char *this_key = &table->keys[table->entries[hash_key].key_offset];
  164|  3.79k|        size_t this_keylen = table->entries[hash_key].key_length;
  165|  3.79k|        if (this_keylen == 0)
  ------------------
  |  Branch (165:13): [True: 1.80k, False: 1.98k]
  ------------------
  166|  1.80k|            return NULL;
  167|  1.98k|        if (this_keylen == keylen && memcmp(this_key, key, keylen) == 0) {
  ------------------
  |  Branch (167:13): [True: 1.79k, False: 195]
  |  Branch (167:38): [True: 1.58k, False: 211]
  ------------------
  168|  1.58k|			return table->entries[hash_key].value;
  169|  1.58k|		}
  170|    406|		hash_key++;
  171|    406|		hash_key %= table->capacity;
  172|    406|    } while (hash_key != end);
  ------------------
  |  Branch (172:14): [True: 406, False: 0]
  ------------------
  173|      0|	return NULL;
  174|  3.39k|}
ck_str_hash_insert:
  177|  7.25k|{
  178|  7.25k|    size_t keylen = strlen(key);
  179|  7.25k|    return ck_str_n_hash_insert(key, keylen, value, table);
  180|  7.25k|}
ck_str_n_hash_insert:
  210|  7.25k|{    
  211|  7.25k|	if (table->capacity == 0)
  ------------------
  |  Branch (211:6): [True: 0, False: 7.25k]
  ------------------
  212|      0|		return 0;
  213|       |    	
  214|  7.25k|	if (keylen == 0)
  ------------------
  |  Branch (214:6): [True: 3.51k, False: 3.73k]
  ------------------
  215|  3.51k|		return 0;
  216|       |    
  217|  3.73k|    if (table->count >= 0.75 * table->capacity) {
  ------------------
  |  Branch (217:9): [True: 0, False: 3.73k]
  ------------------
  218|      0|        if (ck_hash_table_grow(table) == -1) {
  ------------------
  |  Branch (218:13): [True: 0, False: 0]
  ------------------
  219|      0|            return 0;
  220|      0|        }
  221|      0|    }
  222|       |	
  223|  3.73k|    uint64_t hash_key = ck_hash_str(key, keylen);
  224|  3.73k|	hash_key %= table->capacity;
  225|  3.73k|    uint64_t end = hash_key;
  226|  4.58k|    do {
  227|  4.58k|        ck_hash_entry_t *entry = &table->entries[hash_key];
  228|  4.58k|        char *this_key = &table->keys[entry->key_offset];
  229|  4.58k|        if (entry->key_length == 0) {
  ------------------
  |  Branch (229:13): [True: 951, False: 3.63k]
  ------------------
  230|    951|            table->count++;
  231|    951|            while (table->keys_used + keylen > table->keys_capacity) {
  ------------------
  |  Branch (231:20): [True: 0, False: 951]
  ------------------
  232|      0|                table->keys_capacity *= 2;
  233|      0|                table->keys = realloc(table->keys, table->keys_capacity);
  234|      0|            }
  235|    951|            memcpy(table->keys + table->keys_used, key, keylen);
  236|    951|            entry->key_offset = table->keys_used;
  237|    951|            entry->key_length = keylen;
  238|    951|            table->keys_used += keylen;
  239|    951|            entry->value = value;
  240|    951|            return 1;
  241|  3.63k|        } else if (entry->key_length == keylen &&
  ------------------
  |  Branch (241:20): [True: 3.12k, False: 512]
  ------------------
  242|  3.12k|                   memcmp(this_key, key, keylen) == 0) {
  ------------------
  |  Branch (242:20): [True: 2.78k, False: 332]
  ------------------
  243|  2.78k|			table->entries[hash_key].value = value;
  244|  2.78k|			return 1;
  245|  2.78k|		}
  246|    844|		hash_key++;
  247|    844|		hash_key %= table->capacity;
  248|    844|    } while (hash_key != end);
  ------------------
  |  Branch (248:14): [True: 844, False: 0]
  ------------------
  249|      0|	return 0;
  250|  3.73k|}
ck_hash_table_init:
  253|  2.55k|{
  254|  2.55k|	ck_hash_table_t *table;
  255|  2.55k|	if ((table = malloc(sizeof(ck_hash_table_t))) == NULL)
  ------------------
  |  Branch (255:6): [True: 0, False: 2.55k]
  ------------------
  256|      0|		return NULL;
  257|       |    
  258|  2.55k|    if ((table->keys = malloc(num_entries * mean_key_length)) == NULL) {
  ------------------
  |  Branch (258:9): [True: 0, False: 2.55k]
  ------------------
  259|      0|        free(table);
  260|      0|        return NULL;
  261|      0|    }
  262|  2.55k|    table->keys_capacity = num_entries * mean_key_length;
  263|       |    
  264|  2.55k|    num_entries *= 2;
  265|       |    
  266|  2.55k|    if ((table->entries = malloc(num_entries * sizeof(ck_hash_entry_t))) == NULL) {
  ------------------
  |  Branch (266:9): [True: 0, False: 2.55k]
  ------------------
  267|      0|        free(table->keys);
  268|      0|        free(table);
  269|      0|        return NULL;
  270|      0|    }
  271|  2.55k|	table->capacity = num_entries;
  272|  2.55k|    ck_hash_table_wipe(table);
  273|  2.55k|	return table;
  274|  2.55k|}
ck_hash_table_free:
  276|  2.55k|void ck_hash_table_free(ck_hash_table_t *table) {
  277|  2.55k|    free(table->entries);
  278|  2.55k|    if (table->keys)
  ------------------
  |  Branch (278:9): [True: 2.55k, False: 0]
  ------------------
  279|  2.55k|        free(table->keys);
  280|  2.55k|    free(table);
  281|  2.55k|}
ck_hash_table_wipe:
  283|  2.55k|void ck_hash_table_wipe(ck_hash_table_t *table) {
  284|  2.55k|    table->keys_used = 0;
  285|  2.55k|    table->count = 0;
  286|  2.55k|    memset(table->entries, 0, table->capacity * sizeof(ck_hash_entry_t));
  287|  2.55k|}
CKHashTable.c:ck_hash_str:
  121|  7.12k|{
  122|  7.12k|    uint64_t hash;
  123|  7.12k|    unsigned char k[16] = { 0 };
  124|  7.12k|    siphash((unsigned char *)&hash, (const unsigned char *)str, keylen, k);
  125|  7.12k|    return hash;
  126|  7.12k|}
CKHashTable.c:siphash:
   57|  7.12k|{
   58|       |    /* "somepseudorandomlygeneratedbytes" */
   59|  7.12k|    u64 v0 = 0x736f6d6570736575ULL;
   60|  7.12k|    u64 v1 = 0x646f72616e646f6dULL;
   61|  7.12k|    u64 v2 = 0x6c7967656e657261ULL;
   62|  7.12k|    u64 v3 = 0x7465646279746573ULL;
   63|  7.12k|    u64 b;
   64|  7.12k|    u64 k0 = U8TO64_LE( k );
  ------------------
  |  |   37|  7.12k|#define U8TO64_LE(p) \
  |  |   38|  7.12k|(((u64)((p)[0])      ) | \
  |  |   39|  7.12k|((u64)((p)[1]) <<  8) | \
  |  |   40|  7.12k|((u64)((p)[2]) << 16) | \
  |  |   41|  7.12k|((u64)((p)[3]) << 24) | \
  |  |   42|  7.12k|((u64)((p)[4]) << 32) | \
  |  |   43|  7.12k|((u64)((p)[5]) << 40) | \
  |  |   44|  7.12k|((u64)((p)[6]) << 48) | \
  |  |   45|  7.12k|((u64)((p)[7]) << 56))
  ------------------
   65|  7.12k|    u64 k1 = U8TO64_LE( k + 8 );
  ------------------
  |  |   37|  7.12k|#define U8TO64_LE(p) \
  |  |   38|  7.12k|(((u64)((p)[0])      ) | \
  |  |   39|  7.12k|((u64)((p)[1]) <<  8) | \
  |  |   40|  7.12k|((u64)((p)[2]) << 16) | \
  |  |   41|  7.12k|((u64)((p)[3]) << 24) | \
  |  |   42|  7.12k|((u64)((p)[4]) << 32) | \
  |  |   43|  7.12k|((u64)((p)[5]) << 40) | \
  |  |   44|  7.12k|((u64)((p)[6]) << 48) | \
  |  |   45|  7.12k|((u64)((p)[7]) << 56))
  ------------------
   66|  7.12k|    u64 m;
   67|  7.12k|    const u8 *end = in + inlen - ( inlen % sizeof( u64 ) );
   68|  7.12k|    const int left = inlen & 7;
   69|  7.12k|    b = ( ( u64 )inlen ) << 56;
   70|  7.12k|    v3 ^= k1;
   71|  7.12k|    v2 ^= k0;
   72|  7.12k|    v1 ^= k1;
   73|  7.12k|    v0 ^= k0;
   74|       |    
   75|  13.0k|    for ( ; in != end; in += 8 )
  ------------------
  |  Branch (75:13): [True: 5.93k, False: 7.12k]
  ------------------
   76|  5.93k|    {
   77|  5.93k|        m = U8TO64_LE( in );
  ------------------
  |  |   37|  5.93k|#define U8TO64_LE(p) \
  |  |   38|  5.93k|(((u64)((p)[0])      ) | \
  |  |   39|  5.93k|((u64)((p)[1]) <<  8) | \
  |  |   40|  5.93k|((u64)((p)[2]) << 16) | \
  |  |   41|  5.93k|((u64)((p)[3]) << 24) | \
  |  |   42|  5.93k|((u64)((p)[4]) << 32) | \
  |  |   43|  5.93k|((u64)((p)[5]) << 40) | \
  |  |   44|  5.93k|((u64)((p)[6]) << 48) | \
  |  |   45|  5.93k|((u64)((p)[7]) << 56))
  ------------------
   78|       |        
   79|  5.93k|        v3 ^= m;
   80|       |        
   81|  5.93k|        SIPROUND;
  ------------------
  |  |   47|  5.93k|#define SIPROUND            \
  |  |   48|  5.93k|do {              \
  |  |   49|  5.93k|v0 += v1; v1=ROTL(v1,13); v1 ^= v0; v0=ROTL(v0,32); \
  |  |  ------------------
  |  |  |  |   27|  5.93k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |               v0 += v1; v1=ROTL(v1,13); v1 ^= v0; v0=ROTL(v0,32); \
  |  |  ------------------
  |  |  |  |   27|  5.93k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |   50|  5.93k|v2 += v3; v3=ROTL(v3,16); v3 ^= v2;     \
  |  |  ------------------
  |  |  |  |   27|  5.93k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |   51|  5.93k|v0 += v3; v3=ROTL(v3,21); v3 ^= v0;     \
  |  |  ------------------
  |  |  |  |   27|  5.93k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |   52|  5.93k|v2 += v1; v1=ROTL(v1,17); v1 ^= v2; v2=ROTL(v2,32); \
  |  |  ------------------
  |  |  |  |   27|  5.93k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |               v2 += v1; v1=ROTL(v1,17); v1 ^= v2; v2=ROTL(v2,32); \
  |  |  ------------------
  |  |  |  |   27|  5.93k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |   53|  5.93k|} while(0)
  |  |  ------------------
  |  |  |  Branch (53:9): [Folded, False: 5.93k]
  |  |  ------------------
  ------------------
   82|       |        
   83|  5.93k|        v0 ^= m;
   84|  5.93k|    }
   85|       |    
   86|  7.12k|    switch( left )
  ------------------
  |  Branch (86:13): [True: 7.12k, False: 0]
  ------------------
   87|  7.12k|    {
   88|    224|        case 7: b |= ( ( u64 )in[ 6] )  << 48;
  ------------------
  |  Branch (88:9): [True: 224, False: 6.90k]
  ------------------
   89|       |            
   90|  1.72k|        case 6: b |= ( ( u64 )in[ 5] )  << 40;
  ------------------
  |  Branch (90:9): [True: 1.50k, False: 5.62k]
  ------------------
   91|       |            
   92|  2.15k|        case 5: b |= ( ( u64 )in[ 4] )  << 32;
  ------------------
  |  Branch (92:9): [True: 426, False: 6.70k]
  ------------------
   93|       |            
   94|  3.10k|        case 4: b |= ( ( u64 )in[ 3] )  << 24;
  ------------------
  |  Branch (94:9): [True: 952, False: 6.17k]
  ------------------
   95|       |            
   96|  3.58k|        case 3: b |= ( ( u64 )in[ 2] )  << 16;
  ------------------
  |  Branch (96:9): [True: 476, False: 6.65k]
  ------------------
   97|       |            
   98|  4.32k|        case 2: b |= ( ( u64 )in[ 1] )  <<  8;
  ------------------
  |  Branch (98:9): [True: 746, False: 6.38k]
  ------------------
   99|       |            
  100|  5.35k|        case 1: b |= ( ( u64 )in[ 0] ); break;
  ------------------
  |  Branch (100:9): [True: 1.03k, False: 6.09k]
  ------------------
  101|       |            
  102|  1.77k|        case 0: break;
  ------------------
  |  Branch (102:9): [True: 1.77k, False: 5.35k]
  ------------------
  103|  7.12k|    }
  104|       |
  105|  7.12k|    v3 ^= b;
  106|       |    
  107|  7.12k|    SIPROUND;
  ------------------
  |  |   47|  7.12k|#define SIPROUND            \
  |  |   48|  7.12k|do {              \
  |  |   49|  7.12k|v0 += v1; v1=ROTL(v1,13); v1 ^= v0; v0=ROTL(v0,32); \
  |  |  ------------------
  |  |  |  |   27|  7.12k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |               v0 += v1; v1=ROTL(v1,13); v1 ^= v0; v0=ROTL(v0,32); \
  |  |  ------------------
  |  |  |  |   27|  7.12k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |   50|  7.12k|v2 += v3; v3=ROTL(v3,16); v3 ^= v2;     \
  |  |  ------------------
  |  |  |  |   27|  7.12k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |   51|  7.12k|v0 += v3; v3=ROTL(v3,21); v3 ^= v0;     \
  |  |  ------------------
  |  |  |  |   27|  7.12k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |   52|  7.12k|v2 += v1; v1=ROTL(v1,17); v1 ^= v2; v2=ROTL(v2,32); \
  |  |  ------------------
  |  |  |  |   27|  7.12k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |               v2 += v1; v1=ROTL(v1,17); v1 ^= v2; v2=ROTL(v2,32); \
  |  |  ------------------
  |  |  |  |   27|  7.12k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |   53|  7.12k|} while(0)
  |  |  ------------------
  |  |  |  Branch (53:9): [Folded, False: 7.12k]
  |  |  ------------------
  ------------------
  108|       |    
  109|  7.12k|    v0 ^= b;
  110|  7.12k|    v2 ^= 0xff;
  111|       |    
  112|  7.12k|    SIPROUND;
  ------------------
  |  |   47|  7.12k|#define SIPROUND            \
  |  |   48|  7.12k|do {              \
  |  |   49|  7.12k|v0 += v1; v1=ROTL(v1,13); v1 ^= v0; v0=ROTL(v0,32); \
  |  |  ------------------
  |  |  |  |   27|  7.12k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |               v0 += v1; v1=ROTL(v1,13); v1 ^= v0; v0=ROTL(v0,32); \
  |  |  ------------------
  |  |  |  |   27|  7.12k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |   50|  7.12k|v2 += v3; v3=ROTL(v3,16); v3 ^= v2;     \
  |  |  ------------------
  |  |  |  |   27|  7.12k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |   51|  7.12k|v0 += v3; v3=ROTL(v3,21); v3 ^= v0;     \
  |  |  ------------------
  |  |  |  |   27|  7.12k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |   52|  7.12k|v2 += v1; v1=ROTL(v1,17); v1 ^= v2; v2=ROTL(v2,32); \
  |  |  ------------------
  |  |  |  |   27|  7.12k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |               v2 += v1; v1=ROTL(v1,17); v1 ^= v2; v2=ROTL(v2,32); \
  |  |  ------------------
  |  |  |  |   27|  7.12k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |   53|  7.12k|} while(0)
  |  |  ------------------
  |  |  |  Branch (53:9): [Folded, False: 7.12k]
  |  |  ------------------
  ------------------
  113|  7.12k|    SIPROUND;
  ------------------
  |  |   47|  7.12k|#define SIPROUND            \
  |  |   48|  7.12k|do {              \
  |  |   49|  7.12k|v0 += v1; v1=ROTL(v1,13); v1 ^= v0; v0=ROTL(v0,32); \
  |  |  ------------------
  |  |  |  |   27|  7.12k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |               v0 += v1; v1=ROTL(v1,13); v1 ^= v0; v0=ROTL(v0,32); \
  |  |  ------------------
  |  |  |  |   27|  7.12k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |   50|  7.12k|v2 += v3; v3=ROTL(v3,16); v3 ^= v2;     \
  |  |  ------------------
  |  |  |  |   27|  7.12k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |   51|  7.12k|v0 += v3; v3=ROTL(v3,21); v3 ^= v0;     \
  |  |  ------------------
  |  |  |  |   27|  7.12k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |   52|  7.12k|v2 += v1; v1=ROTL(v1,17); v1 ^= v2; v2=ROTL(v2,32); \
  |  |  ------------------
  |  |  |  |   27|  7.12k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |               v2 += v1; v1=ROTL(v1,17); v1 ^= v2; v2=ROTL(v2,32); \
  |  |  ------------------
  |  |  |  |   27|  7.12k|#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
  |  |  ------------------
  |  |   53|  7.12k|} while(0)
  |  |  ------------------
  |  |  |  Branch (53:9): [Folded, False: 7.12k]
  |  |  ------------------
  ------------------
  114|       |    
  115|  7.12k|    b = v0 ^ v1 ^ v2  ^ v3;
  116|  7.12k|    U64TO8_LE( out, b );
  ------------------
  |  |   33|  7.12k|#define U64TO8_LE(p, v)         \
  |  |  ------------------
  |  |  |  |   29|  7.12k|#define U32TO8_LE(p, v)         \
  |  |  |  |   30|  7.12k|(p)[0] = (u8)((v)      ); (p)[1] = (u8)((v) >>  8); \
  |  |  |  |   31|  7.12k|(p)[2] = (u8)((v) >> 16); (p)[3] = (u8)((v) >> 24);
  |  |  ------------------
  |  |   34|  7.12k|U32TO8_LE((p),     (u32)((v)      ));   \
  |  |  ------------------
  |  |  |  |   29|  7.12k|#define U32TO8_LE(p, v)         \
  |  |  |  |   30|  7.12k|(p)[0] = (u8)((v)      ); (p)[1] = (u8)((v) >>  8); \
  |  |  |  |   31|  7.12k|(p)[2] = (u8)((v) >> 16); (p)[3] = (u8)((v) >> 24);
  |  |  ------------------
  |  |   35|  7.12k|U32TO8_LE((p) + 4, (u32)((v) >> 32));
  ------------------
  117|  7.12k|    return 0;
  118|  7.12k|}

fuzzer_parser_init:
   33|  2.55k|readstat_parser_t *fuzzer_parser_init(const uint8_t *Data, size_t Size) {
   34|  2.55k|    readstat_parser_t *parser = readstat_parser_init();
   35|  2.55k|    readstat_set_open_handler(parser, rt_open_handler);
   36|  2.55k|    readstat_set_close_handler(parser, rt_close_handler);
   37|  2.55k|    readstat_set_seek_handler(parser, rt_seek_handler);
   38|  2.55k|    readstat_set_read_handler(parser, rt_read_handler);
   39|  2.55k|    readstat_set_update_handler(parser, rt_update_handler);
   40|       |
   41|  2.55k|    readstat_set_metadata_handler(parser, &handle_metadata);
   42|  2.55k|    readstat_set_note_handler(parser, &handle_note);
   43|  2.55k|    readstat_set_variable_handler(parser, &handle_variable);
   44|  2.55k|    readstat_set_fweight_handler(parser, &handle_fweight);
   45|  2.55k|    readstat_set_value_handler(parser, &handle_value);
   46|  2.55k|    readstat_set_value_label_handler(parser, &handle_value_label);
   47|       |
   48|  2.55k|    return parser;
   49|  2.55k|}
fuzz_format.c:handle_metadata:
    8|  1.07k|static int handle_metadata(readstat_metadata_t *metadata, void *ctx) {
    9|  1.07k|    return READSTAT_HANDLER_OK;
   10|  1.07k|}
fuzz_format.c:handle_note:
   12|  1.03k|static int handle_note(int index, const char *note, void *ctx) {
   13|  1.03k|    return READSTAT_HANDLER_OK;
   14|  1.03k|}
fuzz_format.c:handle_variable:
   21|  1.21k|                           const char *val_labels, void *ctx) {
   22|  1.21k|    return READSTAT_HANDLER_OK;
   23|  1.21k|}
fuzz_format.c:handle_fweight:
   16|      2|static int handle_fweight(readstat_variable_t *variable, void *ctx) {
   17|      2|    return READSTAT_HANDLER_OK;
   18|      2|}
fuzz_format.c:handle_value:
   25|  16.6k|static int handle_value(int obs_index, readstat_variable_t *variable, readstat_value_t value, void *ctx) {
   26|  16.6k|    return READSTAT_HANDLER_OK;
   27|  16.6k|}
fuzz_format.c:handle_value_label:
   29|  12.2k|static int handle_value_label(const char *val_labels, readstat_value_t value, const char *label, void *ctx) {
   30|  12.2k|    return READSTAT_HANDLER_OK;
   31|  12.2k|}

LLVMFuzzerTestOneInput:
   10|  2.55k|int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
   11|  2.55k|    rt_buffer_t buffer = { .bytes = (char *)Data, .size = Size, .used = Size };
   12|  2.55k|    rt_buffer_ctx_t buffer_ctx = { .buffer = &buffer };
   13|       |
   14|  2.55k|    readstat_parser_t *parser = fuzzer_parser_init(Data, Size);
   15|  2.55k|    readstat_set_io_ctx(parser, &buffer_ctx);
   16|       |
   17|  2.55k|    readstat_parse_por(parser, NULL, NULL);
   18|  2.55k|    readstat_parser_free(parser);
   19|  2.55k|    return 0;
   20|  2.55k|}

readstat_convert:
   39|  20.0k|readstat_error_t readstat_convert(char *dst, size_t dst_len, const char *src, size_t src_len, iconv_t converter) {
   40|  20.0k|    return readstat_convert_impl(dst, dst_len, src, src_len, converter, 1);
   41|  20.0k|}
readstat_convert.c:readstat_convert_impl:
    8|  20.0k|        iconv_t converter, int trim_spaces) {
    9|       |    /* strip off spaces from the input because the programs use ASCII space
   10|       |     * padding even with non-ASCII encoding. */
   11|  79.0k|    while (src_len && ((trim_spaces && src[src_len-1] == ' ') || src[src_len-1] == '\0')) {
  ------------------
  |  Branch (11:12): [True: 71.6k, False: 7.39k]
  |  Branch (11:25): [True: 71.6k, False: 0]
  |  Branch (11:40): [True: 50.7k, False: 20.8k]
  |  Branch (11:66): [True: 8.19k, False: 12.7k]
  ------------------
   12|  58.9k|        src_len--;
   13|  58.9k|    }
   14|  20.0k|    if (dst_len == 0) {
  ------------------
  |  Branch (14:9): [True: 0, False: 20.0k]
  ------------------
   15|      0|        return READSTAT_ERROR_CONVERT_LONG_STRING;
   16|  20.0k|    } else if (converter) {
  ------------------
  |  Branch (16:16): [True: 0, False: 20.0k]
  ------------------
   17|      0|        size_t dst_left = dst_len - 1;
   18|      0|        char *dst_end = dst;
   19|      0|        size_t status = iconv(converter, (readstat_iconv_inbuf_t)&src, &src_len, &dst_end, &dst_left);
   20|      0|        if (status == (size_t)-1) {
  ------------------
  |  Branch (20:13): [True: 0, False: 0]
  ------------------
   21|      0|            if (errno == E2BIG) {
  ------------------
  |  Branch (21:17): [True: 0, False: 0]
  ------------------
   22|      0|                return READSTAT_ERROR_CONVERT_LONG_STRING;
   23|      0|            } else if (errno == EILSEQ) {
  ------------------
  |  Branch (23:24): [True: 0, False: 0]
  ------------------
   24|      0|                return READSTAT_ERROR_CONVERT_BAD_STRING;
   25|      0|            } else if (errno != EINVAL) { /* EINVAL indicates improper truncation; accept it */
  ------------------
  |  Branch (25:24): [True: 0, False: 0]
  ------------------
   26|      0|                return READSTAT_ERROR_CONVERT;
   27|      0|            }
   28|      0|        }
   29|      0|        dst[dst_len - dst_left - 1] = '\0';
   30|  20.0k|    } else if (src_len + 1 > dst_len) {
  ------------------
  |  Branch (30:16): [True: 0, False: 20.0k]
  ------------------
   31|      0|        return READSTAT_ERROR_CONVERT_LONG_STRING;
   32|  20.0k|    } else {
   33|  20.0k|        memcpy(dst, src, src_len);
   34|  20.0k|        dst[src_len] = '\0';
   35|  20.0k|    }
   36|  20.0k|    return READSTAT_OK;
   37|  20.0k|}

unistd_io_init:
  121|  2.55k|readstat_error_t unistd_io_init(readstat_parser_t *parser) {
  122|  2.55k|    readstat_error_t retval = READSTAT_OK;
  123|  2.55k|    unistd_io_ctx_t *io_ctx = NULL;
  124|       |
  125|  2.55k|    if ((retval = readstat_set_open_handler(parser, unistd_open_handler)) != READSTAT_OK)
  ------------------
  |  Branch (125:9): [True: 0, False: 2.55k]
  ------------------
  126|      0|        return retval;
  127|       |
  128|  2.55k|    if ((retval = readstat_set_close_handler(parser, unistd_close_handler)) != READSTAT_OK)
  ------------------
  |  Branch (128:9): [True: 0, False: 2.55k]
  ------------------
  129|      0|        return retval;
  130|       |
  131|  2.55k|    if ((retval = readstat_set_seek_handler(parser, unistd_seek_handler)) != READSTAT_OK)
  ------------------
  |  Branch (131:9): [True: 0, False: 2.55k]
  ------------------
  132|      0|        return retval;
  133|       |
  134|  2.55k|    if ((retval = readstat_set_read_handler(parser, unistd_read_handler)) != READSTAT_OK)
  ------------------
  |  Branch (134:9): [True: 0, False: 2.55k]
  ------------------
  135|      0|        return retval;
  136|       |
  137|  2.55k|    if ((readstat_set_update_handler(parser, unistd_update_handler)) != READSTAT_OK)
  ------------------
  |  Branch (137:9): [True: 0, False: 2.55k]
  ------------------
  138|      0|        return retval;
  139|       |
  140|  2.55k|    io_ctx = calloc(1, sizeof(unistd_io_ctx_t));
  141|  2.55k|    io_ctx->fd = -1;
  142|       |
  143|  2.55k|    retval = readstat_set_io_ctx(parser, (void*) io_ctx);
  144|  2.55k|    parser->io->io_ctx_needs_free = 1;
  145|       |
  146|  2.55k|    return retval;
  147|  2.55k|}

readstat_calloc:
   17|  2.17k|void *readstat_calloc(size_t count, size_t size) {
   18|  2.17k|    if (count > MAX_MALLOC_SIZE || size > MAX_MALLOC_SIZE || count * size > MAX_MALLOC_SIZE) {
  ------------------
  |  |    3|  4.34k|#define MAX_MALLOC_SIZE 0x1000000
  ------------------
                  if (count > MAX_MALLOC_SIZE || size > MAX_MALLOC_SIZE || count * size > MAX_MALLOC_SIZE) {
  ------------------
  |  |    3|  4.34k|#define MAX_MALLOC_SIZE 0x1000000
  ------------------
                  if (count > MAX_MALLOC_SIZE || size > MAX_MALLOC_SIZE || count * size > MAX_MALLOC_SIZE) {
  ------------------
  |  |    3|  2.17k|#define MAX_MALLOC_SIZE 0x1000000
  ------------------
  |  Branch (18:9): [True: 0, False: 2.17k]
  |  Branch (18:36): [True: 0, False: 2.17k]
  |  Branch (18:62): [True: 7, False: 2.16k]
  ------------------
   19|      7|        return NULL;
   20|      7|    }
   21|  2.16k|    if (count == 0 || size == 0) {
  ------------------
  |  Branch (21:9): [True: 10, False: 2.15k]
  |  Branch (21:23): [True: 0, False: 2.15k]
  ------------------
   22|     10|        return NULL;
   23|     10|    }
   24|  2.15k|    return calloc(count, size);
   25|  2.16k|}

readstat_parser_init:
    6|  2.55k|readstat_parser_t *readstat_parser_init(void) {
    7|  2.55k|    readstat_parser_t *parser = calloc(1, sizeof(readstat_parser_t));
    8|  2.55k|    parser->io = calloc(1, sizeof(readstat_io_t));
    9|  2.55k|    if (unistd_io_init(parser) != READSTAT_OK) {
  ------------------
  |  Branch (9:9): [True: 0, False: 2.55k]
  ------------------
   10|      0|        readstat_parser_free(parser);
   11|      0|        return NULL;
   12|      0|    }
   13|  2.55k|    parser->output_encoding = "UTF-8";
   14|  2.55k|    return parser;
   15|  2.55k|}
readstat_parser_free:
   17|  2.55k|void readstat_parser_free(readstat_parser_t *parser) {
   18|  2.55k|    if (parser) {
  ------------------
  |  Branch (18:9): [True: 2.55k, False: 0]
  ------------------
   19|  2.55k|        if (parser->io) {
  ------------------
  |  Branch (19:13): [True: 2.55k, False: 0]
  ------------------
   20|       |            readstat_set_io_ctx(parser, NULL);
   21|  2.55k|            free(parser->io);
   22|  2.55k|        }
   23|  2.55k|        free(parser);
   24|  2.55k|    }
   25|  2.55k|}
readstat_set_metadata_handler:
   27|  2.55k|readstat_error_t readstat_set_metadata_handler(readstat_parser_t *parser, readstat_metadata_handler metadata_handler) {
   28|  2.55k|    parser->handlers.metadata = metadata_handler;
   29|  2.55k|    return READSTAT_OK;
   30|  2.55k|}
readstat_set_note_handler:
   32|  2.55k|readstat_error_t readstat_set_note_handler(readstat_parser_t *parser, readstat_note_handler note_handler) {
   33|  2.55k|    parser->handlers.note = note_handler;
   34|  2.55k|    return READSTAT_OK;
   35|  2.55k|}
readstat_set_variable_handler:
   37|  2.55k|readstat_error_t readstat_set_variable_handler(readstat_parser_t *parser, readstat_variable_handler variable_handler) {
   38|  2.55k|    parser->handlers.variable = variable_handler;
   39|  2.55k|    return READSTAT_OK;
   40|  2.55k|}
readstat_set_value_handler:
   42|  2.55k|readstat_error_t readstat_set_value_handler(readstat_parser_t *parser, readstat_value_handler value_handler) {
   43|  2.55k|    parser->handlers.value = value_handler;
   44|  2.55k|    return READSTAT_OK;
   45|  2.55k|}
readstat_set_value_label_handler:
   47|  2.55k|readstat_error_t readstat_set_value_label_handler(readstat_parser_t *parser, readstat_value_label_handler label_handler) {
   48|  2.55k|    parser->handlers.value_label = label_handler;
   49|  2.55k|    return READSTAT_OK;
   50|  2.55k|}
readstat_set_fweight_handler:
   62|  2.55k|readstat_error_t readstat_set_fweight_handler(readstat_parser_t *parser, readstat_fweight_handler fweight_handler) {
   63|  2.55k|    parser->handlers.fweight = fweight_handler;
   64|  2.55k|    return READSTAT_OK;
   65|  2.55k|}
readstat_set_open_handler:
   67|  5.11k|readstat_error_t readstat_set_open_handler(readstat_parser_t *parser, readstat_open_handler open_handler) {
   68|  5.11k|    parser->io->open = open_handler;
   69|  5.11k|    return READSTAT_OK;
   70|  5.11k|}
readstat_set_close_handler:
   72|  5.11k|readstat_error_t readstat_set_close_handler(readstat_parser_t *parser, readstat_close_handler close_handler) {
   73|  5.11k|    parser->io->close = close_handler;
   74|  5.11k|    return READSTAT_OK;
   75|  5.11k|}
readstat_set_seek_handler:
   77|  5.11k|readstat_error_t readstat_set_seek_handler(readstat_parser_t *parser, readstat_seek_handler seek_handler) {
   78|  5.11k|    parser->io->seek = seek_handler;
   79|  5.11k|    return READSTAT_OK;
   80|  5.11k|}
readstat_set_read_handler:
   82|  5.11k|readstat_error_t readstat_set_read_handler(readstat_parser_t *parser, readstat_read_handler read_handler) {
   83|  5.11k|    parser->io->read = read_handler;
   84|  5.11k|    return READSTAT_OK;
   85|  5.11k|}
readstat_set_update_handler:
   87|  5.11k|readstat_error_t readstat_set_update_handler(readstat_parser_t *parser, readstat_update_handler update_handler) {
   88|  5.11k|    parser->io->update = update_handler;
   89|  5.11k|    return READSTAT_OK;
   90|  5.11k|}
readstat_set_io_ctx:
   92|  7.67k|readstat_error_t readstat_set_io_ctx(readstat_parser_t *parser, void *io_ctx) {
   93|  7.67k|    if (parser->io->io_ctx_needs_free) {
  ------------------
  |  Branch (93:9): [True: 2.55k, False: 5.11k]
  ------------------
   94|  2.55k|        free(parser->io->io_ctx);
   95|  2.55k|    }
   96|       |
   97|  7.67k|    parser->io->io_ctx = io_ctx;
   98|  7.67k|    parser->io->io_ctx_needs_free = 0;
   99|       |
  100|  7.67k|    return READSTAT_OK;
  101|  7.67k|}

por_ctx_init:
   75|  2.55k|por_ctx_t *por_ctx_init(void) {
   76|  2.55k|    por_ctx_t *ctx = calloc(1, sizeof(por_ctx_t));
   77|       |
   78|  2.55k|    ctx->space = ' ';
   79|  2.55k|    ctx->base30_precision = 20;
   80|  2.55k|    ctx->var_dict = ck_hash_table_init(1024, 8);
   81|  2.55k|    return ctx;
   82|  2.55k|}
por_ctx_free:
   84|  2.55k|void por_ctx_free(por_ctx_t *ctx) {
   85|  2.55k|    if (ctx->string_buffer)
  ------------------
  |  Branch (85:9): [True: 1.71k, False: 840]
  ------------------
   86|  1.71k|        free(ctx->string_buffer);
   87|  2.55k|    if (ctx->varinfo) {
  ------------------
  |  Branch (87:9): [True: 1.07k, False: 1.48k]
  ------------------
   88|  1.07k|        int i;
   89|  3.57M|        for (i=0; i<ctx->var_count; i++) {
  ------------------
  |  Branch (89:19): [True: 3.57M, False: 1.07k]
  ------------------
   90|  3.57M|            if (ctx->varinfo[i].label)
  ------------------
  |  Branch (90:17): [True: 120, False: 3.57M]
  ------------------
   91|    120|                free(ctx->varinfo[i].label);
   92|  3.57M|        }
   93|  1.07k|        free(ctx->varinfo);
   94|  1.07k|    }
   95|  2.55k|    if (ctx->variables) {
  ------------------
  |  Branch (95:9): [True: 1.08k, False: 1.47k]
  ------------------
   96|  1.08k|        int i;
   97|  7.56M|        for (i=0; i<ctx->var_count; i++) {
  ------------------
  |  Branch (97:19): [True: 7.56M, False: 1.08k]
  ------------------
   98|  7.56M|            if (ctx->variables[i])
  ------------------
  |  Branch (98:17): [True: 1.21k, False: 7.55M]
  ------------------
   99|  1.21k|                free(ctx->variables[i]);
  100|  7.56M|        }
  101|  1.08k|        free(ctx->variables);
  102|  1.08k|    }
  103|  2.55k|    if (ctx->var_dict)
  ------------------
  |  Branch (103:9): [True: 2.55k, False: 0]
  ------------------
  104|  2.55k|        ck_hash_table_free(ctx->var_dict);
  105|  2.55k|    if (ctx->converter)
  ------------------
  |  Branch (105:9): [True: 0, False: 2.55k]
  ------------------
  106|      0|        iconv_close(ctx->converter);
  107|  2.55k|    free(ctx);
  108|  2.55k|}
por_utf8_encode:
  168|   161k|        char *output, size_t output_len, uint16_t lookup[256]) {
  169|   161k|    size_t offset = 0;
  170|   161k|    size_t i;
  171|  2.23M|    for (i=0; i<input_len; i++) {
  ------------------
  |  Branch (171:15): [True: 2.08M, False: 157k]
  ------------------
  172|  2.08M|        uint16_t codepoint = lookup[input[i]];
  173|       |
  174|       |        /* Some software (SPSS?) uses an undefined character (zero) if a
  175|       |         * character can't be encoded. Use Unicode replacement character */
  176|  2.08M|        if (codepoint == 0) {
  ------------------
  |  Branch (176:13): [True: 9.46k, False: 2.07M]
  ------------------
  177|  9.46k|            codepoint = 0xFFFD;
  178|  9.46k|        }
  179|       |
  180|  2.08M|        if (codepoint < 0x20) {
  ------------------
  |  Branch (180:13): [True: 0, False: 2.08M]
  ------------------
  181|      0|            return -1;
  182|  2.08M|        } else if (codepoint <= 0x7F) {
  ------------------
  |  Branch (182:20): [True: 2.07M, False: 10.2k]
  ------------------
  183|  2.07M|            if (offset + 1 > output_len)
  ------------------
  |  Branch (183:17): [True: 1.76k, False: 2.06M]
  ------------------
  184|  1.76k|                return offset;
  185|       |
  186|  2.06M|            output[offset++] = codepoint;
  187|  2.06M|        } else if (codepoint <= 0x07FF) {
  ------------------
  |  Branch (187:20): [True: 604, False: 9.60k]
  ------------------
  188|    604|            if (offset + 2 > output_len)
  ------------------
  |  Branch (188:17): [True: 196, False: 408]
  ------------------
  189|    196|                return offset;
  190|       |
  191|    408|            output[offset++] = 0xC0 | (codepoint >> 6);
  192|    408|            output[offset++] = 0x80 | (codepoint & 0x3F);
  193|  9.60k|        } else {
  194|  9.60k|            if (offset + 3 > output_len)
  ------------------
  |  Branch (194:17): [True: 2.37k, False: 7.23k]
  ------------------
  195|  2.37k|                return offset;
  196|       |
  197|  7.23k|            output[offset++] = 0xE0 | (codepoint >> 12);
  198|  7.23k|            output[offset++] = 0x80 | ((codepoint >> 6) & 0x3F);
  199|  7.23k|            output[offset++] = 0x80 | (codepoint & 0x3F);
  200|  7.23k|        }
  201|  2.08M|    }
  202|   157k|    return offset;
  203|   161k|}
por_base30_to_double:
  399|   125k|double por_base30_to_double(const unsigned char *digits, size_t n_digits, long exponent) {
  400|   125k|    uint64_t mantissa = 0;
  401|   125k|    size_t mantissa_digits = 0;
  402|   125k|    long magnitude = 0;
  403|   125k|    long scale = 0;
  404|   125k|    double value = 0.0;
  405|   125k|    int iterations = 0;
  406|       |
  407|   125k|    while (n_digits > 0 && digits[0] == 0) {
  ------------------
  |  Branch (407:12): [True: 91.9k, False: 33.6k]
  |  Branch (407:28): [True: 0, False: 91.9k]
  ------------------
  408|      0|        digits++;
  409|      0|        n_digits--;
  410|      0|    }
  411|   234k|    while (n_digits > 0 && digits[n_digits-1] == 0) {
  ------------------
  |  Branch (411:12): [True: 200k, False: 33.6k]
  |  Branch (411:28): [True: 108k, False: 91.9k]
  ------------------
  412|   108k|        n_digits--;
  413|   108k|        exponent++;
  414|   108k|    }
  415|   125k|    if (n_digits == 0)
  ------------------
  |  Branch (415:9): [True: 33.6k, False: 91.9k]
  ------------------
  416|  33.6k|        return 0.0;
  417|       |
  418|       |    /* The value lies in [30^(magnitude-1), 30^magnitude) */
  419|  91.9k|    magnitude = (long)n_digits + exponent;
  420|  91.9k|    if (magnitude >= 210) /* 30^209 exceeds DBL_MAX */
  ------------------
  |  Branch (420:9): [True: 444, False: 91.4k]
  ------------------
  421|    444|        return HUGE_VAL;
  422|  91.4k|    if (magnitude <= -225) /* 30^-225 is below half the smallest denormal */
  ------------------
  |  Branch (422:9): [True: 894, False: 90.5k]
  ------------------
  423|    894|        return 0.0;
  424|       |
  425|       |    /* Initial approximation from the leading 13 digits (30^13 < 2^64) */
  426|   329k|    while (mantissa_digits < n_digits && mantissa_digits < 13) {
  ------------------
  |  Branch (426:12): [True: 243k, False: 85.2k]
  |  Branch (426:42): [True: 238k, False: 5.32k]
  ------------------
  427|   238k|        mantissa = mantissa * 30 + digits[mantissa_digits];
  428|   238k|        mantissa_digits++;
  429|   238k|    }
  430|  90.5k|    scale = exponent + (long)(n_digits - mantissa_digits);
  431|       |
  432|  90.5k|    if (mantissa <= (1ULL << 53) && scale >= -13 && scale <= 13) {
  ------------------
  |  Branch (432:9): [True: 80.4k, False: 10.1k]
  |  Branch (432:37): [True: 77.2k, False: 3.25k]
  |  Branch (432:53): [True: 75.8k, False: 1.34k]
  ------------------
  433|       |        /* Both operands are exact, so the single multiplication or division
  434|       |         * below is correctly rounded (30^13 = 2^13 * 15^13 and 15^13 < 2^53) */
  435|  75.8k|        double pow30 = 1.0;
  436|  75.8k|        long k = scale < 0 ? -scale : scale;
  ------------------
  |  Branch (436:18): [True: 629, False: 75.2k]
  ------------------
  437|  80.6k|        while (k-- > 0)
  ------------------
  |  Branch (437:16): [True: 4.74k, False: 75.8k]
  ------------------
  438|  4.74k|            pow30 *= 30.0;
  439|  75.8k|        return scale < 0 ? (double)mantissa / pow30 : (double)mantissa * pow30;
  ------------------
  |  Branch (439:16): [True: 629, False: 75.2k]
  ------------------
  440|  75.8k|    }
  441|       |
  442|  14.7k|    value = (double)mantissa;
  443|  21.0k|    while (scale > 0) {
  ------------------
  |  Branch (443:12): [True: 6.31k, False: 14.7k]
  ------------------
  444|  6.31k|        long step = scale > 200 ? 200 : scale;
  ------------------
  |  Branch (444:21): [True: 205, False: 6.10k]
  ------------------
  445|  6.31k|        value *= pow(30.0, (double)step);
  446|  6.31k|        scale -= step;
  447|  6.31k|    }
  448|  20.5k|    while (scale < 0) {
  ------------------
  |  Branch (448:12): [True: 5.82k, False: 14.7k]
  ------------------
  449|  5.82k|        long step = scale < -200 ? -200 : scale;
  ------------------
  |  Branch (449:21): [True: 494, False: 5.33k]
  ------------------
  450|  5.82k|        value *= pow(30.0, (double)step);
  451|  5.82k|        scale -= step;
  452|  5.82k|    }
  453|  14.7k|    if (isinf(value))
  ------------------
  |  Branch (453:9): [True: 504, False: 14.2k]
  ------------------
  454|    504|        value = DBL_MAX;
  455|       |
  456|       |    /* Correct the approximation by comparing the exact value against the
  457|       |     * midpoints between the candidate and its neighbors, moving one ulp at a
  458|       |     * time. Ties round to even. */
  459|  18.0k|    for (iterations=0; iterations<256; iterations++) {
  ------------------
  |  Branch (459:24): [True: 18.0k, False: 0]
  ------------------
  460|  18.0k|        uint64_t m = 0;
  461|  18.0k|        long e = -1074;
  462|  18.0k|        uint64_t midpoint_mantissa = 0;
  463|  18.0k|        long midpoint_exponent = 0;
  464|  18.0k|        int cmp = 0;
  465|       |
  466|  18.0k|        if (isinf(value))
  ------------------
  |  Branch (466:13): [True: 504, False: 17.5k]
  ------------------
  467|    504|            break;
  468|       |
  469|  17.5k|        if (value != 0.0) {
  ------------------
  |  Branch (469:13): [True: 17.3k, False: 217]
  ------------------
  470|  17.3k|            int exp2 = 0;
  471|  17.3k|            double significand = frexp(value, &exp2);
  472|  17.3k|            m = (uint64_t)ldexp(significand, 53);
  473|  17.3k|            e = exp2 - 53;
  474|  17.3k|            if (e < -1074) {
  ------------------
  |  Branch (474:17): [True: 274, False: 17.0k]
  ------------------
  475|       |                /* denormal: the spacing is fixed at 2^-1074 */
  476|    274|                m = (uint64_t)ldexp(value, 1074);
  477|    274|                e = -1074;
  478|    274|            }
  479|  17.3k|        }
  480|       |
  481|       |        /* midpoint above: (2m + 1) * 2^(e - 1) */
  482|  17.5k|        midpoint_mantissa = 2 * m + 1;
  483|  17.5k|        midpoint_exponent = e - 1;
  484|  17.5k|        cmp = por_compare_with_binary(digits, n_digits, exponent, midpoint_mantissa, midpoint_exponent);
  485|  17.5k|        if (cmp == 2)
  ------------------
  |  Branch (485:13): [True: 0, False: 17.5k]
  ------------------
  486|      0|            break;
  487|  17.5k|        if (cmp > 0) {
  ------------------
  |  Branch (487:13): [True: 2.45k, False: 15.0k]
  ------------------
  488|  2.45k|            value = nextafter(value, HUGE_VAL);
  489|  2.45k|            continue;
  490|  2.45k|        }
  491|  15.0k|        if (cmp == 0) {
  ------------------
  |  Branch (491:13): [True: 828, False: 14.2k]
  ------------------
  492|    828|            if (m & 1)
  ------------------
  |  Branch (492:17): [True: 194, False: 634]
  ------------------
  493|    194|                value = nextafter(value, HUGE_VAL);
  494|    828|            break;
  495|    828|        }
  496|  14.2k|        if (m == 0)
  ------------------
  |  Branch (496:13): [True: 217, False: 14.0k]
  ------------------
  497|    217|            break;
  498|       |
  499|       |        /* midpoint below: the spacing halves just below a power of two */
  500|  14.0k|        if (m == (1ULL << 52) && e > -1074) {
  ------------------
  |  Branch (500:13): [True: 207, False: 13.8k]
  |  Branch (500:34): [True: 207, False: 0]
  ------------------
  501|    207|            midpoint_mantissa = 4 * m - 1;
  502|    207|            midpoint_exponent = e - 2;
  503|  13.8k|        } else {
  504|  13.8k|            midpoint_mantissa = 2 * m - 1;
  505|  13.8k|            midpoint_exponent = e - 1;
  506|  13.8k|        }
  507|  14.0k|        cmp = por_compare_with_binary(digits, n_digits, exponent, midpoint_mantissa, midpoint_exponent);
  508|  14.0k|        if (cmp == 2)
  ------------------
  |  Branch (508:13): [True: 0, False: 14.0k]
  ------------------
  509|      0|            break;
  510|  14.0k|        if (cmp < 0) {
  ------------------
  |  Branch (510:13): [True: 864, False: 13.1k]
  ------------------
  511|    864|            value = nextafter(value, 0.0);
  512|    864|            continue;
  513|    864|        }
  514|  13.1k|        if (cmp == 0) {
  ------------------
  |  Branch (514:13): [True: 2.37k, False: 10.7k]
  ------------------
  515|       |            /* value's mantissa is 2m in the finer grid below a power of two,
  516|       |             * which is even, so only the ordinary case can move */
  517|  2.37k|            if (midpoint_mantissa == 2 * m - 1 && (m & 1))
  ------------------
  |  Branch (517:17): [True: 2.37k, False: 0]
  |  Branch (517:51): [True: 265, False: 2.11k]
  ------------------
  518|    265|                value = nextafter(value, 0.0);
  519|  2.37k|            break;
  520|  2.37k|        }
  521|  10.7k|        break;
  522|  13.1k|    }
  523|       |
  524|  14.7k|    return value;
  525|  90.5k|}
readstat_por.c:por_big_set:
  249|  63.0k|static void por_big_set(por_bignum_t *big, uint64_t value) {
  250|  63.0k|    big->n = 0;
  251|  63.0k|    big->overflow = 0;
  252|   125k|    while (value) {
  ------------------
  |  Branch (252:12): [True: 62.4k, False: 63.0k]
  ------------------
  253|  62.4k|        big->limbs[big->n++] = (uint32_t)(value % POR_BIG_LIMB_BASE);
  ------------------
  |  |  239|  62.4k|#define POR_BIG_LIMB_BASE   729000000u  /* 30^6 */
  ------------------
  254|  62.4k|        value /= POR_BIG_LIMB_BASE;
  ------------------
  |  |  239|  62.4k|#define POR_BIG_LIMB_BASE   729000000u  /* 30^6 */
  ------------------
  255|  62.4k|    }
  256|  63.0k|}
readstat_por.c:por_big_mul_pow:
  279|  43.4k|static void por_big_mul_pow(por_bignum_t *big, uint32_t base, long exponent) {
  280|  43.4k|    uint32_t chunk_mult = 1;
  281|  43.4k|    long chunk = 0;
  282|   968k|    while ((uint64_t)chunk_mult * base <= 0xFFFFFFFFu) {
  ------------------
  |  Branch (282:12): [True: 925k, False: 43.4k]
  ------------------
  283|   925k|        chunk_mult *= base;
  284|   925k|        chunk++;
  285|   925k|    }
  286|   449k|    while (exponent >= chunk && !big->overflow) {
  ------------------
  |  Branch (286:12): [True: 405k, False: 43.4k]
  |  Branch (286:33): [True: 405k, False: 0]
  ------------------
  287|   405k|        por_big_mul_add(big, chunk_mult, 0);
  288|   405k|        exponent -= chunk;
  289|   405k|    }
  290|  43.4k|    if (exponent > 0) {
  ------------------
  |  Branch (290:9): [True: 39.0k, False: 4.36k]
  ------------------
  291|  39.0k|        uint32_t mult = 1;
  292|   495k|        while (exponent-- > 0)
  ------------------
  |  Branch (292:16): [True: 456k, False: 39.0k]
  ------------------
  293|   456k|            mult *= base;
  294|  39.0k|        por_big_mul_add(big, mult, 0);
  295|  39.0k|    }
  296|  43.4k|}
readstat_por.c:por_big_mul_add:
  259|   570k|static void por_big_mul_add(por_bignum_t *big, uint32_t mult, uint32_t add) {
  260|   570k|    uint64_t carry = add;
  261|   570k|    int i;
  262|  6.15M|    for (i=0; i<big->n; i++) {
  ------------------
  |  Branch (262:15): [True: 5.58M, False: 570k]
  ------------------
  263|  5.58M|        uint64_t product = (uint64_t)big->limbs[i] * mult + carry;
  264|  5.58M|        big->limbs[i] = (uint32_t)(product % POR_BIG_LIMB_BASE);
  ------------------
  |  |  239|  5.58M|#define POR_BIG_LIMB_BASE   729000000u  /* 30^6 */
  ------------------
  265|  5.58M|        carry = product / POR_BIG_LIMB_BASE;
  ------------------
  |  |  239|  5.58M|#define POR_BIG_LIMB_BASE   729000000u  /* 30^6 */
  ------------------
  266|  5.58M|    }
  267|  1.14M|    while (carry) {
  ------------------
  |  Branch (267:12): [True: 571k, False: 570k]
  ------------------
  268|   571k|        if (big->n == POR_BIG_LIMBS) {
  ------------------
  |  |  241|   571k|#define POR_BIG_LIMBS       200         /* 1200 trigesimals; a denormal needs ~870 */
  ------------------
  |  Branch (268:13): [True: 0, False: 571k]
  ------------------
  269|      0|            big->overflow = 1;
  270|      0|            return;
  271|      0|        }
  272|   571k|        big->limbs[big->n++] = (uint32_t)(carry % POR_BIG_LIMB_BASE);
  ------------------
  |  |  239|   571k|#define POR_BIG_LIMB_BASE   729000000u  /* 30^6 */
  ------------------
  273|   571k|        carry /= POR_BIG_LIMB_BASE;
  ------------------
  |  |  239|   571k|#define POR_BIG_LIMB_BASE   729000000u  /* 30^6 */
  ------------------
  274|   571k|    }
  275|   570k|}
readstat_por.c:por_compare_with_binary:
  362|  31.5k|        uint64_t mantissa, long exp2) {
  363|  31.5k|    por_bignum_t lhs, rhs;
  364|  31.5k|    size_t i;
  365|  31.5k|    uint32_t chunk = 0;
  366|  31.5k|    uint32_t chunk_mult = 1;
  367|       |
  368|  31.5k|    por_big_set(&lhs, 0);
  369|   716k|    for (i=0; i<n_digits; i++) {
  ------------------
  |  Branch (369:15): [True: 685k, False: 31.5k]
  ------------------
  370|   685k|        chunk = chunk * 30 + digits[i];
  371|   685k|        chunk_mult *= 30;
  372|   685k|        if (chunk_mult == POR_BIG_LIMB_BASE) {
  ------------------
  |  |  239|   685k|#define POR_BIG_LIMB_BASE   729000000u  /* 30^6 */
  ------------------
  |  Branch (372:13): [True: 100k, False: 584k]
  ------------------
  373|   100k|            por_big_mul_add(&lhs, chunk_mult, chunk);
  374|   100k|            chunk = 0;
  375|   100k|            chunk_mult = 1;
  376|   100k|        }
  377|   685k|    }
  378|  31.5k|    if (chunk_mult > 1)
  ------------------
  |  Branch (378:9): [True: 25.0k, False: 6.53k]
  ------------------
  379|  25.0k|        por_big_mul_add(&lhs, chunk_mult, chunk);
  380|       |
  381|  31.5k|    por_big_set(&rhs, mantissa);
  382|       |
  383|  31.5k|    if (exp30 > 0) {
  ------------------
  |  Branch (383:9): [True: 4.50k, False: 27.0k]
  ------------------
  384|  4.50k|        por_big_mul_pow(&lhs, 30, exp30);
  385|  27.0k|    } else if (exp30 < 0) {
  ------------------
  |  Branch (385:16): [True: 12.2k, False: 14.7k]
  ------------------
  386|  12.2k|        por_big_mul_pow(&rhs, 30, -exp30);
  387|  12.2k|    }
  388|  31.5k|    if (exp2 > 0) {
  ------------------
  |  Branch (388:9): [True: 14.6k, False: 16.9k]
  ------------------
  389|  14.6k|        por_big_mul_pow(&rhs, 2, exp2);
  390|  16.9k|    } else if (exp2 < 0) {
  ------------------
  |  Branch (390:16): [True: 11.9k, False: 4.94k]
  ------------------
  391|  11.9k|        por_big_mul_pow(&lhs, 2, -exp2);
  392|  11.9k|    }
  393|  31.5k|    if (lhs.overflow || rhs.overflow)
  ------------------
  |  Branch (393:9): [True: 0, False: 31.5k]
  |  Branch (393:25): [True: 0, False: 31.5k]
  ------------------
  394|      0|        return 2;
  395|       |
  396|  31.5k|    return por_big_compare(&lhs, &rhs);
  397|  31.5k|}
readstat_por.c:por_big_compare:
  298|  31.5k|static int por_big_compare(const por_bignum_t *a, const por_bignum_t *b) {
  299|  31.5k|    int i;
  300|  31.5k|    if (a->n != b->n)
  ------------------
  |  Branch (300:9): [True: 490, False: 31.0k]
  ------------------
  301|    490|        return a->n > b->n ? 1 : -1;
  ------------------
  |  Branch (301:16): [True: 286, False: 204]
  ------------------
  302|  81.7k|    for (i=a->n-1; i>=0; i--) {
  ------------------
  |  Branch (302:20): [True: 78.5k, False: 3.20k]
  ------------------
  303|  78.5k|        if (a->limbs[i] != b->limbs[i])
  ------------------
  |  Branch (303:13): [True: 27.8k, False: 50.6k]
  ------------------
  304|  27.8k|            return a->limbs[i] > b->limbs[i] ? 1 : -1;
  ------------------
  |  Branch (304:20): [True: 12.9k, False: 14.9k]
  ------------------
  305|  78.5k|    }
  306|  3.20k|    return 0;
  307|  31.0k|}

readstat_por_parse_double:
   79|   125k|readstat_error_handler error_cb, void *user_ctx) {
   80|   125k|	ssize_t retval = 0;
   81|   125k|	double val = 0.0;
   82|       |	
   83|       |	/* Significant digits of the mantissa, most significant first; leading
   84|       |	* zeros are dropped and digits beyond POR_PARSE_MAX_DIGITS are folded
   85|       |	* into the scale. */
   86|   125k|	unsigned char digits[POR_PARSE_MAX_DIGITS] = { 0 };
   87|   125k|	size_t n_digits = 0;
   88|   125k|	long scale = 0;
   89|   125k|	long exp = 0;
   90|       |	
   91|   125k|	const unsigned char *p = (const unsigned char *)data;
   92|   125k|	const unsigned char *pe = p + len;
   93|       |	
   94|   125k|	int cs;
   95|   125k|	int is_negative = 0, exp_is_negative = 0;
   96|   125k|	int got_dot = 0;
   97|   125k|	int is_missing = 0;
   98|   125k|	int success = 0;
   99|       |	
  100|       |	
  101|   125k|#line 102 "src/spss/readstat_por_parse.c"
  102|   125k|	{
  103|   125k|		cs = (int)por_field_parse_start;
  104|   125k|	}
  105|       |	
  106|   125k|#line 107 "src/spss/readstat_por_parse.c"
  107|   125k|	{
  108|   125k|		int _klen;
  109|   125k|		unsigned int _trans = 0;
  110|   125k|		const char * _keys;
  111|   125k|		const signed char * _acts;
  112|   125k|		unsigned int _nacts;
  113|  1.76M|		_resume: {}
  114|  1.76M|		if ( p == pe )
  ------------------
  |  Branch (114:8): [True: 0, False: 1.76M]
  ------------------
  115|      0|			goto _out;
  116|  1.76M|		_keys = ( _por_field_parse_trans_keys + (_por_field_parse_key_offsets[cs]));
  117|  1.76M|		_trans = (unsigned int)_por_field_parse_index_offsets[cs];
  118|       |		
  119|  1.76M|		_klen = (int)_por_field_parse_single_lengths[cs];
  120|  1.76M|		if ( _klen > 0 ) {
  ------------------
  |  Branch (120:8): [True: 1.75M, False: 7.24k]
  ------------------
  121|  1.75M|			const char *_lower = _keys;
  122|  1.75M|			const char *_upper = _keys + _klen - 1;
  123|  1.75M|			const char *_mid;
  124|  6.38M|			while ( 1 ) {
  ------------------
  |  Branch (124:12): [True: 6.38M, Folded]
  ------------------
  125|  6.38M|				if ( _upper < _lower ) {
  ------------------
  |  Branch (125:10): [True: 1.47M, False: 4.91M]
  ------------------
  126|  1.47M|					_keys += _klen;
  127|  1.47M|					_trans += (unsigned int)_klen;
  128|  1.47M|					break;
  129|  1.47M|				}
  130|       |				
  131|  4.91M|				_mid = _lower + ((_upper-_lower) >> 1);
  132|  4.91M|				if ( ( (*( p))) < (*( _mid)) )
  ------------------
  |  Branch (132:10): [True: 151k, False: 4.76M]
  ------------------
  133|   151k|					_upper = _mid - 1;
  134|  4.76M|				else if ( ( (*( p))) > (*( _mid)) )
  ------------------
  |  Branch (134:15): [True: 4.48M, False: 285k]
  ------------------
  135|  4.48M|					_lower = _mid + 1;
  136|   285k|				else {
  137|   285k|					_trans += (unsigned int)(_mid - _keys);
  138|   285k|					goto _match;
  139|   285k|				}
  140|  4.91M|			}
  141|  1.75M|		}
  142|       |		
  143|  1.47M|		_klen = (int)_por_field_parse_range_lengths[cs];
  144|  1.47M|		if ( _klen > 0 ) {
  ------------------
  |  Branch (144:8): [True: 1.47M, False: 2]
  ------------------
  145|  1.47M|			const char *_lower = _keys;
  146|  1.47M|			const char *_upper = _keys + (_klen<<1) - 2;
  147|  1.47M|			const char *_mid;
  148|  1.65M|			while ( 1 ) {
  ------------------
  |  Branch (148:12): [True: 1.65M, Folded]
  ------------------
  149|  1.65M|				if ( _upper < _lower ) {
  ------------------
  |  Branch (149:10): [True: 140, False: 1.65M]
  ------------------
  150|    140|					_trans += (unsigned int)_klen;
  151|    140|					break;
  152|    140|				}
  153|       |				
  154|  1.65M|				_mid = _lower + (((_upper-_lower) >> 1) & ~1);
  155|  1.65M|				if ( ( (*( p))) < (*( _mid)) )
  ------------------
  |  Branch (155:10): [True: 61, False: 1.65M]
  ------------------
  156|     61|					_upper = _mid - 2;
  157|  1.65M|				else if ( ( (*( p))) > (*( _mid + 1)) )
  ------------------
  |  Branch (157:15): [True: 180k, False: 1.47M]
  ------------------
  158|   180k|					_lower = _mid + 2;
  159|  1.47M|				else {
  160|  1.47M|					_trans += (unsigned int)((_mid - _keys)>>1);
  161|  1.47M|					break;
  162|  1.47M|				}
  163|  1.65M|			}
  164|  1.47M|		}
  165|       |		
  166|  1.76M|		_match: {}
  167|  1.76M|		cs = (int)_por_field_parse_cond_targs[_trans];
  168|       |		
  169|  1.76M|		if ( _por_field_parse_cond_actions[_trans] != 0 ) {
  ------------------
  |  Branch (169:8): [True: 1.61M, False: 151k]
  ------------------
  170|       |			
  171|  1.61M|			_acts = ( _por_field_parse_actions + (_por_field_parse_cond_actions[_trans]));
  172|  1.61M|			_nacts = (unsigned int)(*( _acts));
  173|  1.61M|			_acts += 1;
  174|  3.09M|			while ( _nacts > 0 ) {
  ------------------
  |  Branch (174:12): [True: 1.61M, False: 1.48M]
  ------------------
  175|  1.61M|				switch ( (*( _acts)) )
  ------------------
  |  Branch (175:14): [True: 1.61M, False: 0]
  ------------------
  176|  1.61M|				{
  177|  1.41M|					case 0:  {
  ------------------
  |  Branch (177:6): [True: 1.41M, False: 193k]
  ------------------
  178|  1.41M|						{
  179|  1.41M|#line 42 "src/spss/readstat_por_parse.rl"
  180|       |							
  181|  1.41M|							int digit = por_base30_digit_value((( (*( p)))));
  182|  1.41M|							if (n_digits == 0 && digit == 0) {
  ------------------
  |  Branch (182:12): [True: 1.01M, False: 399k]
  |  Branch (182:29): [True: 927k, False: 91.9k]
  ------------------
  183|   927k|								if (got_dot)
  ------------------
  |  Branch (183:13): [True: 1.10k, False: 926k]
  ------------------
  184|  1.10k|								scale--;
  185|   927k|							} else if (n_digits < POR_PARSE_MAX_DIGITS) {
  ------------------
  |  |    7|   491k|#define POR_PARSE_MAX_DIGITS 128
  ------------------
  |  Branch (185:19): [True: 491k, False: 0]
  ------------------
  186|   491k|								digits[n_digits++] = digit;
  187|   491k|								if (got_dot)
  ------------------
  |  Branch (187:13): [True: 67.2k, False: 424k]
  ------------------
  188|  67.2k|								scale--;
  189|   491k|							} else if (!got_dot) {
  ------------------
  |  Branch (189:19): [True: 0, False: 0]
  ------------------
  190|      0|								scale++;
  191|      0|							}
  192|  1.41M|						}
  193|       |						
  194|  1.41M|#line 195 "src/spss/readstat_por_parse.c"
  195|       |						
  196|  1.41M|						break; 
  197|      0|					}
  198|  59.9k|					case 1:  {
  ------------------
  |  Branch (198:6): [True: 59.9k, False: 1.55M]
  ------------------
  199|  59.9k|						{
  200|  59.9k|#line 56 "src/spss/readstat_por_parse.rl"
  201|       |							
  202|  59.9k|							if (exp < 100000)
  ------------------
  |  Branch (202:12): [True: 39.8k, False: 20.0k]
  ------------------
  203|  39.8k|							exp = 30 * exp + por_base30_digit_value((( (*( p)))));
  204|  59.9k|						}
  205|       |						
  206|  59.9k|#line 207 "src/spss/readstat_por_parse.c"
  207|       |						
  208|  59.9k|						break; 
  209|      0|					}
  210|  1.55k|					case 2:  {
  ------------------
  |  Branch (210:6): [True: 1.55k, False: 1.61M]
  ------------------
  211|  1.55k|						{
  212|  1.55k|#line 63 "src/spss/readstat_por_parse.rl"
  213|  1.55k|							got_dot = 1; }
  214|       |						
  215|  1.55k|#line 216 "src/spss/readstat_por_parse.c"
  216|       |						
  217|  1.55k|						break; 
  218|      0|					}
  219|  1.02k|					case 3:  {
  ------------------
  |  Branch (219:6): [True: 1.02k, False: 1.61M]
  ------------------
  220|  1.02k|						{
  221|  1.02k|#line 64 "src/spss/readstat_por_parse.rl"
  222|  1.02k|							got_dot = 1; }
  223|       |						
  224|  1.02k|#line 225 "src/spss/readstat_por_parse.c"
  225|       |						
  226|  1.02k|						break; 
  227|      0|					}
  228|  4.93k|					case 4:  {
  ------------------
  |  Branch (228:6): [True: 4.93k, False: 1.60M]
  ------------------
  229|  4.93k|						{
  230|  4.93k|#line 66 "src/spss/readstat_por_parse.rl"
  231|  4.93k|							exp_is_negative = 1; }
  232|       |						
  233|  4.93k|#line 234 "src/spss/readstat_por_parse.c"
  234|       |						
  235|  4.93k|						break; 
  236|      0|					}
  237|    367|					case 5:  {
  ------------------
  |  Branch (237:6): [True: 367, False: 1.61M]
  ------------------
  238|    367|						{
  239|    367|#line 68 "src/spss/readstat_por_parse.rl"
  240|    367|							is_negative = 1; }
  241|       |						
  242|    367|#line 243 "src/spss/readstat_por_parse.c"
  243|       |						
  244|    367|						break; 
  245|      0|					}
  246|    194|					case 6:  {
  ------------------
  |  Branch (246:6): [True: 194, False: 1.61M]
  ------------------
  247|    194|						{
  248|    194|#line 70 "src/spss/readstat_por_parse.rl"
  249|    194|							is_missing = 1; }
  250|       |						
  251|    194|#line 252 "src/spss/readstat_por_parse.c"
  252|       |						
  253|    194|						break; 
  254|      0|					}
  255|   125k|					case 7:  {
  ------------------
  |  Branch (255:6): [True: 125k, False: 1.48M]
  ------------------
  256|   125k|						{
  257|   125k|#line 72 "src/spss/readstat_por_parse.rl"
  258|   125k|							success = 1; {p += 1; goto _out; } }
  259|       |						
  260|      0|#line 261 "src/spss/readstat_por_parse.c"
  261|       |						
  262|      0|						break; 
  263|      0|					}
  264|  1.61M|				}
  265|  1.48M|				_nacts -= 1;
  266|  1.48M|				_acts += 1;
  267|  1.48M|			}
  268|       |			
  269|  1.61M|		}
  270|       |		
  271|  1.63M|		if ( cs != 0 ) {
  ------------------
  |  Branch (271:8): [True: 1.63M, False: 142]
  ------------------
  272|  1.63M|			p += 1;
  273|  1.63M|			goto _resume;
  274|  1.63M|		}
  275|   125k|		_out: {}
  276|   125k|	}
  277|       |	
  278|      0|#line 76 "src/spss/readstat_por_parse.rl"
  279|       |	
  280|       |	
  281|   125k|	if (is_missing) {
  ------------------
  |  Branch (281:6): [True: 194, False: 125k]
  ------------------
  282|    194|		val = NAN;
  283|   125k|	} else {
  284|   125k|		if (exp_is_negative)
  ------------------
  |  Branch (284:7): [True: 4.93k, False: 120k]
  ------------------
  285|  4.93k|			exp = -exp;
  286|   125k|		val = por_base30_to_double(digits, n_digits, scale + exp);
  287|   125k|		if (is_negative)
  ------------------
  |  Branch (287:7): [True: 367, False: 125k]
  ------------------
  288|    367|			val = -val;
  289|   125k|	}
  290|       |	
  291|   125k|	if (!success) {
  ------------------
  |  Branch (291:6): [True: 142, False: 125k]
  ------------------
  292|    142|		retval = -1;
  293|    142|		if (error_cb) {
  ------------------
  |  Branch (293:7): [True: 0, False: 142]
  ------------------
  294|      0|			char error_buf[1024];
  295|      0|			snprintf(error_buf, sizeof(error_buf), "Read bytes: %ld   String: %.*s  Ending state: %d",
  296|      0|			(long)(p - (const unsigned char *)data), (int)len, data, cs);
  297|      0|			error_cb(error_buf, user_ctx);
  298|      0|		}
  299|    142|	}
  300|       |	
  301|   125k|	if (retval == 0) {
  ------------------
  |  Branch (301:6): [True: 125k, False: 142]
  ------------------
  302|   125k|		if (result)
  ------------------
  |  Branch (302:7): [True: 125k, False: 0]
  ------------------
  303|   125k|			*result = val;
  304|       |		
  305|   125k|		retval = (p - (const unsigned char *)data);
  306|   125k|	}
  307|       |	
  308|       |	/* suppress warning */
  309|   125k|	(void)por_field_parse_en_main;
  310|       |	
  311|   125k|	return retval;
  312|  1.63M|}
readstat_por_parse.c:por_base30_digit_value:
   72|  1.45M|static int por_base30_digit_value(unsigned char c) {
   73|  1.45M|	if (c >= '0' && c <= '9')
  ------------------
  |  Branch (73:6): [True: 1.45M, False: 0]
  |  Branch (73:18): [True: 1.28M, False: 178k]
  ------------------
   74|  1.28M|		return c - '0';
   75|   178k|	return 10 + c - 'A';
   76|  1.45M|}

read_version_and_timestamp:
  695|  2.23k|readstat_error_t read_version_and_timestamp(por_ctx_t *ctx) {
  696|  2.23k|    readstat_error_t retval = READSTAT_OK;
  697|  2.23k|    char string[256];
  698|  2.23k|    struct tm timestamp = { .tm_isdst = -1 };
  699|  2.23k|    unsigned char version;
  700|       |
  701|  2.23k|    if (read_bytes(ctx, &version, sizeof(version)) != sizeof(version)) {
  ------------------
  |  Branch (701:9): [True: 9, False: 2.22k]
  ------------------
  702|      9|        retval = READSTAT_ERROR_READ;
  703|      9|        goto cleanup;
  704|      9|    }
  705|  2.22k|    if ((retval = read_string(ctx, string, sizeof(string))) != READSTAT_OK) { /* creation date */
  ------------------
  |  Branch (705:9): [True: 430, False: 1.79k]
  ------------------
  706|    430|        goto cleanup;
  707|    430|    }
  708|  1.79k|    if (sscanf(string, "%04d%02d%02d", &timestamp.tm_year, &timestamp.tm_mon, &timestamp.tm_mday) != 3) {
  ------------------
  |  Branch (708:9): [True: 156, False: 1.63k]
  ------------------
  709|    156|        retval = READSTAT_ERROR_BAD_TIMESTAMP_STRING;
  710|    156|        goto cleanup;
  711|    156|    }
  712|  1.63k|    if ((retval = read_string(ctx, string, sizeof(string))) != READSTAT_OK) { /* creation time */
  ------------------
  |  Branch (712:9): [True: 29, False: 1.61k]
  ------------------
  713|     29|        goto cleanup;
  714|     29|    }
  715|  1.61k|    if (sscanf(string, "%02d%02d%02d", &timestamp.tm_hour, &timestamp.tm_min, &timestamp.tm_sec) != 3) {
  ------------------
  |  Branch (715:9): [True: 1.48k, False: 125]
  ------------------
  716|       |        /* optional */
  717|  1.48k|    }
  718|       |
  719|  1.61k|    timestamp.tm_year -= 1900;
  720|  1.61k|    timestamp.tm_mon--;
  721|       |
  722|  1.61k|    ctx->timestamp = mktime(&timestamp);
  723|  1.61k|    ctx->version = ctx->byte2unicode[version] - 'A';
  724|       |
  725|  2.23k|cleanup:
  726|  2.23k|    return retval;
  727|  1.61k|}
handle_variables:
  729|    366|readstat_error_t handle_variables(por_ctx_t *ctx) {
  730|    366|    readstat_error_t retval = READSTAT_OK;
  731|    366|    int i;
  732|    366|    int index_after_skipping = 0;
  733|  1.57k|    for (i=0; i<ctx->var_count; i++) {
  ------------------
  |  Branch (733:15): [True: 1.21k, False: 366]
  ------------------
  734|  1.21k|        char label_name_buf[256];
  735|  1.21k|        spss_varinfo_t *info = &ctx->varinfo[i];
  736|  1.21k|        info->index = i;
  737|       |
  738|  1.21k|        ctx->variables[i] = spss_init_variable_for_info(info, index_after_skipping, ctx->converter);
  739|       |
  740|  1.21k|        snprintf(label_name_buf, sizeof(label_name_buf), POR_LABEL_NAME_PREFIX "%d", info->labels_index);
  ------------------
  |  |   25|  1.21k|#define POR_LABEL_NAME_PREFIX   "labels"
  ------------------
  741|       |
  742|  1.21k|        int cb_retval = READSTAT_HANDLER_OK;
  743|       |
  744|  1.21k|        if (ctx->handle.variable) {
  ------------------
  |  Branch (744:13): [True: 1.21k, False: 0]
  ------------------
  745|  1.21k|            cb_retval = ctx->handle.variable(i, ctx->variables[i],
  746|  1.21k|                    info->labels_index == -1 ? NULL : label_name_buf,
  ------------------
  |  Branch (746:21): [True: 1.20k, False: 13]
  ------------------
  747|  1.21k|                    ctx->user_ctx);
  748|  1.21k|        }
  749|       |
  750|  1.21k|        if (cb_retval == READSTAT_HANDLER_ABORT) {
  ------------------
  |  Branch (750:13): [True: 0, False: 1.21k]
  ------------------
  751|      0|            retval = READSTAT_ERROR_USER_ABORT;
  752|      0|            goto cleanup;
  753|      0|        }
  754|       |
  755|  1.21k|        if (cb_retval == READSTAT_HANDLER_SKIP_VARIABLE) {
  ------------------
  |  Branch (755:13): [True: 0, False: 1.21k]
  ------------------
  756|      0|            ctx->variables[i]->skip = 1;
  757|  1.21k|        } else {
  758|  1.21k|            index_after_skipping++;
  759|  1.21k|        }
  760|  1.21k|    }
  761|    366|    if (ctx->handle.fweight && ctx->fweight_name[0]) {
  ------------------
  |  Branch (761:9): [True: 366, False: 0]
  |  Branch (761:32): [True: 89, False: 277]
  ------------------
  762|    248|        for (i=0; i<ctx->var_count; i++) {
  ------------------
  |  Branch (762:19): [True: 161, False: 87]
  ------------------
  763|    161|            spss_varinfo_t *info = &ctx->varinfo[i];
  764|    161|            if (strcmp(info->name, ctx->fweight_name) == 0) {
  ------------------
  |  Branch (764:17): [True: 2, False: 159]
  ------------------
  765|      2|                if (ctx->handle.fweight(ctx->variables[i], ctx->user_ctx) != READSTAT_HANDLER_OK) {
  ------------------
  |  Branch (765:21): [True: 0, False: 2]
  ------------------
  766|      0|                    retval = READSTAT_ERROR_USER_ABORT;
  767|      0|                    goto cleanup;
  768|      0|                }
  769|      2|                break;
  770|      2|            }
  771|    161|        }
  772|     89|    }
  773|    366|cleanup:
  774|    366|    return retval;
  775|    366|}
readstat_parse_por:
  777|  2.55k|readstat_error_t readstat_parse_por(readstat_parser_t *parser, const char *path, void *user_ctx) {
  778|  2.55k|    readstat_error_t retval = READSTAT_OK;
  779|  2.55k|    readstat_io_t *io = parser->io;
  780|  2.55k|    unsigned char reverse_lookup[256];
  781|  2.55k|    char vanity[5][40];
  782|  2.55k|    char error_buf[1024];
  783|       |
  784|  2.55k|    por_ctx_t *ctx = por_ctx_init();
  785|       |    
  786|  2.55k|    ctx->handle = parser->handlers;
  787|  2.55k|    ctx->user_ctx = user_ctx;
  788|  2.55k|    ctx->io = io;
  789|  2.55k|    ctx->row_limit = parser->row_limit;
  790|  2.55k|    if (parser->row_offset > 0)
  ------------------
  |  Branch (790:9): [True: 0, False: 2.55k]
  ------------------
  791|      0|        ctx->row_offset = parser->row_offset;
  792|       |
  793|  2.55k|    if (parser->output_encoding) {
  ------------------
  |  Branch (793:9): [True: 2.55k, False: 0]
  ------------------
  794|  2.55k|        if (strcmp(parser->output_encoding, "UTF-8") != 0)
  ------------------
  |  Branch (794:13): [True: 0, False: 2.55k]
  ------------------
  795|      0|            ctx->converter = iconv_open(parser->output_encoding, "UTF-8");
  796|       |
  797|  2.55k|        if (ctx->converter == (iconv_t)-1) {
  ------------------
  |  Branch (797:13): [True: 0, False: 2.55k]
  ------------------
  798|      0|            ctx->converter = NULL;
  799|      0|            retval = READSTAT_ERROR_UNSUPPORTED_CHARSET;
  800|      0|            goto cleanup;
  801|      0|        }
  802|  2.55k|    }
  803|       |    
  804|  2.55k|    if (io->open(path, io->io_ctx) == -1) {
  ------------------
  |  Branch (804:9): [True: 0, False: 2.55k]
  ------------------
  805|      0|        retval = READSTAT_ERROR_OPEN;
  806|      0|        goto cleanup;
  807|      0|    }
  808|       |
  809|  2.55k|    if ((ctx->file_size = io->seek(0, READSTAT_SEEK_END, io->io_ctx)) == -1) {
  ------------------
  |  Branch (809:9): [True: 0, False: 2.55k]
  ------------------
  810|      0|        retval = READSTAT_ERROR_SEEK;
  811|      0|        goto cleanup;
  812|      0|    }
  813|       |
  814|  2.55k|    if (io->seek(0, READSTAT_SEEK_SET, io->io_ctx) == -1) {
  ------------------
  |  Branch (814:9): [True: 0, False: 2.55k]
  ------------------
  815|      0|        retval = READSTAT_ERROR_SEEK;
  816|      0|        goto cleanup;
  817|      0|    }
  818|       |    
  819|  2.55k|    if (read_bytes(ctx, vanity, sizeof(vanity)) != sizeof(vanity)) {
  ------------------
  |  Branch (819:9): [True: 59, False: 2.50k]
  ------------------
  820|     59|        retval = READSTAT_ERROR_READ;
  821|     59|        goto cleanup;
  822|     59|    }
  823|       |
  824|  2.50k|    retval = readstat_convert(ctx->file_label, sizeof(ctx->file_label), vanity[1] + 20, 20, NULL);
  825|  2.50k|    if (retval != READSTAT_OK)
  ------------------
  |  Branch (825:9): [True: 0, False: 2.50k]
  ------------------
  826|      0|        goto cleanup;
  827|       |    
  828|  2.50k|    if (read_bytes(ctx, reverse_lookup, sizeof(reverse_lookup)) != sizeof(reverse_lookup)) {
  ------------------
  |  Branch (828:9): [True: 92, False: 2.40k]
  ------------------
  829|     92|        retval = READSTAT_ERROR_READ;
  830|     92|        goto cleanup;
  831|     92|    }
  832|       |    
  833|  2.40k|    ctx->space = reverse_lookup[126];
  834|       |
  835|  2.40k|    int i;
  836|       |
  837|       |    /* A byte that appears at several positions in the translation table
  838|       |     * keeps its first meaning, as in PSPP and R's foreign package. PSPP for
  839|       |     * instance maps the superscript digits (positions 167-176) to '0'-'9'
  840|       |     * as well, and last-writer-wins would turn every digit into a
  841|       |     * superscript. */
  842|   618k|    for (i=0; i<256; i++) {
  ------------------
  |  Branch (842:15): [True: 616k, False: 2.40k]
  ------------------
  843|   616k|        if (ctx->byte2unicode[reverse_lookup[i]])
  ------------------
  |  Branch (843:13): [True: 303k, False: 312k]
  ------------------
  844|   303k|            continue;
  845|   312k|        if (por_ascii_lookup[i]) {
  ------------------
  |  Branch (845:13): [True: 98.7k, False: 214k]
  ------------------
  846|  98.7k|            ctx->byte2unicode[reverse_lookup[i]] = por_ascii_lookup[i];
  847|   214k|        } else if (por_unicode_lookup[i]) {
  ------------------
  |  Branch (847:20): [True: 464, False: 213k]
  ------------------
  848|    464|            ctx->byte2unicode[reverse_lookup[i]] = por_unicode_lookup[i];
  849|    464|        }
  850|   312k|    }
  851|       |
  852|  2.40k|    ctx->byte2unicode[reverse_lookup[64]] = por_unicode_lookup[64];
  853|       |
  854|  2.40k|    unsigned char check[8];
  855|  2.40k|    char tr_check[8];
  856|       |    
  857|  2.40k|    if (read_bytes(ctx, check, sizeof(check)) != sizeof(check)) {
  ------------------
  |  Branch (857:9): [True: 37, False: 2.37k]
  ------------------
  858|     37|        retval = READSTAT_ERROR_READ;
  859|     37|        goto cleanup;
  860|     37|    }
  861|       |
  862|  2.37k|    ssize_t encoded_len;
  863|       |
  864|  2.37k|    if ((encoded_len = por_utf8_encode(check, sizeof(check), tr_check, sizeof(tr_check), ctx->byte2unicode)) == -1) {
  ------------------
  |  Branch (864:9): [True: 0, False: 2.37k]
  ------------------
  865|      0|        if (ctx->handle.error) {
  ------------------
  |  Branch (865:13): [True: 0, False: 0]
  ------------------
  866|      0|            snprintf(error_buf, sizeof(error_buf), "Error converting check string: %.*s", (int)sizeof(check), check);
  867|      0|            ctx->handle.error(error_buf, ctx->user_ctx);
  868|      0|        }
  869|      0|        retval = READSTAT_ERROR_CONVERT;
  870|      0|        goto cleanup;
  871|      0|    }
  872|       |
  873|  2.37k|    if (strncmp("SPSSPORT", tr_check, encoded_len) != 0) {
  ------------------
  |  Branch (873:9): [True: 137, False: 2.23k]
  ------------------
  874|    137|        retval = READSTAT_ERROR_PARSE;
  875|    137|        goto cleanup;
  876|    137|    }
  877|       |    
  878|  2.23k|    ctx->var_offset = -1;
  879|       |    
  880|  2.23k|    char string[256];
  881|       |
  882|  2.23k|    retval = read_version_and_timestamp(ctx);
  883|  2.23k|    if (retval != READSTAT_OK)
  ------------------
  |  Branch (883:9): [True: 624, False: 1.61k]
  ------------------
  884|    624|        goto cleanup;
  885|       |
  886|  21.1k|    while (1) {
  ------------------
  |  Branch (886:12): [True: 21.1k, Folded]
  ------------------
  887|  21.1k|        uint16_t tr_tag = read_tag(ctx);
  888|  21.1k|        switch (tr_tag) {
  889|    249|            case '1': /* product ID */
  ------------------
  |  Branch (889:13): [True: 249, False: 20.9k]
  ------------------
  890|    623|            case '2': /* author ID */
  ------------------
  |  Branch (890:13): [True: 374, False: 20.8k]
  ------------------
  891|    839|            case '3': /* sub-product ID */
  ------------------
  |  Branch (891:13): [True: 216, False: 20.9k]
  ------------------
  892|    839|                retval = read_string(ctx, string, sizeof(string));
  893|    839|                break;
  894|  1.11k|            case '4': /* variable count */
  ------------------
  |  Branch (894:13): [True: 1.11k, False: 20.0k]
  ------------------
  895|  1.11k|                retval = read_variable_count_record(ctx);
  896|  1.11k|                break;
  897|    481|            case '5': /* precision */
  ------------------
  |  Branch (897:13): [True: 481, False: 20.6k]
  ------------------
  898|    481|                retval = read_precision_record(ctx);
  899|    481|                break;
  900|  1.14k|            case '6': /* case weight */
  ------------------
  |  Branch (900:13): [True: 1.14k, False: 20.0k]
  ------------------
  901|  1.14k|                retval = read_case_weight_record(ctx);
  902|  1.14k|                break;
  903|  7.31k|            case '7': /* variable */
  ------------------
  |  Branch (903:13): [True: 7.31k, False: 13.8k]
  ------------------
  904|  7.31k|                retval = read_variable_record(ctx);
  905|  7.31k|                break;
  906|    659|            case '8': /* missing value */
  ------------------
  |  Branch (906:13): [True: 659, False: 20.5k]
  ------------------
  907|    659|                retval = read_missing_value_record(ctx);
  908|    659|                break;
  909|  1.24k|            case 'B': /* missing value range */
  ------------------
  |  Branch (909:13): [True: 1.24k, False: 19.9k]
  ------------------
  910|  1.24k|                retval = read_missing_value_range_record(ctx);
  911|  1.24k|                break;
  912|  1.62k|            case '9': /* LO THRU x */
  ------------------
  |  Branch (912:13): [True: 1.62k, False: 19.5k]
  ------------------
  913|  1.62k|                retval = read_missing_value_lo_range_record(ctx);
  914|  1.62k|                break;
  915|  1.11k|            case 'A': /* x THRU HI */
  ------------------
  |  Branch (915:13): [True: 1.11k, False: 20.0k]
  ------------------
  916|  1.11k|                retval = read_missing_value_hi_range_record(ctx);
  917|  1.11k|                break;
  918|    519|            case 'C': /* variable label */
  ------------------
  |  Branch (918:13): [True: 519, False: 20.6k]
  ------------------
  919|    519|                retval = read_variable_label_record(ctx);
  920|    519|                break;
  921|  3.92k|            case 'D': /* value label */
  ------------------
  |  Branch (921:13): [True: 3.92k, False: 17.2k]
  ------------------
  922|  3.92k|                retval = read_value_label_record(ctx);
  923|  3.92k|                break;
  924|    547|            case 'E': /* document record */
  ------------------
  |  Branch (924:13): [True: 547, False: 20.6k]
  ------------------
  925|    547|                retval = read_document_record(ctx);
  926|    547|                break;
  927|    394|            case 'F': /* file data */
  ------------------
  |  Branch (927:13): [True: 394, False: 20.7k]
  ------------------
  928|    394|                if (ctx->var_offset != ctx->var_count - 1) {
  ------------------
  |  Branch (928:21): [True: 28, False: 366]
  ------------------
  929|     28|                    retval = READSTAT_ERROR_COLUMN_COUNT_MISMATCH;
  930|     28|                    goto cleanup;
  931|     28|                }
  932|       |
  933|    366|                retval = handle_variables(ctx);
  934|    366|                if (retval != READSTAT_OK)
  ------------------
  |  Branch (934:21): [True: 0, False: 366]
  ------------------
  935|      0|                    goto cleanup;
  936|       |
  937|    366|                if (ctx->handle.value) {
  ------------------
  |  Branch (937:21): [True: 366, False: 0]
  ------------------
  938|    366|                    retval = read_por_file_data(ctx);
  939|    366|                }
  940|    366|                goto cleanup;
  941|    248|            default:
  ------------------
  |  Branch (941:13): [True: 248, False: 20.9k]
  ------------------
  942|    248|                retval = READSTAT_ERROR_PARSE;
  943|    248|                goto cleanup;
  944|  21.1k|        }
  945|  20.5k|        if (retval != READSTAT_OK)
  ------------------
  |  Branch (945:13): [True: 968, False: 19.5k]
  ------------------
  946|    968|            break;
  947|  20.5k|    }
  948|       |
  949|  2.55k|cleanup:
  950|  2.55k|    io->close(io->io_ctx);
  951|  2.55k|    por_ctx_free(ctx);
  952|       |    
  953|  2.55k|    return retval;
  954|  1.61k|}
readstat_por_read.c:read_bytes:
   49|  1.85M|static ssize_t read_bytes(por_ctx_t *ctx, void *dst, size_t len) {
   50|  1.85M|    char *dst_pos = (char *)dst;
   51|  1.85M|    readstat_io_t *io = ctx->io;
   52|  1.85M|    char byte;
   53|       |
   54|  5.35M|    while (dst_pos < (char *)dst + len) {
  ------------------
  |  Branch (54:12): [True: 3.50M, False: 1.84M]
  ------------------
   55|  3.50M|        if (ctx->num_spaces) {
  ------------------
  |  Branch (55:13): [True: 2.39M, False: 1.11M]
  ------------------
   56|  2.39M|            *dst_pos++ = ctx->space;
   57|  2.39M|            ctx->num_spaces--;
   58|  2.39M|            continue;
   59|  2.39M|        }
   60|  1.11M|        ssize_t bytes_read = io->read(&byte, 1, io->io_ctx);
   61|  1.11M|        if (bytes_read == 0) {
  ------------------
  |  Branch (61:13): [True: 1.69k, False: 1.10M]
  ------------------
   62|  1.69k|            break;
   63|  1.69k|        }
   64|  1.10M|        if (bytes_read == -1) {
  ------------------
  |  Branch (64:13): [True: 0, False: 1.10M]
  ------------------
   65|      0|            return -1;
   66|      0|        }
   67|       |        /* Like PSPP: ignore carriage returns entirely; a line feed ends the
   68|       |         * line, and a line shorter than 80 characters is padded with spaces.
   69|       |         * Lines longer than 80 characters are read as-is. */
   70|  1.10M|        if (byte == '\r') {
  ------------------
  |  Branch (70:13): [True: 3.09k, False: 1.10M]
  ------------------
   71|  3.09k|            continue;
   72|  1.10M|        } else if (byte == '\n') {
  ------------------
  |  Branch (72:20): [True: 37.8k, False: 1.06M]
  ------------------
   73|  37.8k|            if (ctx->pos < POR_LINE_LENGTH)
  ------------------
  |  |   24|  37.8k|#define POR_LINE_LENGTH         80
  ------------------
  |  Branch (73:17): [True: 36.1k, False: 1.70k]
  ------------------
   74|  36.1k|                ctx->num_spaces = POR_LINE_LENGTH - ctx->pos;
  ------------------
  |  |   24|  36.1k|#define POR_LINE_LENGTH         80
  ------------------
   75|  37.8k|            ctx->pos = 0;
   76|  37.8k|            continue;
   77|  37.8k|        }
   78|  1.06M|        *dst_pos++ = byte;
   79|  1.06M|        ctx->pos++;
   80|  1.06M|    }
   81|       |    
   82|  1.85M|    return (int)(dst_pos - (char *)dst);
   83|  1.85M|}
readstat_por_read.c:read_string:
  246|  34.4k|static readstat_error_t read_string(por_ctx_t *ctx, char *data, size_t len) {
  247|  34.4k|    int finished = 0;
  248|  34.4k|    readstat_error_t retval = maybe_read_string(ctx, data, len, &finished);
  249|  34.4k|    if (retval == READSTAT_OK && finished) {
  ------------------
  |  Branch (249:9): [True: 33.4k, False: 962]
  |  Branch (249:34): [True: 10, False: 33.4k]
  ------------------
  250|     10|        return READSTAT_ERROR_PARSE;
  251|     10|    }
  252|  34.4k|    return retval;
  253|  34.4k|}
readstat_por_read.c:maybe_read_string:
  196|  34.8k|static readstat_error_t maybe_read_string(por_ctx_t *ctx, char *data, size_t len, int *out_finished) {
  197|  34.8k|    readstat_error_t retval = READSTAT_OK;
  198|  34.8k|    double value;
  199|  34.8k|    int finished = 0;
  200|  34.8k|    char error_buf[1024];
  201|  34.8k|    size_t string_length = 0;
  202|  34.8k|    retval = maybe_read_double(ctx, &value, &finished);
  203|  34.8k|    if (retval != READSTAT_OK || finished) {
  ------------------
  |  Branch (203:9): [True: 799, False: 34.0k]
  |  Branch (203:34): [True: 13, False: 34.0k]
  ------------------
  204|    812|        if (out_finished)
  ------------------
  |  Branch (204:13): [True: 812, False: 0]
  ------------------
  205|    812|            *out_finished = finished;
  206|       |
  207|    812|        return retval;
  208|    812|    }
  209|       |    
  210|  34.0k|    if (value < 0 || value > MAX_STRING_LENGTH || isnan(value)) {
  ------------------
  |  |   31|  68.0k|#define MAX_STRING_LENGTH   20000
  ------------------
  |  Branch (210:9): [True: 1, False: 34.0k]
  |  Branch (210:22): [True: 198, False: 33.8k]
  |  Branch (210:51): [True: 1, False: 33.8k]
  ------------------
  211|    200|        retval = READSTAT_ERROR_PARSE;
  212|    200|        goto cleanup;
  213|    200|    }
  214|  33.8k|    string_length = (size_t)value;
  215|       |    
  216|  33.8k|    if (string_length > ctx->string_buffer_len) {
  ------------------
  |  Branch (216:9): [True: 2.25k, False: 31.5k]
  ------------------
  217|  2.25k|        ctx->string_buffer_len = string_length;
  218|  2.25k|        ctx->string_buffer = realloc(ctx->string_buffer, ctx->string_buffer_len);
  219|  2.25k|        memset(ctx->string_buffer, 0, ctx->string_buffer_len);
  220|  2.25k|    }
  221|       |    
  222|  33.8k|    if (read_bytes(ctx, ctx->string_buffer, string_length) != string_length) {
  ------------------
  |  Branch (222:9): [True: 125, False: 33.7k]
  ------------------
  223|    125|        retval = READSTAT_ERROR_READ;
  224|    125|        goto cleanup;
  225|    125|    }
  226|  33.7k|    size_t bytes_encoded = por_utf8_encode(ctx->string_buffer, string_length, 
  227|  33.7k|            data, len - 1, ctx->byte2unicode);
  228|  33.7k|    if (bytes_encoded == -1) {
  ------------------
  |  Branch (228:9): [True: 0, False: 33.7k]
  ------------------
  229|      0|        if (ctx->handle.error) {
  ------------------
  |  Branch (229:13): [True: 0, False: 0]
  ------------------
  230|      0|            snprintf(error_buf, sizeof(error_buf), "Error converting string: %.*s", 
  231|      0|                    (int)string_length, ctx->string_buffer);
  232|      0|            ctx->handle.error(error_buf, ctx->user_ctx);
  233|      0|        }
  234|      0|        retval = READSTAT_ERROR_CONVERT;
  235|      0|        goto cleanup;
  236|      0|    }
  237|       |    
  238|  33.7k|    data[bytes_encoded] = '\0';
  239|  33.7k|    if (out_finished)
  ------------------
  |  Branch (239:9): [True: 33.7k, False: 0]
  ------------------
  240|  33.7k|        *out_finished = 0;
  241|       |
  242|  34.0k|cleanup:
  243|  34.0k|    return retval;
  244|  33.7k|}
readstat_por_read.c:maybe_read_double:
  176|  51.4k|static readstat_error_t maybe_read_double(por_ctx_t *ctx, double *out_double, int *out_finished) {
  177|  51.4k|    unsigned char peek;
  178|  51.4k|    size_t bytes_read = read_bytes(ctx, &peek, 1);
  179|  51.4k|    if (bytes_read != 1)
  ------------------
  |  Branch (179:9): [True: 487, False: 50.9k]
  ------------------
  180|    487|        return READSTAT_ERROR_PARSE;
  181|       |
  182|  50.9k|    if (ctx->byte2unicode[peek] == 'Z') {
  ------------------
  |  Branch (182:9): [True: 16, False: 50.9k]
  ------------------
  183|     16|        if (out_double)
  ------------------
  |  Branch (183:13): [True: 16, False: 0]
  ------------------
  184|     16|            *out_double = NAN;
  185|     16|        if (out_finished)
  ------------------
  |  Branch (185:13): [True: 16, False: 0]
  ------------------
  186|     16|            *out_finished = 1;
  187|     16|        return READSTAT_OK;
  188|     16|    }
  189|       |
  190|  50.9k|    if (out_finished)
  ------------------
  |  Branch (190:9): [True: 50.9k, False: 0]
  ------------------
  191|  50.9k|        *out_finished = 0;
  192|       |
  193|  50.9k|    return read_double_with_peek(ctx, out_double, peek);
  194|  50.9k|}
readstat_por_read.c:read_double_with_peek:
   94|   126k|        unsigned char peek) {
   95|   126k|    readstat_error_t retval = READSTAT_OK;
   96|   126k|    double value = NAN;
   97|   126k|    unsigned char buffer[100];
   98|   126k|    char utf8_buffer[300];
   99|   126k|    char error_buf[1024];
  100|   126k|    int64_t len = 0;
  101|   126k|    ssize_t bytes_read = 0;
  102|       |
  103|   126k|    buffer[0] = peek;
  104|       |
  105|   126k|    bytes_read = read_bytes(ctx, &buffer[1], 1);
  106|   126k|    if (bytes_read != 1)
  ------------------
  |  Branch (106:9): [True: 146, False: 126k]
  ------------------
  107|    146|        return READSTAT_ERROR_PARSE;
  108|       |
  109|   126k|    if (ctx->byte2unicode[buffer[0]] == '*' && 
  ------------------
  |  Branch (109:9): [True: 265, False: 126k]
  ------------------
  110|    265|            ctx->byte2unicode[buffer[1]] == '.') {
  ------------------
  |  Branch (110:13): [True: 253, False: 12]
  ------------------
  111|    253|        if (out_double)
  ------------------
  |  Branch (111:13): [True: 253, False: 0]
  ------------------
  112|    253|            *out_double = NAN;
  113|    253|        return READSTAT_OK;
  114|    253|    }
  115|   126k|    int64_t i=2;
  116|  1.65M|    while (i<sizeof(buffer) && ctx->byte2unicode[buffer[i-1]] != '/') {
  ------------------
  |  Branch (116:12): [True: 1.65M, False: 28]
  |  Branch (116:32): [True: 1.53M, False: 125k]
  ------------------
  117|  1.53M|        bytes_read = read_bytes(ctx, &buffer[i], 1);
  118|  1.53M|        if (bytes_read != 1)
  ------------------
  |  Branch (118:13): [True: 354, False: 1.53M]
  ------------------
  119|    354|            return READSTAT_ERROR_PARSE;
  120|  1.53M|        i++;
  121|  1.53M|    }
  122|       |
  123|   125k|    if (i == sizeof(buffer)) {
  ------------------
  |  Branch (123:9): [True: 28, False: 125k]
  ------------------
  124|     28|        return READSTAT_ERROR_PARSE;
  125|     28|    }
  126|       |
  127|   125k|    len = por_utf8_encode(buffer, i, utf8_buffer, sizeof(utf8_buffer), ctx->byte2unicode);
  128|   125k|    if (len == -1) {
  ------------------
  |  Branch (128:9): [True: 0, False: 125k]
  ------------------
  129|      0|        if (ctx->handle.error) {
  ------------------
  |  Branch (129:13): [True: 0, False: 0]
  ------------------
  130|      0|            snprintf(error_buf, sizeof(error_buf), "Error converting double string (length=%" PRId64 "): %.*s", 
  131|      0|                    i, (int)i, buffer);
  132|      0|            ctx->handle.error(error_buf, ctx->user_ctx);
  133|      0|        }
  134|      0|        retval = READSTAT_ERROR_CONVERT;
  135|      0|        goto cleanup;
  136|      0|    }
  137|       |    
  138|   125k|    bytes_read = readstat_por_parse_double(utf8_buffer, len, &value, ctx->handle.error, ctx->user_ctx);
  139|   125k|    if (bytes_read == -1) {
  ------------------
  |  Branch (139:9): [True: 142, False: 125k]
  ------------------
  140|    142|        if (ctx->handle.error) {
  ------------------
  |  Branch (140:13): [True: 0, False: 142]
  ------------------
  141|      0|            snprintf(error_buf, sizeof(error_buf), "Error parsing double string (length=%" PRId64 "): %.*s [%s]", 
  142|      0|                    len, (int)len, utf8_buffer, buffer);
  143|      0|            ctx->handle.error(error_buf, ctx->user_ctx);
  144|      0|        }
  145|    142|        retval = READSTAT_ERROR_PARSE;
  146|    142|        goto cleanup;
  147|    142|    }
  148|       |    
  149|   125k|cleanup:
  150|   125k|    if (out_double)
  ------------------
  |  Branch (150:9): [True: 125k, False: 0]
  ------------------
  151|   125k|        *out_double = value;
  152|       |
  153|   125k|    return retval;
  154|   125k|}
readstat_por_read.c:read_tag:
   85|  21.1k|static uint16_t read_tag(por_ctx_t *ctx) {
   86|  21.1k|    unsigned char tag;
   87|  21.1k|    if (read_bytes(ctx, &tag, 1) != 1) {
  ------------------
  |  Branch (87:9): [True: 178, False: 21.0k]
  ------------------
   88|    178|        return -1;
   89|    178|    }
   90|  21.0k|    return ctx->byte2unicode[tag];
   91|  21.1k|}
readstat_por_read.c:read_variable_count_record:
  255|  1.11k|static readstat_error_t read_variable_count_record(por_ctx_t *ctx) {
  256|  1.11k|    int value;
  257|  1.11k|    readstat_error_t retval = READSTAT_OK;
  258|  1.11k|    if (ctx->var_count) {
  ------------------
  |  Branch (258:9): [True: 15, False: 1.10k]
  ------------------
  259|     15|        retval = READSTAT_ERROR_PARSE;
  260|     15|        goto cleanup;
  261|     15|    }
  262|  1.10k|    if ((retval = read_integer_in_range(ctx, 0, MAX_VARS, &value)) != READSTAT_OK) {
  ------------------
  |  |   35|  1.10k|#define MAX_VARS    1000000
  ------------------
  |  Branch (262:9): [True: 16, False: 1.08k]
  ------------------
  263|     16|        goto cleanup;
  264|     16|    }
  265|  1.08k|    ctx->var_count = value;
  266|  1.08k|    ctx->variables = readstat_calloc(ctx->var_count, sizeof(readstat_variable_t *));
  267|  1.08k|    ctx->varinfo = readstat_calloc(ctx->var_count, sizeof(spss_varinfo_t));
  268|  1.08k|    if (ctx->variables == NULL || ctx->varinfo == NULL) {
  ------------------
  |  Branch (268:9): [True: 5, False: 1.08k]
  |  Branch (268:35): [True: 7, False: 1.07k]
  ------------------
  269|     12|        retval = READSTAT_ERROR_MALLOC;
  270|     12|        goto cleanup;
  271|     12|    }
  272|       |
  273|  1.07k|    if (ctx->handle.metadata) {
  ------------------
  |  Branch (273:9): [True: 1.07k, False: 0]
  ------------------
  274|  1.07k|        readstat_metadata_t metadata = {
  275|  1.07k|            .row_count = -1,
  276|  1.07k|            .var_count = ctx->var_count,
  277|  1.07k|            .creation_time = ctx->timestamp,
  278|  1.07k|            .modified_time = ctx->timestamp,
  279|  1.07k|            .file_format_version = ctx->version,
  280|  1.07k|            .file_label = ctx->file_label
  281|  1.07k|        };
  282|  1.07k|        if (ctx->handle.metadata(&metadata, ctx->user_ctx) != READSTAT_HANDLER_OK) {
  ------------------
  |  Branch (282:13): [True: 0, False: 1.07k]
  ------------------
  283|      0|            retval = READSTAT_ERROR_USER_ABORT;
  284|      0|            goto cleanup;
  285|      0|        }
  286|  1.07k|    }
  287|       |        
  288|  1.11k|cleanup:
  289|  1.11k|    return retval;
  290|  1.07k|}
readstat_por_read.c:read_integer_in_range:
  164|  59.9k|static readstat_error_t read_integer_in_range(por_ctx_t *ctx, int min, int max, int *out_integer) {
  165|  59.9k|    double dval = NAN;
  166|  59.9k|    readstat_error_t retval = read_double(ctx, &dval);
  167|  59.9k|    if (retval != READSTAT_OK)
  ------------------
  |  Branch (167:9): [True: 249, False: 59.7k]
  ------------------
  168|    249|        return retval;
  169|  59.7k|    if (isnan(dval) || dval < min || dval > max)
  ------------------
  |  Branch (169:9): [True: 11, False: 59.7k]
  |  Branch (169:24): [True: 9, False: 59.7k]
  |  Branch (169:38): [True: 16, False: 59.7k]
  ------------------
  170|     36|        return READSTAT_ERROR_PARSE;
  171|  59.7k|    if (out_integer)
  ------------------
  |  Branch (171:9): [True: 59.7k, False: 0]
  ------------------
  172|  59.7k|        *out_integer = (int)dval;
  173|  59.7k|    return READSTAT_OK;
  174|  59.7k|}
readstat_por_read.c:read_double:
  156|  75.8k|static readstat_error_t read_double(por_ctx_t *ctx, double *out_double) {
  157|  75.8k|    unsigned char peek;
  158|  75.8k|    size_t bytes_read = read_bytes(ctx, &peek, 1);
  159|  75.8k|    if (bytes_read != 1)
  ------------------
  |  Branch (159:9): [True: 211, False: 75.6k]
  ------------------
  160|    211|        return READSTAT_ERROR_PARSE;
  161|  75.6k|    return read_double_with_peek(ctx, out_double, peek);
  162|  75.8k|}
readstat_por_read.c:read_precision_record:
  292|    481|static readstat_error_t read_precision_record(por_ctx_t *ctx) {
  293|    481|    int precision = 0;
  294|    481|    readstat_error_t error = read_integer_in_range(ctx, 0, 100, &precision);
  295|    481|    if (error == READSTAT_OK)
  ------------------
  |  Branch (295:9): [True: 463, False: 18]
  ------------------
  296|    463|        ctx->base30_precision = precision;
  297|    481|    return error;
  298|    481|}
readstat_por_read.c:read_case_weight_record:
  300|  1.14k|static readstat_error_t read_case_weight_record(por_ctx_t *ctx) {
  301|  1.14k|    return read_string(ctx, ctx->fweight_name, sizeof(ctx->fweight_name));
  302|  1.14k|}
readstat_por_read.c:read_variable_record:
  304|  7.31k|static readstat_error_t read_variable_record(por_ctx_t *ctx) {
  305|  7.31k|    readstat_error_t retval = READSTAT_OK;
  306|  7.31k|    int value;
  307|  7.31k|    int i;
  308|  7.31k|    spss_varinfo_t *varinfo = NULL;
  309|  7.31k|    spss_format_t *formats[2];
  310|       |
  311|  7.31k|    ctx->var_offset++;
  312|       |
  313|  7.31k|    if (ctx->var_offset == ctx->var_count) {
  ------------------
  |  Branch (313:9): [True: 1, False: 7.31k]
  ------------------
  314|      1|        retval = READSTAT_ERROR_PARSE;
  315|      1|        goto cleanup;
  316|      1|    }
  317|       |
  318|  7.31k|    varinfo = &ctx->varinfo[ctx->var_offset];
  319|  7.31k|    formats[0] = &varinfo->print_format;
  320|  7.31k|    formats[1] = &varinfo->write_format;
  321|       |
  322|  7.31k|    varinfo->labels_index = -1;
  323|  7.31k|    if ((retval = read_integer_in_range(ctx, 0, MAX_WIDTH, &value)) != READSTAT_OK) {
  ------------------
  |  |   36|  7.31k|#define MAX_WIDTH   1000000
  ------------------
  |  Branch (323:9): [True: 20, False: 7.29k]
  ------------------
  324|     20|        goto cleanup;
  325|     20|    }
  326|  7.29k|    varinfo->width = value;
  327|  7.29k|    if (varinfo->width == 0) {
  ------------------
  |  Branch (327:9): [True: 3.34k, False: 3.94k]
  ------------------
  328|  3.34k|        varinfo->type = READSTAT_TYPE_DOUBLE;
  329|  3.34k|        varinfo->width = 1; /* one eight-byte slot, as in SAV files */
  330|  3.94k|    } else {
  331|  3.94k|        varinfo->type = READSTAT_TYPE_STRING;
  332|       |        /* The declared width is the string length in characters */
  333|  3.94k|        varinfo->string_length = value;
  334|  3.94k|    }
  335|  7.29k|    if ((retval = read_string(ctx, varinfo->name, sizeof(varinfo->name))) != READSTAT_OK) {
  ------------------
  |  Branch (335:9): [True: 41, False: 7.25k]
  ------------------
  336|     41|        goto cleanup;
  337|     41|    }
  338|  7.25k|    ck_str_hash_insert(varinfo->name, varinfo, ctx->var_dict);
  339|       |
  340|  21.4k|    for (i=0; i<sizeof(formats)/sizeof(spss_format_t *); i++) {
  ------------------
  |  Branch (340:15): [True: 14.3k, False: 7.09k]
  ------------------
  341|  14.3k|        spss_format_t *format = formats[i];
  342|  14.3k|        if ((retval = read_integer_in_range(ctx, 0, MAX_FORMAT_TYPE, &value)) != READSTAT_OK) {
  ------------------
  |  |   28|  14.3k|#define MAX_FORMAT_TYPE     (POR_FORMAT_SHIFT+SPSS_FORMAT_TYPE_YMDHMS)
  |  |  ------------------
  |  |  |  |   27|  14.3k|#define POR_FORMAT_SHIFT     82
  |  |  ------------------
  |  |               #define MAX_FORMAT_TYPE     (POR_FORMAT_SHIFT+SPSS_FORMAT_TYPE_YMDHMS)
  |  |  ------------------
  |  |  |  |   38|  14.3k|#define SPSS_FORMAT_TYPE_YMDHMS   41
  |  |  ------------------
  ------------------
  |  Branch (342:13): [True: 94, False: 14.2k]
  ------------------
  343|     94|            goto cleanup;
  344|     94|        }
  345|  14.2k|        if (value > POR_FORMAT_SHIFT) {
  ------------------
  |  |   27|  14.2k|#define POR_FORMAT_SHIFT     82
  ------------------
  |  Branch (345:13): [True: 82, False: 14.1k]
  ------------------
  346|       |            // Some files in the wild have their format types shifted by 82 for date/time values
  347|       |            // I have no idea why, but see test files linked from:
  348|       |            // https://github.com/WizardMac/ReadStat/issues/158
  349|     82|            format->type = value - POR_FORMAT_SHIFT;
  ------------------
  |  |   27|     82|#define POR_FORMAT_SHIFT     82
  ------------------
  350|  14.1k|        } else {
  351|  14.1k|            format->type = value;
  352|  14.1k|        }
  353|       |
  354|  14.2k|        if ((retval = read_integer_in_range(ctx, 0, MAX_FORMAT_WIDTH, &value)) != READSTAT_OK) {
  ------------------
  |  |   29|  14.2k|#define MAX_FORMAT_WIDTH    20000
  ------------------
  |  Branch (354:13): [True: 47, False: 14.2k]
  ------------------
  355|     47|            goto cleanup;
  356|     47|        }
  357|  14.2k|        format->width = value;
  358|       |
  359|  14.2k|        if ((retval = read_integer_in_range(ctx, 0, MAX_FORMAT_DECIMALS, &value)) != READSTAT_OK) {
  ------------------
  |  |   30|  14.2k|#define MAX_FORMAT_DECIMALS   100
  ------------------
  |  Branch (359:13): [True: 17, False: 14.2k]
  ------------------
  360|     17|            goto cleanup;
  361|     17|        }
  362|  14.2k|        format->decimal_places = value;
  363|  14.2k|    }
  364|       |
  365|  7.31k|cleanup:
  366|  7.31k|    return retval;
  367|  7.25k|}
readstat_por_read.c:read_missing_value_record:
  400|    659|static readstat_error_t read_missing_value_record(por_ctx_t *ctx) {
  401|    659|    readstat_error_t retval = READSTAT_OK;
  402|    659|    spss_varinfo_t *varinfo = NULL;
  403|       |
  404|    659|    if (ctx->var_offset < 0 || ctx->var_offset >= ctx->var_count) {
  ------------------
  |  Branch (404:9): [True: 1, False: 658]
  |  Branch (404:32): [True: 0, False: 658]
  ------------------
  405|      1|        retval = READSTAT_ERROR_PARSE;
  406|      1|        goto cleanup;
  407|      1|    }
  408|    658|    varinfo = &ctx->varinfo[ctx->var_offset];
  409|       |
  410|    658|    if (varinfo->n_missing_values >= 3) {
  ------------------
  |  Branch (410:9): [True: 6, False: 652]
  ------------------
  411|      6|        retval = READSTAT_ERROR_PARSE;
  412|      6|        goto cleanup;
  413|      6|    }
  414|    652|    if (varinfo->type == READSTAT_TYPE_DOUBLE) {
  ------------------
  |  Branch (414:9): [True: 304, False: 348]
  ------------------
  415|    304|        if ((retval = read_double(ctx, &varinfo->missing_double_values[varinfo->n_missing_values])) != READSTAT_OK) {
  ------------------
  |  Branch (415:13): [True: 15, False: 289]
  ------------------
  416|     15|            goto cleanup;
  417|     15|        }
  418|    348|    } else {
  419|    348|        if ((retval = read_missing_string_value(ctx, varinfo, varinfo->n_missing_values)) != READSTAT_OK) {
  ------------------
  |  Branch (419:13): [True: 9, False: 339]
  ------------------
  420|      9|            goto cleanup;
  421|      9|        }
  422|    348|    }
  423|    628|    varinfo->n_missing_values++;
  424|       |
  425|    659|cleanup:
  426|    659|    return retval;
  427|    628|}
readstat_por_read.c:read_missing_string_value:
  395|  2.12k|static readstat_error_t read_missing_string_value(por_ctx_t *ctx, spss_varinfo_t *varinfo, int index) {
  396|  2.12k|    return read_converted_string(ctx, varinfo->missing_string_values[index],
  397|  2.12k|            sizeof(varinfo->missing_string_values[index]));
  398|  2.12k|}
readstat_por_read.c:read_converted_string:
  373|  15.8k|static readstat_error_t read_converted_string(por_ctx_t *ctx, char *dst, size_t dst_len) {
  374|  15.8k|    readstat_error_t retval = READSTAT_OK;
  375|  15.8k|    char string[POR_STRING_BUFFER_SIZE];
  376|  15.8k|    size_t len = 0;
  377|       |
  378|  15.8k|    if ((retval = read_string(ctx, string, sizeof(string))) != READSTAT_OK)
  ------------------
  |  Branch (378:9): [True: 208, False: 15.6k]
  ------------------
  379|    208|        goto cleanup;
  380|       |
  381|  15.6k|    len = strlen(string);
  382|  16.3k|    while (len > 0 && string[len-1] == ' ')
  ------------------
  |  Branch (382:12): [True: 12.8k, False: 3.53k]
  |  Branch (382:23): [True: 743, False: 12.0k]
  ------------------
  383|    743|        len--;
  384|  15.6k|    if (len + 1 > dst_len) {
  ------------------
  |  Branch (384:9): [True: 334, False: 15.2k]
  ------------------
  385|    334|        len = dst_len - 1;
  386|    535|        while (len > 0 && (string[len] & 0xC0) == 0x80)
  ------------------
  |  Branch (386:16): [True: 535, False: 0]
  |  Branch (386:27): [True: 201, False: 334]
  ------------------
  387|    201|            len--;
  388|    334|    }
  389|  15.6k|    retval = readstat_convert(dst, dst_len, string, len, ctx->converter);
  390|       |
  391|  15.8k|cleanup:
  392|  15.8k|    return retval;
  393|  15.6k|}
readstat_por_read.c:read_missing_value_range_record:
  429|  1.24k|static readstat_error_t read_missing_value_range_record(por_ctx_t *ctx) {
  430|  1.24k|    readstat_error_t retval = READSTAT_OK;
  431|  1.24k|    spss_varinfo_t *varinfo = NULL;
  432|       |
  433|  1.24k|    if (ctx->var_offset < 0 || ctx->var_offset == ctx->var_count) {
  ------------------
  |  Branch (433:9): [True: 1, False: 1.24k]
  |  Branch (433:32): [True: 0, False: 1.24k]
  ------------------
  434|      1|        retval = READSTAT_ERROR_PARSE;
  435|      1|        goto cleanup;
  436|      1|    }
  437|  1.24k|    varinfo = &ctx->varinfo[ctx->var_offset];
  438|       |
  439|  1.24k|    varinfo->missing_range = 1;
  440|  1.24k|    varinfo->n_missing_values = 2;
  441|  1.24k|    if (varinfo->type == READSTAT_TYPE_DOUBLE) {
  ------------------
  |  Branch (441:9): [True: 719, False: 521]
  ------------------
  442|    719|        if ((retval = read_double(ctx, &varinfo->missing_double_values[0])) != READSTAT_OK) {
  ------------------
  |  Branch (442:13): [True: 18, False: 701]
  ------------------
  443|     18|            goto cleanup;
  444|     18|        }
  445|    701|        if ((retval = read_double(ctx, &varinfo->missing_double_values[1])) != READSTAT_OK) {
  ------------------
  |  Branch (445:13): [True: 12, False: 689]
  ------------------
  446|     12|            goto cleanup;
  447|     12|        }
  448|    701|    } else {
  449|    521|        if ((retval = read_missing_string_value(ctx, varinfo, 0)) != READSTAT_OK) {
  ------------------
  |  Branch (449:13): [True: 16, False: 505]
  ------------------
  450|     16|            goto cleanup;
  451|     16|        }
  452|    505|        if ((retval = read_missing_string_value(ctx, varinfo, 1)) != READSTAT_OK) {
  ------------------
  |  Branch (452:13): [True: 27, False: 478]
  ------------------
  453|     27|            goto cleanup;
  454|     27|        }
  455|    505|    }
  456|  1.24k|cleanup:
  457|  1.24k|    return retval;
  458|  1.24k|}
readstat_por_read.c:read_missing_value_lo_range_record:
  460|  1.62k|static readstat_error_t read_missing_value_lo_range_record(por_ctx_t *ctx) {
  461|  1.62k|    readstat_error_t retval = READSTAT_OK;
  462|  1.62k|    spss_varinfo_t *varinfo = NULL;
  463|       |
  464|  1.62k|    if (ctx->var_offset < 0 || ctx->var_offset == ctx->var_count) {
  ------------------
  |  Branch (464:9): [True: 1, False: 1.62k]
  |  Branch (464:32): [True: 0, False: 1.62k]
  ------------------
  465|      1|        retval = READSTAT_ERROR_PARSE;
  466|      1|        goto cleanup;
  467|      1|    }
  468|  1.62k|    varinfo = &ctx->varinfo[ctx->var_offset];
  469|       |
  470|  1.62k|    varinfo->missing_range = 1;
  471|  1.62k|    varinfo->n_missing_values = 2;
  472|  1.62k|    if (varinfo->type == READSTAT_TYPE_DOUBLE) {
  ------------------
  |  Branch (472:9): [True: 1.17k, False: 454]
  ------------------
  473|  1.17k|        varinfo->missing_double_values[0] = -HUGE_VAL;
  474|  1.17k|        if ((retval = read_double(ctx, &varinfo->missing_double_values[1])) != READSTAT_OK) {
  ------------------
  |  Branch (474:13): [True: 18, False: 1.15k]
  ------------------
  475|     18|            goto cleanup;
  476|     18|        }
  477|  1.17k|    } else {
  478|    454|        varinfo->missing_string_values[0][0] = '\0';
  479|    454|        if ((retval = read_missing_string_value(ctx, varinfo, 1)) != READSTAT_OK) {
  ------------------
  |  Branch (479:13): [True: 15, False: 439]
  ------------------
  480|     15|            goto cleanup;
  481|     15|        }
  482|    454|    }
  483|  1.62k|cleanup:
  484|  1.62k|    return retval;
  485|  1.62k|}
readstat_por_read.c:read_missing_value_hi_range_record:
  487|  1.11k|static readstat_error_t read_missing_value_hi_range_record(por_ctx_t *ctx) {
  488|  1.11k|    readstat_error_t retval = READSTAT_OK;
  489|  1.11k|    spss_varinfo_t *varinfo = NULL;
  490|       |
  491|  1.11k|    if (ctx->var_offset < 0 || ctx->var_offset == ctx->var_count) {
  ------------------
  |  Branch (491:9): [True: 1, False: 1.11k]
  |  Branch (491:32): [True: 0, False: 1.11k]
  ------------------
  492|      1|        retval = READSTAT_ERROR_PARSE;
  493|      1|        goto cleanup;
  494|      1|    }
  495|  1.11k|    varinfo = &ctx->varinfo[ctx->var_offset];
  496|       |
  497|  1.11k|    varinfo->missing_range = 1;
  498|  1.11k|    varinfo->n_missing_values = 2;
  499|  1.11k|    if (varinfo->type == READSTAT_TYPE_DOUBLE) {
  ------------------
  |  Branch (499:9): [True: 819, False: 298]
  ------------------
  500|    819|        if ((retval = read_double(ctx, &varinfo->missing_double_values[0])) != READSTAT_OK) {
  ------------------
  |  Branch (500:13): [True: 18, False: 801]
  ------------------
  501|     18|            goto cleanup;
  502|     18|        }
  503|    801|        varinfo->missing_double_values[1] = HUGE_VAL;
  504|    801|    } else {
  505|    298|        if ((retval = read_missing_string_value(ctx, varinfo, 0)) != READSTAT_OK) {
  ------------------
  |  Branch (505:13): [True: 14, False: 284]
  ------------------
  506|     14|            goto cleanup;
  507|     14|        }
  508|    284|        varinfo->missing_string_values[1][0] = '\0';
  509|    284|    }
  510|  1.11k|cleanup:
  511|  1.11k|    return retval;
  512|  1.11k|}
readstat_por_read.c:read_variable_label_record:
  537|    519|static readstat_error_t read_variable_label_record(por_ctx_t *ctx) {
  538|    519|    readstat_error_t retval = READSTAT_OK;
  539|    519|    char string[POR_STRING_BUFFER_SIZE];
  540|    519|    spss_varinfo_t *varinfo = NULL;
  541|       |
  542|    519|    if (ctx->var_offset < 0 || ctx->var_offset == ctx->var_count) {
  ------------------
  |  Branch (542:9): [True: 2, False: 517]
  |  Branch (542:32): [True: 0, False: 517]
  ------------------
  543|      2|        retval = READSTAT_ERROR_PARSE;
  544|      2|        goto cleanup;
  545|      2|    }
  546|    517|    varinfo = &ctx->varinfo[ctx->var_offset];
  547|       |
  548|    517|    if ((retval = read_string(ctx, string, sizeof(string))) != READSTAT_OK) {
  ------------------
  |  Branch (548:9): [True: 30, False: 487]
  ------------------
  549|     30|        goto cleanup;
  550|     30|    }
  551|       |
  552|    487|    varinfo->label = realloc(varinfo->label, 4*strlen(string) + 1);
  553|    487|    retval = readstat_convert(varinfo->label, 4*strlen(string) + 1, string, strlen(string), ctx->converter);
  554|       |
  555|    519|cleanup:
  556|    519|    return retval;
  557|    487|}
readstat_por_read.c:read_value_label_record:
  559|  3.92k|static readstat_error_t read_value_label_record(por_ctx_t *ctx) {
  560|  3.92k|    readstat_error_t retval = READSTAT_OK;
  561|  3.92k|    double dval;
  562|  3.92k|    int i;
  563|  3.92k|    char string[POR_STRING_BUFFER_SIZE];
  564|  3.92k|    int count = 0, label_count = 0;
  565|  3.92k|    char label_name_buf[256];
  566|  3.92k|    char key_buf[4*POR_STRING_BUFFER_SIZE+1];
  567|  3.92k|    char label_buf[4*POR_STRING_BUFFER_SIZE+1];
  568|  3.92k|    snprintf(label_name_buf, sizeof(label_name_buf), POR_LABEL_NAME_PREFIX "%d", ctx->labels_offset);
  ------------------
  |  |   25|  3.92k|#define POR_LABEL_NAME_PREFIX   "labels"
  ------------------
  569|  3.92k|    readstat_type_t value_type = READSTAT_TYPE_DOUBLE;
  570|  3.92k|    if ((retval = read_integer_in_range(ctx, 0, MAX_STRINGS, &count)) != READSTAT_OK) {
  ------------------
  |  |   38|  3.92k|#define MAX_STRINGS 1000000
  ------------------
  |  Branch (570:9): [True: 22, False: 3.90k]
  ------------------
  571|     22|        goto cleanup;
  572|     22|    }
  573|  8.65k|    for (i=0; i<count; i++) {
  ------------------
  |  Branch (573:15): [True: 4.92k, False: 3.73k]
  ------------------
  574|  4.92k|        if ((retval = read_string(ctx, string, sizeof(string))) != READSTAT_OK) {
  ------------------
  |  Branch (574:13): [True: 170, False: 4.75k]
  ------------------
  575|    170|            goto cleanup;
  576|    170|        }
  577|  4.75k|        spss_varinfo_t *info = (spss_varinfo_t *)ck_str_hash_lookup(string, ctx->var_dict);
  578|  4.75k|        if (info) {
  ------------------
  |  Branch (578:13): [True: 1.58k, False: 3.17k]
  ------------------
  579|  1.58k|            value_type = info->type;
  580|  1.58k|            info->labels_index = ctx->labels_offset;
  581|  1.58k|        }
  582|  4.75k|    }
  583|  3.73k|    if ((retval = read_integer_in_range(ctx, 0, MAX_LABELS, &label_count)) != READSTAT_OK) {
  ------------------
  |  |   39|  3.73k|#define MAX_LABELS  1000000
  ------------------
  |  Branch (583:9): [True: 42, False: 3.69k]
  ------------------
  584|     42|        goto cleanup;
  585|     42|    }
  586|  15.9k|    for (i=0; i<label_count; i++) {
  ------------------
  |  Branch (586:15): [True: 12.4k, False: 3.57k]
  ------------------
  587|  12.4k|        readstat_value_t value = { .type = value_type };
  588|  12.4k|        if (value_type == READSTAT_TYPE_STRING) {
  ------------------
  |  Branch (588:13): [True: 264, False: 12.1k]
  ------------------
  589|    264|            if ((retval = read_converted_string(ctx, key_buf, sizeof(key_buf))) != READSTAT_OK) {
  ------------------
  |  Branch (589:17): [True: 9, False: 255]
  ------------------
  590|      9|                goto cleanup;
  591|      9|            }
  592|    255|            if ((retval = read_converted_string(ctx, label_buf, sizeof(label_buf))) != READSTAT_OK) {
  ------------------
  |  Branch (592:17): [True: 2, False: 253]
  ------------------
  593|      2|                goto cleanup;
  594|      2|            }
  595|    253|            value.v.string_value = key_buf;
  596|  12.1k|        } else {
  597|  12.1k|            if ((retval = read_double(ctx, &dval)) != READSTAT_OK) {
  ------------------
  |  Branch (597:17): [True: 49, False: 12.0k]
  ------------------
  598|     49|                goto cleanup;
  599|     49|            }
  600|  12.0k|            if ((retval = read_converted_string(ctx, label_buf, sizeof(label_buf))) != READSTAT_OK) {
  ------------------
  |  Branch (600:17): [True: 58, False: 12.0k]
  ------------------
  601|     58|                goto cleanup;
  602|     58|            }
  603|  12.0k|            value.v.double_value = dval;
  604|  12.0k|        }
  605|  12.2k|        if (ctx->handle.value_label) {
  ------------------
  |  Branch (605:13): [True: 12.2k, False: 0]
  ------------------
  606|  12.2k|            if (ctx->handle.value_label(label_name_buf, value, label_buf, ctx->user_ctx) != READSTAT_HANDLER_OK) {
  ------------------
  |  Branch (606:17): [True: 0, False: 12.2k]
  ------------------
  607|      0|                retval = READSTAT_ERROR_USER_ABORT;
  608|      0|                goto cleanup;
  609|      0|            }
  610|  12.2k|        }
  611|  12.2k|    }
  612|  3.57k|    ctx->labels_offset++;
  613|       |
  614|  3.92k|cleanup:
  615|  3.92k|    return retval;
  616|  3.57k|}
readstat_por_read.c:read_document_record:
  514|    547|static readstat_error_t read_document_record(por_ctx_t *ctx) {
  515|    547|    readstat_error_t retval = READSTAT_OK;
  516|    547|    char string[4*POR_STRING_BUFFER_SIZE+1];
  517|    547|    int i;
  518|    547|    int line_count = 0;
  519|    547|    if ((retval = read_integer_in_range(ctx, 0, MAX_LINES, &line_count)) != READSTAT_OK) {
  ------------------
  |  |   37|    547|#define MAX_LINES   1000000
  ------------------
  |  Branch (519:9): [True: 9, False: 538]
  ------------------
  520|      9|        goto cleanup;
  521|      9|    }
  522|  1.57k|    for (i=0; i<line_count; i++) {
  ------------------
  |  Branch (522:15): [True: 1.09k, False: 480]
  ------------------
  523|  1.09k|        if ((retval = read_converted_string(ctx, string, sizeof(string))) != READSTAT_OK) {
  ------------------
  |  Branch (523:13): [True: 58, False: 1.03k]
  ------------------
  524|     58|            goto cleanup;
  525|     58|        }
  526|  1.03k|        if (ctx->handle.note) {
  ------------------
  |  Branch (526:13): [True: 1.03k, False: 0]
  ------------------
  527|  1.03k|            if (ctx->handle.note(i, string, ctx->user_ctx) != READSTAT_OK) {
  ------------------
  |  Branch (527:17): [True: 0, False: 1.03k]
  ------------------
  528|      0|                retval = READSTAT_ERROR_USER_ABORT;
  529|      0|                goto cleanup;
  530|      0|            }
  531|  1.03k|        }
  532|  1.03k|    }
  533|    547|cleanup:
  534|    547|    return retval;
  535|    538|}
readstat_por_read.c:read_por_file_data:
  618|    366|static readstat_error_t read_por_file_data(por_ctx_t *ctx) {
  619|    366|    int i;
  620|    366|    char input_string[POR_STRING_BUFFER_SIZE];
  621|    366|    char output_string[4*POR_STRING_BUFFER_SIZE+1];
  622|    366|    char error_buf[1024];
  623|    366|    readstat_error_t rs_retval = READSTAT_OK;
  624|       |
  625|    366|    if (ctx->var_count == 0)
  ------------------
  |  Branch (625:9): [True: 8, False: 358]
  ------------------
  626|      8|        return READSTAT_OK;
  627|       |
  628|  9.54k|    while (1) {
  ------------------
  |  Branch (628:12): [True: 9.54k, Folded]
  ------------------
  629|  9.54k|        int finished = 0;
  630|  26.1k|        for (i=0; i<ctx->var_count; i++) {
  ------------------
  |  Branch (630:19): [True: 16.9k, False: 9.18k]
  ------------------
  631|  16.9k|            spss_varinfo_t *info = &ctx->varinfo[i];
  632|  16.9k|            readstat_value_t value = { .type = info->type };
  633|       |
  634|  16.9k|            if (info->type == READSTAT_TYPE_STRING) {
  ------------------
  |  Branch (634:17): [True: 432, False: 16.5k]
  ------------------
  635|    432|                rs_retval = maybe_read_string(ctx, input_string, sizeof(input_string), &finished);
  636|    432|                if (rs_retval != READSTAT_OK) {
  ------------------
  |  Branch (636:21): [True: 162, False: 270]
  ------------------
  637|    162|                    if (ctx->handle.error) {
  ------------------
  |  Branch (637:25): [True: 0, False: 162]
  ------------------
  638|      0|                        snprintf(error_buf, sizeof(error_buf), "Error in %s (row=%d)", 
  639|      0|                                info->name, ctx->obs_count+1);
  640|      0|                        ctx->handle.error(error_buf, ctx->user_ctx);
  641|      0|                    }
  642|    162|                    goto cleanup;
  643|    270|                } else if (finished) {
  ------------------
  |  Branch (643:28): [True: 3, False: 267]
  ------------------
  644|      3|                    if (i != 0)
  ------------------
  |  Branch (644:25): [True: 2, False: 1]
  ------------------
  645|      2|                        rs_retval = READSTAT_ERROR_PARSE;
  646|      3|                    goto cleanup;
  647|      3|                }
  648|    267|                rs_retval = readstat_convert(output_string, sizeof(output_string),
  649|    267|                        input_string, strlen(input_string), ctx->converter);
  650|    267|                if (rs_retval != READSTAT_OK) {
  ------------------
  |  Branch (650:21): [True: 0, False: 267]
  ------------------
  651|      0|                    goto cleanup;
  652|      0|                }
  653|    267|                value.v.string_value = output_string;
  654|  16.5k|            } else if (info->type == READSTAT_TYPE_DOUBLE) {
  ------------------
  |  Branch (654:24): [True: 16.5k, False: 0]
  ------------------
  655|  16.5k|                rs_retval = maybe_read_double(ctx, &value.v.double_value, &finished);
  656|  16.5k|                if (rs_retval != READSTAT_OK) {
  ------------------
  |  Branch (656:21): [True: 190, False: 16.3k]
  ------------------
  657|    190|                    if (ctx->handle.error) {
  ------------------
  |  Branch (657:25): [True: 0, False: 190]
  ------------------
  658|      0|                        snprintf(error_buf, sizeof(error_buf), "Error in %s (row=%d)", 
  659|      0|                                info->name, ctx->obs_count+1);
  660|      0|                        ctx->handle.error(error_buf, ctx->user_ctx);
  661|      0|                    }
  662|    190|                    goto cleanup;
  663|  16.3k|                } else if (finished) {
  ------------------
  |  Branch (663:28): [True: 3, False: 16.3k]
  ------------------
  664|      3|                    if (i != 0)
  ------------------
  |  Branch (664:25): [True: 2, False: 1]
  ------------------
  665|      2|                        rs_retval = READSTAT_ERROR_PARSE;
  666|      3|                    goto cleanup;
  667|      3|                }
  668|  16.3k|                value.is_system_missing = isnan(value.v.double_value);
  669|  16.3k|            }
  670|  16.6k|            if (ctx->handle.value && !ctx->variables[i]->skip && !ctx->row_offset) {
  ------------------
  |  Branch (670:17): [True: 16.6k, False: 0]
  |  Branch (670:38): [True: 16.6k, False: 0]
  |  Branch (670:66): [True: 16.6k, False: 0]
  ------------------
  671|  16.6k|                if (ctx->handle.value(ctx->obs_count, ctx->variables[i], value, ctx->user_ctx) != READSTAT_HANDLER_OK) {
  ------------------
  |  Branch (671:21): [True: 0, False: 16.6k]
  ------------------
  672|      0|                    rs_retval = READSTAT_ERROR_USER_ABORT;
  673|      0|                    goto cleanup;
  674|      0|                }
  675|  16.6k|            }
  676|       |
  677|  16.6k|        }
  678|  9.18k|        if (ctx->row_offset) {
  ------------------
  |  Branch (678:13): [True: 0, False: 9.18k]
  ------------------
  679|      0|            ctx->row_offset--;
  680|  9.18k|        } else {
  681|  9.18k|            ctx->obs_count++;
  682|  9.18k|        }
  683|       |
  684|  9.18k|        rs_retval = por_update_progress(ctx);
  685|  9.18k|        if (rs_retval != READSTAT_OK)
  ------------------
  |  Branch (685:13): [True: 0, False: 9.18k]
  ------------------
  686|      0|            break;
  687|       |            
  688|  9.18k|        if (ctx->row_limit > 0 && ctx->obs_count == ctx->row_limit)
  ------------------
  |  Branch (688:13): [True: 0, False: 9.18k]
  |  Branch (688:35): [True: 0, False: 0]
  ------------------
  689|      0|            break;
  690|  9.18k|    }
  691|    358|cleanup:
  692|    358|    return rs_retval;
  693|    358|}
readstat_por_read.c:por_update_progress:
   44|  9.18k|static readstat_error_t por_update_progress(por_ctx_t *ctx) {
   45|  9.18k|    readstat_io_t *io = ctx->io;
   46|  9.18k|    return io->update(ctx->file_size, ctx->handle.progress, ctx->user_ctx, io->io_ctx);
   47|  9.18k|}

spss_format:
   51|  1.21k|int spss_format(char *buffer, size_t len, spss_format_t *format) {
   52|  1.21k|    if (format->type < 0 
  ------------------
  |  Branch (52:9): [True: 0, False: 1.21k]
  ------------------
   53|  1.21k|            || format->type >= sizeof(spss_type_strings)/sizeof(spss_type_strings[0])
  ------------------
  |  Branch (53:16): [True: 14, False: 1.19k]
  ------------------
   54|  1.19k|            || spss_type_strings[format->type][0] == '\0') {
  ------------------
  |  Branch (54:16): [True: 306, False: 893]
  ------------------
   55|    320|        return 0;
   56|    320|    }
   57|    893|    char *string = spss_type_strings[format->type];
   58|       |
   59|    893|    if (format->decimal_places || format->type == SPSS_FORMAT_TYPE_F) {
  ------------------
  |  |    6|    371|#define SPSS_FORMAT_TYPE_F        5
  ------------------
  |  Branch (59:9): [True: 522, False: 371]
  |  Branch (59:35): [True: 91, False: 280]
  ------------------
   60|    613|        snprintf(buffer, len, "%s%d.%d", string, format->width, format->decimal_places);
   61|    613|    } else if (format->width) {
  ------------------
  |  Branch (61:16): [True: 204, False: 76]
  ------------------
   62|    204|        snprintf(buffer, len, "%s%d", string, format->width);
   63|    204|    } else {
   64|     76|        snprintf(buffer, len, "%s", string);
   65|     76|    }
   66|       |
   67|    893|    return 1;
   68|  1.21k|}
spss_missingness_for_info:
  127|  1.21k|readstat_missingness_t spss_missingness_for_info(spss_varinfo_t *info) {
  128|  1.21k|    readstat_missingness_t missingness;
  129|  1.21k|    memset(&missingness, '\0', sizeof(readstat_missingness_t));
  130|       |
  131|  1.21k|    if (info->missing_range) {
  ------------------
  |  Branch (131:9): [True: 86, False: 1.12k]
  ------------------
  132|     86|        missingness.missing_ranges_count++;
  133|     86|        missingness.missing_ranges[0] = spss_boxed_missing_value(info, 0);
  134|     86|        missingness.missing_ranges[1] = spss_boxed_missing_value(info, 1);
  135|       |
  136|     86|        if (info->n_missing_values == 3) {
  ------------------
  |  Branch (136:13): [True: 29, False: 57]
  ------------------
  137|     29|            missingness.missing_ranges_count++;
  138|     29|            missingness.missing_ranges[2] = missingness.missing_ranges[3] = spss_boxed_missing_value(info, 2);
  139|     29|        }
  140|  1.12k|    } else if (info->n_missing_values > 0) {
  ------------------
  |  Branch (140:16): [True: 38, False: 1.08k]
  ------------------
  141|     38|        missingness.missing_ranges_count = info->n_missing_values;
  142|     38|        int i=0;
  143|    101|        for (i=0; i<info->n_missing_values; i++) {
  ------------------
  |  Branch (143:19): [True: 63, False: 38]
  ------------------
  144|     63|            missingness.missing_ranges[2*i] = missingness.missing_ranges[2*i+1] = spss_boxed_missing_value(info, i);
  145|     63|        }
  146|     38|    }
  147|  1.21k|    return missingness;
  148|  1.21k|}
spss_init_variable_for_info:
  151|  1.21k|        iconv_t converter) {
  152|  1.21k|    readstat_variable_t *variable = calloc(1, sizeof(readstat_variable_t));
  153|       |
  154|  1.21k|    variable->index = info->index;
  155|  1.21k|    variable->index_after_skipping = index_after_skipping;
  156|  1.21k|    variable->type = info->type;
  157|  1.21k|    if (info->string_length) {
  ------------------
  |  Branch (157:9): [True: 709, False: 504]
  ------------------
  158|    709|        variable->storage_width = info->string_length;
  159|    709|    } else {
  160|    504|        variable->storage_width = 8 * info->width;
  161|    504|    }
  162|       |
  163|  1.21k|    if (info->longname[0]) {
  ------------------
  |  Branch (163:9): [True: 0, False: 1.21k]
  ------------------
  164|      0|        readstat_convert(variable->name, sizeof(variable->name),
  165|      0|                info->longname, sizeof(info->longname), converter);
  166|  1.21k|    } else {
  167|  1.21k|        readstat_convert(variable->name, sizeof(variable->name),
  168|  1.21k|                info->name, sizeof(info->name), converter);
  169|  1.21k|    }
  170|  1.21k|    if (info->label) {
  ------------------
  |  Branch (170:9): [True: 58, False: 1.15k]
  ------------------
  171|     58|        snprintf(variable->label, sizeof(variable->label), "%s", info->label);
  172|     58|    }
  173|       |
  174|  1.21k|    spss_format(variable->format, sizeof(variable->format), &info->print_format);
  175|       |
  176|  1.21k|    variable->missingness = spss_missingness_for_info(info);
  177|  1.21k|    variable->measure = info->measure;
  178|  1.21k|    variable->alignment = info->alignment;
  179|  1.21k|    if (info->display_width) {
  ------------------
  |  Branch (179:9): [True: 0, False: 1.21k]
  ------------------
  180|      0|        variable->display_width = info->display_width;
  181|  1.21k|    } else {
  182|  1.21k|        variable->display_width = info->print_format.width;
  183|  1.21k|    }
  184|       |
  185|  1.21k|    return variable;
  186|  1.21k|}
readstat_spss.c:spss_boxed_missing_value:
  120|    264|static readstat_value_t spss_boxed_missing_value(spss_varinfo_t *info, int i) {
  121|    264|    if (info->type == READSTAT_TYPE_DOUBLE) {
  ------------------
  |  Branch (121:9): [True: 124, False: 140]
  ------------------
  122|    124|        return spss_boxed_double_value(info->missing_double_values[i]);
  123|    124|    }
  124|    140|    return spss_boxed_string_value(info->missing_string_values[i]);
  125|    264|}
readstat_spss.c:spss_boxed_double_value:
  103|    124|static readstat_value_t spss_boxed_double_value(double fp_value) {
  104|    124|    readstat_value_t value = {
  105|    124|        .type = READSTAT_TYPE_DOUBLE,
  106|    124|        .v = { .double_value = fp_value },
  107|       |        .is_system_missing = isnan(fp_value)
  108|    124|    };
  109|    124|    return value;
  110|    124|}
readstat_spss.c:spss_boxed_string_value:
  112|    140|static readstat_value_t spss_boxed_string_value(const char *string) {
  113|    140|    readstat_value_t value = {
  114|    140|        .type = READSTAT_TYPE_STRING,
  115|    140|        .v = { .string_value = string }
  116|    140|    };
  117|    140|    return value;
  118|    140|}

rt_open_handler:
    8|  2.55k|int rt_open_handler(const char *path, void *io_ctx) {
    9|  2.55k|    return 0;
   10|  2.55k|}
rt_close_handler:
   12|  2.55k|int rt_close_handler(void *io_ctx) {
   13|  2.55k|    return 0;
   14|  2.55k|}
rt_seek_handler:
   17|  5.11k|        readstat_io_flags_t whence, void *io_ctx) {
   18|  5.11k|    rt_buffer_ctx_t *buffer_ctx = (rt_buffer_ctx_t *)io_ctx;
   19|  5.11k|    readstat_off_t newpos = -1;
   20|  5.11k|    if (whence == READSTAT_SEEK_SET) {
  ------------------
  |  Branch (20:9): [True: 2.55k, False: 2.55k]
  ------------------
   21|  2.55k|        newpos = offset;
   22|  2.55k|    } else if (whence == READSTAT_SEEK_CUR) {
  ------------------
  |  Branch (22:16): [True: 0, False: 2.55k]
  ------------------
   23|      0|        newpos = buffer_ctx->pos + offset;
   24|  2.55k|    } else if (whence == READSTAT_SEEK_END) {
  ------------------
  |  Branch (24:16): [True: 2.55k, False: 0]
  ------------------
   25|  2.55k|        newpos = buffer_ctx->buffer->used + offset;
   26|  2.55k|    }
   27|       |
   28|  5.11k|    if (newpos < 0)
  ------------------
  |  Branch (28:9): [True: 0, False: 5.11k]
  ------------------
   29|      0|        return -1;
   30|       |
   31|  5.11k|    if (newpos > buffer_ctx->buffer->used)
  ------------------
  |  Branch (31:9): [True: 0, False: 5.11k]
  ------------------
   32|      0|        return -1;
   33|       |
   34|  5.11k|    buffer_ctx->pos = newpos;
   35|  5.11k|    return newpos;
   36|  5.11k|}
rt_read_handler:
   38|  1.11M|ssize_t rt_read_handler(void *buf, size_t nbytes, void *io_ctx) {
   39|  1.11M|    rt_buffer_ctx_t *buffer_ctx = (rt_buffer_ctx_t *)io_ctx;
   40|  1.11M|    ssize_t bytes_copied = 0;
   41|  1.11M|    ssize_t bytes_left = buffer_ctx->buffer->used - buffer_ctx->pos;
   42|  1.11M|    if (nbytes <= bytes_left) {
  ------------------
  |  Branch (42:9): [True: 1.10M, False: 1.69k]
  ------------------
   43|  1.10M|        memcpy(buf, buffer_ctx->buffer->bytes + buffer_ctx->pos, nbytes);
   44|  1.10M|        bytes_copied = nbytes;
   45|  1.10M|    } else if (bytes_left > 0) {
  ------------------
  |  Branch (45:16): [True: 0, False: 1.69k]
  ------------------
   46|      0|        memcpy(buf, buffer_ctx->buffer->bytes + buffer_ctx->pos, bytes_left);
   47|      0|        bytes_copied = bytes_left;
   48|      0|    }
   49|  1.11M|    buffer_ctx->pos += bytes_copied;
   50|  1.11M|    return bytes_copied;
   51|  1.11M|}
rt_update_handler:
   54|  9.18k|        void *user_ctx, void *io_ctx) {
   55|  9.18k|    if (!progress_handler)
  ------------------
  |  Branch (55:9): [True: 9.18k, False: 0]
  ------------------
   56|  9.18k|        return READSTAT_OK;
   57|       |
   58|      0|    rt_buffer_ctx_t *buffer_ctx = (rt_buffer_ctx_t *)io_ctx;
   59|       |
   60|      0|    if (progress_handler(1.0 * buffer_ctx->pos / buffer_ctx->buffer->used, user_ctx))
  ------------------
  |  Branch (60:9): [True: 0, False: 0]
  ------------------
   61|      0|        return READSTAT_ERROR_USER_ABORT;
   62|       |
   63|      0|    return READSTAT_OK;
   64|      0|}

