/* 'checkit_tiff' is a conformance checker for baseline TIFFs
 *
 * author: Andreas Romeyke, 2015-2022
 * licensed under conditions of libtiff
 * (see http://libtiff.maptools.org/misc.html)
 *
 */

#include <assert.h>
#include "simple_string.h"

#include <ctype.h>
#include <stdio.h>
#include <string.h>

#include "strcopy.h"

unsigned long atoul (const char * s) {
    /*
    errno = 0;
    char *endptr;
    unsigned long val = strtoul(s, &endptr, 10);
    if (errno != 0) {
        perror("strtoul");
        exit(EXIT_FAILURE);
    }
    if (endptr == s) {
        fprintf(stderr, "No digits were found\n");
        exit(EXIT_FAILURE);
    }
    printf("ATOUL: '%s' -> %lu\n", s, val);
    return val;
     */
    long long int tmp = atoll(s);
    if (tmp < 0) {
        perror("negative numbers not supported");
        exit(EXIT_FAILURE);
    }
    unsigned long v = (unsigned long) tmp & 0xffffffff;
    return v;
}

unsigned int count_multiple_zero_bytes(const char *val, uint32 count) {
    unsigned int r = 0;
    for (uint32 i=0; i<count-1; i++) {
        if (val[i] == '\0' && val[i+1] =='\0') {
            r = i+1;
            break;
        }
    }
    return r;
}

void sprint_string_as_hexdump(char *hexdump_str, size_t hexdump_len, const char *val, uint32 len) {
    /* largest possible value is:
     * 12                    -> for string constants
     * strlen(val) * 2  + 2  -> for worst case of string
     * strlen(val) * 14      -> for worst case of hexdump
     * + some extra space    -> reserved + \0
     */
    assert(NULL != hexdump_str);
    assert(hexdump_len > 100);
    if (hexdump_len < (len * 16 + 64) ) {
        sprintf(hexdump_str, "(hexdump exceeds limit of useful view size, len=%zu > %zu)\n", (size_t) (len*16+64), hexdump_len);
        return;
    }
    unsigned int res_pos = 0;
    const char * str = "str='";
    const char * undef_s = "�";
    const char * hex = "' hex=";
    const size_t str_len=strlen(str);
    const size_t undef_len=strlen(undef_s);
    const size_t hex_len = strlen(hex);
    cit_strcopy(hexdump_str+res_pos, hexdump_len-res_pos, str, str_len);
    //strncpy(hexdump_str + res_pos, str , hexdump_len - 1);
    res_pos+=strlen(str);
    for (unsigned int i = 0; i<= len-1; i++) {
        if (isprint(val[i]) ) {
            hexdump_str[res_pos] = val[i];
        } else {
            //strncpy(hexdump_str + res_pos, "�", hexdump_len - res_pos - 1);
            cit_strcopy(hexdump_str + res_pos, hexdump_len-res_pos,undef_s, undef_len);
            res_pos+=2;
        }
        res_pos++;
    }

    cit_strcopy(hexdump_str + res_pos, hexdump_len-res_pos, hex, hex_len);
    res_pos+=hex_len;

    /* hex output */
    for (unsigned int i = 0; i<= len-1; i++) {
        if (isprint(val[i])) {
            snprintf(hexdump_str + res_pos, hexdump_len - res_pos - 1, " %02x", val[i]);
            res_pos += 3;
        } else {
            /* problem here ist to determine the size of output */
            char tmp[hexdump_len];
            snprintf(tmp, hexdump_len - 1, " ---->%02x<----", (unsigned char) val[i]);
            unsigned int tmp_len = strlen( tmp);
            //strncpy(hexdump_str + res_pos, tmp, hexdump_len - res_pos - 1);
            cit_strcopy(hexdump_str+res_pos, hexdump_len-res_pos, tmp, tmp_len);
            res_pos += tmp_len;
        }
        if (res_pos >= hexdump_len - 1 ) {
            hexdump_str[hexdump_len - 1] = '\0';
            break;
        }
    }
    hexdump_str[res_pos] = '\0';
    //printf("respos=%u (hexdump_len=%lu)", res_pos, hexdump_len);
}
