|
|
@@ -0,0 +1,189 @@
|
|
|
+#include "toolbox/str.h"
|
|
|
+
|
|
|
+#include <stdlib.h>
|
|
|
+#include <string.h>
|
|
|
+
|
|
|
+#include "toolbox/errno.h"
|
|
|
+#include "toolbox/log.h"
|
|
|
+#include "toolbox/cstring.h"
|
|
|
+
|
|
|
+#define true ((unsigned char) 1L)
|
|
|
+#define false ((unsigned char) 0L)
|
|
|
+
|
|
|
+#define TEST_FOR_NULL(POINTER) \
|
|
|
+ if ( POINTER == NULL ) { \
|
|
|
+ LOG_ERROR("Null Pointer Not Expected"); \
|
|
|
+ toolbox_errno = RET_EVN; \
|
|
|
+ return toolbox_errno; \
|
|
|
+ }
|
|
|
+
|
|
|
+#define TEST_FOR_NULL_SR(POINTER, RET) \
|
|
|
+ if ( POINTER == NULL ) { \
|
|
|
+ LOG_ERROR("Null Pointer Not Expected"); \
|
|
|
+ toolbox_errno = RET_EVN; \
|
|
|
+ return RET; \
|
|
|
+ }
|
|
|
+
|
|
|
+#define CHECK_MALLOC(POINTER, RET) \
|
|
|
+ if ( POINTER == NULL ) { \
|
|
|
+ LOG_ERROR("Failed to malloc"); \
|
|
|
+ toolbox_errno = RET_EFM; \
|
|
|
+ return RET; \
|
|
|
+ }
|
|
|
+
|
|
|
+#define CHECK_MALLOC_FREE(POINTER, RET, FREE) \
|
|
|
+ if ( POINTER == NULL ) { \
|
|
|
+ free(FREE); \
|
|
|
+ LOG_ERROR("Failed to malloc"); \
|
|
|
+ toolbox_errno = RET_EFM; \
|
|
|
+ return RET; \
|
|
|
+ }
|
|
|
+
|
|
|
+struct str*
|
|
|
+str_create(const char *cstring, size_t cstring_size)
|
|
|
+{
|
|
|
+ toolbox_errno = RET_OK;
|
|
|
+
|
|
|
+ struct str *ret = malloc(sizeof(struct str));
|
|
|
+ CHECK_MALLOC(ret, NULL);
|
|
|
+
|
|
|
+ ret->_c_size = cstring_size;
|
|
|
+ ret->size = ret->_c_size;
|
|
|
+
|
|
|
+ ret->data = malloc(ret->_c_size);
|
|
|
+ CHECK_MALLOC_FREE(ret, NULL, ret);
|
|
|
+ *ret->data = -1;
|
|
|
+
|
|
|
+ ret->_c_data = ret->data;
|
|
|
+ memcpy(ret->data, cstring, ret->_c_size);
|
|
|
+
|
|
|
+ if ( *ret->data == -1 ) {
|
|
|
+ str_destroy(ret);
|
|
|
+ LOG_ERROR("Failed to memcpy");
|
|
|
+ toolbox_errno = RET_EFMC;
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+struct str*
|
|
|
+str_create_ns(const char *cstring)
|
|
|
+{
|
|
|
+ toolbox_errno = RET_OK;
|
|
|
+ return str_create(cstring, cstring_len(cstring));
|
|
|
+}
|
|
|
+
|
|
|
+RET_TYPE
|
|
|
+str_destroy(struct str *str)
|
|
|
+{
|
|
|
+ TEST_FOR_NULL(str);
|
|
|
+ toolbox_errno = RET_OK;
|
|
|
+
|
|
|
+ free(str->data);
|
|
|
+ free(str);
|
|
|
+
|
|
|
+ return RET_OK;
|
|
|
+}
|
|
|
+
|
|
|
+RET_TYPE
|
|
|
+str_to_lowercase(struct str *str)
|
|
|
+{
|
|
|
+ TEST_FOR_NULL(str);
|
|
|
+ TEST_FOR_NULL(str->_c_data);
|
|
|
+ toolbox_errno = RET_OK;
|
|
|
+
|
|
|
+ for ( size_t z = 0; z < str->_c_size; ++z ) {
|
|
|
+ char c = str->_c_data[z];
|
|
|
+ str->_c_data[z] += (char) ((c >= 'A' && c <= 'Z') * 32);
|
|
|
+ }
|
|
|
+
|
|
|
+ return RET_OK;
|
|
|
+}
|
|
|
+
|
|
|
+RET_TYPE
|
|
|
+str_to_uppercase(struct str *str)
|
|
|
+{
|
|
|
+ TEST_FOR_NULL(str);
|
|
|
+ TEST_FOR_NULL(str->_c_data);
|
|
|
+ toolbox_errno = RET_OK;
|
|
|
+
|
|
|
+ for ( size_t z = 0; z < str->_c_size; ++z ) {
|
|
|
+ char c = str->_c_data[z];
|
|
|
+ str->_c_data[z] -= (char)((c >= 'a' && c <= 'z') * 32);
|
|
|
+ }
|
|
|
+
|
|
|
+ return RET_OK;
|
|
|
+}
|
|
|
+
|
|
|
+RET_TYPE
|
|
|
+str_to_titlecase(struct str *str)
|
|
|
+{
|
|
|
+ TEST_FOR_NULL(str);
|
|
|
+ TEST_FOR_NULL(str->_c_data);
|
|
|
+ toolbox_errno = RET_OK;
|
|
|
+
|
|
|
+ size_t limit = str->_c_size - 1;
|
|
|
+ char pc = ' ';
|
|
|
+ for ( size_t z = 1; z < limit; ++z ) {
|
|
|
+ char c = str->_c_data[z];
|
|
|
+ char nc = str->_c_data[z+1];
|
|
|
+ str->_c_data[z] = (char) (
|
|
|
+ ((c >= 'a' && c <= 'z')
|
|
|
+ && (nc != ' ' && pc == ' ')) * (c - 32)
|
|
|
+ + ((c >= 'A' && c <= 'Z')
|
|
|
+ && (pc != ' ' || nc == ' ')) * (c + 32));
|
|
|
+ pc = c;
|
|
|
+ }
|
|
|
+
|
|
|
+ return RET_OK;
|
|
|
+}
|
|
|
+
|
|
|
+_Bool
|
|
|
+str_starts_with(struct str *str, struct str* start)
|
|
|
+{
|
|
|
+ TEST_FOR_NULL_SR(str, false);
|
|
|
+ TEST_FOR_NULL_SR(str->_c_data, false);
|
|
|
+ TEST_FOR_NULL_SR(start, false);
|
|
|
+ TEST_FOR_NULL_SR(start->_c_data, false);
|
|
|
+ toolbox_errno = RET_OK;
|
|
|
+ _Bool ret = false;
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+_Bool
|
|
|
+str_starts_with_char(struct str *str, char chr)
|
|
|
+{
|
|
|
+ TEST_FOR_NULL_SR(str, false);
|
|
|
+ TEST_FOR_NULL_SR(str->_c_data, false);
|
|
|
+ toolbox_errno = RET_OK;
|
|
|
+
|
|
|
+ return (*str->data == chr);
|
|
|
+}
|
|
|
+
|
|
|
+_Bool
|
|
|
+str_starts_with_cstring(struct str *str, char *cstring, size_t cstring_size);
|
|
|
+_Bool
|
|
|
+str_starts_with_cstring_ns(struct str *str, char *cstring);
|
|
|
+
|
|
|
+_Bool
|
|
|
+str_ends_with(struct str *str, struct str* end);
|
|
|
+_Bool
|
|
|
+str_ends_with_char(struct str *str, char chr);
|
|
|
+_Bool
|
|
|
+str_ends_with_cstring(struct str *str, char *cstring, size_t cstring_size);
|
|
|
+_Bool
|
|
|
+str_ends_with_cstring_ns(struct str *str, char *cstring);
|
|
|
+
|
|
|
+_Bool
|
|
|
+str_is_empty(struct str *str);
|
|
|
+
|
|
|
+size_t
|
|
|
+str_count_str(struct str *str, struct str *str2);
|
|
|
+size_t
|
|
|
+str_count_char(struct str *str, char chr);
|
|
|
+size_t
|
|
|
+str_count_cstring(struct str *str, char *cstring, size_t cstring_size);
|
|
|
+size_t
|
|
|
+str_count_cstring_ns(struct str *str, char *cstring);
|