octstr.c

来自「The Kannel Open Source WAP and SMS gatew」· C语言 代码 · 共 2,586 行 · 第 1/5 页

C
2,586
字号
    if (pos < octstr_len(os))    	list_append(list, octstr_copy(os, pos, octstr_len(os)));        return list;}int octstr_item_match(void *item, void *pattern){    return octstr_compare(item, pattern) == 0;}int octstr_item_case_match(void *item, void *pattern){    return octstr_case_compare(item, pattern) == 0;}void octstr_dump(const Octstr *ostr, int level){    unsigned char *p, *d, buf[1024], charbuf[256];    long pos;    const int octets_per_line = 16;    int c, this_line_begins_at;    if (ostr == NULL)        return;    seems_valid(ostr);    debug("gwlib.octstr", 0, "%*sOctet string at %p:", level, "",          (void *) ostr);    debug("gwlib.octstr", 0, "%*s  len:  %lu", level, "",          (unsigned long) ostr->len);    debug("gwlib.octstr", 0, "%*s  size: %lu", level, "",          (unsigned long) ostr->size);    debug("gwlib.octstr", 0, "%*s  immutable: %d", level, "",          ostr->immutable);    buf[0] = '\0';    p = buf;    d = charbuf;    this_line_begins_at = 0;    for (pos = 0; pos < octstr_len(ostr); ) {        c = octstr_get_char(ostr, pos);        sprintf(p, "%02x ", c);        p = strchr(p, '\0');        if (isprint(c))            *d++ = c;        else            *d++ = '.';        ++pos;        if (pos - this_line_begins_at == octets_per_line) {            *d = '\0';            debug("gwlib.octstr", 0, "%*s  data: %s  %s", level, "",                  buf, charbuf);            buf[0] = '\0';            charbuf[0] = '\0';            p = buf;            d = charbuf;            this_line_begins_at = pos;        }    }    if (pos - this_line_begins_at > 0) {        *d = '\0';        debug("gwlib.octstr", 0, "%*s  data: %-*.*s  %s", level, "",              octets_per_line*3,              octets_per_line*3, buf, charbuf);    }    debug("gwlib.octstr", 0, "%*sOctet string dump ends.", level, "");}void octstr_dump_short(Octstr *ostr, int level, const char *name){    char buf[100];    char *p;    long i;    int c;    if (ostr == NULL) {        debug("gwlib.octstr", 0, "%*s%s: NULL", level, "", name);        return;    }    seems_valid(ostr);    if (ostr->len < 20) {        p = buf;        for (i = 0; i < ostr->len; i++) {            c = ostr->data[i];            if (c == '\n') {                *p++ = '\\';                *p++ = 'n';            } else if (!isprint(c)) {                break;            } else if (c == '"') {                *p++ = '\\';                *p++ = '"';            } else if (c == '\\') {                *p++ = '\\';                *p++ = '\\';            } else {                *p++ = c;            }        }        if (i == ostr->len) {            *p++ = 0;            /* We got through the loop without hitting nonprintable             * characters. */            debug("gwlib.octstr", 0, "%*s%s: \"%s\"", level, "", name, buf);            return;        }    }    debug("gwlib.octstr", 0, "%*s%s:", level, "", name);    octstr_dump(ostr, level + 1);}void octstr_url_encode(Octstr *ostr){    long i, n, len = 0;    int all_safe;    unsigned char c, *str, *str2, *res, *hexits;    if (ostr == NULL)        return;    seems_valid(ostr);    gw_assert(!ostr->immutable);    if (ostr->len == 0)        return;    /* calculate new length */    for (i = n = 0, str = ostr->data, all_safe = 1; i < ostr->len; i++) {        c = *str++;	        if (c == ' ') {            all_safe = 0;            continue;        }        if (!is_safe[c]) {	    n++;            all_safe = 0;        }     }    if (all_safe) /* we are done, all chars are safe */       return;    hexits = "0123456789ABCDEF";    /*     * no need to reallocate if n == 0, so we make replace in place.     * NOTE: we don't do if (xxx) ... else ... because conditional jump     * is not so fast as just compare (alex).     */    res = str2 = (n ? gw_malloc((len = ostr->len + 2 * n + 1)) : ostr->data);    for (i = 0, str = ostr->data; i < ostr->len; i++) {        c = *str++;        if (c == ' ') {            *str2++ = '+';            continue;        }        if (!is_safe[c]) {            *str2++ = '%';            *str2++ = hexits[c >> 4 & 0xf];            *str2++ = hexits[c & 0xf];            continue;        }        *str2++ = c;    }    *str2 = 0;        /* we made replace in place */    if (n) {        gw_free(ostr->data);        ostr->data = res;        ostr->size = len;        ostr->len = len - 1;    }    seems_valid(ostr);}int octstr_url_decode(Octstr *ostr){    unsigned char *string = ostr->data;    unsigned char *dptr = ostr->data;    int code, code2, ret = 0;    if (ostr == NULL)        return 0;    seems_valid(ostr);    gw_assert(!ostr->immutable);    if (ostr->len == 0)        return 0;    do {        if (*string == '%') {            if (*(string + 1) == '\0' || *(string + 2) == '\0') {                warning(0, "octstr_url_decode: corrupted end-of-string <%s>", string);                ret = -1;                break;            }            code = H2B(*(string + 1));            code2 = H2B(*(string + 2));            if (code == -1 || code2 == -1) {                warning(0, "octstr_url_decode: garbage detected (%c%c%c) skipping.",                            *string, *(string + 1), *(string + 2));                *dptr++ = *string++;                *dptr++ = *string++;                *dptr++ = *string++;                ret = -1;                continue;            }            *dptr++ = code << 4 | code2;            string += 3;        }        else if (*string == '+') {            *dptr++ = ' ';            string++;        } else            *dptr++ = *string++;    } while (*string); 	/* we stop here because it terimates encoded string */    *dptr = '\0';    ostr->len = (dptr - ostr->data);    seems_valid(ostr);    return ret;}long octstr_get_bits(Octstr *ostr, long bitpos, int numbits){    long pos;    long result;    int mask;    int shiftwidth;    seems_valid(ostr);    gw_assert(bitpos >= 0);    gw_assert(numbits <= 32);    gw_assert(numbits >= 0);    pos = bitpos / 8;    bitpos = bitpos % 8;    /* This also takes care of the len == 0 case */    if (pos >= ostr->len)        return 0;    mask = (1 << numbits) - 1;    /* It's easy if the range fits in one octet */    if (bitpos + numbits <= 8) {        /* shiftwidth is the number of bits to ignore on the right.         * bitpos 0 is the leftmost bit. */        shiftwidth = 8 - (bitpos + numbits);        return (ostr->data[pos] >> shiftwidth) & mask;    }    /* Otherwise... */    result = 0;    while (bitpos + numbits > 8) {        result = (result << 8) | ostr->data[pos];        numbits -= (8 - bitpos);        bitpos = 0;        pos++;        if (pos >= ostr->len)            return (result << numbits) & mask;    }    gw_assert(bitpos == 0);    result <<= numbits;    result |= ostr->data[pos] >> (8 - numbits);    return result & mask;}void octstr_set_bits(Octstr *ostr, long bitpos, int numbits,                     unsigned long value){    long pos;    unsigned long mask;    int shiftwidth;    int bits;    int maxlen;    int c;    seems_valid(ostr);    gw_assert(!ostr->immutable);    gw_assert(bitpos >= 0);    gw_assert(numbits <= 32);    gw_assert(numbits >= 0);    maxlen = (bitpos + numbits + 7) / 8;    if (maxlen > ostr->len) {        octstr_grow(ostr, maxlen);        /* Make sure the new octets start out with value 0 */        for (pos = ostr->len; pos < maxlen; pos++) {            ostr->data[pos] = 0;        }        ostr->len = maxlen;        ostr->data[maxlen] = 0;    }    mask = (1 << numbits) - 1;    /* mask is also the largest value that fits */    gw_assert(value <= mask);    pos = bitpos / 8;    bitpos = bitpos % 8;    /* Does the range fit in one octet? */    if (bitpos + numbits <= 8) {        /* shiftwidth is the number of bits to ignore on the right.         * bitpos 0 is the leftmost bit. */        shiftwidth = 8 - (bitpos + numbits);        /* Extract the bits we don't want to affect */        c = ostr->data[pos] & ~(mask << shiftwidth);        c |= value << shiftwidth;        gw_assert(pos < ostr->len);        ostr->data[pos] = c;        return;    }    /* Otherwise... */    /* If speed is a problem here, we could have separate cases for     * the first octet (which may have bitpos > 0), and the rest,     * which don't. */    while (bitpos + numbits > 8) {        /* We want this many bits from the value */        bits = 8 - bitpos;        /* There are this many bits to their right in the value */        shiftwidth = numbits - bits;        /* Construct a mask for "bits" bits on the far right */        mask = (1 << bits) - 1;        /* Get the bits we want */        c = (value >> shiftwidth) & mask;        /* Merge them with the bits that are already there */        gw_assert(pos < ostr->len);        ostr->data[pos] = (ostr->data[pos] & ~mask) | c;        numbits -= (8 - bitpos);        bitpos = 0;        pos++;    }    gw_assert(bitpos == 0);    gw_assert(pos < ostr->len);    /* Set remaining bits.  This is just like the single-octet case     * before the loop, except that we know bitpos is 0. */    mask = (1 << numbits) - 1;    shiftwidth = 8 - numbits;    c = ostr->data[pos] & ~(mask << shiftwidth);    c |= value << shiftwidth;    ostr->data[pos] = c;    seems_valid(ostr);}void octstr_append_uintvar(Octstr *ostr, unsigned long value){    /* A uintvar is defined to be up to 32 bits large, so it will     * fit in 5 octets. */    unsigned char octets[5];    int i;    int start;    /* Handle last byte separately; it has no continuation bit,     * and must be encoded even if value is 0. */    octets[4] = value & 0x7f;    value >>= 7;    for (i = 3; value > 0 && i >= 0; i--) {        octets[i] = 0x80 | (value & 0x7f);        value >>= 7;    }    start = i + 1;    octstr_append_data(ostr, octets + start, 5 - start);}long octstr_extract_uintvar(Octstr *ostr, unsigned long *value, long pos){    int c;    int count;    unsigned long ui;    ui = 0;    for (count = 0; count < 5; count++) {        c = octstr_get_char(ostr, pos + count);        if (c < 0)            return -1;        ui = (ui << 7) | (c & 0x7f);        if (!(c & 0x80)) {            *value = ui;            return pos + count + 1;        }    }    return -1;}void octstr_append_decimal(Octstr *ostr, long value){    char tmp[128];    sprintf(tmp, "%ld", value);    octstr_append_cstr(ostr, tmp);}/********************************************************************** * octstr_format and related private functions *//* * A parsed form of the format string. This struct has been carefully * defined so that it can be initialized with {0} and it will have  * the correct defaults. */struct format{    int minus;    int zero;    long min_width;    int has_prec;    long prec;    long type;};static void format_flags(struct format *format, const char **fmt){    int done;    done = 0;    do    {        switch (**fmt) {        case '-':            format->minus = 1;            break;        case '0':            format->zero = 1;            break;        default:            done = 1;        }        if (!done)            ++(*fmt);    } while (!done);}static void format_width(struct format *format, const char **fmt,                         VALPARM(args)){    char *end;    if (**fmt == '*')    {        format->min_width = va_arg(VALST(args), int);        ++(*fmt);    } else if (isdigit(**(const unsigned char **) fmt))    {        format->min_width = strtol(*fmt, &end, 10);        *fmt = end;        /* XXX error checking is missing from here */    }}static void format_prec(struct format *format, const char **fmt,                        VALPARM(args)){    char *end;    if (**fmt != '.')        return;    ++(*fmt);    if (**fmt == '*')    {        format->has_prec = 1;        format->prec = va_arg(VALST(args), int);        ++(*fmt);    } else if (isdigit(**(const unsigned char **) fmt))    {        format->has_prec = 1;        format->prec = strtol(*fmt, &end, 10);        *fmt = end;        /* XXX error checking is missing from here */    }}

⌨️ 快捷键说明

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