mstring.c 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. #include "defs.h"
  2. #include "mstring.h"
  3. #include <stdarg.h>
  4. /* parameters about string length. START_STR is the starting size and
  5. ** START_STR+TAIL should be a power of two
  6. Renamed to START_STR because START is defined in defs.h with another value */
  7. #define START_STR 24
  8. #define TAIL 8
  9. void msprintf(struct mstring *s, const char *fmt, ...)
  10. {
  11. static char buf[4096]; /* a big static buffer */
  12. va_list args;
  13. int len;
  14. if (!s || !s->base) return;
  15. va_start(args, fmt);
  16. vsprintf(buf, fmt, args);
  17. va_end(args);
  18. len = strlen(buf);
  19. if (len > (s->end - s->ptr)) {
  20. int cp = s->ptr - s->base, cl = s->end - s->base, nl = cl;
  21. while (len > (nl - cp))
  22. nl = nl + nl + TAIL;
  23. if ((s->base = realloc(s->base, nl))) {
  24. s->ptr = s->base + cp;
  25. s->end = s->base + nl; }
  26. else {
  27. s->ptr = s->end = 0;
  28. return; } }
  29. memcpy(s->ptr, buf, len);
  30. s->ptr += len;
  31. }
  32. int mputchar(struct mstring *s, int ch)
  33. {
  34. if (!s || !s->base) return ch;
  35. if (s->ptr == s->end) {
  36. int len = s->end - s->base;
  37. if ((s->base = realloc(s->base, len+len+TAIL))) {
  38. s->ptr = s->base + len;
  39. s->end = s->base + len+len+TAIL; }
  40. else {
  41. s->ptr = s->end = 0;
  42. return ch; } }
  43. *s->ptr++ = ch;
  44. return ch;
  45. }
  46. struct mstring *msnew(void) {
  47. struct mstring *n = malloc(sizeof(struct mstring));
  48. if (n && (n->base = n->ptr = malloc(START_STR)))
  49. n->end = n->base + START_STR;
  50. else if (n) {
  51. free(n);
  52. n = 0; }
  53. return n;
  54. }
  55. char *msdone(struct mstring *s)
  56. {
  57. char *r = 0;
  58. if (s) {
  59. mputc(s, 0);
  60. r = s->base;
  61. free(s); }
  62. return r;
  63. }
  64. /* compare two strings, ignoring whitespace, except between two letters or
  65. ** digits (and treat all of these as equal) */
  66. int strnscmp(const char *a, const char *b)
  67. {
  68. while(1) {
  69. while (isspace(*a)) a++;
  70. while (isspace(*b)) b++;
  71. while (*a && *a == *b) a++,b++;
  72. if (isspace(*a)) {
  73. if (isalnum(a[-1]) && isalnum(*b))
  74. break; }
  75. else if (isspace(*b)) {
  76. if (isalnum(b[-1]) && isalnum(*a))
  77. break; }
  78. else
  79. break; }
  80. return *a - *b;
  81. }
  82. unsigned int strnshash(const char *s)
  83. {
  84. unsigned int h = 0;
  85. while (*s) {
  86. if (!isspace(*s))
  87. h = (h<<5) - h + *s;
  88. s++; }
  89. return h;
  90. }