summaryrefslogtreecommitdiffstats
path: root/tinySAK/src/tsk_string.c
diff options
context:
space:
mode:
Diffstat (limited to 'tinySAK/src/tsk_string.c')
-rw-r--r--tinySAK/src/tsk_string.c619
1 files changed, 619 insertions, 0 deletions
diff --git a/tinySAK/src/tsk_string.c b/tinySAK/src/tsk_string.c
new file mode 100644
index 0000000..abb4831
--- /dev/null
+++ b/tinySAK/src/tsk_string.c
@@ -0,0 +1,619 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_string.c
+ * @brief Useful string functions to manipulate strings.
+ * As I'm a lazy man, some comments come from <ahref="http://www.cplusplus.com">this website</a>
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tsk_string.h"
+#include "tsk_memory.h"
+#include "tsk_time.h"
+#include "tsk_debug.h"
+#include "tsk_common.h"
+
+#include <stdarg.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if defined(_MSC_VER)
+# define snprintf _snprintf
+# define vsnprintf _vsnprintf
+# define strdup _strdup
+# define stricmp _stricmp
+# define strnicmp _strnicmp
+#else
+# if !HAVE_STRNICMP && !HAVE_STRICMP
+# define stricmp strcasecmp
+# define strnicmp strncasecmp
+# endif
+#endif
+
+/**@defgroup tsk_string_group String utillity functions.
+*/
+
+static char HEX[] = "0123456789abcdef";
+
+/**@ingroup tsk_string_group
+*/
+tsk_string_t* tsk_string_create(const char* str)
+{
+ return tsk_object_new(tsk_string_def_t, str);
+}
+
+/**@ingroup tsk_string_group
+* From base 10 to base 16
+* @param c the base 10 char to convert to base 16
+* @retval The base 16 value
+*/
+char tsk_b10tob16(char c)
+{
+ return HEX[c & 15];
+}
+
+/**@ingroup tsk_string_group
+* From base 16 to base 10
+* @param c The base 16 char to convert to base 10
+* @retval The base 10 value
+*/
+char tsk_b16tob10(char c)
+{
+ return isdigit(c) ? c - '0' : tolower(c) - 'a' + 10;
+}
+
+/**@ingroup tsk_string_group
+* Compare two Null-terminated strings (case insensitive)
+* Compares the C string str1 to the C string str2.
+* This function starts comparing the first character of each string. If they are equal to each other, it continues with the following pairs
+* until the characters differ or until a terminanting null-character is reached.
+* @param str1 First C string to be compared.
+* @param str2 Second C string to be compared.
+* @retval Returns an integral value indicating the relationship between the strings:
+* <0 : str1 less than str2.<br>
+* 0 : str1 identical to str2.<br>
+* >0 : str1 greater than str2.<br>
+*/
+int tsk_stricmp(const char * str1, const char * str2)
+{
+ return (str1 && str2) ?
+ ( (tolower(*str1) == tolower(*str2)) ? stricmp(str1, str2) : (*str1-*str2) ) /* Compare first charaters before doing complete comparison */
+ :
+ ( (!str1 && !str2) ? 0 : -1 );
+}
+
+/**@ingroup tsk_string_group
+* Compare two Null-terminated strings (case insensitive)
+* Compares the C string str1 to the C string str2.
+* This function starts comparing the first character of each string. If they are equal to each other, it continues with the following pairs
+* until the characters differ or until a terminanting null-character is reached or @a n characters passed.
+* @param str1 First C string to be compared.
+* @param str2 Second C string to be compared.
+* @param n The maximum number of characters to compare.
+* @retval Returns an integral value indicating the relationship between the strings:
+* <0 : str1 less than str2.<br>
+* 0 : str1 identical to str2.<br>
+* >0 : str1 greater than str2.<br>
+*/
+int tsk_strnicmp(const char * str1, const char * str2, tsk_size_t n)
+{
+ return (str1 && str2 && n) ?
+ ( (tolower(*str1) == tolower(*str2)) ? strnicmp(str1, str2, n) : (*str1-*str2) ) /* Compare first charaters before doing complete comparison */
+ :
+ ( (!str1 && !str2) ? 0 : -1 );
+}
+
+/**@ingroup tsk_string_group
+*/
+int tsk_strcmp(const char * str1, const char * str2)
+{
+ return (str1 && str2) ?
+ ( (*str1 == *str2) ? stricmp(str1, str2) : (*str1-*str2) ) /* Compare first charaters before doing complete comparison */
+ :
+ ( (!str1 && !str2) ? 0 : -1 );
+}
+
+/**@ingroup tsk_string_group
+* Compare two Null-terminated strings (case sensitive)
+* Compares the C string str1 to the C string str2.
+* This function starts comparing the first character of each string. If they are equal to each other, it continues with the following pairs
+* until the characters differ or until a terminanting null-character is reached.
+* @param str1 First C string to be compared.
+* @param str2 Second C string to be compared.
+* @param n The maximum number of characters to compare.
+* @retval Returns an integral value indicating the relationship between the strings:
+* <0 : str1 less than str2.<br>
+* 0 : str1 identical to str2.<br>
+* >0 : str1 greater than str2.<br>
+*/
+int tsk_strncmp(const char * str1, const char * str2, tsk_size_t n)
+{
+ return (str1 && str2) ? ((*str1 != *str2) ? -1 : strncmp(str1, str2, n)) : ((!str1 && !str2) ? 0 : -1);
+}
+
+/**@ingroup tsk_string_group
+* Duplicate a Null-terminated string.
+* @param s1 The string to duplicate.
+* @retval The duplicated string. It's up to you to free the returned string.
+*/
+char* tsk_strdup(const char *s1)
+{
+ if(s1){
+ return strdup(s1);
+ }
+ return tsk_null;
+}
+
+/** Duplicates the first @a n chars of @a s1.
+ * @param s1 The string to duplicate.
+ * @param n The number of characters to copy to the new string.
+ * @retval null A copy of @a s1.
+**/
+char* tsk_strndup(const char *s1, tsk_size_t n)
+{
+ char *ret = tsk_null;
+
+ if(s1 && n){
+ tsk_size_t len = tsk_strlen(s1);
+ tsk_size_t nret = (n > len) ? (len) : (n);
+
+ ret = tsk_calloc((nret+1), sizeof(uint8_t));
+ memcpy(ret, s1, nret);
+ }
+
+ return ret;
+}
+
+/**@ingroup tsk_string_group
+* Checks if @a str contains @a substring.
+* @param str The master string.
+* @param size The size of the master string.
+* @param substring the substring.
+* @retval @a tsk_true if @a str contains at least one occurence of @a substring and @a tsk_false othewise.
+*/
+tsk_bool_t tsk_strcontains(const char * str, tsk_size_t size, const char * substring)
+{
+ return (tsk_strindexOf(str, size, substring) >= 0);
+}
+
+/**@ingroup tsk_string_group
+* Gets the first occurrence of @a substring within @a str.
+* @param str The master string.
+* @param size The size of the master string.
+* @param substring The substring that is to be searched for within @a str.
+* @retval The index of the first ocurrence of @a substring in @a str.
+* If no occurrence of @a substring is found, then -1 is returned.
+*/
+int tsk_strindexOf(const char * str, tsk_size_t size, const char * substring)
+{
+ if(str && substring){
+ const char* sub_start = strstr(str, substring);
+ if(sub_start && (sub_start < (str + size))){
+ return (sub_start - str);
+ }
+ }
+ return -1;
+}
+
+/**@ingroup tsk_string_group
+*/
+int tsk_strLastIndexOf(const char * str, tsk_size_t size, const char * substring)
+{
+ if(str && substring){
+ tsk_size_t sub_size = tsk_strlen(substring);
+ const char* last_sub_start = tsk_null;
+ const char* sub_start = strstr(str, substring);
+ const char* end = (str + size);
+ while(sub_start && (sub_start < end)){
+ last_sub_start = sub_start;
+ if((sub_start + sub_size)<end){
+ sub_start = strstr((sub_start + sub_size), substring);
+ }
+ else{
+ break;
+ }
+ }
+ if(last_sub_start){
+ return (last_sub_start - str);
+ }
+ }
+ return -1;
+}
+
+/**@ingroup tsk_string_group
+* Appends a copy of the source string to the destination string. The terminating null character in destination is overwritten by the first character of source,
+* and a new null-character is appended at the end of the new string formed by the concatenation of both in destination. If the destination is NULL then new
+* memory will allocated and filled with source value.
+* @param destination Pointer de the destination array containing the new string.
+* @param source C string to be appended. This should not overlap destination. If NULL then nothing is done.
+*/
+void tsk_strcat(char** destination, const char* source)
+{
+ tsk_strncat(destination, source, tsk_strlen(source));
+}
+
+/**@ingroup tsk_string_group
+*/
+void tsk_strcat_2(char** destination, const char* format, ...)
+{
+ char* temp = tsk_null;
+ int len;
+ va_list ap;
+
+ /* initialize variable arguments */
+ va_start(ap, format);
+ /* compute */
+ if((len = tsk_sprintf_2(&temp, format, &ap))){
+ tsk_strncat(destination, temp, len);
+ }
+ /* reset variable arguments */
+ va_end(ap);
+ TSK_FREE(temp);
+}
+
+/**@ingroup tsk_string_group
+*/
+void tsk_strncat(char** destination, const char* source, tsk_size_t n)
+{
+ tsk_size_t index = 0;
+ tsk_size_t tsk_size_to_cat = (n > tsk_strlen(source)) ? tsk_strlen(source) : n;
+
+ if(!source || !n){
+ return;
+ }
+
+ if(!*destination){
+ *destination = (char*)tsk_malloc(tsk_size_to_cat+1);
+ strncpy(*destination, source, tsk_size_to_cat+1);
+ }else{
+ index = tsk_strlen(*destination);
+ *destination = tsk_realloc(*destination, index + tsk_size_to_cat+1);
+ strncpy(((*destination)+index), source, tsk_size_to_cat+1);
+ }
+ (*destination)[index + tsk_size_to_cat] = '\0';
+}
+
+/**@ingroup tsk_string_group
+* Writes into the array pointed by str a C string consisting on a sequence of data formatted as the format argument specifies. After the format parameter,
+* the function expects at least as many additional arguments as specified in format.
+* This function behaves exactly as printf does, but writing its results to a string instead of stdout. The size of the array passed as str should be enough to
+* contain the entire formatted string.
+* @param str Pointer to an array of char elements where the resulting C string is stored.
+* MUST be NULL.
+* @param format C string that contains the text to be written to the buffer. For more information see definiton of C function @a sprintf
+* @retval On success, the total number of characters written is returned. This count does not include the additional null-character automatically appended
+* at the end of the string.
+* On failure, a negative number is returned.
+*/
+int tsk_sprintf(char** str, const char* format, ...)
+{
+ int len;
+ va_list ap;
+
+ /* initialize variable arguments */
+ va_start(ap, format);
+ /* compute */
+ len = tsk_sprintf_2(str, format, &ap);
+ /* reset variable arguments */
+ va_end(ap);
+
+ return len;
+}
+
+/**@ingroup tsk_string_group
+*/
+int tsk_sprintf_2(char** str, const char* format, va_list* ap)
+{
+ int len = 0;
+ va_list ap2;
+
+ /* free previous value */
+ if(*str){
+ tsk_free((void**)str);
+ }
+
+ /* needed for 64bit platforms where vsnprintf will change the va_list */
+ tsk_va_copy(ap2, *ap);
+
+ /* compute destination len for windows mobile
+ */
+#if defined(_WIN32_WCE)
+ {
+ int n;
+ len = (tsk_strlen(format)*2);
+ *str = (char*)tsk_calloc(1, len+1);
+ for(;;){
+ if( (n = vsnprintf(*str, len, format, *ap)) >= 0 && (n<len) ){
+ len = n;
+ goto done;
+ }
+ else{
+ len += 10;
+ *str = tsk_realloc(*str, len+1);
+ }
+ }
+done:
+ (*str)[len] = '\0';
+ }
+#else
+ len = vsnprintf(0, 0, format, *ap);
+ *str = (char*)tsk_calloc(1, len+1);
+ vsnprintf(*str, len
+#if !defined(_MSC_VER) || defined(__GNUC__)
+ +1
+#endif
+ , format, ap2);
+#endif
+
+ va_end(ap2);
+
+ return len;
+}
+
+/**@ingroup tsk_string_group
+* Updates the value of @a str.
+* @param str The string to update.
+* @param newval The new value of @a str.
+*/
+void tsk_strupdate(char** str, const char* newval)
+{
+ tsk_free((void**)str);
+ *str = tsk_strdup(newval);
+}
+
+
+/**@ingroup tsk_string_group
+* Removes all occurrences of white space characters from the beginning of this @a str.
+* @param str The string to trim.
+*/
+void tsk_strtrim_left(char **str)
+{
+ if(str && *str){
+ tsk_size_t count = 0;
+ while(isspace(*((*str)+count))) count++;
+ if(count){
+ strcpy((*str), (*str)+count);
+ }
+ }
+}
+
+/**@ingroup tsk_string_group
+* Removes all occurrences of white space characters from the end of @a str.
+* @param str The string to trim.
+*/
+void tsk_strtrim_right(char **str)
+{
+ if(str && *str){
+ tsk_size_t size;
+ if((size = tsk_strlen(*str))){
+ while(isspace(*((*str)+size-1))) size--;
+ *(*str + size) = '\0';
+ }
+ }
+}
+/**@ingroup tsk_string_group
+* Removes all occurrences of white space characters from the beginning and end of @a str.
+* @param str The string to trim.
+*/
+void tsk_strtrim(char **str)
+{
+ // left
+ tsk_strtrim_left(str);
+ // right
+ tsk_strtrim_right(str);
+}
+
+/**@ingroup tsk_string_group
+* Adds quotes ("") to the beginning and end of @a str.<br>
+* @param str The string to quote.
+* Example: tsk_strquote("doubango") = ""doubango\"".
+*/
+void tsk_strquote(char **str)
+{
+ tsk_strquote_2(str, '"', '"');
+}
+
+/**@ingroup tsk_string_group
+* Adds quotes to the beginning and end of @a str.
+* @param str The string to quote.
+* @param lquote Quote to add to the begining of @a str.
+* @param rquote Quote to add to the end of @a str.
+*/
+void tsk_strquote_2(char **str, char lquote, char rquote)
+{
+ if(str && *str){
+ char *result = tsk_null;
+ tsk_sprintf(&result, "%c%s%c", lquote, *str, rquote);
+ tsk_free((void**)str);
+ *str = result;
+ }
+}
+
+/**@ingroup tsk_string_group
+* Removes quotes ("") from the beginning and end of @a str.<br>
+* @param str The string to unquote.
+* Example: tsk_strunquote(""doubango"") = "doubango".
+*/
+void tsk_strunquote(char **str)
+{
+ tsk_strunquote_2(str, '"', '"');
+}
+
+/**@ingroup tsk_string_group
+* Removes quotes from the beginning and end of @a str. The string must starts with @a lquote
+* and end with @a rquote.
+* @param str The string to unquote.
+* @param lquote Quote to remove from the begining of @a str.
+* @param rquote Quote to remove from the end of @a str.
+*/
+void tsk_strunquote_2(char **str, char lquote, char rquote)
+{
+ if(str && *str){
+ tsk_size_t size = tsk_strlen(*str);
+ if(size>=2 && **str == lquote && *((*str)+size-1) == rquote){
+ strcpy((*str), (*str)+1);
+ *((*str)+size-2) = '\0';
+ }
+ }
+}
+
+/**@ingroup tsk_string_group
+* Conversts an integer to string.
+* @param i The integer number to convert to a string.
+* @param result Pointer to the string where to copy the result.
+*/
+void tsk_itoa(int64_t i, tsk_istr_t *result)
+{
+ memset(result, 0, sizeof(*result));
+ sprintf(*result,"%lld",i);
+}
+
+/**@ingroup tsk_string_group
+*/
+int64_t tsk_atoll(const char* str)
+{
+ // FIXME: use HAVE_ATOLL and use macro instead of function
+ if(str){
+#if defined(_MSC_VER)
+ return _atoi64(str);
+#elif defined(__GNUC__)
+ return atoll(str);
+#else
+ return atol(str);
+#endif
+ }
+ return 0;
+}
+
+/**@ingroup tsk_string_group
+*/
+long tsk_atox(const char* str)
+{
+ long ret = 0;
+ if(str){
+ sscanf(str, "%lx", &ret);
+ }
+ return ret;
+}
+
+/**@ingroup tsk_string_group
+ * Generates a random string.
+ *
+ * @param result A pointer to the result.
+**/
+void tsk_strrandom(tsk_istr_t *result)
+{
+ static uint64_t __counter = 1;
+ tsk_itoa((tsk_time_epoch() ^ (rand())) ^ ++__counter, result);
+}
+
+/**@ingroup tsk_string_group
+ *
+ * Converts hexadecimal bytes into string representation.
+ *
+ * @param hex The hexadecimal bytes to convert.
+ * @param size The size of the hexadecimal bytes.
+ * @param str The pointer to the result. MUST be enought large to hold the result.
+ * It is up to you to add the final '\\0'.
+ * @sa @ref tsk_str_to_hex
+**/
+void tsk_str_from_hex(const uint8_t *hex, tsk_size_t size, char* str)
+{
+ static const char *TSK_HEXA_VALUES = {"0123456789abcdef"};
+ tsk_size_t i;
+
+ for (i = 0 ; i<size; i++){
+ str[2*i] = TSK_HEXA_VALUES [ (*(hex+i) & 0xf0) >> 4 ];
+ str[(2*i)+1] = TSK_HEXA_VALUES [ (*(hex+i) & 0x0f) ];
+ }
+}
+
+/**@ingroup tsk_string_group
+ * Converts string chars into hexadecimal bytes.
+ *
+ * @param str If non-null, the string.
+ * @param size The size.
+ * @param hex If non-null, the hexadecimal.
+**/
+void tsk_str_to_hex(const char *str, tsk_size_t size, uint8_t* hex)
+{
+ // to avoid SIGBUS error when memory is misaligned do not use sscanf("%2x")
+ TSK_DEBUG_FATAL("Not implemented.");
+}
+
+
+
+
+
+
+
+
+
+
+//=================================================================================================
+// String object definition
+//
+static tsk_object_t* tsk_string_ctor(tsk_object_t * self, va_list * app)
+{
+ tsk_string_t *string = self;
+ const char *value = va_arg(*app, const char *);
+ if(value){
+ string->value = tsk_strdup(value);
+ }
+ return self;
+}
+
+static tsk_object_t* tsk_string_dtor(tsk_object_t * self)
+{
+ tsk_string_t *string = self;
+ if(string){
+ TSK_FREE(string->value);
+ }
+
+ return self;
+}
+
+static int tsk_string_cmp(const tsk_object_t *_s1, const tsk_object_t *_s2)
+{
+ const tsk_string_t *s1 = _s1;
+ const tsk_string_t *s2 = _s2;
+
+ if(s1 && s2){
+ return tsk_stricmp(s1->value, s2->value);
+ }
+ else if(!s1 && !s2) return 0;
+ else return -1;
+}
+
+static const tsk_object_def_t tsk_string_def_s =
+{
+ sizeof(tsk_string_t),
+ tsk_string_ctor,
+ tsk_string_dtor,
+ tsk_string_cmp,
+};
+const tsk_object_def_t *tsk_string_def_t = &tsk_string_def_s;
+
OpenPOWER on IntegriCloud