octstr.c
来自「The Kannel Open Source WAP and SMS gatew」· C语言 代码 · 共 2,586 行 · 第 1/5 页
C
2,586 行
/* ==================================================================== * The Kannel Software License, Version 1.0 * * Copyright (c) 2001-2004 Kannel Group * Copyright (c) 1998-2001 WapIT Ltd. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Kannel Group (http://www.kannel.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Kannel" and "Kannel Group" must not be used to * endorse or promote products derived from this software without * prior written permission. For written permission, please * contact org@kannel.org. * * 5. Products derived from this software may not be called "Kannel", * nor may "Kannel" appear in their name, without prior written * permission of the Kannel Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Kannel Group. For more information on * the Kannel Group, please see <http://www.kannel.org/>. * * Portions of this software are based upon software originally written at * WapIT Ltd., Helsinki, Finland for the Kannel project. */ /* * octstr.c - implementation of Octet strings * * See octstr.h for explanations of what public functions should do. * * Lars Wirzenius */#include <ctype.h>#include <limits.h>#include <errno.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include "gwlib.h"/* * Unfortunately some platforms base va_list an an array type * which makes passing of the &args a bit tricky */#if defined(__linux__) && (defined(__powerpc__) || defined(__s390__))#define VARGS(x) (x)#define VALPARM(y) va_list y#define VALST(z) (z)#else#define VARGS(x) (&x)#define VALPARM(y) va_list *y#define VALST(z) (*z)#endif/*********************************************************************** * Definitions of data structures. These are not visible to the external * world -- they may be accessed only via the functions declared in * octstr.h. This ensures they really are abstract. *//* * The octet string. * * `data' is a pointer to dynamically allocated memory are where the * octets in the string. It may be bigger than the actual length of the * string. * * `len' is the length of the string. * * `size' is the size of the memory area `data' points at. * * When `size' is greater than zero, it is at least `len+1', and the * character at `len' is '\0'. This is so that octstr_get_cstr will * always work. * * `immutable' defines whether the octet string is immutable or not. */struct Octstr{ unsigned char *data; long len; long size; int immutable;};/********************************************************************** * Hash table of immutable octet strings. */#define MAX_IMMUTABLES 1024static Octstr *immutables[MAX_IMMUTABLES];static Mutex immutables_mutex;static int immutables_init = 0;static char is_safe[UCHAR_MAX + 1];/* * Convert a pointer to a C string literal to a long that can be used * for hashing. This is done by converting the pointer into an integer * and discarding the lowest to bits to get rid of typical alignment * bits. */#define CSTR_TO_LONG(ptr) (((long) ptr) >> 2)/* * HEX to ASCII preprocessor macro */#define H2B(a) (a >= '0' && a <= '9' ? \ a - '0' : (a >= 'a' && a <= 'f' ? \ a - 'a' + 10 : (a >= 'A' && a <= 'F' ? a - 'A' + 10 : -1) \ ) \ )/*********************************************************************** * Declarations of internal functions. These are defined at the end of * the file. */static void seems_valid_real(const Octstr *ostr, const char *filename, long lineno, const char *function);#ifdef NO_GWASSERT#define seems_valid(ostr)#else#define seems_valid(ostr) \ (seems_valid_real(ostr, __FILE__, __LINE__, __func__))#endif/*********************************************************************** * Implementations of the functions declared in octstr.h. See the * header for explanations of what they should do. *//* Reserve space for at least 'size' octets */static void octstr_grow(Octstr *ostr, long size){ gw_assert(!ostr->immutable); seems_valid(ostr); gw_assert(size >= 0); size++; /* make room for the invisible terminating NUL */ if (size > ostr->size) { /* always reallocate in 1kB chunks */ size += 1024 - (size % 1024); ostr->data = gw_realloc(ostr->data, size); ostr->size = size; }}/* * Fill is_safe table. is_safe[c] means that c can be left as such when * url-encoded. * RFC 2396 defines the list of characters that need to be encoded. * Space is treated as an exception by the encoding routine; * it's listed as safe here, but is actually changed to '+'. */static void urlcode_init(void){ int i; unsigned char *safe = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz-_.!~*'()"; for (i = 0; safe[i] != '\0'; ++i) is_safe[safe[i]] = 1;}void octstr_init(void){ urlcode_init(); mutex_init_static(&immutables_mutex); immutables_init = 1;}void octstr_shutdown(void){ long i, n; n = 0; for (i = 0; i < MAX_IMMUTABLES; ++i) { if (immutables[i] != NULL) { gw_free(immutables[i]); ++n; } } if(n>0) debug("gwlib.octstr", 0, "Immutable octet strings: %ld.", n); mutex_destroy(&immutables_mutex);}Octstr *octstr_create_real(const char *cstr, const char *file, long line, const char *func){ gw_assert(cstr != NULL); return octstr_create_from_data_trace(cstr, strlen(cstr), file, line, func);}Octstr *octstr_create_from_data_real(const char *data, long len, const char *file, long line, const char *func){ Octstr *ostr; gw_assert(len >= 0); if (data == NULL) gw_assert(len == 0); ostr = gw_malloc_trace(sizeof(*ostr), file, line, func); if (len == 0) { ostr->len = 0; ostr->size = 0; ostr->data = NULL; } else { ostr->len = len; ostr->size = len + 1; ostr->data = gw_malloc_trace(ostr->size, file, line, func); memcpy(ostr->data, data, len); ostr->data[len] = '\0'; } ostr->immutable = 0; seems_valid(ostr); return ostr;}Octstr *octstr_imm(const char *cstr){ Octstr *os; long i, index; unsigned char *data; gw_assert(immutables_init); gw_assert(cstr != NULL); index = CSTR_TO_LONG(cstr) % MAX_IMMUTABLES; data = (unsigned char *) cstr; mutex_lock(&immutables_mutex); i = index; for (; ; ) { if (immutables[i] == NULL || immutables[i]->data == data) break; i = (i + 1) % MAX_IMMUTABLES; if (i == index) panic(0, "Too many immutable strings."); } os = immutables[i]; if (os == NULL) { /* * Can't use octstr_create() because it copies the string, * which would break our hashing. */ os = gw_malloc(sizeof(*os)); os->data = data; os->len = strlen(data); os->size = os->len + 1; os->immutable = 1; immutables[i] = os; seems_valid(os); } mutex_unlock(&immutables_mutex); return os;}void octstr_destroy(Octstr *ostr){ if (ostr != NULL) { seems_valid(ostr); if (!ostr->immutable) { gw_free(ostr->data); gw_free(ostr); } }}void octstr_destroy_item(void *os){ octstr_destroy(os);}long octstr_len(const Octstr *ostr){ if (ostr == NULL) return 0; seems_valid(ostr); return ostr->len;}Octstr *octstr_copy_real(const Octstr *ostr, long from, long len, const char *file, long line, const char *func){ seems_valid(ostr); gw_assert(from >= 0); gw_assert(len >= 0); if (from >= ostr->len) return octstr_create(""); if (len > ostr->len - from) len = ostr->len - from; return octstr_create_from_data_trace(ostr->data + from, len, file, line, func);}Octstr *octstr_duplicate_real(const Octstr *ostr, const char *file, long line, const char *func){ if (ostr == NULL) return NULL; seems_valid(ostr); return octstr_create_from_data_trace(ostr->data, ostr->len, file, line, func);}Octstr *octstr_cat(Octstr *ostr1, Octstr *ostr2){ Octstr *ostr; seems_valid(ostr1); seems_valid(ostr2); gw_assert(!ostr1->immutable); ostr = octstr_create(""); ostr->len = ostr1->len + ostr2->len; ostr->size = ostr->len + 1; ostr->data = gw_malloc(ostr->size); if (ostr1->len > 0) memcpy(ostr->data, ostr1->data, ostr1->len); if (ostr2->len > 0) memcpy(ostr->data + ostr1->len, ostr2->data, ostr2->len); ostr->data[ostr->len] = '\0'; seems_valid(ostr); return ostr;}int octstr_get_char(const Octstr *ostr, long pos){ seems_valid(ostr); if (pos >= ostr->len || pos < 0) return -1; return ostr->data[pos];}void octstr_set_char(Octstr *ostr, long pos, int ch){ seems_valid(ostr); gw_assert(!ostr->immutable); if (pos < ostr->len) ostr->data[pos] = ch; seems_valid(ostr);}void octstr_get_many_chars(char *buf, Octstr *ostr, long pos, long len){ gw_assert(buf != NULL); seems_valid(ostr); if (pos >= ostr->len) return; if (pos + len > ostr->len) len = ostr->len - pos; if (len > 0) memcpy(buf, ostr->data + pos, len);}char *octstr_get_cstr_real(const Octstr *ostr, const char *file, long line, const char *func){ if (!ostr) return "(null)"; seems_valid_real(ostr, file, line, func); if (ostr->len == 0) return ""; return ostr->data;}void octstr_append_from_hex(Octstr *ostr, char *hex){ Octstr *output; seems_valid(ostr); gw_assert(!ostr->immutable); output = octstr_create(hex); octstr_hex_to_binary(output); octstr_append(ostr, output); octstr_destroy(output);}void octstr_binary_to_hex(Octstr *ostr, int uppercase){ unsigned char *hexits; long i, tmp; seems_valid(ostr); gw_assert(!ostr->immutable); if (ostr->len == 0) return; hexits = uppercase ? "0123456789ABCDEF" : "0123456789abcdef"; octstr_grow(ostr, ostr->len * 2); /* In-place modification must be done back-to-front to avoid * overwriting the data while we read it. Even the order of * the two assignments is important, to get i == 0 right. */ for (i = ostr->len - 1; i >= 0; i--) { tmp = i << 1; /* tmp = i * 2; */ ostr->data[tmp + 1] = hexits[ostr->data[i] & 0xf]; ostr->data[tmp] = hexits[ostr->data[i] >> 4]; } ostr->len = ostr->len * 2; ostr->data[ostr->len] = '\0'; seems_valid(ostr);}int octstr_hex_to_binary(Octstr *ostr){ long len, i; unsigned char *p; seems_valid(ostr); gw_assert(!ostr->immutable); if (ostr->len == 0) return 0; /* Check if it's in the right format */ if (!octstr_check_range(ostr, 0, ostr->len, gw_isxdigit)) return -1; len = ostr->len; /* Convert ascii data to binary values */ for (i = 0, p = ostr->data; i < len; i++, p++) { if (*p >= '0' && *p <= '9') *p -= '0'; else if (*p >= 'a' && *p <= 'f') *p = *p - 'a' + 10; else if (*p >= 'A' && *p <= 'F') *p = *p - 'A' + 10; else { /* isxdigit checked the whole string, so we should * not be able to get here. */ gw_assert(0); *p = 0; } } /* De-hexing will compress data by factor of 2 */ len = ostr->len / 2; for (i = 0; i < len; i++) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?