str_util.c.svn-base

来自「SumatraPDF是一款小型开源的pdf阅读工具。虽然玲珑小巧(只有800多K」· SVN-BASE 代码 · 共 1,161 行 · 第 1/2 页

SVN-BASE
1,161
字号
char *mem_to_hexstr(const unsigned char *buf, int len){    int i;    char *tmp;    /* 2 hex chars per byte, +1 for terminating 0 */    char *ret = (char*)malloc(len * 2 + 1);    if (!ret)        return NULL;    tmp = ret;    for (i = 0; i < len; i++) {        char_to_hex(*buf++, tmp);        tmp += 2;    }    *tmp = 0;    return ret;}/* replace a string pointed by <dst> with a copy of <src>   (i.e. free existing <dst>).   Returns FALSE if failed to replace (due to out of memory) */BOOL str_dup_replace(char **dst, const char *src){    char *dup = (char*)strdup(src);    if (!dup)        return FALSE;    free(*dst);    *dst = dup;    return TRUE;}/* Reverse of mem_to_hexstr. Convert a 0-terminatd hex-encoded string <s> to   binary data pointed by <buf> of max sisze bufLen.   Returns FALSE if size of <s> doesn't match <bufLen>. */BOOL hexstr_to_mem(const char *s, unsigned char *buf, int bufLen){    int i, c;    for (i=0; i<bufLen; i++) {        c = hex_str_decode_byte(&s);        if (-1 == c)            return FALSE;        *buf++ = (unsigned char)c;    }    return *s == 0;}int str_contains(const char *str, char c){    const char *pos = str_find_char(str, c);    if (!pos)        return FALSE;    return TRUE;}#define CHAR_URL_DONT_ENCODE   "-_.!~*'()"int char_needs_url_encode(char c){    if ((c >= 'a') && (c <= 'z'))        return FALSE;    if ((c >= 'A') && (c <= 'Z'))        return FALSE;    if ((c >= '0') && (c <= '9'))        return FALSE;    if (str_contains(CHAR_URL_DONT_ENCODE, c))        return FALSE;    return TRUE;}/* url-encode 'str'. Returns NULL in case of error. Caller needs to free()   the result */char *str_url_encode(const char *str){    char *          encoded;    char *          result;    int             res_len = 0;    const char *    tmp = str;    /* calc the size of the string after url encoding */    while (*tmp) {        if (char_needs_url_encode(*tmp))            res_len += 3;        else            ++res_len;        tmp++;    }    if (0 == res_len)        return NULL;    encoded = (char*)malloc(res_len+1);    if (!encoded)        return NULL;    result = encoded;    tmp = str;    while (*tmp) {        if (char_needs_url_encode(*tmp)) {            *encoded++ = '%';            char_to_hex(*tmp, encoded);            encoded += 2;        } else {            if (' ' == *tmp)                *encoded++ = '+';            else                *encoded++ = *tmp;        }        tmp++;    }    *encoded = 0;    return result;}char *str_escape(const char *txt){    /* TODO: */    return str_dup(txt);}char *str_printf(const char *format, ...){    char *result;    va_list     args;    va_start(args, format);    result = str_printf_args(format, args);    va_end(args);    return result;}char *str_printf_args(const char *format, va_list args){#ifdef _WIN32    char        message[256];    char  *     buf;    size_t      bufCchSize;    buf = &(message[0]);    bufCchSize = sizeof(message);# ifndef DISABLE_STRSAFE    for (;;)    {        /* TODO: this only works on windows with recent C library */        HRESULT hr = StringCchVPrintfA(buf, bufCchSize, format, args);        if (S_OK == hr)            break;        if (STRSAFE_E_INSUFFICIENT_BUFFER != hr)        {            /* any error other than buffer not big enough:               a) should not happen               b) means we give up */            assert(FALSE);            goto Error;        }        /* we have to make the buffer bigger. The algorithm used to calculate           the new size is arbitrary (aka. educated guess) */        if (buf != &(message[0]))            free(buf);        if (bufCchSize < 4*1024)            bufCchSize += bufCchSize;        else            bufCchSize += 1024;        buf = (char *)malloc(bufCchSize*sizeof(char));        if (NULL == buf)            goto Error;    }# else /* strsafe is disabled */    {        int len = vsnprintf(buf, bufCchSize, format, args);                if(len >= bufCchSize)        {            bufCchSize = len + 1;            buf = (char *)malloc(bufCchSize*sizeof(char));            if (NULL == buf)                goto Error;                        len = vsnprintf(buf, bufCchSize, format, args);        }                if(len < 0)            goto Error;    }# endif    /* free the buffer if it was dynamically allocated */    if (buf == &(message[0]))        return str_dup(buf);    return buf;Error:    if (buf != &(message[0]))        free((void*)buf);    return NULL;#else    char*   buf;    int     len = vasprintf(&buf, format, args);    return buf;#endif}#ifdef _WIN32void win32_dbg_out(const char *format, ...) {    char        buf[4096];    char *      p = buf;    int         written;    va_list     args;    va_start(args, format);    written = _vsnprintf(p,sizeof(buf), format, args);/*    printf(buf);    fflush(stdout); */    OutputDebugStringA(buf);    va_end(args);}void win32_dbg_out_hex(const char *dsc, const unsigned char *data, int dataLen){    unsigned char    buf[64+1];    unsigned char *  curPos;    int              bufCharsLeft;    if (dsc) win32_dbg_out(dsc); /* a bit dangerous if contains formatting codes */    if (!data) return;    bufCharsLeft = sizeof(buf)-1;    curPos = buf;    while (dataLen > 0) {        if (bufCharsLeft <= 1) {            *curPos = 0;            win32_dbg_out((char*)buf);            bufCharsLeft = sizeof(buf)-1;            curPos = buf;        }        char_to_hex(*data, curPos);        curPos += 2;        bufCharsLeft -= 2;        --dataLen;        ++data;    }    if (curPos != buf) {        *curPos = 0;        win32_dbg_out(buf);    }    win32_dbg_out("\n");}#endif/* If the string at <*strp> starts with string at <expect>, skip <*strp> past    it and return TRUE; otherwise return FALSE. */int str_skip(const char **strp, const char *expect){    size_t len = str_len(expect);    if (0 == strncmp(*strp, expect, len)) {        *strp += len;        return TRUE;    }    else {        return FALSE;    }}/* Copy the string from <*strp> into <dst> until <stop> is found, and point    <*strp> at the end. Returns TRUE unless <dst_size> isn't big enough, in    which case <*strp> is still updated, but FALE is returned and <dst> is    truncated. If <delim> is not found, <*strp> will point to the end of the    string and FALSE is returned. */intstr_copy_skip_until(const char **strp, char *dst, size_t dst_size, char stop){    const char *const str = *strp;    size_t len = str_len(str);    *strp = memchr(str, stop, len);    if (NULL==*strp) {        *strp = str+len;        return FALSE;    }    else        return str_copyn(dst, dst_size, str, *strp - str);}/* Given a pointer to a string in '*txt', skip past whitespace in the string   and put the result in '*txt' */void str_skip_ws(char **txtInOut){    char *cur;    if (!txtInOut)        return;    cur = *txtInOut;    if (!cur)        return;    while (char_is_ws(*cur)) {        ++cur;    }    *txtInOut = cur;}char *str_parse_quoted(char **txt){    char *      strStart;    char *      strCopy;    char *      cur;    char *      dst;    char        c;    size_t      len;    assert(txt);    if (!txt) return NULL;    strStart = *txt;    assert(strStart);    if (!strStart) return NULL;    assert('"' == *strStart);    /* TODO: rewrite as 2-phase logic so that counting and copying are always in sync */    ++strStart;    cur = strStart;    len = 0;    for (;;) {        c = *cur;        if ((0 == c) || ('"' == c))            break;        if ('\\' == c) {            /* TODO: should I un-escape more than '"' ?               I used to un-escape '\' as well, but it wasn't right and               files with UNC path like "\\foo\file.pdf" failed to load */            if ('"' == cur[1]) {                ++cur;                c = *cur;            }        }        ++cur;        ++len;    }    strCopy = (char*)malloc(len+1);    if (!strCopy)        return NULL;    cur = strStart;    dst = strCopy;    for (;;) {        c = *cur;        if (0 == c)            break;        if ('"' == c) {            ++cur;            break;        }        if ('\\' == c) {            /* TODO: should I un-escape more than '"' ?               I used to un-escape '\' as well, but it wasn't right and               files with UNC path like "\\foo\file.pdf" failed to load */            if ('"' == cur[1]) {                ++cur;                c = *cur;            }        }        *dst++ = c;        ++cur;    }    *dst = 0;    *txt = cur;    return strCopy;}char *str_parse_non_quoted(char **txt){    char *  cur;    char *  strStart;    char *  strCopy;    char    c;    size_t  strLen;    strStart = *txt;    assert(strStart);    if (!strStart) return NULL;    assert('"' != *strStart);    cur = strStart;    for (;;) {        c = *cur;        if (char_is_ws_or_zero(c))            break;        ++cur;    }    strLen = cur - strStart;    assert(strLen > 0);    strCopy = str_dupn(strStart, strLen);    *txt = cur;    return strCopy;}/* 'txt' is path that can be:  - escaped, in which case it starts with '"', ends with '"' and each '"' that is part of the name is escaped    with '\'  - unescaped, in which case it start with != '"' and ends with ' ' or eol (0)  This function extracts escaped or unescaped path from 'txt'. Returns NULL in case of error.  Caller needs to free() the result. */char *str_parse_possibly_quoted(char **txt){    char *  cur;    char *  str_copy;    if (!txt)        return NULL;    cur = *txt;    if (!cur)        return NULL;    str_skip_ws(&cur);    if (0 == *cur)        return NULL;    if ('"' == *cur)        str_copy = str_parse_quoted(&cur);    else        str_copy = str_parse_non_quoted(&cur);    *txt = cur;    return str_copy;}BOOL str_to_double(const char *txt, double *resOut){    int res;    assert(txt);    if (!txt) return FALSE;    res = sscanf(txt, "%lf", resOut);    if (1 != res)        return FALSE;    return TRUE;}/* Return the number of digits needed to represents a given number in base 10   string representation.*/size_t digits_for_number(int64_t num){    size_t digits = 1;    /* negative numbers need '-' in front of them */    if (num < 0) {        ++digits;        num = -num;    }    while (num >= 10)    {        ++digits;        num = num / 10;    }    return digits;}void  str_array_init(str_array *str_arr){    assert(str_arr);    if (!str_arr) return;    memzero(str_arr, sizeof(str_array));}void str_array_free(str_array *str_arr){    int i;    assert(str_arr);    if (!str_arr) return;    for (i = 0; i < str_arr->items_count; i++)        free(str_arr->items[i]);    free(str_arr->items);    str_array_init(str_arr);}void str_array_delete(str_array *str_arr){    assert(str_arr);    if (!str_arr) return;    str_array_free(str_arr);    free((void*)str_arr);}str_item *str_array_get(str_array *str_arr, int index){    assert(str_arr);    if (!str_arr) return NULL;    assert(index >= 0);    assert(index < str_arr->items_count);    if ((index < 0) || (index >= str_arr->items_count))        return NULL;    return str_arr->items[index];}int str_array_get_count(str_array *str_arr){    assert(str_arr);    if (!str_arr) return 0;    return str_arr->items_count;}/* Set one string at position 'index' in 'str_arr'. Space for the item   must already be allocated. */str_item *str_array_set(str_array *str_arr, int index, const char *str){    str_item *  new_item;    size_t      str_len_cch;    assert(str_arr);    if (!str_arr) return NULL;    if (index >= str_arr->items_count)        return NULL;    str_len_cch = str_len(str);    new_item = (str_item*)malloc(sizeof(str_item) + str_len_cch*sizeof(char));    if (!new_item)        return NULL;    str_copy(new_item->str, str_len_cch+1, str);    if (str_arr->items[index])        free(str_arr->items[index]);    str_arr->items[index] = new_item;    return new_item;}#define STR_ARR_GROW_VALUE 32/* make a generic array alloc */str_item *str_array_add(str_array *str_arr, const char *str){    str_item ** tmp;    str_item *  new_item;    void *      data;    int         n;    if (str_arr->items_count >= str_arr->items_allocated) {        /* increase memory for items if necessary */        n = str_arr->items_allocated + STR_ARR_GROW_VALUE;        tmp = (str_item**)realloc(str_arr->items, n * sizeof(str_item *));        if (!tmp)            return NULL;        str_arr->items = tmp;        data = &(str_arr->items[str_arr->items_count]);        memzero(data, STR_ARR_GROW_VALUE * sizeof(str_item *));        str_arr->items_allocated = n;    }    str_arr->items_count++;    new_item = str_array_set(str_arr, str_arr->items_count - 1, str);    if (!new_item)        --str_arr->items_count;    return new_item;}int str_array_exists_no_case(str_array *str_arr, const char *str){    int         count, i;    str_item *  item;    char *      item_str;    if (!str_arr || !str)        return FALSE;    count = str_arr->items_count;    for (i = 0; i < count; i++)    {        item = str_arr->items[i];        item_str = item->str;        if (str_ieq(str, item_str))            return TRUE;    }    return FALSE;}str_item *str_array_add_no_dups(str_array *str_arr, const char *str){    if (str_array_exists_no_case(str_arr, str))        return NULL;    return str_array_add(str_arr, str);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?