run_burl_normalize:
   26|  1.62k|						size_t in_len) {
   27|  1.62k|    int qs;
   28|  1.62k|    buffer_copy_string_len(psrc, in, in_len);
   29|  1.62k|    qs = burl_normalize(psrc, ptmp, flags);
   30|  1.62k|}
LLVMFuzzerTestOneInput:
   32|  1.62k|int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
   33|  1.62k|    if (size <= 4) {
  ------------------
  |  Branch (33:9): [True: 4, False: 1.62k]
  ------------------
   34|      4|        return 0;
   35|      4|    }
   36|  1.62k|    int flags = ((int*)data)[0];
   37|  1.62k|    data += 4;
   38|  1.62k|    size -= 4;
   39|  1.62k|    char *new_str = (char *)malloc(size+1);
   40|  1.62k|    if (new_str == NULL){
  ------------------
  |  Branch (40:9): [True: 0, False: 1.62k]
  ------------------
   41|      0|        return 0;
   42|      0|    }
   43|  1.62k|    memcpy(new_str, data, size);
   44|  1.62k|    new_str[size] = '\0';
   45|       |
   46|       |    /* main fuzzer entrypoint for library */
   47|  1.62k|    buffer *psrc = buffer_init();
   48|  1.62k|    buffer *ptmp = buffer_init();
   49|  1.62k|    run_burl_normalize(psrc, ptmp, flags, __LINE__, new_str, size);
   50|  1.62k|    buffer_urldecode_path(psrc);
   51|       |
   52|  1.62k|    buffer_free(psrc);
   53|  1.62k|    buffer_free(ptmp);
   54|  1.62k|    free(new_str);
   55|  1.62k|    return 0;     
   56|  1.62k|}

buffer_init:
   14|  3.24k|buffer* buffer_init(void) {
   15|       |  #if 0 /* buffer_init() and chunk_init() can be hot,
   16|       |	 * so avoid the additional hop of indirection */
   17|       |	return ck_calloc(1, sizeof(buffer));
   18|       |  #else
   19|  3.24k|	buffer * const b = calloc(1, sizeof(*b));
   20|  3.24k|	force_assert(b);
  ------------------
  |  |  448|  3.24k|#define force_assert(x) ck_assert(x)
  |  |  ------------------
  |  |  |  |  115|  3.24k|        do { if (!(x)) ck_assert_failed(__FILE__, __LINE__, #x); } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (115:18): [True: 0, False: 3.24k]
  |  |  |  |  |  Branch (115:75): [Folded, False: 3.24k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
   21|  3.24k|	return b;
   22|  3.24k|  #endif
   23|  3.24k|}
buffer_free:
   25|  3.24k|void buffer_free(buffer *b) {
   26|  3.24k|	if (NULL == b) return;
  ------------------
  |  Branch (26:6): [True: 0, False: 3.24k]
  ------------------
   27|  3.24k|	free(b->ptr);
   28|  3.24k|	free(b);
   29|  3.24k|}
buffer_string_prepare_copy:
   82|  1.24k|char* buffer_string_prepare_copy(buffer * const b, const size_t size) {
   83|  1.24k|    b->used = 0;
   84|       |  #ifdef __COVERITY__ /*(b->ptr is not NULL if b->size is not 0)*/
   85|       |    force_assert(size >= b->size || b->ptr);
   86|       |  #endif
   87|  1.24k|    return (size < b->size)
  ------------------
  |  Branch (87:12): [True: 0, False: 1.24k]
  ------------------
   88|  1.24k|      ? b->ptr
   89|  1.24k|      : buffer_alloc_replace(b, size);
   90|  1.24k|}
buffer_extend:
  127|    153|{
  128|       |    /* extend buffer to append x (reallocate by power-2 (or larger), if needed)
  129|       |     * (combine buffer_string_prepare_append() and buffer_commit())
  130|       |     * (future: might make buffer.h static inline func for HTTP/1.1 performance)
  131|       |     * pre-sets '\0' byte and b->used (unlike buffer_string_prepare_append())*/
  132|       |  #if 0
  133|       |    char * const s = buffer_string_prepare_append(b, x);
  134|       |    b->used += x + (0 == b->used);
  135|       |  #else
  136|    153|    const uint32_t len = b->used ? b->used-1 : 0;
  ------------------
  |  Branch (136:26): [True: 153, False: 0]
  ------------------
  137|    153|    char * const s = (b->size - len >= x + 1)
  ------------------
  |  Branch (137:22): [True: 153, False: 0]
  ------------------
  138|    153|      ? b->ptr + len
  139|    153|      : buffer_string_prepare_append_resize(b, x);
  140|    153|    b->used = len+x+1;
  141|    153|  #endif
  142|    153|    s[x] = '\0';
  143|    153|    return s;
  144|    153|}
buffer_copy_string_len:
  172|  3.01k|void buffer_copy_string_len(buffer * const restrict b, const char * const restrict s, const size_t len) {
  173|  3.01k|    b->used = len + 1;
  174|  3.01k|    char * const restrict d = (len < b->size)
  ------------------
  |  Branch (174:31): [True: 922, False: 2.09k]
  ------------------
  175|  3.01k|      ? b->ptr
  176|  3.01k|      : buffer_alloc_replace(b, len);
  177|  3.01k|    d[len] = '\0';
  178|  3.01k|    memcpy(d, s, len);
  179|  3.01k|}
buffer_append_string_len:
  198|    153|void buffer_append_string_len(buffer * const restrict b, const char * const restrict s, const size_t len) {
  199|    153|    memcpy(buffer_extend(b, len), s, len);
  200|    153|}
hex2int:
  386|  94.1M|char hex2int(unsigned char hex) {
  387|  94.1M|	unsigned char n;
  388|  94.1M|	return li_cton(hex,n) ? (char)n : 0xFF;
  ------------------
  |  |  381|  94.1M|  (((n) = (c) - '0') <= 9 || (((n) = ((c)&0xdf) - 'A') <= 5 ? ((n) += 10) : 0))
  |  |  ------------------
  |  |  |  Branch (381:4): [True: 82.5M, False: 11.5M]
  |  |  |  Branch (381:30): [True: 11.5M, False: 0]
  |  |  |  Branch (381:31): [True: 11.5M, False: 0]
  |  |  ------------------
  ------------------
  389|  94.1M|}
buffer_urldecode_path:
  792|  1.62k|void buffer_urldecode_path(buffer * const b) {
  793|  1.62k|    const size_t len = buffer_clen(b);
  794|  1.62k|    char *src = len ? memchr(b->ptr, '%', len) : NULL;
  ------------------
  |  Branch (794:17): [True: 1.61k, False: 4]
  ------------------
  795|  1.62k|    if (NULL == src) return;
  ------------------
  |  Branch (795:9): [True: 339, False: 1.28k]
  ------------------
  796|       |
  797|  1.28k|    char *dst = src;
  798|  47.0M|    do {
  799|       |        /* *src == '%' */
  800|  47.0M|        unsigned char high = ((unsigned char *)src)[1];
  801|  47.0M|        unsigned char low = high ? hex2int(((unsigned char *)src)[2]) : 0xFF;
  ------------------
  |  Branch (801:29): [True: 47.0M, False: 0]
  ------------------
  802|  47.0M|        if (0xFF != (high = hex2int(high)) && 0xFF != low) {
  ------------------
  |  Branch (802:13): [True: 47.0M, False: 0]
  |  Branch (802:47): [True: 47.0M, False: 0]
  ------------------
  803|  47.0M|            high = (high << 4) | low;   /* map ctrls to '_' */
  804|  47.0M|            *dst = (high >= 32 && high != 127) ? high : '_';
  ------------------
  |  Branch (804:21): [True: 8.77M, False: 38.2M]
  |  Branch (804:35): [True: 6.86M, False: 1.91M]
  ------------------
  805|  47.0M|            src += 2;
  806|  47.0M|        } /* else ignore this '%'; leave as-is and move on */
  807|       |
  808|  50.2M|        while ((*++dst = *++src) != '%' && *src) ;
  ------------------
  |  Branch (808:16): [True: 3.22M, False: 47.0M]
  |  Branch (808:44): [True: 3.21M, False: 1.28k]
  ------------------
  809|  47.0M|    } while (*src);
  ------------------
  |  Branch (809:14): [True: 47.0M, False: 1.28k]
  ------------------
  810|  1.28k|    b->used = (dst - b->ptr) + 1;
  811|  1.28k|}
buffer_path_simplify:
  864|    372|{
  865|    372|    char *out = b->ptr;
  866|    372|    char * const end = b->ptr + b->used - 1;
  867|       |
  868|    372|    if (__builtin_expect( (buffer_is_blank(b)), 0)) {
  ------------------
  |  Branch (868:9): [True: 0, False: 372]
  ------------------
  869|      0|        buffer_blank(b);
  870|      0|        return;
  871|      0|    }
  872|       |
  873|       |  #if defined(_WIN32) || defined(__CYGWIN__)
  874|       |    /* cygwin is treating \ and / the same, so we have to that too */
  875|       |    for (char *p = b->ptr; *p; p++) {
  876|       |        if (*p == '\\') *p = '/';
  877|       |    }
  878|       |  #endif
  879|       |
  880|    372|    *end = '/'; /*(end of path modified to avoid need to check '\0')*/
  881|       |
  882|    372|    char *walk = out;
  883|    372|    if (__builtin_expect( (*walk == '/'), 1)) {
  ------------------
  |  Branch (883:9): [True: 149, False: 223]
  ------------------
  884|       |        /* scan to detect (potential) need for path simplification
  885|       |         * (repeated '/' or "/.") */
  886|    393|        do {
  887|    393|            if (*++walk == '.' || *walk == '/')
  ------------------
  |  Branch (887:17): [True: 79, False: 314]
  |  Branch (887:35): [True: 70, False: 244]
  ------------------
  888|    149|                break;
  889|  1.06M|            do { ++walk; } while (*walk != '/');
  ------------------
  |  Branch (889:35): [True: 1.06M, False: 244]
  ------------------
  890|    244|        } while (walk != end);
  ------------------
  |  Branch (890:18): [True: 244, False: 0]
  ------------------
  891|    149|        if (__builtin_expect( (walk == end), 1)) {
  ------------------
  |  Branch (891:13): [True: 0, False: 149]
  ------------------
  892|       |            /* common case: no repeated '/' or "/." */
  893|      0|            *end = '\0'; /* overwrite extra '/' added to end of path */
  894|      0|            return;
  895|      0|        }
  896|    149|        out = walk-1;
  897|    149|    }
  898|    223|    else {
  899|    223|        if (walk[0] == '.' && walk[1] == '/')
  ------------------
  |  Branch (899:13): [True: 117, False: 106]
  |  Branch (899:31): [True: 63, False: 54]
  ------------------
  900|     63|            *out = *++walk;
  901|    160|        else if (walk[0] == '.' && walk[1] == '.' && walk[2] == '/')
  ------------------
  |  Branch (901:18): [True: 54, False: 106]
  |  Branch (901:36): [True: 10, False: 44]
  |  Branch (901:54): [True: 2, False: 8]
  ------------------
  902|      2|            *out = *(walk += 2);
  903|    158|        else {
  904|  10.4M|            while (*++walk != '/') ;
  ------------------
  |  Branch (904:20): [True: 10.4M, False: 158]
  ------------------
  905|    158|            out = walk;
  906|    158|        }
  907|    223|        ++walk;
  908|    223|    }
  909|       |
  910|  10.6k|    while (walk <= end) {
  ------------------
  |  Branch (910:12): [True: 10.4k, False: 212]
  ------------------
  911|       |        /* previous char is '/' at this point (or start of string w/o '/') */
  912|  10.4k|        if (__builtin_expect( (walk[0] == '/'), 0)) {
  ------------------
  |  Branch (912:13): [True: 2.27k, False: 8.17k]
  ------------------
  913|       |            /* skip repeated '/' (e.g. "///" -> "/") */
  914|  2.27k|            if (++walk < end)
  ------------------
  |  Branch (914:17): [True: 2.22k, False: 55]
  ------------------
  915|  2.22k|                continue;
  916|     55|            else {
  917|     55|                ++out;
  918|     55|                break;
  919|     55|            }
  920|  2.27k|        }
  921|  8.17k|        else if (__builtin_expect( (walk[0] == '.'), 0)) {
  ------------------
  |  Branch (921:18): [True: 6.12k, False: 2.04k]
  ------------------
  922|       |            /* handle "./" and "../" */
  923|  6.12k|            if (walk[1] == '.' && walk[2] == '/') {
  ------------------
  |  Branch (923:17): [True: 3.33k, False: 2.79k]
  |  Branch (923:35): [True: 1.15k, False: 2.18k]
  ------------------
  924|       |                /* handle "../" */
  925|  6.70M|                while (out > b->ptr && *--out != '/') ;
  ------------------
  |  Branch (925:24): [True: 6.70M, False: 649]
  |  Branch (925:40): [True: 6.70M, False: 505]
  ------------------
  926|  1.15k|                *out = '/'; /*(in case path had not started with '/')*/
  927|  1.15k|                if ((walk += 3) >= end) {
  ------------------
  |  Branch (927:21): [True: 51, False: 1.10k]
  ------------------
  928|     51|                    ++out;
  929|     51|                    break;
  930|     51|                }
  931|  1.10k|                else
  932|  1.10k|                continue;
  933|  1.15k|            }
  934|  4.97k|            else if (walk[1] == '/') {
  ------------------
  |  Branch (934:22): [True: 1.44k, False: 3.52k]
  ------------------
  935|       |                /* handle "./" */
  936|  1.44k|                if ((walk += 2) >= end) {
  ------------------
  |  Branch (936:21): [True: 54, False: 1.39k]
  ------------------
  937|     54|                    ++out;
  938|     54|                    break;
  939|     54|                }
  940|  1.39k|                continue;
  941|  1.44k|            }
  942|  3.52k|            else {
  943|       |                /* accept "." if not part of "../" or "./" */
  944|  3.52k|                *++out = '.';
  945|  3.52k|                ++walk;
  946|  3.52k|            }
  947|  6.12k|        }
  948|       |
  949|  29.1M|        while ((*++out = *walk++) != '/') ;
  ------------------
  |  Branch (949:16): [True: 29.1M, False: 5.56k]
  ------------------
  950|  5.56k|    }
  951|    372|    *out = *end = '\0'; /* overwrite extra '/' added to end of path */
  952|    372|    b->used = (out - b->ptr) + 1;
  953|       |    /*buffer_truncate(b, out - b->ptr);*/
  954|    372|}
buffer.c:buffer_alloc_replace:
   71|  3.34k|static char* buffer_alloc_replace(buffer * const restrict b, const size_t size) {
   72|       |    /*(discard old data so realloc() does not copy)*/
   73|  3.34k|    if (NULL != b->ptr) {
  ------------------
  |  Branch (73:9): [True: 462, False: 2.87k]
  ------------------
   74|    462|        free(b->ptr);
   75|    462|        b->ptr = NULL;
   76|    462|    }
   77|       |    /*(note: if size larger than one lshift, use size instead of power-2)*/
   78|  3.34k|    const size_t bsize2x = (b->size & ~1uL) << 1;
   79|  3.34k|    return buffer_realloc(b, bsize2x > size ? bsize2x-1 : size);
  ------------------
  |  Branch (79:30): [True: 226, False: 3.11k]
  ------------------
   80|  3.34k|}
buffer.c:buffer_realloc:
   49|  3.34k|static char* buffer_realloc(buffer * const restrict b, const size_t len) {
   50|  3.34k|    #define BUFFER_PIECE_SIZE 64uL  /*(must be power-of-2)*/
   51|  3.34k|    size_t sz = (len + 1 + BUFFER_PIECE_SIZE-1) & ~(BUFFER_PIECE_SIZE-1);
  ------------------
  |  |   50|  3.34k|    #define BUFFER_PIECE_SIZE 64uL  /*(must be power-of-2)*/
  ------------------
                  size_t sz = (len + 1 + BUFFER_PIECE_SIZE-1) & ~(BUFFER_PIECE_SIZE-1);
  ------------------
  |  |   50|  3.34k|    #define BUFFER_PIECE_SIZE 64uL  /*(must be power-of-2)*/
  ------------------
   52|  3.34k|    force_assert(sz > len);
  ------------------
  |  |  448|  3.34k|#define force_assert(x) ck_assert(x)
  |  |  ------------------
  |  |  |  |  115|  3.34k|        do { if (!(x)) ck_assert_failed(__FILE__, __LINE__, #x); } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (115:18): [True: 0, False: 3.34k]
  |  |  |  |  |  Branch (115:75): [Folded, False: 3.34k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
   53|  3.34k|    if ((sz & (sz-1)) && sz < INT_MAX) {/* not power-2; huge val not expected */
  ------------------
  |  Branch (53:9): [True: 1.15k, False: 2.18k]
  |  Branch (53:26): [True: 1.15k, False: 0]
  ------------------
   54|       |        /*(optimizer should recognize this and use ffs or clz or equivalent)*/
   55|  1.15k|        const size_t psz = sz;
   56|  7.91k|        for (sz = 256; sz < psz; sz <<= 1) ;
  ------------------
  |  Branch (56:24): [True: 6.76k, False: 1.15k]
  ------------------
   57|  1.15k|    }
   58|  3.34k|    sz |= 1; /*(extra +1 for '\0' when needed buffer size is exact power-2)*/
   59|       |
   60|  3.34k|    b->size = sz;
   61|  3.34k|    b->ptr = realloc(b->ptr, sz);
   62|       |
   63|  3.34k|    force_assert(NULL != b->ptr);
  ------------------
  |  |  448|  3.34k|#define force_assert(x) ck_assert(x)
  |  |  ------------------
  |  |  |  |  115|  3.34k|        do { if (!(x)) ck_assert_failed(__FILE__, __LINE__, #x); } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (115:18): [True: 0, False: 3.34k]
  |  |  |  |  |  Branch (115:75): [Folded, False: 3.34k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
   64|  3.34k|    return b->ptr;
   65|  3.34k|}

burl.c:buffer_truncate:
  349|    427|static inline void buffer_truncate(buffer *b, uint32_t len) {
  350|    427|    b->ptr[len] = '\0'; /* b->ptr must exist; use buffer_blank() for trunc 0 */
  351|    427|    b->used = len + 1;
  352|    427|}
burl.c:light_isalnum:
  232|  16.9k|static inline int light_isalnum(int c) {
  233|  16.9k|	return light_isdigit(c) || light_isalpha(c);
  ------------------
  |  Branch (233:9): [True: 241, False: 16.6k]
  |  Branch (233:29): [True: 667, False: 16.0k]
  ------------------
  234|  16.9k|}
burl.c:light_isdigit:
  214|  16.9k|static inline int light_isdigit(int c) {
  215|  16.9k|	return ((uint32_t)c-'0' <= '9'-'0');
  216|  16.9k|}
burl.c:light_isalpha:
  226|  16.6k|static inline int light_isalpha(int c) {
  227|  16.6k|	return (((uint32_t)c | 0x20)-'a' <= 'z'-'a');
  228|  16.6k|}
burl.c:buffer_clen:
  323|  6.06k|static inline uint32_t buffer_clen (const buffer *b) {
  324|  6.06k|    return b->used - (0 != b->used);
  325|  6.06k|}
buffer.c:buffer_clen:
  323|  1.62k|static inline uint32_t buffer_clen (const buffer *b) {
  324|  1.62k|    return b->used - (0 != b->used);
  325|  1.62k|}
buffer.c:buffer_is_blank:
  315|    372|static inline int buffer_is_blank(const buffer *b) {
  316|    372|    return b->used < 2; /* buffer_is_blank() || buffer_is_unset() */
  317|    372|}

burl_normalize:
  338|  1.62k|{
  339|  1.62k|    int qs;
  340|       |
  341|       |  #if defined(_WIN32) || defined(__CYGWIN__)
  342|       |    /* Windows and Cygwin treat '\\' as '/' if '\\' is present in path;
  343|       |     * convert to '/' for consistency before percent-encoding
  344|       |     * normalization which will convert '\\' to "%5C" in the URL.
  345|       |     * (Clients still should not be sending '\\' unencoded in requests.) */
  346|       |    if (flags & HTTP_PARSEOPT_URL_NORMALIZE_PATH_BACKSLASH_TRANS) {
  347|       |        for (char *p = b->ptr; *p != '?' && *p != '\0'; ++p) {
  348|       |            if (*p == '\\') *p = '/';
  349|       |        }
  350|       |    }
  351|       |  #endif
  352|       |
  353|  1.62k|    qs = (flags & HTTP_PARSEOPT_URL_NORMALIZE_REQUIRED)
  ------------------
  |  Branch (353:10): [True: 853, False: 769]
  ------------------
  354|  1.62k|      ? burl_normalize_basic_required(b, t)
  355|  1.62k|      : burl_normalize_basic_unreserved(b, t);
  356|  1.62k|    if (-2 == qs) {
  ------------------
  |  Branch (356:9): [True: 480, False: 1.14k]
  ------------------
  357|    480|        if (flags & HTTP_PARSEOPT_URL_NORMALIZE_INVALID_UTF8_REJECT) return -2;
  ------------------
  |  Branch (357:13): [True: 113, False: 367]
  ------------------
  358|    367|        qs = burl_scan_qmark(b);
  359|    367|    }
  360|       |
  361|  1.50k|    if (flags & HTTP_PARSEOPT_URL_NORMALIZE_CTRLS_REJECT) {
  ------------------
  |  Branch (361:9): [True: 345, False: 1.16k]
  ------------------
  362|    345|        if (burl_contains_ctrls(b)) return -2;
  ------------------
  |  Branch (362:13): [True: 85, False: 260]
  ------------------
  363|    345|    }
  364|       |
  365|  1.42k|    if (flags & (HTTP_PARSEOPT_URL_NORMALIZE_PATH_2F_DECODE
  ------------------
  |  Branch (365:9): [True: 1.18k, False: 239]
  ------------------
  366|  1.42k|                |HTTP_PARSEOPT_URL_NORMALIZE_PATH_2F_REJECT)) {
  367|  1.18k|        qs = burl_normalize_2F_to_slash(b, qs, flags);
  368|  1.18k|        if (-2 == qs) return -2;
  ------------------
  |  Branch (368:13): [True: 7, False: 1.17k]
  ------------------
  369|  1.18k|    }
  370|       |
  371|  1.41k|    if (flags & (HTTP_PARSEOPT_URL_NORMALIZE_PATH_DOTSEG_REMOVE
  ------------------
  |  Branch (371:9): [True: 1.14k, False: 272]
  ------------------
  372|  1.41k|                |HTTP_PARSEOPT_URL_NORMALIZE_PATH_DOTSEG_REJECT)) {
  373|  1.14k|        qs = burl_normalize_path(b, t, qs, flags);
  374|  1.14k|        if (-2 == qs) return -2;
  ------------------
  |  Branch (374:13): [True: 16, False: 1.12k]
  ------------------
  375|  1.14k|    }
  376|       |
  377|  1.40k|    if (flags & HTTP_PARSEOPT_URL_NORMALIZE_QUERY_20_PLUS) {
  ------------------
  |  Branch (377:9): [True: 862, False: 539]
  ------------------
  378|    862|        if (qs >= 0) burl_normalize_qs20_to_plus(b, qs);
  ------------------
  |  Branch (378:13): [True: 395, False: 467]
  ------------------
  379|    862|    }
  380|       |
  381|  1.40k|    return qs;
  382|  1.41k|}
burl.c:burl_normalize_basic_required:
  175|    853|{
  176|    853|    const unsigned char * const s = (unsigned char *)b->ptr;
  177|    853|    const int used = (int)buffer_clen(b);
  178|    853|    unsigned int n1, n2, x;
  179|    853|    int qs = -1;
  180|    853|    int invalid_utf8 = 0;
  181|       |
  182|  1.05M|    for (int i = 0; i < used; ++i) {
  ------------------
  |  Branch (182:21): [True: 1.05M, False: 195]
  ------------------
  183|  1.05M|        if (!encoded_chars_http_uri_reqd[s[i]]) {
  ------------------
  |  Branch (183:13): [True: 999k, False: 59.9k]
  ------------------
  184|   999k|            if (s[i] == '?') qs = i;
  ------------------
  |  Branch (184:17): [True: 49.0k, False: 950k]
  ------------------
  185|   999k|        }
  186|  59.9k|        else if (s[i]=='%' && li_cton(s[i+1], n1) && li_cton(s[i+2], n2)
  ------------------
  |  |   43|   119k|  (((n) = (c) - '0') <= 9 || (((n) = ((c)&0xdf) - 'A') <= 5 ? ((n) += 10) : 0))
  |  |  ------------------
  |  |  |  Branch (43:4): [True: 55.9k, False: 3.47k]
  |  |  |  Branch (43:30): [True: 3.38k, False: 89]
  |  |  |  Branch (43:31): [True: 3.38k, False: 89]
  |  |  ------------------
  ------------------
                      else if (s[i]=='%' && li_cton(s[i+1], n1) && li_cton(s[i+2], n2)
  ------------------
  |  |   43|   119k|  (((n) = (c) - '0') <= 9 || (((n) = ((c)&0xdf) - 'A') <= 5 ? ((n) += 10) : 0))
  |  |  ------------------
  |  |  |  Branch (43:4): [True: 36.3k, False: 23.0k]
  |  |  |  Branch (43:30): [True: 22.9k, False: 52]
  |  |  |  Branch (43:31): [True: 22.9k, False: 52]
  |  |  ------------------
  ------------------
  |  Branch (186:18): [True: 59.4k, False: 454]
  ------------------
  187|  59.3k|                 && (encoded_chars_http_uri_reqd[(x = (n1 << 4) | n2)]
  ------------------
  |  Branch (187:22): [True: 10.6k, False: 48.6k]
  ------------------
  188|  48.6k|                     || (qs < 0
  ------------------
  |  Branch (188:25): [True: 48.6k, False: 63]
  |  Branch (188:26): [True: 585, False: 48.0k]
  ------------------
  189|  48.6k|                         ? (x == '/' || x == '?')
  ------------------
  |  Branch (189:29): [True: 314, False: 271]
  |  Branch (189:41): [True: 241, False: 30]
  ------------------
  190|  59.2k|                         : (x == '&' || x == '=' || x == ';' || x == '+')))) {
  ------------------
  |  Branch (190:29): [True: 27.5k, False: 20.5k]
  |  Branch (190:41): [True: 13.4k, False: 7.00k]
  |  Branch (190:53): [True: 1.36k, False: 5.64k]
  |  Branch (190:65): [True: 5.61k, False: 33]
  ------------------
  191|  59.2k|            invalid_utf8 |= li_utf8_invalid_byte(x);
  ------------------
  |  |   49|  59.2k|#define li_utf8_invalid_byte(b) light_utf8_invalid_byte(b)
  |  |  ------------------
  |  |  |  |  260|  59.2k|  (   __builtin_expect( ((c) >= 0xF5),       0) \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (260:7): [True: 517, False: 58.7k]
  |  |  |  |  ------------------
  |  |  |  |  261|  59.2k|   || __builtin_expect( (((c)|0x1) == 0xC1), 0) )
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (261:7): [True: 312, False: 58.4k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  192|  59.2k|            if (s[i+1] >= 'a') b->ptr[i+1] &= 0xdf; /* uppercase hex */
  ------------------
  |  Branch (192:17): [True: 925, False: 58.3k]
  ------------------
  193|  59.2k|            if (s[i+2] >= 'a') b->ptr[i+2] &= 0xdf; /* uppercase hex */
  ------------------
  |  Branch (193:17): [True: 7.70k, False: 51.5k]
  ------------------
  194|  59.2k|            i+=2;
  195|  59.2k|        }
  196|    658|        else if (s[i] == '#') { /* ignore fragment */
  ------------------
  |  Branch (196:18): [True: 2, False: 656]
  ------------------
  197|      2|            buffer_truncate(b, (size_t)i);
  198|      2|            break;
  199|      2|        }
  200|    656|        else {
  201|    656|            qs = burl_normalize_basic_required_fix(b, t, i, qs);
  202|    656|            break;
  203|    656|        }
  204|  1.05M|    }
  205|       |
  206|    853|    return !invalid_utf8 ? qs : -2;
  ------------------
  |  Branch (206:12): [True: 826, False: 27]
  ------------------
  207|    853|}
burl.c:burl_normalize_basic_required_fix:
  131|    656|{
  132|    656|    int j = i;
  133|    656|    const int used = (int)buffer_clen(b);
  134|    656|    const unsigned char * const s = (unsigned char *)b->ptr;
  135|    656|    unsigned char * const p =
  136|    656|      (unsigned char *)buffer_string_prepare_copy(t,i+(used-i)*3+1);
  137|    656|    unsigned int n1, n2;
  138|    656|    int invalid_utf8 = 0;
  139|    656|    memcpy(p, s, (size_t)i);
  140|  28.1M|    for (; i < used; ++i, ++j) {
  ------------------
  |  Branch (140:12): [True: 28.1M, False: 645]
  ------------------
  141|  28.1M|        if (!encoded_chars_http_uri_reqd[s[i]]) {
  ------------------
  |  Branch (141:13): [True: 574k, False: 27.5M]
  ------------------
  142|   574k|            p[j] = s[i];
  143|   574k|            if (__builtin_expect( (s[i] == '?'), 0)) qs = j;
  ------------------
  |  Branch (143:17): [True: 11.3k, False: 563k]
  ------------------
  144|   574k|        }
  145|  27.5M|        else if (s[i]=='%' && li_cton(s[i+1], n1) && li_cton(s[i+2], n2)) {
  ------------------
  |  |   43|  27.5M|  (((n) = (c) - '0') <= 9 || (((n) = ((c)&0xdf) - 'A') <= 5 ? ((n) += 10) : 0))
  |  |  ------------------
  |  |  |  Branch (43:4): [True: 22.9k, False: 26.6k]
  |  |  |  Branch (43:30): [True: 6.28k, False: 20.3k]
  |  |  |  Branch (43:31): [True: 6.28k, False: 20.3k]
  |  |  ------------------
  ------------------
                      else if (s[i]=='%' && li_cton(s[i+1], n1) && li_cton(s[i+2], n2)) {
  ------------------
  |  |   43|  29.2k|  (((n) = (c) - '0') <= 9 || (((n) = ((c)&0xdf) - 'A') <= 5 ? ((n) += 10) : 0))
  |  |  ------------------
  |  |  |  Branch (43:4): [True: 13.5k, False: 15.7k]
  |  |  |  Branch (43:30): [True: 12.5k, False: 3.18k]
  |  |  |  Branch (43:31): [True: 12.5k, False: 3.18k]
  |  |  ------------------
  ------------------
  |  Branch (145:18): [True: 49.6k, False: 27.4M]
  ------------------
  146|  26.1k|            const unsigned int x = (n1 << 4) | n2;
  147|  26.1k|            if (!encoded_chars_http_uri_reqd[x]
  ------------------
  |  Branch (147:17): [True: 17.9k, False: 8.18k]
  ------------------
  148|  17.9k|                && (qs < 0
  ------------------
  |  Branch (148:20): [True: 5.15k, False: 12.7k]
  |  Branch (148:21): [True: 2.85k, False: 15.0k]
  ------------------
  149|  17.9k|                    ? (x != '/' && x != '?')
  ------------------
  |  Branch (149:24): [True: 1.94k, False: 909]
  |  Branch (149:36): [True: 1.52k, False: 418]
  ------------------
  150|  17.9k|                    : (x != '&' && x != '=' && x != ';' && x != '+'))) {
  ------------------
  |  Branch (150:24): [True: 9.12k, False: 5.93k]
  |  Branch (150:36): [True: 6.02k, False: 3.10k]
  |  Branch (150:48): [True: 5.26k, False: 758]
  |  Branch (150:60): [True: 3.62k, False: 1.63k]
  ------------------
  151|  5.15k|                p[j] = x;
  152|  5.15k|            }
  153|  20.9k|            else {
  154|  20.9k|                p[j]   = '%';
  155|  20.9k|                p[++j] = hex_chars_uc[n1]; /*(s[i+1] & 0xdf)*/
  156|  20.9k|                p[++j] = hex_chars_uc[n2]; /*(s[i+2] & 0xdf)*/
  157|  20.9k|                invalid_utf8 |= li_utf8_invalid_byte(x);
  ------------------
  |  |   49|  20.9k|#define li_utf8_invalid_byte(b) light_utf8_invalid_byte(b)
  |  |  ------------------
  |  |  |  |  260|  20.9k|  (   __builtin_expect( ((c) >= 0xF5),       0) \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (260:7): [True: 1.66k, False: 19.2k]
  |  |  |  |  ------------------
  |  |  |  |  261|  20.9k|   || __builtin_expect( (((c)|0x1) == 0xC1), 0) )
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (261:7): [True: 371, False: 18.9k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  158|  20.9k|            }
  159|  26.1k|            i+=2;
  160|  26.1k|        }
  161|  27.5M|        else if (s[i] == '#') break; /* ignore fragment */
  ------------------
  |  Branch (161:18): [True: 11, False: 27.5M]
  ------------------
  162|  27.5M|        else {
  163|  27.5M|            p[j]   = '%';
  164|  27.5M|            p[++j] = hex_chars_uc[(s[i] >> 4) & 0xF];
  165|  27.5M|            p[++j] = hex_chars_uc[s[i] & 0xF];
  166|  27.5M|            invalid_utf8 |= li_utf8_invalid_byte(s[i]);
  ------------------
  |  |   49|  27.5M|#define li_utf8_invalid_byte(b) light_utf8_invalid_byte(b)
  |  |  ------------------
  |  |  |  |  260|  27.5M|  (   __builtin_expect( ((c) >= 0xF5),       0) \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (260:7): [True: 2.41M, False: 25.0M]
  |  |  |  |  ------------------
  |  |  |  |  261|  27.5M|   || __builtin_expect( (((c)|0x1) == 0xC1), 0) )
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (261:7): [True: 943, False: 25.0M]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  167|  27.5M|        }
  168|  28.1M|    }
  169|    656|    buffer_copy_string_len(b, (char *)p, (size_t)j);
  170|    656|    return !invalid_utf8 ? qs : -2;
  ------------------
  |  Branch (170:12): [True: 419, False: 237]
  ------------------
  171|    656|}
burl.c:burl_normalize_basic_unreserved:
   99|    769|{
  100|    769|    const unsigned char * const s = (unsigned char *)b->ptr;
  101|    769|    const int used = (int)buffer_clen(b);
  102|    769|    unsigned int n1, n2, x;
  103|    769|    int qs = -1;
  104|       |
  105|   575k|    for (int i = 0; i < used; ++i) {
  ------------------
  |  Branch (105:21): [True: 575k, False: 180]
  ------------------
  106|   575k|        if (!encoded_chars_http_uri_reqd[s[i]]) {
  ------------------
  |  Branch (106:13): [True: 571k, False: 4.19k]
  ------------------
  107|   571k|            if (__builtin_expect( (s[i] == '?'), 0) && -1 == qs) qs = i;
  ------------------
  |  Branch (107:17): [True: 1.81k, False: 569k]
  |  Branch (107:56): [True: 77, False: 1.73k]
  ------------------
  108|   571k|        }
  109|  4.19k|        else if (s[i]=='%' && li_cton(s[i+1], n1) && li_cton(s[i+2], n2)
  ------------------
  |  |   43|  7.96k|  (((n) = (c) - '0') <= 9 || (((n) = ((c)&0xdf) - 'A') <= 5 ? ((n) += 10) : 0))
  |  |  ------------------
  |  |  |  Branch (43:4): [True: 2.60k, False: 1.16k]
  |  |  |  Branch (43:30): [True: 1.10k, False: 56]
  |  |  |  Branch (43:31): [True: 1.10k, False: 56]
  |  |  ------------------
  ------------------
                      else if (s[i]=='%' && li_cton(s[i+1], n1) && li_cton(s[i+2], n2)
  ------------------
  |  |   43|  7.91k|  (((n) = (c) - '0') <= 9 || (((n) = ((c)&0xdf) - 'A') <= 5 ? ((n) += 10) : 0))
  |  |  ------------------
  |  |  |  Branch (43:4): [True: 2.10k, False: 1.60k]
  |  |  |  Branch (43:30): [True: 1.55k, False: 49]
  |  |  |  Branch (43:31): [True: 1.55k, False: 49]
  |  |  ------------------
  ------------------
  |  Branch (109:18): [True: 3.76k, False: 429]
  ------------------
  110|  3.66k|                 && !burl_is_unreserved((x = (n1 << 4) | n2))) {
  ------------------
  |  Branch (110:21): [True: 3.60k, False: 55]
  ------------------
  111|  3.60k|            if (li_utf8_invalid_byte(x)) qs = -2;
  ------------------
  |  |   49|  3.60k|#define li_utf8_invalid_byte(b) light_utf8_invalid_byte(b)
  |  |  ------------------
  |  |  |  |  260|  3.60k|  (   __builtin_expect( ((c) >= 0xF5),       0) \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (260:7): [True: 442, False: 3.16k]
  |  |  |  |  ------------------
  |  |  |  |  261|  3.60k|   || __builtin_expect( (((c)|0x1) == 0xC1), 0) )
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (261:7): [True: 370, False: 2.79k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  112|  3.60k|            if (s[i+1] >= 'a') b->ptr[i+1] &= 0xdf; /* uppercase hex */
  ------------------
  |  Branch (112:17): [True: 969, False: 2.64k]
  ------------------
  113|  3.60k|            if (s[i+2] >= 'a') b->ptr[i+2] &= 0xdf; /* uppercase hex */
  ------------------
  |  Branch (113:17): [True: 743, False: 2.86k]
  ------------------
  114|  3.60k|            i+=2;
  115|  3.60k|        }
  116|    589|        else if (s[i] == '#') { /* ignore fragment */
  ------------------
  |  Branch (116:18): [True: 1, False: 588]
  ------------------
  117|      1|            buffer_truncate(b, (size_t)i);
  118|      1|            break;
  119|      1|        }
  120|    588|        else {
  121|    588|            qs = burl_normalize_basic_unreserved_fix(b, t, i, qs);
  122|    588|            break;
  123|    588|        }
  124|   575k|    }
  125|       |
  126|    769|    return qs;
  127|    769|}
burl.c:burl_is_unreserved:
   53|  16.9k|{
   54|  16.9k|    return (light_isalnum(c) || c == '-' || c == '.' || c == '_' || c == '~');
  ------------------
  |  Branch (54:13): [True: 908, False: 16.0k]
  |  Branch (54:33): [True: 347, False: 15.6k]
  |  Branch (54:45): [True: 584, False: 15.0k]
  |  Branch (54:57): [True: 253, False: 14.8k]
  |  Branch (54:69): [True: 305, False: 14.5k]
  ------------------
   55|  16.9k|}
burl.c:burl_normalize_basic_unreserved_fix:
   59|    588|{
   60|    588|    int j = i;
   61|    588|    const int used = (int)buffer_clen(b);
   62|    588|    const unsigned char * const s = (unsigned char *)b->ptr;
   63|    588|    unsigned char * const p =
   64|    588|      (unsigned char *)buffer_string_prepare_copy(t,i+(used-i)*3+1);
   65|    588|    unsigned int n1, n2;
   66|    588|    memcpy(p, s, (size_t)i);
   67|  23.0M|    for (; i < used; ++i, ++j) {
  ------------------
  |  Branch (67:12): [True: 23.0M, False: 584]
  ------------------
   68|  23.0M|        if (!encoded_chars_http_uri_reqd[s[i]]) {
  ------------------
  |  Branch (68:13): [True: 1.31M, False: 21.7M]
  ------------------
   69|  1.31M|            p[j] = s[i];
   70|  1.31M|            if (__builtin_expect( (s[i] == '?'), 0) && -1 == qs) qs = j;
  ------------------
  |  Branch (70:17): [True: 1.56k, False: 1.31M]
  |  Branch (70:56): [True: 82, False: 1.47k]
  ------------------
   71|  1.31M|        }
   72|  21.7M|        else if (s[i]=='%' && li_cton(s[i+1], n1) && li_cton(s[i+2], n2)) {
  ------------------
  |  |   43|  21.7M|  (((n) = (c) - '0') <= 9 || (((n) = ((c)&0xdf) - 'A') <= 5 ? ((n) += 10) : 0))
  |  |  ------------------
  |  |  |  Branch (43:4): [True: 8.62k, False: 10.3k]
  |  |  |  Branch (43:30): [True: 7.30k, False: 3.04k]
  |  |  |  Branch (43:31): [True: 7.30k, False: 3.04k]
  |  |  ------------------
  ------------------
                      else if (s[i]=='%' && li_cton(s[i+1], n1) && li_cton(s[i+2], n2)) {
  ------------------
  |  |   43|  15.9k|  (((n) = (c) - '0') <= 9 || (((n) = ((c)&0xdf) - 'A') <= 5 ? ((n) += 10) : 0))
  |  |  ------------------
  |  |  |  Branch (43:4): [True: 5.50k, False: 10.4k]
  |  |  |  Branch (43:30): [True: 7.74k, False: 2.68k]
  |  |  |  Branch (43:31): [True: 7.74k, False: 2.68k]
  |  |  ------------------
  ------------------
  |  Branch (72:18): [True: 18.9k, False: 21.7M]
  ------------------
   73|  13.2k|            const unsigned int x = (n1 << 4) | n2;
   74|  13.2k|            if (burl_is_unreserved(x)) {
  ------------------
  |  Branch (74:17): [True: 2.34k, False: 10.9k]
  ------------------
   75|  2.34k|                p[j] = x;
   76|  2.34k|            }
   77|  10.9k|            else {
   78|  10.9k|                p[j]   = '%';
   79|  10.9k|                p[++j] = hex_chars_uc[n1]; /*(s[i+1] & 0xdf)*/
   80|  10.9k|                p[++j] = hex_chars_uc[n2]; /*(s[i+2] & 0xdf)*/
   81|  10.9k|                if (li_utf8_invalid_byte(x)) qs = -2;
  ------------------
  |  |   49|  10.9k|#define li_utf8_invalid_byte(b) light_utf8_invalid_byte(b)
  |  |  ------------------
  |  |  |  |  260|  10.9k|  (   __builtin_expect( ((c) >= 0xF5),       0) \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (260:7): [True: 3.82k, False: 7.07k]
  |  |  |  |  ------------------
  |  |  |  |  261|  10.9k|   || __builtin_expect( (((c)|0x1) == 0xC1), 0) )
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (261:7): [True: 234, False: 6.84k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
   82|  10.9k|            }
   83|  13.2k|            i+=2;
   84|  13.2k|        }
   85|  21.7M|        else if (s[i] == '#') break; /* ignore fragment */
  ------------------
  |  Branch (85:18): [True: 4, False: 21.7M]
  ------------------
   86|  21.7M|        else {
   87|  21.7M|            p[j]   = '%';
   88|  21.7M|            p[++j] = hex_chars_uc[(s[i] >> 4) & 0xF];
   89|  21.7M|            p[++j] = hex_chars_uc[s[i] & 0xF];
   90|  21.7M|            if (li_utf8_invalid_byte(s[i])) qs = -2;
  ------------------
  |  |   49|  21.7M|#define li_utf8_invalid_byte(b) light_utf8_invalid_byte(b)
  |  |  ------------------
  |  |  |  |  260|  21.7M|  (   __builtin_expect( ((c) >= 0xF5),       0) \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (260:7): [True: 554k, False: 21.1M]
  |  |  |  |  ------------------
  |  |  |  |  261|  21.7M|   || __builtin_expect( (((c)|0x1) == 0xC1), 0) )
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (261:7): [True: 3.79k, False: 21.1M]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
   91|  21.7M|        }
   92|  23.0M|    }
   93|    588|    buffer_copy_string_len(b, (char *)p, (size_t)j);
   94|    588|    return qs;
   95|    588|}
burl.c:burl_scan_qmark:
  331|    367|static int burl_scan_qmark (const buffer * const b) {
  332|    367|    const char * const qmark = strchr(b->ptr, '?');
  333|    367|    return qmark ? (int)(qmark - b->ptr) : -1;
  ------------------
  |  Branch (333:12): [True: 180, False: 187]
  ------------------
  334|    367|}
burl.c:burl_contains_ctrls:
  211|    345|{
  212|    345|    const char * const s = b->ptr;
  213|    345|    const int used = (int)buffer_clen(b);
  214|  7.43M|    for (int i = 0; i < used; ++i) {
  ------------------
  |  Branch (214:21): [True: 7.43M, False: 260]
  ------------------
  215|  7.43M|        if (s[i] == '%' && (s[i+1] < '2' || (s[i+1] == '7' && s[i+2] == 'F')))
  ------------------
  |  Branch (215:13): [True: 2.15M, False: 5.27M]
  |  Branch (215:29): [True: 80, False: 2.15M]
  |  Branch (215:46): [True: 535, False: 2.15M]
  |  Branch (215:63): [True: 5, False: 530]
  ------------------
  216|     85|            return 1;
  217|  7.43M|    }
  218|    260|    return 0;
  219|    345|}
burl.c:burl_normalize_2F_to_slash:
  276|  1.18k|{
  277|       |    /*("%2F" must already have been uppercased during normalization)*/
  278|  1.18k|    const char * const s = b->ptr;
  279|  1.18k|    const int used = qs < 0 ? (int)buffer_clen(b) : qs;
  ------------------
  |  Branch (279:22): [True: 738, False: 447]
  ------------------
  280|  73.2M|    for (int i = 0; i < used; ++i) {
  ------------------
  |  Branch (280:21): [True: 73.2M, False: 999]
  ------------------
  281|  73.2M|        if (s[i] == '%' && s[i+1] == '2' && s[i+2] == 'F') {
  ------------------
  |  Branch (281:13): [True: 24.0M, False: 49.2M]
  |  Branch (281:28): [True: 41.5k, False: 24.0M]
  |  Branch (281:45): [True: 186, False: 41.3k]
  ------------------
  282|    186|            return (flags & HTTP_PARSEOPT_URL_NORMALIZE_PATH_2F_DECODE)
  ------------------
  |  Branch (282:20): [True: 179, False: 7]
  ------------------
  283|    186|              ? burl_normalize_2F_to_slash_fix(b, qs, i)
  284|    186|              : -2; /*(flags & HTTP_PARSEOPT_URL_NORMALIZE_PATH_2F_REJECT)*/
  285|    186|        }
  286|  73.2M|    }
  287|    999|    return qs;
  288|  1.18k|}
burl.c:burl_normalize_2F_to_slash_fix:
  252|    179|{
  253|    179|    char * const s = b->ptr;
  254|    179|    const int blen = (int)buffer_clen(b);
  255|    179|    const int used = qs < 0 ? blen : qs;
  ------------------
  |  Branch (255:22): [True: 113, False: 66]
  ------------------
  256|    179|    int j = i;
  257|  16.0M|    for (; i < used; ++i, ++j) {
  ------------------
  |  Branch (257:12): [True: 16.0M, False: 179]
  ------------------
  258|  16.0M|        s[j] = s[i];
  259|  16.0M|        if (s[i] == '%' && s[i+1] == '2' && s[i+2] == 'F') {
  ------------------
  |  Branch (259:13): [True: 5.33M, False: 10.6M]
  |  Branch (259:28): [True: 23.1k, False: 5.31M]
  |  Branch (259:45): [True: 1.18k, False: 21.9k]
  ------------------
  260|  1.18k|            s[j] = '/';
  261|  1.18k|            i+=2;
  262|  1.18k|        }
  263|  16.0M|    }
  264|    179|    if (qs >= 0) {
  ------------------
  |  Branch (264:9): [True: 66, False: 113]
  ------------------
  265|     66|        const int qslen = blen - qs;
  266|     66|        memmove(s+j, s+qs, (size_t)qslen);
  267|     66|        qs = j;
  268|     66|        j += qslen;
  269|     66|    }
  270|    179|    buffer_truncate(b, j);
  271|    179|    return qs;
  272|    179|}
burl.c:burl_normalize_path:
  292|  1.14k|{
  293|  1.14k|    const unsigned char * const s = (unsigned char *)b->ptr;
  294|  1.14k|    const int used = (int)buffer_clen(b);
  295|  1.14k|    int path_simplify = 0;
  296|  4.41k|    for (int i = 0, len = qs < 0 ? used : qs; i < len; ++i) {
  ------------------
  |  Branch (296:27): [True: 707, False: 438]
  |  Branch (296:47): [True: 3.66k, False: 757]
  ------------------
  297|  3.66k|        if (s[i] == '.' && (s[i+1] != '.' || ++i)
  ------------------
  |  Branch (297:13): [True: 1.64k, False: 2.01k]
  |  Branch (297:29): [True: 1.10k, False: 543]
  |  Branch (297:46): [True: 543, False: 0]
  ------------------
  298|  1.64k|            && (s[i+1] == '/' || s[i+1] == '?' || s[i+1] == '\0')) {
  ------------------
  |  Branch (298:17): [True: 93, False: 1.55k]
  |  Branch (298:34): [True: 81, False: 1.47k]
  |  Branch (298:51): [True: 69, False: 1.40k]
  ------------------
  299|    243|            path_simplify = 1;
  300|    243|            break;
  301|    243|        }
  302|  68.4M|        while (i < len && s[i] != '/') ++i;
  ------------------
  |  Branch (302:16): [True: 68.4M, False: 611]
  |  Branch (302:27): [True: 68.4M, False: 2.80k]
  ------------------
  303|  3.41k|        if (s[i] == '/' && s[i+1] == '/') { /*(s[len] != '/')*/
  ------------------
  |  Branch (303:13): [True: 2.80k, False: 611]
  |  Branch (303:28): [True: 145, False: 2.66k]
  ------------------
  304|    145|            path_simplify = 1;
  305|    145|            break;
  306|    145|        }
  307|  3.41k|    }
  308|       |
  309|  1.14k|    if (path_simplify) {
  ------------------
  |  Branch (309:9): [True: 388, False: 757]
  ------------------
  310|    388|        if (flags & HTTP_PARSEOPT_URL_NORMALIZE_PATH_DOTSEG_REJECT) return -2;
  ------------------
  |  Branch (310:13): [True: 16, False: 372]
  ------------------
  311|    372|        if (qs >= 0) {
  ------------------
  |  Branch (311:13): [True: 153, False: 219]
  ------------------
  312|    153|            buffer_copy_string_len(t, b->ptr+qs, used - qs);
  313|    153|            buffer_truncate(b, qs);
  314|    153|        }
  315|       |
  316|    372|        buffer_path_simplify(b);
  317|       |
  318|    372|        if (qs >= 0) {
  ------------------
  |  Branch (318:13): [True: 153, False: 219]
  ------------------
  319|    153|            qs = (int)buffer_clen(b);
  320|    153|            buffer_append_string_len(b, BUF_PTR_LEN(t));
  ------------------
  |  |  297|    153|#define BUF_PTR_LEN(x)       (x)->ptr, buffer_clen(x)
  ------------------
  321|    153|        }
  322|    372|    }
  323|       |
  324|  1.12k|    return qs;
  325|  1.14k|}
burl.c:burl_normalize_qs20_to_plus:
  239|    395|{
  240|    395|    const char * const s = b->ptr;
  241|    395|    const int used = qs < 0 ? 0 : (int)buffer_clen(b);
  ------------------
  |  Branch (241:22): [True: 0, False: 395]
  ------------------
  242|    395|    int i;
  243|    395|    if (qs < 0) return;
  ------------------
  |  Branch (243:9): [True: 0, False: 395]
  ------------------
  244|  3.52M|    for (i = qs+1; i < used; ++i) {
  ------------------
  |  Branch (244:20): [True: 3.52M, False: 303]
  ------------------
  245|  3.52M|        if (s[i] == '%' && s[i+1] == '2' && s[i+2] == '0') break;
  ------------------
  |  Branch (245:13): [True: 1.16M, False: 2.36M]
  |  Branch (245:28): [True: 2.10k, False: 1.15M]
  |  Branch (245:45): [True: 92, False: 2.01k]
  ------------------
  246|  3.52M|    }
  247|    395|    if (i != used) burl_normalize_qs20_to_plus_fix(b, i);
  ------------------
  |  Branch (247:9): [True: 92, False: 303]
  ------------------
  248|    395|}
burl.c:burl_normalize_qs20_to_plus_fix:
  223|     92|{
  224|     92|    char * const s = b->ptr;
  225|     92|    const int used = (int)buffer_clen(b);
  226|     92|    int j = i;
  227|  5.99M|    for (; i < used; ++i, ++j) {
  ------------------
  |  Branch (227:12): [True: 5.99M, False: 92]
  ------------------
  228|  5.99M|        s[j] = s[i];
  229|  5.99M|        if (s[i] == '%' && s[i+1] == '2' && s[i+2] == '0') {
  ------------------
  |  Branch (229:13): [True: 1.99M, False: 4.00M]
  |  Branch (229:28): [True: 6.02k, False: 1.98M]
  |  Branch (229:45): [True: 2.14k, False: 3.87k]
  ------------------
  230|  2.14k|            s[j] = '+';
  231|  2.14k|            i+=2;
  232|  2.14k|        }
  233|  5.99M|    }
  234|     92|    buffer_truncate(b, j);
  235|     92|}

