string.h 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. #ifndef __MHL_STRING_H
  2. #define __MHL_STRING_H
  3. #include <ctype.h>
  4. #include <stdarg.h>
  5. #include <mhl/memory.h>
  6. #define mhl_str_dup(str) ((str ? strdup(str) : strdup("")))
  7. #define mhl_str_ndup(str,len) ((str ? strndup(str,len) : strdup("")))
  8. #define mhl_str_len(str) ((str ? strlen(str) : 0))
  9. static inline char * mhl_str_dup_range(const char * s_start, const char * s_bound)
  10. {
  11. return mhl_str_ndup(s_start, s_bound - s_start);
  12. }
  13. static inline char* mhl_str_trim(char* str)
  14. {
  15. if (!str) return NULL; // NULL string ?! bail out.
  16. // find the first non-space
  17. char* start; for (start=str; ((*str) && (!isspace(*str))); str++);
  18. // only spaces ?
  19. if (!(*str)) { *str = 0; return str; }
  20. // get the size (cannot be empty - catched above)
  21. size_t _sz = strlen(str);
  22. // find the proper end
  23. char* end;
  24. for (end=(str+_sz-1); ((end>str) && (isspace(*end))); end--);
  25. end[1] = 0; // terminate, just to be sure
  26. // if we have no leading spaces, just trucate
  27. if (start==str) { end++; *end = 0; return str; }
  28. // if it' only one char, dont need memmove for that
  29. if (start==end) { str[0]=*start; str[1]=0; return str; }
  30. // by here we have a (non-empty) region between start end end
  31. memmove(str,start,(end-start+1));
  32. return str;
  33. }
  34. static inline void mhl_str_toupper(char* str)
  35. {
  36. if (str)
  37. for (;*str;str++)
  38. *str = toupper(*str);
  39. }
  40. #define __STR_CONCAT_MAX 32
  41. /* _NEVER_ call this function directly ! */
  42. static inline char* __mhl_str_concat_hlp(const char* base, ...)
  43. {
  44. static const char* arg_ptr[__STR_CONCAT_MAX];
  45. static size_t arg_sz[__STR_CONCAT_MAX];
  46. int count = 0;
  47. size_t totalsize = 0;
  48. // first pass: scan through the params and count string sizes
  49. va_list par;
  50. if (base)
  51. {
  52. arg_ptr[0] = base;
  53. arg_sz[0] = totalsize = strlen(base);
  54. count = 1;
  55. }
  56. va_list args;
  57. va_start(args,base);
  58. char* a;
  59. // note: we use ((char*)(1)) as terminator - NULL is a valid argument !
  60. while ((a = va_arg(args, char*))!=(char*)1)
  61. {
  62. // printf("a=%u\n", a);
  63. if (a)
  64. {
  65. arg_ptr[count] = a;
  66. arg_sz[count] = strlen(a);
  67. totalsize += arg_sz[count];
  68. count++;
  69. }
  70. }
  71. if (!count)
  72. return mhl_str_dup("");
  73. // now as we know how much to copy, allocate the buffer
  74. char* buffer = (char*)mhl_mem_alloc_u(totalsize+2);
  75. char* current = buffer;
  76. int x=0;
  77. for (x=0; x<count; x++)
  78. {
  79. memcpy(current, arg_ptr[x], arg_sz[x]);
  80. current += arg_sz[x];
  81. }
  82. *current = 0;
  83. return buffer;
  84. }
  85. #define mhl_str_concat(...) (__mhl_str_concat_hlp(__VA_ARGS__, (char*)(1)))
  86. static inline char* mhl_str_reverse(char* ptr)
  87. {
  88. if (!ptr) return NULL; // missing string
  89. if (!(ptr[0] && ptr[1])) return ptr; // empty or 1-ch string
  90. size_t _sz = strlen(ptr);
  91. char* start = ptr;
  92. char* end = ptr+_sz-1;
  93. while (start<end)
  94. {
  95. char c = *start;
  96. *start = *end;
  97. *end = c;
  98. start++;
  99. end--;
  100. }
  101. return ptr;
  102. }
  103. #endif /* __MHL_STRING_H */