tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

avstring.c (10819B)


      1 /*
      2 * Copyright (c) 2000, 2001, 2002 Fabrice Bellard
      3 * Copyright (c) 2007 Mans Rullgard
      4 *
      5 * This file is part of FFmpeg.
      6 *
      7 * FFmpeg is free software; you can redistribute it and/or
      8 * modify it under the terms of the GNU Lesser General Public
      9 * License as published by the Free Software Foundation; either
     10 * version 2.1 of the License, or (at your option) any later version.
     11 *
     12 * FFmpeg is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     15 * Lesser General Public License for more details.
     16 *
     17 * You should have received a copy of the GNU Lesser General Public
     18 * License along with FFmpeg; if not, write to the Free Software
     19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     20 */
     21 
     22 #include <limits.h>
     23 #include <stdarg.h>
     24 #include <stdint.h>
     25 #include <stdio.h>
     26 #include <string.h>
     27 
     28 #include "config.h"
     29 #include "mem.h"
     30 #include "avassert.h"
     31 #include "avstring.h"
     32 #include "bprint.h"
     33 #include "error.h"
     34 #include "macros.h"
     35 
     36 int av_strstart(const char *str, const char *pfx, const char **ptr)
     37 {
     38    while (*pfx && *pfx == *str) {
     39        pfx++;
     40        str++;
     41    }
     42    if (!*pfx && ptr)
     43        *ptr = str;
     44    return !*pfx;
     45 }
     46 
     47 int av_stristart(const char *str, const char *pfx, const char **ptr)
     48 {
     49    while (*pfx && av_toupper((unsigned)*pfx) == av_toupper((unsigned)*str)) {
     50        pfx++;
     51        str++;
     52    }
     53    if (!*pfx && ptr)
     54        *ptr = str;
     55    return !*pfx;
     56 }
     57 
     58 char *av_stristr(const char *s1, const char *s2)
     59 {
     60    if (!*s2)
     61        return (char*)(intptr_t)s1;
     62 
     63    do
     64        if (av_stristart(s1, s2, NULL))
     65            return (char*)(intptr_t)s1;
     66    while (*s1++);
     67 
     68    return NULL;
     69 }
     70 
     71 char *av_strnstr(const char *haystack, const char *needle, size_t hay_length)
     72 {
     73    size_t needle_len = strlen(needle);
     74    if (!needle_len)
     75        return (char*)haystack;
     76    while (hay_length >= needle_len) {
     77        hay_length--;
     78        if (!memcmp(haystack, needle, needle_len))
     79            return (char*)haystack;
     80        haystack++;
     81    }
     82    return NULL;
     83 }
     84 
     85 size_t av_strlcpy(char *dst, const char *src, size_t size)
     86 {
     87    size_t len = 0;
     88    while (++len < size && *src)
     89        *dst++ = *src++;
     90    if (len <= size)
     91        *dst = 0;
     92    return len + strlen(src) - 1;
     93 }
     94 
     95 size_t av_strlcat(char *dst, const char *src, size_t size)
     96 {
     97    size_t len = strlen(dst);
     98    if (size <= len + 1)
     99        return len + strlen(src);
    100    return len + av_strlcpy(dst + len, src, size - len);
    101 }
    102 
    103 size_t av_strlcatf(char *dst, size_t size, const char *fmt, ...)
    104 {
    105    size_t len = strlen(dst);
    106    va_list vl;
    107 
    108    va_start(vl, fmt);
    109    len += vsnprintf(dst + len, size > len ? size - len : 0, fmt, vl);
    110    va_end(vl);
    111 
    112    return len;
    113 }
    114 
    115 char *av_asprintf(const char *fmt, ...)
    116 {
    117    char *p = NULL;
    118    va_list va;
    119    int len;
    120 
    121    va_start(va, fmt);
    122    len = vsnprintf(NULL, 0, fmt, va);
    123    va_end(va);
    124    if (len < 0)
    125        goto end;
    126 
    127    p = av_malloc(len + 1);
    128    if (!p)
    129        goto end;
    130 
    131    va_start(va, fmt);
    132    len = vsnprintf(p, len + 1, fmt, va);
    133    va_end(va);
    134    if (len < 0)
    135        av_freep(&p);
    136 
    137 end:
    138    return p;
    139 }
    140 
    141 #define WHITESPACES " \n\t\r"
    142 
    143 char *av_get_token(const char **buf, const char *term)
    144 {
    145    char *out     = av_malloc(strlen(*buf) + 1);
    146    char *ret     = out, *end = out;
    147    const char *p = *buf;
    148    if (!out)
    149        return NULL;
    150    p += strspn(p, WHITESPACES);
    151 
    152    while (*p && !strspn(p, term)) {
    153        char c = *p++;
    154        if (c == '\\' && *p) {
    155            *out++ = *p++;
    156            end    = out;
    157        } else if (c == '\'') {
    158            while (*p && *p != '\'')
    159                *out++ = *p++;
    160            if (*p) {
    161                p++;
    162                end = out;
    163            }
    164        } else {
    165            *out++ = c;
    166        }
    167    }
    168 
    169    do
    170        *out-- = 0;
    171    while (out >= end && strspn(out, WHITESPACES));
    172 
    173    *buf = p;
    174 
    175    return ret;
    176 }
    177 
    178 char *av_strtok(char *s, const char *delim, char **saveptr)
    179 {
    180    char *tok;
    181 
    182    if (!s && !(s = *saveptr))
    183        return NULL;
    184 
    185    /* skip leading delimiters */
    186    s += strspn(s, delim);
    187 
    188    /* s now points to the first non delimiter char, or to the end of the string */
    189    if (!*s) {
    190        *saveptr = NULL;
    191        return NULL;
    192    }
    193    tok = s++;
    194 
    195    /* skip non delimiters */
    196    s += strcspn(s, delim);
    197    if (*s) {
    198        *s = 0;
    199        *saveptr = s+1;
    200    } else {
    201        *saveptr = NULL;
    202    }
    203 
    204    return tok;
    205 }
    206 
    207 int av_strcasecmp(const char *a, const char *b)
    208 {
    209    uint8_t c1, c2;
    210    do {
    211        c1 = av_tolower(*a++);
    212        c2 = av_tolower(*b++);
    213    } while (c1 && c1 == c2);
    214    return c1 - c2;
    215 }
    216 
    217 int av_strncasecmp(const char *a, const char *b, size_t n)
    218 {
    219    uint8_t c1, c2;
    220    if (n <= 0)
    221        return 0;
    222    do {
    223        c1 = av_tolower(*a++);
    224        c2 = av_tolower(*b++);
    225    } while (--n && c1 && c1 == c2);
    226    return c1 - c2;
    227 }
    228 
    229 char *av_strireplace(const char *str, const char *from, const char *to)
    230 {
    231    char *ret = NULL;
    232    const char *pstr2, *pstr = str;
    233    size_t tolen = strlen(to), fromlen = strlen(from);
    234    AVBPrint pbuf;
    235 
    236    av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
    237    while ((pstr2 = av_stristr(pstr, from))) {
    238        av_bprint_append_data(&pbuf, pstr, pstr2 - pstr);
    239        pstr = pstr2 + fromlen;
    240        av_bprint_append_data(&pbuf, to, tolen);
    241    }
    242    av_bprint_append_data(&pbuf, pstr, strlen(pstr));
    243    if (!av_bprint_is_complete(&pbuf)) {
    244        av_bprint_finalize(&pbuf, NULL);
    245    } else {
    246        av_bprint_finalize(&pbuf, &ret);
    247    }
    248 
    249    return ret;
    250 }
    251 
    252 const char *av_basename(const char *path)
    253 {
    254    char *p;
    255 #if HAVE_DOS_PATHS
    256    char *q, *d;
    257 #endif
    258 
    259    if (!path || *path == '\0')
    260        return ".";
    261 
    262    p = strrchr(path, '/');
    263 #if HAVE_DOS_PATHS
    264    q = strrchr(path, '\\');
    265    d = strchr(path, ':');
    266    p = FFMAX3(p, q, d);
    267 #endif
    268 
    269    if (!p)
    270        return path;
    271 
    272    return p + 1;
    273 }
    274 
    275 const char *av_dirname(char *path)
    276 {
    277    char *p = path ? strrchr(path, '/') : NULL;
    278 
    279 #if HAVE_DOS_PATHS
    280    char *q = path ? strrchr(path, '\\') : NULL;
    281    char *d = path ? strchr(path, ':')  : NULL;
    282 
    283    d = d ? d + 1 : d;
    284 
    285    p = FFMAX3(p, q, d);
    286 #endif
    287 
    288    if (!p)
    289        return ".";
    290 
    291    *p = '\0';
    292 
    293    return path;
    294 }
    295 
    296 char *av_append_path_component(const char *path, const char *component)
    297 {
    298    size_t p_len, c_len;
    299    char *fullpath;
    300 
    301    if (!path)
    302        return av_strdup(component);
    303    if (!component)
    304        return av_strdup(path);
    305 
    306    p_len = strlen(path);
    307    c_len = strlen(component);
    308    if (p_len > SIZE_MAX - c_len || p_len + c_len > SIZE_MAX - 2)
    309        return NULL;
    310    fullpath = av_malloc(p_len + c_len + 2);
    311    if (fullpath) {
    312        if (p_len) {
    313            av_strlcpy(fullpath, path, p_len + 1);
    314            if (c_len) {
    315                if (fullpath[p_len - 1] != '/' && component[0] != '/')
    316                    fullpath[p_len++] = '/';
    317                else if (fullpath[p_len - 1] == '/' && component[0] == '/')
    318                    p_len--;
    319            }
    320        }
    321        av_strlcpy(&fullpath[p_len], component, c_len + 1);
    322        fullpath[p_len + c_len] = 0;
    323    }
    324    return fullpath;
    325 }
    326 
    327 int av_escape(char **dst, const char *src, const char *special_chars,
    328              enum AVEscapeMode mode, int flags)
    329 {
    330    AVBPrint dstbuf;
    331    int ret;
    332 
    333    av_bprint_init(&dstbuf, 1, INT_MAX); /* (int)dstbuf.len must be >= 0 */
    334    av_bprint_escape(&dstbuf, src, special_chars, mode, flags);
    335 
    336    if (!av_bprint_is_complete(&dstbuf)) {
    337        av_bprint_finalize(&dstbuf, NULL);
    338        return AVERROR(ENOMEM);
    339    }
    340    if ((ret = av_bprint_finalize(&dstbuf, dst)) < 0)
    341        return ret;
    342    return dstbuf.len;
    343 }
    344 
    345 int av_match_name(const char *name, const char *names)
    346 {
    347    const char *p;
    348    size_t len, namelen;
    349 
    350    if (!name || !names)
    351        return 0;
    352 
    353    namelen = strlen(name);
    354    while (*names) {
    355        int negate = '-' == *names;
    356        p = strchr(names, ',');
    357        if (!p)
    358            p = names + strlen(names);
    359        names += negate;
    360        len = FFMAX(p - names, namelen);
    361        if (!av_strncasecmp(name, names, len) || !strncmp("ALL", names, FFMAX(3, p - names)))
    362            return !negate;
    363        names = p + (*p == ',');
    364    }
    365    return 0;
    366 }
    367 
    368 int av_utf8_decode(int32_t *codep, const uint8_t **bufp, const uint8_t *buf_end,
    369                   unsigned int flags)
    370 {
    371    const uint8_t *p = *bufp;
    372    uint32_t top;
    373    uint64_t code;
    374    int ret = 0, tail_len;
    375    uint32_t overlong_encoding_mins[6] = {
    376        0x00000000, 0x00000080, 0x00000800, 0x00010000, 0x00200000, 0x04000000,
    377    };
    378 
    379    if (p >= buf_end)
    380        return 0;
    381 
    382    code = *p++;
    383 
    384    /* first sequence byte starts with 10, or is 1111-1110 or 1111-1111,
    385       which is not admitted */
    386    if ((code & 0xc0) == 0x80 || code >= 0xFE) {
    387        ret = AVERROR(EILSEQ);
    388        goto end;
    389    }
    390    top = (code & 128) >> 1;
    391 
    392    tail_len = 0;
    393    while (code & top) {
    394        int tmp;
    395        tail_len++;
    396        if (p >= buf_end) {
    397            (*bufp) ++;
    398            return AVERROR(EILSEQ); /* incomplete sequence */
    399        }
    400 
    401        /* we assume the byte to be in the form 10xx-xxxx */
    402        tmp = *p++ - 128;   /* strip leading 1 */
    403        if (tmp>>6) {
    404            (*bufp) ++;
    405            return AVERROR(EILSEQ);
    406        }
    407        code = (code<<6) + tmp;
    408        top <<= 5;
    409    }
    410    code &= (top << 1) - 1;
    411 
    412    /* check for overlong encodings */
    413    av_assert0(tail_len <= 5);
    414    if (code < overlong_encoding_mins[tail_len]) {
    415        ret = AVERROR(EILSEQ);
    416        goto end;
    417    }
    418 
    419    if (code >= 1U<<31) {
    420        ret = AVERROR(EILSEQ);  /* out-of-range value */
    421        goto end;
    422    }
    423 
    424    *codep = code;
    425 
    426    if (code > 0x10FFFF &&
    427        !(flags & AV_UTF8_FLAG_ACCEPT_INVALID_BIG_CODES))
    428        ret = AVERROR(EILSEQ);
    429    if (code < 0x20 && code != 0x9 && code != 0xA && code != 0xD &&
    430        flags & AV_UTF8_FLAG_EXCLUDE_XML_INVALID_CONTROL_CODES)
    431        ret = AVERROR(EILSEQ);
    432    if (code >= 0xD800 && code <= 0xDFFF &&
    433        !(flags & AV_UTF8_FLAG_ACCEPT_SURROGATES))
    434        ret = AVERROR(EILSEQ);
    435    if ((code == 0xFFFE || code == 0xFFFF) &&
    436        !(flags & AV_UTF8_FLAG_ACCEPT_NON_CHARACTERS))
    437        ret = AVERROR(EILSEQ);
    438 
    439 end:
    440    *bufp = p;
    441    return ret;
    442 }
    443 
    444 int av_match_list(const char *name, const char *list, char separator)
    445 {
    446    const char *p, *q;
    447 
    448    for (p = name; p && *p; ) {
    449        for (q = list; q && *q; ) {
    450            int k;
    451            for (k = 0; p[k] == q[k] || (p[k]*q[k] == 0 && p[k]+q[k] == separator); k++)
    452                if (k && (!p[k] || p[k] == separator))
    453                    return 1;
    454            q = strchr(q, separator);
    455            q += !!q;
    456        }
    457        p = strchr(p, separator);
    458        p += !!p;
    459    }
    460 
    461    return 0;
    462 }