Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

wsp_strings.c

Go to the documentation of this file.
00001 /* ==================================================================== 
00002  * The Kannel Software License, Version 1.0 
00003  * 
00004  * Copyright (c) 2001-2008 Kannel Group  
00005  * Copyright (c) 1998-2001 WapIT Ltd.   
00006  * All rights reserved. 
00007  * 
00008  * Redistribution and use in source and binary forms, with or without 
00009  * modification, are permitted provided that the following conditions 
00010  * are met: 
00011  * 
00012  * 1. Redistributions of source code must retain the above copyright 
00013  *    notice, this list of conditions and the following disclaimer. 
00014  * 
00015  * 2. Redistributions in binary form must reproduce the above copyright 
00016  *    notice, this list of conditions and the following disclaimer in 
00017  *    the documentation and/or other materials provided with the 
00018  *    distribution. 
00019  * 
00020  * 3. The end-user documentation included with the redistribution, 
00021  *    if any, must include the following acknowledgment: 
00022  *       "This product includes software developed by the 
00023  *        Kannel Group (http://www.kannel.org/)." 
00024  *    Alternately, this acknowledgment may appear in the software itself, 
00025  *    if and wherever such third-party acknowledgments normally appear. 
00026  * 
00027  * 4. The names "Kannel" and "Kannel Group" must not be used to 
00028  *    endorse or promote products derived from this software without 
00029  *    prior written permission. For written permission, please  
00030  *    contact org@kannel.org. 
00031  * 
00032  * 5. Products derived from this software may not be called "Kannel", 
00033  *    nor may "Kannel" appear in their name, without prior written 
00034  *    permission of the Kannel Group. 
00035  * 
00036  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 
00037  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
00038  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
00039  * DISCLAIMED.  IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS 
00040  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,  
00041  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  
00042  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR  
00043  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
00044  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE  
00045  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,  
00046  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
00047  * ==================================================================== 
00048  * 
00049  * This software consists of voluntary contributions made by many 
00050  * individuals on behalf of the Kannel Group.  For more information on  
00051  * the Kannel Group, please see <http://www.kannel.org/>. 
00052  * 
00053  * Portions of this software are based upon software originally written at  
00054  * WapIT Ltd., Helsinki, Finland for the Kannel project.  
00055  */ 
00056 
00057 /* wsp_strings.c: lookup code for various tables defined by WSP standard
00058  *
00059  * This file provides functions to translate strings to numbers and numbers
00060  * to strings according to the Assigned Numbers tables in appendix A
00061  * of the WSP specification.
00062  *
00063  * The tables are in wsp_strings.def, in a special format suitable for
00064  * use with the C preprocessor, which we abuse liberally to get the
00065  * interface we want. 
00066  *
00067  * Richard Braakman
00068  */
00069 
00070 #include "gwlib/gwlib.h"
00071 #include "wsp_strings.h"
00072 
00073 #define TABLE_SIZE(table) ((long)(sizeof(table) / sizeof(table[0])))
00074 
00075 static int initialized;
00076 
00077 /* The arrays in a table structure are all of equal length, and their
00078  * elements correspond.  The number for string 0 is in numbers[0], etc.
00079  * Table structures are initialized dynamically.
00080  */
00081 struct table
00082 {
00083     long size;          /* Nr of entries in each of the tables below */
00084     Octstr **strings;   /* Immutable octstrs */
00085     long *numbers;      /* Assigned numbers, or NULL for linear tables */
00086     int *versions;      /* WSP Encoding-versions, or NULL if non-versioned */
00087     int linear;         /* True for tables defined as LINEAR */
00088 };
00089 
00090 struct numbered_element
00091 {
00092     char *str;
00093     long number;
00094     int version;    
00095 };
00096 
00097 struct linear_element
00098 {
00099     char *str;
00100     int version;    
00101 };
00102 
00103 /* Local functions */
00104 static Octstr *number_to_string(long number, struct table *table);
00105 static unsigned char *number_to_cstr(long number, struct table *table);
00106 static long string_to_number(Octstr *ostr, struct table *table);
00107 static long string_to_versioned_number(Octstr *ostr, struct table *table, int version);
00108 
00109 
00110 /* Declare the data.  For each table "foo", create a foo_strings array
00111  * to hold the data, and a (still empty) foo_table structure. */
00112 #define LINEAR(name, strings) \
00113     static const struct linear_element name##_strings[] = { strings }; \
00114     static struct table name##_table;
00115 #define STRING(string) { string, 0 },
00116 #define VSTRING(version, string) { string, version }, 
00117 #define NUMBERED(name, strings) \
00118     static const struct numbered_element name##_strings[] = { strings }; \
00119     static struct table name##_table;
00120 #define ASSIGN(string, number) { string, number, 0 },
00121 #define VASSIGN(version, string, number) { string, number, version },
00122 #include "wsp_strings.def"
00123 
00124 /* Define the functions for translating number to Octstr */
00125 #define LINEAR(name, strings) \
00126 Octstr *wsp_##name##_to_string(long number) { \
00127     return number_to_string(number, &name##_table); \
00128 }
00129 #include "wsp_strings.def"
00130 
00131 /* Define the functions for translating number to constant string */
00132 #define LINEAR(name, strings) \
00133 unsigned char *wsp_##name##_to_cstr(long number) { \
00134     return number_to_cstr(number, &name##_table); \
00135 }
00136 #include "wsp_strings.def"
00137 
00138 #define LINEAR(name, strings) \
00139 long wsp_string_to_##name(Octstr *ostr) { \
00140      return string_to_number(ostr, &name##_table); \
00141 }
00142 #include "wsp_strings.def"
00143 
00144 #define LINEAR(name, strings) \
00145 long wsp_string_to_versioned_##name(Octstr *ostr, int version) { \
00146      return string_to_versioned_number(ostr, &name##_table, version); \
00147 }
00148 #include "wsp_strings.def"
00149 
00150 static Octstr *number_to_string(long number, struct table *table)
00151 {
00152     long i;
00153 
00154     gw_assert(initialized);
00155 
00156     if (table->linear) {
00157         if (number >= 0 && number < table->size)
00158             return octstr_duplicate(table->strings[number]);
00159     } else {
00160         for (i = 0; i < table->size; i++) {
00161             if (table->numbers[i] == number)
00162                 return octstr_duplicate(table->strings[i]);
00163         }
00164     }
00165     return NULL;
00166 }
00167 
00168 static unsigned char *number_to_cstr(long number, struct table *table)
00169 {
00170     long i;
00171 
00172     gw_assert(initialized);
00173 
00174     if (table->linear) {
00175     if (number >= 0 && number < table->size)
00176         return (unsigned char *)octstr_get_cstr(table->strings[number]);
00177     } else {
00178     for (i = 0; i < table->size; i++) {
00179          if (table->numbers[i] == number)
00180         return (unsigned char *)octstr_get_cstr(table->strings[i]);
00181     }
00182     }
00183     return NULL;
00184 }
00185 
00186 /* Case-insensitive string lookup */
00187 static long string_to_number(Octstr *ostr, struct table *table)
00188 {
00189     long i;
00190 
00191     gw_assert(initialized);
00192 
00193     for (i = 0; i < table->size; i++) {
00194     if (octstr_case_compare(ostr, table->strings[i]) == 0) {
00195         return table->linear ? i : table->numbers[i];
00196     }
00197     }
00198 
00199     return -1;
00200 }
00201 
00202 /* Case-insensitive string lookup according to passed WSP encoding version */
00203 static long string_to_versioned_number(Octstr *ostr, struct table *table, 
00204                                        int version)
00205 {
00206     long i, ret;
00207 
00208     gw_assert(initialized);
00209 
00210     /* walk the whole table and pick the highest versioned token */
00211     ret = -1;
00212     for (i = 0; i < table->size; i++) {
00213         if (octstr_case_compare(ostr, table->strings[i]) == 0 &&
00214             table->versions[i] <= version) {
00215                 ret = table->linear ? i : table->numbers[i];
00216         }
00217     }
00218 
00219     debug("wsp.strings",0,"WSP: Mapping `%s', WSP 1.%d to 0x%04lx.", 
00220           octstr_get_cstr(ostr), version, ret);
00221 
00222     return ret;
00223 }
00224 
00225 static void construct_linear_table(struct table *table, const struct linear_element *strings, 
00226                                    long size)
00227 {
00228     long i;
00229 
00230     table->size = size;
00231     table->strings = gw_malloc(size * (sizeof table->strings[0]));
00232     table->numbers = NULL;
00233     table->versions = gw_malloc(size * (sizeof table->versions[0]));
00234     table->linear = 1;
00235 
00236     for (i = 0; i < size; i++) {
00237         table->strings[i] = octstr_imm(strings[i].str);
00238         table->versions[i] = strings[i].version;
00239     }
00240 }
00241 
00242 static void construct_numbered_table(struct table *table, const struct numbered_element *strings, 
00243                                      long size)
00244 {
00245     long i;
00246 
00247     table->size = size;
00248     table->strings = gw_malloc(size * (sizeof table->strings[0]));
00249     table->numbers = gw_malloc(size * (sizeof table->numbers[0]));
00250     table->versions = gw_malloc(size * (sizeof table->versions[0]));
00251     table->linear = 0;
00252 
00253     for (i = 0; i < size; i++) {
00254         table->strings[i] = octstr_imm(strings[i].str);
00255         table->numbers[i] = strings[i].number;
00256         table->versions[i] = strings[i].version;
00257     }
00258 }
00259 
00260 static void destroy_table(struct table *table)
00261 {
00262     /* No need to call octstr_destroy on immutable octstrs */
00263 
00264     gw_free(table->strings);
00265     gw_free(table->numbers);
00266     gw_free(table->versions);
00267 }
00268 
00269 void wsp_strings_init(void)
00270 {
00271     if (initialized > 0) {
00272          initialized++;
00273          return;
00274     }
00275 
00276 #define LINEAR(name, strings) \
00277     construct_linear_table(&name##_table, \
00278         name##_strings, TABLE_SIZE(name##_strings));
00279 #define NUMBERED(name, strings) \
00280     construct_numbered_table(&name##_table, \
00281             name##_strings, TABLE_SIZE(name##_strings));
00282 #include "wsp_strings.def"
00283     initialized++;
00284 }
00285 
00286 void wsp_strings_shutdown(void)
00287 {
00288     /* If we were initialized more than once, then wait for more than
00289      * one shutdown. */
00290     if (initialized > 1) {
00291         initialized--;
00292         return;
00293     }
00294 
00295 #define LINEAR(name, strings) \
00296     destroy_table(&name##_table);
00297 #include "wsp_strings.def"
00298 
00299     initialized = 0;
00300 }
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.