Main Page   Modules   Compound List   File List   Compound Members   File Members   Related Pages  

wbxml_buffers.c

Go to the documentation of this file.
00001 /*
00002  * WBXML Lib, the WBXML Library.
00003  * Copyright (C) 2002-2003  Aymerick Jéhanne
00004  * 
00005  * This library is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Lesser General Public
00007  * License (version 2.1) as published by the Free Software Foundation.
00008  * 
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Lesser General Public License for more details.
00013  * 
00014  * You should have received a copy of the GNU Lesser General Public
00015  * License along with this library; if not, write to the Free Software
00016  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017  *
00018  * LGPL v2.1: http://www.gnu.org/licenses/lgpl.txt
00019  *
00020  * Author Contact: libwbxml@jehanne.org
00021  * WBXML Lib home: http://libwbxml.jehanne.org
00022  */
00023  
00036 #include <limits.h>
00037 #include <ctype.h>
00038 #include <stdlib.h>
00039 #include <string.h>
00040 
00041 #include "wbxml.h"
00042 
00043 
00044 /* Memory management define */
00045 #define WBXML_BUFFER_SPLIT_BLOCK 20
00046 
00050 struct WBXMLBuffer_s
00051 {
00052     WB_UTINY *data;             
00053     WB_ULONG len;               
00054     WB_ULONG malloced;          
00055     WB_ULONG malloc_block;      
00056 };
00057 
00058 
00059 static WB_BOOL grow_buff(WBXMLBuffer *buffer, WB_ULONG size);
00060 static WB_BOOL insert_data(WBXMLBuffer *buffer, WB_ULONG pos, const WB_UTINY *data, WB_ULONG len);
00061 
00062 
00063 
00064 /**********************************
00065  *    Public functions
00066  */
00067 
00068 
00069 WBXML_DECLARE(WBXMLBuffer *) wbxml_buffer_create_real(const WB_UTINY *data, WB_ULONG len, WB_ULONG malloc_block)
00070 {
00071     WBXMLBuffer *buffer = NULL;
00072 
00073     buffer = (WBXMLBuffer *) wbxml_malloc(sizeof(WBXMLBuffer));
00074     if (buffer == NULL)
00075         return NULL;
00076         
00077     buffer->malloc_block = malloc_block;
00078 
00079     if ((len <= 0) || (data == NULL)) {        
00080         buffer->malloced = 0;
00081         buffer->len = 0;
00082         buffer->data = NULL;
00083     } 
00084     else {               
00085         if (len + 1 > malloc_block + 1)
00086             buffer->malloced = len + 1 + malloc_block;
00087         else
00088             buffer->malloced = malloc_block + 1;
00089         
00090         buffer->data = (WB_UTINY *) wbxml_malloc(buffer->malloced * sizeof(WB_UTINY));
00091         if (buffer->data == NULL) {
00092             wbxml_free(buffer);
00093             return NULL;
00094         }
00095 
00096         buffer->len = len;
00097         memcpy(buffer->data, data, len);
00098         buffer->data[len] = '\0';
00099     }
00100 
00101     return buffer;
00102 }
00103 
00104 
00105 WBXML_DECLARE(void) wbxml_buffer_destroy(WBXMLBuffer *buffer)
00106 {
00107     if (buffer != NULL) {
00108         wbxml_free(buffer->data);
00109         wbxml_free(buffer);
00110     }
00111 }
00112 
00113 
00114 WBXML_DECLARE_NONSTD(void) wbxml_buffer_destroy_item(void *buff)
00115 {
00116     wbxml_buffer_destroy((WBXMLBuffer *) buff);
00117 }
00118 
00119 
00120 WBXML_DECLARE(WBXMLBuffer *) wbxml_buffer_duplicate(WBXMLBuffer *buff)
00121 {
00122     WBXMLBuffer *result = NULL;
00123 
00124     if (buff == NULL)
00125         return NULL;
00126 
00127     result = wbxml_buffer_create_real(wbxml_buffer_get_cstr(buff),
00128                                       wbxml_buffer_len(buff),  
00129                                       wbxml_buffer_len(buff));
00130 
00131     return result;
00132 }
00133 
00134 
00135 WBXML_DECLARE(WB_ULONG) wbxml_buffer_len(WBXMLBuffer *buffer)
00136 {
00137     if (buffer == NULL)
00138         return 0;
00139         
00140     return buffer->len;
00141 }
00142 
00143 
00144 WBXML_DECLARE(WB_BOOL) wbxml_buffer_get_char(WBXMLBuffer *buffer, WB_ULONG pos, WB_UTINY *result)
00145 {
00146     if ((buffer == NULL) || (pos >= buffer->len) || (pos < 0))
00147         return FALSE;
00148         
00149     *result = buffer->data[pos];
00150     return TRUE;
00151 }
00152 
00153 
00154 WBXML_DECLARE(void) wbxml_buffer_set_char(WBXMLBuffer *buffer, WB_ULONG pos, WB_UTINY ch)
00155 {
00156     if (pos < buffer->len)
00157         buffer->data[pos] = ch;
00158 }
00159 
00160 
00161 WBXML_DECLARE(WB_UTINY *) wbxml_buffer_get_cstr(WBXMLBuffer *buffer)
00162 {
00163     if ((buffer == NULL) || (buffer->len == 0))
00164         return WBXML_UTINY_NULL_STRING;
00165         
00166     return buffer->data;
00167 }
00168 
00169 
00170 WBXML_DECLARE(WB_BOOL) wbxml_buffer_insert(WBXMLBuffer *to, WBXMLBuffer *buffer, WB_ULONG pos)
00171 {
00172     if ((to != NULL) && (buffer != NULL))
00173         return insert_data(to, pos, buffer->data, buffer->len);
00174 
00175     return FALSE;
00176 }
00177 
00178 
00179 WBXML_DECLARE(WB_BOOL) wbxml_buffer_insert_cstr(WBXMLBuffer *to, WB_UTINY *str, WB_ULONG pos)
00180 {
00181     if ((to != NULL) && (str != NULL))
00182         return insert_data(to, pos, str, WBXML_STRLEN(str));
00183 
00184     return FALSE;
00185 }
00186 
00187 
00188 WBXML_DECLARE(WB_BOOL) wbxml_buffer_append(WBXMLBuffer *dest, WBXMLBuffer *buff)
00189 {
00190     if (dest == NULL)
00191         return FALSE;
00192 
00193     if (buff == NULL)
00194         return TRUE;
00195 
00196     return wbxml_buffer_append_data(dest, wbxml_buffer_get_cstr(buff), wbxml_buffer_len(buff));
00197 }
00198 
00199 
00200 WBXML_DECLARE(WB_BOOL) wbxml_buffer_append_data_real(WBXMLBuffer *buffer, const WB_UTINY *data, WB_ULONG len)
00201 {
00202     if (buffer == NULL)
00203         return FALSE;
00204 
00205     if ((data == NULL) || (len == 0))
00206         return TRUE;
00207 
00208     return insert_data(buffer, buffer->len, data, len);
00209 }
00210 
00211 WBXML_DECLARE(WB_BOOL) wbxml_buffer_append_cstr_real(WBXMLBuffer *buffer, const WB_UTINY *data)
00212 {
00213     if (data == NULL)
00214         return TRUE;
00215 
00216     return wbxml_buffer_append_data(buffer, data, WBXML_STRLEN(data));
00217 }
00218 
00219 
00220 WBXML_DECLARE(WB_BOOL) wbxml_buffer_append_char(WBXMLBuffer *buffer, WB_UTINY ch)
00221 {
00222     WB_UTINY c = ch;
00223 
00224     if ((buffer == NULL) || (ch > UCHAR_MAX))
00225         return FALSE;
00226 
00227     return insert_data(buffer, buffer->len, &c, 1);
00228 }
00229 
00230 
00231 WBXML_DECLARE(WB_BOOL) wbxml_buffer_append_mb_uint_32(WBXMLBuffer *buffer, WB_ULONG value)
00232 {
00233     /* A uintvar is defined to be up to 32 bits large
00234      * so it will fit in 5 octets (to handle continuation bits) 
00235     */
00236     WB_UTINY octets[5];
00237     WB_LONG i = 0, start = 0;
00238 
00239     /* Handle last byte separately; it has no continuation bit,
00240      * and must be encoded even if value is 0. 
00241      */
00242     octets[4] = (WB_UTINY) (value & 0x7f);
00243     value >>= 7;
00244 
00245     for (i = 3; value > 0 && i >= 0; i--) {
00246         octets[i] = (WB_UTINY) (0x80 | (value & 0x7f));
00247         value >>= 7;
00248     }
00249     start = i + 1;
00250 
00251     return wbxml_buffer_append_data(buffer, octets + start, 5 - start);
00252 }
00253 
00254 
00255 WBXML_DECLARE(void) wbxml_buffer_delete(WBXMLBuffer *buffer, WB_ULONG pos, WB_ULONG len)
00256 {
00257     if (pos > buffer->len)
00258         pos = buffer->len;
00259         
00260     if (pos + len > buffer->len)
00261         len = buffer->len - pos;
00262         
00263     if (len > 0) {
00264         memmove(buffer->data + pos, buffer->data + pos + len,
00265                 buffer->len - pos - len);
00266                 
00267         buffer->len -= len;
00268         buffer->data[buffer->len] = '\0';
00269     }
00270 }
00271 
00272 
00273 WBXML_DECLARE(void) wbxml_buffer_shrink_blanks(WBXMLBuffer *buffer)
00274 {
00275     WB_ULONG i = 0, j = 0, end = 0;
00276     WB_UTINY ch = 0;
00277     
00278     if (buffer == NULL)
00279         return;
00280         
00281     end = wbxml_buffer_len(buffer);
00282 
00283     for (i = 0; i < end; i++) 
00284     {
00285         if (wbxml_buffer_get_char(buffer, i, &ch) && isspace(ch)) 
00286         {
00287             /* Replace space by a whitespace */
00288             if (ch != ' ')
00289                 wbxml_buffer_set_char(buffer, i, ' ');           
00290 
00291             /* Remove all following spaces */
00292             j = i = i + 1;
00293             while (wbxml_buffer_get_char(buffer, j, &ch) && isspace(ch))
00294                 j++;
00295 
00296             if (j - i > 1)
00297                 wbxml_buffer_delete(buffer, i, j - i);
00298         }
00299     }
00300 }
00301 
00302 
00303 WBXML_DECLARE(void) wbxml_buffer_strip_blanks(WBXMLBuffer *buffer)
00304 {
00305     WB_ULONG start = 0, end = 0, len = 0;
00306     WB_UTINY ch = 0;
00307 
00308     /* Remove whitespaces at beginning of buffer... */
00309     while (wbxml_buffer_get_char(buffer, start, &ch) && 
00310            isspace(ch) && 
00311                start <= wbxml_buffer_len(buffer))
00312     {
00313         start ++;
00314     }
00315 
00316     if (start > 0)
00317         wbxml_buffer_delete(buffer, 0, start);
00318 
00319     /* ... and at the end */
00320     if ((len = wbxml_buffer_len(buffer)) > 0) {
00321         end = len = len - 1;
00322         while (wbxml_buffer_get_char(buffer, end, &ch) &&
00323             isspace(ch) && 
00324             end >= 0) 
00325         {
00326             end--;
00327         }
00328         wbxml_buffer_delete(buffer, end + 1, len - end);
00329     }
00330 }
00331 
00332 
00333 WBXML_DECLARE(WB_LONG) wbxml_buffer_compare(WBXMLBuffer *buff1, WBXMLBuffer *buff2)
00334 {
00335     WB_LONG ret = 0, len = 0;
00336 
00337     if ((buff1 == NULL) || (buff2 == NULL)) {
00338         if ((buff1 == NULL) && (buff2 == NULL))
00339             return 0;
00340 
00341         if (buff1 == NULL)
00342             return -1;
00343         else
00344             return 1;
00345     }
00346 
00347     if (buff1->len < buff2->len)
00348         len = buff1->len;
00349     else
00350         len = buff2->len;
00351 
00352     if (len == 0) 
00353     {
00354             if (buff1->len == 0 && buff2->len > 0)
00355                 return -1;
00356             if (buff1->len > 0 && buff2->len == 0)
00357                 return 1;
00358         return 0;
00359     }
00360 
00361     if ((ret = memcmp(buff1->data, buff2->data, len)) == 0) 
00362     {
00363         if (buff1->len < buff2->len)
00364             ret = -1;
00365         else {
00366             if (buff1->len > buff2->len)
00367                 ret = 1;
00368         }
00369     }
00370 
00371     return ret;
00372 }
00373 
00374 
00375 WBXML_DECLARE(WB_LONG) wbxml_buffer_compare_cstr(WBXMLBuffer *buff, const WB_TINY *str)
00376 {
00377     WB_LONG ret = 0, len = 0;
00378 
00379     if ((buff == NULL) || (str == NULL)) {
00380         if ((buff == NULL) && (str == NULL))
00381             return 0;
00382 
00383         if (buff == NULL)
00384             return -1;
00385         else
00386             return 1;
00387     }
00388 
00389     if (buff->len < WBXML_STRLEN(str))
00390         len = buff->len;
00391     else
00392         len = WBXML_STRLEN(str);
00393 
00394     if (len == 0) 
00395     {
00396             if (buff->len == 0 && WBXML_STRLEN(str) > 0)
00397                 return -1;
00398             if (buff->len > 0 && WBXML_STRLEN(str) == 0)
00399                 return 1;
00400         return 0;
00401     }
00402 
00403     if ((ret = memcmp(buff->data, str, len)) == 0) 
00404     {
00405         if (buff->len < WBXML_STRLEN(str))
00406             ret = -1;
00407         else {
00408             if (buff->len > WBXML_STRLEN(str))
00409                 ret = 1;
00410         }
00411     }
00412 
00413     return ret;
00414 }
00415 
00416 
00417 WBXML_DECLARE(WBXMLList *) wbxml_buffer_split_words_real(WBXMLBuffer *buff)
00418 {
00419     WB_UTINY *p = NULL;
00420     WBXMLList *list = NULL;
00421     WBXMLBuffer *word = NULL;
00422     WB_ULONG i = 0, start = 0, end = 0;
00423 
00424     if ((list = wbxml_list_create()) == NULL)
00425         return NULL;
00426 
00427     p = buff->data;
00428     i = 0;
00429     while (TRUE)
00430     {
00431         while (i < buff->len && isspace(*p)) {
00432             ++p;
00433             ++i;
00434         }
00435         start = i;
00436 
00437         while (i < buff->len && !isspace(*p)) {
00438             ++p;
00439             ++i;
00440         }
00441         end = i;
00442 
00443         if (start == end)
00444             break;
00445 
00446         if((word = wbxml_buffer_create(buff->data + start, end - start, WBXML_BUFFER_SPLIT_BLOCK)) == NULL) {
00447             wbxml_list_destroy(list, wbxml_buffer_destroy_item);
00448             return NULL;
00449         }
00450 
00451         wbxml_list_append(list, word);
00452     }
00453 
00454     return list;
00455 }
00456 
00457 
00458 WBXML_DECLARE(WB_BOOL) wbxml_buffer_search_char(WBXMLBuffer *to, WB_UTINY ch, WB_ULONG pos, WB_ULONG *result)
00459 {
00460     WB_UTINY *p = NULL;
00461 
00462     if ((to == NULL) || (ch > UCHAR_MAX))
00463         return FALSE;
00464 
00465     if (pos >= to->len)
00466         return FALSE;
00467 
00468     if ((p = (WB_UTINY *) memchr(to->data + pos, ch, to->len - pos)) == NULL)
00469         return FALSE;
00470 
00471     if (result != NULL)
00472         *result = p - to->data;
00473 
00474     return TRUE;
00475 }
00476 
00477 
00478 WBXML_DECLARE(WB_BOOL) wbxml_buffer_search(WBXMLBuffer *to, WBXMLBuffer *search, WB_ULONG pos, WB_ULONG *result)
00479 {
00480     WB_UTINY first = 0;
00481 
00482     if ((to == NULL) || (search == NULL))
00483         return FALSE;
00484 
00485     if (result != NULL)
00486         *result = 0;
00487 
00488     /* Always "find" an empty string */
00489     if (search->len == 0)
00490         return TRUE;
00491 
00492     /* Check if 'search' is greater than 'to' */
00493     if (search->len > to->len)
00494         return FALSE;
00495 
00496     /* We are searching for one char */
00497     if (search->len == 1)
00498         return wbxml_buffer_search_char(to, search->data[0], pos, result);
00499 
00500     /* For each occurrence of search's first character in to, then check if the rest of needle follows.
00501      * Stop if there are no more occurrences, or if the rest of 'search' can't possibly fit in 'to'. */
00502     first = search->data[0];
00503     while ((wbxml_buffer_search_char(to, first, pos, &pos)) && 
00504            (to->len - pos >= search->len)) 
00505     {
00506         if (memcmp(to->data + pos, search->data, search->len) == 0) {
00507             if (result != NULL)
00508                 *result = pos;
00509             return TRUE;
00510         }
00511         pos++;
00512     }
00513 
00514     return FALSE;    
00515 }
00516 
00517 
00518 WBXML_DECLARE(WB_BOOL) wbxml_buffer_search_cstr(WBXMLBuffer *to, WB_UTINY *search, WB_ULONG pos, WB_ULONG *result)
00519 {
00520     WB_UTINY first = 0;
00521 
00522     if ((to == NULL) || (search == NULL))
00523         return FALSE;
00524 
00525     if (result != NULL)
00526         *result = 0;
00527 
00528     /* Always "find" an empty string */
00529     if (WBXML_STRLEN(search) == 0)
00530         return TRUE;
00531 
00532     /* Check if 'search' is greater than 'to' */
00533     if (WBXML_STRLEN(search) > to->len)
00534         return FALSE;
00535 
00536     /* We are searching for one char */
00537     if (WBXML_STRLEN(search) == 1)
00538         return wbxml_buffer_search_char(to, search[0], pos, result);
00539 
00540     /* For each occurrence of search's first character in to, then check if the rest of needle follows.
00541      * Stop if there are no more occurrences, or if the rest of 'search' can't possibly fit in 'to'. */
00542     first = search[0];
00543     while ((wbxml_buffer_search_char(to, first, pos, &pos)) && 
00544            (to->len - pos >= WBXML_STRLEN(search))) 
00545     {
00546         if (memcmp(to->data + pos, search, WBXML_STRLEN(search)) == 0) {
00547             if (result != NULL)
00548                 *result = pos;
00549             return TRUE;
00550         }
00551         pos++;
00552     }
00553 
00554     return FALSE;
00555 }
00556 
00557 
00558 WBXML_DECLARE(WB_BOOL) wbxml_buffer_contains_only_whitespaces(WBXMLBuffer *buffer)
00559 {
00560     WB_ULONG i = 0;
00561 
00562     if (buffer == NULL)
00563         return FALSE;
00564 
00565     for (i=0; i<buffer->len; i++) {
00566         if (!isspace(*(buffer->data + i)))
00567             return FALSE;
00568     }
00569 
00570     return TRUE;
00571 }
00572 
00573 
00574 WBXML_DECLARE(void) wbxml_buffer_hex_to_binary(WBXMLBuffer *buffer)
00575 {
00576     WB_UTINY *p = NULL;
00577     WB_ULONG i = 0, len = 0;
00578 
00579     if (buffer == NULL)
00580         return;
00581 
00582     p = buffer->data;
00583     len = wbxml_buffer_len(buffer);
00584 
00585     /* Convert ascii data to binary values */
00586     for (i = 0; i < len; i++, p++) {
00587         if (*p >= '0' && *p <= '9')
00588             *p -= '0';
00589         else if (*p >= 'a' && *p <= 'f')
00590             *p = *p - 'a' + 10;
00591         else if (*p >= 'A' && *p <= 'F')
00592             *p = *p - 'A' + 10;
00593         else {
00594             /* Bad Bad ! There should be only digits in the buffer ! */
00595             *p = 0;
00596         }
00597     }
00598 
00599     /* De-hexing will compress data by factor of 2 */
00600     len = buffer->len / 2;
00601 
00602     for (i = 0; i < len; i++)
00603         buffer->data[i] = buffer->data[i * 2] * 16 | buffer->data[i * 2 + 1];
00604 
00605     buffer->len = len;
00606     buffer->data[len] = '\0';
00607 }
00608 
00609 
00610 WBXML_DECLARE(WB_BOOL) wbxml_buffer_binary_to_hex(WBXMLBuffer *buffer, WB_BOOL uppercase)
00611 {
00612     WB_UTINY *hexits = NULL;
00613     WB_LONG i = 0;
00614 
00615     if (buffer == NULL)
00616         return FALSE;
00617 
00618     if (wbxml_buffer_len(buffer) == 0)
00619         return TRUE;
00620 
00621     hexits = (WB_UTINY *)(uppercase ? "0123456789ABCDEF" : "0123456789abcdef");
00622 
00623     /* Grows the Buffer size by 2 */
00624     grow_buff(buffer, buffer->len * 2);
00625 
00626     /* In-place modification must be done back-to-front to avoid
00627      * overwriting the data while we read it.  Even the order of
00628      * the two assignments is important, to get i == 0 right. 
00629      */
00630     for (i = buffer->len - 1; i >= 0; i--) {
00631         buffer->data[i * 2 + 1] = hexits[buffer->data[i] % 16];
00632         buffer->data[i * 2] = hexits[(buffer->data[i] / 16) & 0xf];
00633     }
00634 
00635     buffer->len = buffer->len * 2;
00636     buffer->data[buffer->len] = '\0';
00637 
00638     return TRUE;
00639 }
00640 
00641 
00642 WBXML_DECLARE(void) wbxml_buffer_remove_trailing_zeros(WBXMLBuffer **buffer)
00643 {
00644     WB_UTINY ch = 0;
00645 
00646     if ((buffer == NULL) || (*buffer == NULL))
00647         return;
00648 
00649     while ((*buffer)->len > 0) {
00650         if (wbxml_buffer_get_char(*buffer, wbxml_buffer_len(*buffer) - 1, &ch) && (ch == '\0'))
00651             wbxml_buffer_delete(*buffer, wbxml_buffer_len(*buffer) - 1, 1);
00652         else
00653             return;
00654     }
00655 }
00656 
00657 
00658 /**********************************
00659  *    Private functions
00660  */
00661 
00668 static WB_BOOL grow_buff(WBXMLBuffer *buffer, WB_ULONG size)
00669 {
00670     if ((buffer == NULL) || (size < 0))
00671         return FALSE;
00672         
00673     /* Make room for the invisible terminating NUL */
00674     size++; 
00675 
00676     if ((buffer->len + size) > buffer->malloced) {
00677         if ((buffer->malloced + buffer->malloc_block) < (buffer->len + size))
00678             buffer->malloced = buffer->len + size + buffer->malloc_block;
00679         else
00680             buffer->malloced = buffer->malloced + buffer->malloc_block;
00681             
00682         buffer->data = wbxml_realloc(buffer->data, buffer->malloced);
00683         if (buffer->data == NULL)
00684             return FALSE;
00685     }
00686 
00687     return TRUE;
00688 }
00689 
00690 
00699 static WB_BOOL insert_data(WBXMLBuffer *buffer, WB_ULONG pos, const WB_UTINY *data, WB_ULONG len)
00700 {
00701     if ((buffer == NULL) || (len == 0) || (pos > buffer->len))
00702         return FALSE;
00703 
00704     if (!grow_buff(buffer, len))
00705         return FALSE;
00706 
00707     if (buffer->len > pos) {    
00708         /* Only if neccessary */
00709         memmove(buffer->data + pos + len, buffer->data + pos, buffer->len - pos);
00710     }
00711 
00712     memcpy(buffer->data + pos, data, len);
00713     buffer->len += len;
00714     buffer->data[buffer->len] = '\0';
00715 
00716     return TRUE;
00717 }

Generated on Mon Nov 24 20:09:42 2003 for WBXML Library by doxygen1.3-rc1