summaryrefslogblamecommitdiffhomepage
path: root/src/nxt_parse.c
blob: c0f8272e4f2f397e0410b15d96af3d339209b516 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15














                                                        
                                             



                    
                                     



















                                                     
                     
 
                              













                                                           
                                                



                
                                     



















                                                   
                     
 
                              













                                                                           
                                              




                         
                                     
 
                 

                         
                                 




















                                       
                     


                  
                                         



















                                                     
                         
 
                                  














                                                             
                                               



                    
                                     



















                                                     
                     
 
                              
















                                                                       
                       

                    
                       
 
                                     


                  
                 



















                                                 
                 
 
                          
 

                       




















































































                                                                           

/*
 * Copyright (C) Igor Sysoev
 * Copyright (C) NGINX, Inc.
 */

#include <nxt_main.h>


/*
 * nxt_int_parse() returns size_t value >= 0 on success,
 * -1 on failure, and -2 on overflow.
 */

nxt_int_t
nxt_int_parse(const u_char *p, size_t length)
{
    u_char      c;
    nxt_uint_t  val;

    if (nxt_fast_path(length != 0)) {

        val = 0;

        do {
            c = *p++;

            /* Values below '0' become >= 208. */
            c = c - '0';

            if (nxt_slow_path(c > 9)) {
                return -1;
            }

            val = val * 10 + c;

            if (nxt_slow_path((nxt_int_t) val < 0)) {
                /* An overflow. */
                return -2;
            }

            length--;

        } while (length != 0);

        return val;
    }

    return -1;
}


/*
 * nxt_size_t_parse() returns size_t value >= 0 on success,
 * -1 on failure, and -2 on overflow.
 */

ssize_t
nxt_size_t_parse(const u_char *p, size_t length)
{
    u_char  c;
    size_t  val;

    if (nxt_fast_path(length != 0)) {

        val = 0;

        do {
            c = *p++;

            /* Values below '0' become >= 208. */
            c = c - '0';

            if (nxt_slow_path(c > 9)) {
                return -1;
            }

            val = val * 10 + c;

            if (nxt_slow_path((ssize_t) val < 0)) {
                /* An overflow. */
                return -2;
            }

            length--;

        } while (length != 0);

        return val;
    }

    return -1;
}


/*
 * nxt_size_parse() parses size string with optional K or M units and
 * returns size_t value >= 0 on success, -1 on failure, and -2 on overflow.
 */

ssize_t
nxt_size_parse(const u_char *p, size_t length)
{
    u_char      c, unit;
    size_t      val, max;
    nxt_uint_t  shift;

    if (nxt_fast_path(length != 0)) {

        length--;

        /* Upper case. */
        unit = p[length] & ~0x20;

        switch (unit) {

        case 'G':
            max = NXT_SIZE_T_MAX >> 30;
            shift = 30;
            break;

        case 'M':
            max = NXT_SIZE_T_MAX >> 20;
            shift = 20;
            break;

        case 'K':
            max = NXT_SIZE_T_MAX >> 10;
            shift = 10;
            break;

        default:
            max = NXT_SIZE_T_MAX;
            shift = 0;
            length++;
            break;
        }

        if (nxt_fast_path(length != 0)) {

            val = 0;

            do {
                c = *p++;

                /* Values below '0' become >= 208. */
                c = c - '0';

                if (nxt_slow_path(c > 9)) {
                    return -1;
                }

                val = val * 10 + c;

                if (nxt_slow_path(val > max)) {
                    /* An overflow. */
                    return -2;
                }

                length--;

            } while (length != 0);

            return val << shift;
        }
    }

    return -1;
}


/*
 * nxt_off_t_parse() returns nxt_off_t value >= 0 on success,
 * -1 on failure, and -2 on overflow.
 */

nxt_off_t
nxt_off_t_parse(const u_char *p, size_t length)
{
    u_char      c;
    nxt_uoff_t  val;

    if (nxt_fast_path(length != 0)) {

        val = 0;

        do {
            c = *p++;

            /* Values below '0' become >= 208. */
            c = c - '0';

            if (nxt_slow_path(c > 9)) {
                return -1;
            }

            val = val * 10 + c;

            if (nxt_slow_path((nxt_off_t) val < 0)) {
                /* An overflow. */
                return -2;
            }

            length--;

        } while (length != 0);

        return val;
    }

    return -1;
}


/*
 * nxt_str_int_parse() returns nxt_int_t value >= 0 on success,
 * -1 on failure, and -2 on overflow and also updates the 's' argument.
 */

nxt_int_t
nxt_str_int_parse(nxt_str_t *s)
{
    u_char      c, *p;
    size_t      length;
    nxt_uint_t  val;

    length = s->length;

    if (nxt_slow_path(length == 0)) {
        return -1;
    }

    p = s->start;
    val = 0;

    do {
        c = *p;

        /* Values below '0' become >= 208. */
        c = c - '0';

        if (c > 9) {
            break;
        }

        val = val * 10 + c;

        if (nxt_slow_path((nxt_int_t) val < 0)) {
            /* An overflow. */
            return -2;
        }

        p++;
        length--;

    } while (length != 0);

    s->length = length;
    s->start = p;

    return val;
}


/*
 * nxt_number_parse() returns a double value >= 0 and updates the start
 * argument on success, or returns -1 on failure or -2 on overflow.
 */

double
nxt_number_parse(const u_char **start, const u_char *end)
{
    u_char        c;
    nxt_uint_t    integral, frac, power;
    const u_char  *p;

    p = *start;
    integral = 0;

    while (p < end) {
        c = *p;

        if (c == '.') {
            goto dot;
        }

        /* Values below '0' become >= 208. */
        c = c - '0';

        if (c > 9) {
            break;
        }

        integral = integral * 10 + c;

        if (nxt_slow_path((nxt_int_t) integral < 0)) {
            /* An overflow. */
            return -2;
        }

        p++;
    }

    if (nxt_fast_path(p != *start)) {
        *start = p;
        return integral;
    }

    /* No value. */
    return -1;

dot:

    if (nxt_slow_path(p == *start)) {
        /* No leading digit before dot. */
        return -1;
    }

    frac = 0;
    power = 1;

    for (p++; p < end; p++) {
        c = *p;

        /* Values below '0' become >= 208. */
        c = c - '0';

        if (c > 9) {
            break;
        }

        frac = frac * 10 + c;
        power *= 10;

        if (nxt_slow_path((nxt_int_t) frac < 0 || (nxt_int_t) power < 0)) {
            /* An overflow. */
            return -2;
        }
    }

    *start = p;

    return integral + (double) frac / power;
}