|
|
@@ -1,13 +1,19 @@
|
|
|
-#ifndef TOOLBOX_STR_H
|
|
|
-#define TOOLBOX_STR_H
|
|
|
+#ifndef STR_H
|
|
|
+#define STR_H
|
|
|
|
|
|
-#include <stddef.h>
|
|
|
+/* STR RETURN CODE */
|
|
|
+#define STR_RC_TYPE unsigned char
|
|
|
+extern __thread STR_RC_TYPE str_errno;
|
|
|
+#define STR_RC_OK ((STR_RC_TYPE) 0L) /* No Error */
|
|
|
+#define STR_RC_EFM ((STR_RC_TYPE) 1L) /* Failed to malloc */
|
|
|
+#define STR_RC_EVN ((STR_RC_TYPE) 2L) /* Value is Null */
|
|
|
+#define STR_RC_EFMC ((STR_RC_TYPE) 3L) /* Failed to memcpy */
|
|
|
|
|
|
-#include "toolbox/errno.h"
|
|
|
+#include <stddef.h>
|
|
|
|
|
|
-#ifdef TOOLBOX_TYPEDEF
|
|
|
+#if defined(STR_TYPEDEF) || defined(TYPEDEFS)
|
|
|
typedef struct str str_st;
|
|
|
-#endif
|
|
|
+#endif /* STR_TYPEDEF || TYPEDEFS */
|
|
|
|
|
|
|
|
|
struct str {
|
|
|
@@ -24,14 +30,14 @@ str_create(const char *cstring, size_t cstring_size);
|
|
|
struct str*
|
|
|
str_create_ns(const char *cstring);
|
|
|
|
|
|
-RET_TYPE
|
|
|
+STR_RC_TYPE
|
|
|
str_destroy(struct str *str);
|
|
|
|
|
|
-RET_TYPE
|
|
|
+STR_RC_TYPE
|
|
|
str_to_lowercase(struct str *str);
|
|
|
-RET_TYPE
|
|
|
+STR_RC_TYPE
|
|
|
str_to_uppercase(struct str *str);
|
|
|
-RET_TYPE
|
|
|
+STR_RC_TYPE
|
|
|
str_to_titlecase(struct str *str);
|
|
|
|
|
|
_Bool
|
|
|
@@ -89,5 +95,218 @@ str_count_cstring_ns(struct str *str, char *cstring);
|
|
|
// formatted
|
|
|
// join
|
|
|
|
|
|
+#if defined(STR_IMP) || defined(IMPLEMENTATIONS)
|
|
|
+
|
|
|
+#include <string.h>
|
|
|
+#include <stdlib.h>
|
|
|
+
|
|
|
+#if defined(STR_LOG) || defined(LOGS)
|
|
|
+ #define __LOG(OUT, PFX, TXT) fprintf(OUT, PFX" %s: %s", __func__, TXT)
|
|
|
+ #define LOG_ERROR(TXT) __LOG(stderr, "[ERROR]", TXT)
|
|
|
+ #define LOG_INFO(TXT) __LOG(stdout, "[INFO]", TXT)
|
|
|
+#else
|
|
|
+ #define LOG_ERROR(TXT) ;
|
|
|
+ #define LOG_INFO(TXT) ;
|
|
|
+#endif /* STR_LOG */
|
|
|
+
|
|
|
+#define true ((unsigned char) 1L)
|
|
|
+#define false ((unsigned char) 0L)
|
|
|
+
|
|
|
+#define TEST_FOR_NULL(POINTER) \
|
|
|
+ if ( POINTER == NULL ) { \
|
|
|
+ LOG_ERROR("Null Pointer Not Expected"); \
|
|
|
+ str_errno = STR_RC_EVN; \
|
|
|
+ return str_errno; \
|
|
|
+ }
|
|
|
+
|
|
|
+#define TEST_FOR_NULL_SR(POINTER, STR_RC) \
|
|
|
+ if ( POINTER == NULL ) { \
|
|
|
+ LOG_ERROR("Null Pointer Not Expected"); \
|
|
|
+ str_errno = STR_RC_EVN; \
|
|
|
+ return STR_RC; \
|
|
|
+ }
|
|
|
+
|
|
|
+#define CHECK_MALLOC(POINTER, STR_RC) \
|
|
|
+ if ( POINTER == NULL ) { \
|
|
|
+ LOG_ERROR("Failed to malloc"); \
|
|
|
+ str_errno = STR_RC_EFM; \
|
|
|
+ return STR_RC; \
|
|
|
+ }
|
|
|
+
|
|
|
+#define CHECK_MALLOC_FREE(POINTER, STR_RC, FREE) \
|
|
|
+ if ( POINTER == NULL ) { \
|
|
|
+ free(FREE); \
|
|
|
+ LOG_ERROR("Failed to malloc"); \
|
|
|
+ str_errno = STR_RC_EFM; \
|
|
|
+ return STR_RC; \
|
|
|
+ }
|
|
|
+
|
|
|
+struct str*
|
|
|
+str_create(const char *cstring, size_t cstring_size)
|
|
|
+{
|
|
|
+ str_errno = STR_RC_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);
|
|
|
+ str_errno = STR_RC_EFMC;
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+struct str*
|
|
|
+str_create_ns(const char *cstring)
|
|
|
+{
|
|
|
+ str_errno = STR_RC_OK;
|
|
|
+#ifdef CSTRING_H
|
|
|
+ return str_create(cstring, cstring_len(cstring));
|
|
|
+#else
|
|
|
+ return str_create(cstring, strlen(cstring));
|
|
|
+#endif /* CSTRING_H */
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+STR_RC_TYPE
|
|
|
+str_destroy(struct str *str)
|
|
|
+{
|
|
|
+ TEST_FOR_NULL(str);
|
|
|
+ str_errno = STR_RC_OK;
|
|
|
+
|
|
|
+ free(str->data);
|
|
|
+ free(str);
|
|
|
+
|
|
|
+ return STR_RC_OK;
|
|
|
+}
|
|
|
+
|
|
|
+STR_RC_TYPE
|
|
|
+str_to_lowercase(struct str *str)
|
|
|
+{
|
|
|
+ TEST_FOR_NULL(str);
|
|
|
+ TEST_FOR_NULL(str->_c_data);
|
|
|
+ str_errno = STR_RC_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 STR_RC_OK;
|
|
|
+}
|
|
|
+
|
|
|
+STR_RC_TYPE
|
|
|
+str_to_uppercase(struct str *str)
|
|
|
+{
|
|
|
+ TEST_FOR_NULL(str);
|
|
|
+ TEST_FOR_NULL(str->_c_data);
|
|
|
+ str_errno = STR_RC_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 STR_RC_OK;
|
|
|
+}
|
|
|
+
|
|
|
+STR_RC_TYPE
|
|
|
+str_to_titlecase(struct str *str)
|
|
|
+{
|
|
|
+ TEST_FOR_NULL(str);
|
|
|
+ TEST_FOR_NULL(str->_c_data);
|
|
|
+ str_errno = STR_RC_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 STR_RC_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);
|
|
|
+ str_errno = STR_RC_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);
|
|
|
+ str_errno = STR_RC_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);
|
|
|
+
|
|
|
+#undef true
|
|
|
+#undef false
|
|
|
+
|
|
|
+#undef TEST_FOR_NULL
|
|
|
+#undef TEST_FOR_NULL_SR
|
|
|
+
|
|
|
+#undef CHECK_MALLOC
|
|
|
+#undef CHECK_MALLOC_FREE
|
|
|
+
|
|
|
+#undef LOG_ERROR
|
|
|
+#undef LOG_INFO
|
|
|
+
|
|
|
+#endif /* STR_IMP || IMPLEMENTATIONS */
|
|
|
|
|
|
-#endif
|
|
|
+#endif /* STR_H */
|