/libzdb-2.8.1/src/util/StringBuffer.c

# · C · 197 lines · 130 code · 44 blank · 23 comment · 25 complexity · 3f4a209fb9ee58ef38550a62af54b26d MD5 · raw file

  1. /*
  2. * Copyright (C) 2004-2011 Tildeslash Ltd. All rights reserved.
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License version 3.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. * You should have received a copy of the GNU General Public License
  13. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. #include "Config.h"
  16. #include <stdio.h>
  17. #include <string.h>
  18. #include <ctype.h>
  19. #include "StringBuffer.h"
  20. /**
  21. * Implementation of the StringBuffer interface.
  22. *
  23. * @file
  24. */
  25. /* ----------------------------------------------------------- Definitions */
  26. #define T StringBuffer_T
  27. struct T {
  28. int used;
  29. int length;
  30. uchar_t *buffer;
  31. };
  32. /* ------------------------------------------------------- Private methods */
  33. static inline void doAppend(T S, const char *s, va_list ap) {
  34. va_list ap_copy;
  35. while (true) {
  36. va_copy(ap_copy, ap);
  37. int n = vsnprintf(S->buffer + S->used, S->length - S->used, s, ap_copy);
  38. va_end(ap_copy);
  39. if (n > -1 && (S->used + n) < S->length) {
  40. S->used += n;
  41. break;
  42. }
  43. if (n > -1)
  44. S->length += STRLEN + n;
  45. else
  46. S->length *= 2;
  47. RESIZE(S->buffer, S->length + 1);
  48. }
  49. }
  50. /* Replace all occurences of ? in this string buffer with prefix[0..99] */
  51. static int StringBuffer_prepareSQL(T S, char prefix) {
  52. int n, i;
  53. for (n = i = 0; S->buffer[i]; i++) if (S->buffer[i] == '?') n++;
  54. if (n > 99)
  55. THROW(SQLException, "Max 99 parameters are allowed in a prepared statement. Found %d parameters in statement", n);
  56. else if (n) {
  57. int j, xl;
  58. char x[3] = {prefix};
  59. int required = (n * 2) + S->used;
  60. if (required >= S->length) {
  61. S->length = required;
  62. RESIZE(S->buffer, S->length);
  63. }
  64. for (i = 0, j = 1; (j <= n); i++) {
  65. if (S->buffer[i] == '?') {
  66. if(j<10){xl=2;x[1]=j+'0';}else{xl=3;x[1]=(j/10)+'0';x[2]=(j%10)+'0';}
  67. memmove(S->buffer + i + xl, S->buffer + i + 1, (S->used - (i + 1)));
  68. memmove(S->buffer + i, x, xl);
  69. S->used += xl - 1;
  70. j++;
  71. }
  72. }
  73. S->buffer[S->used] = 0;
  74. }
  75. return n;
  76. }
  77. /* ----------------------------------------------------- Protected methods */
  78. #ifdef PACKAGE_PROTECTED
  79. #pragma GCC visibility push(hidden)
  80. #endif
  81. T StringBuffer_new(const char *s) {
  82. T S;
  83. NEW(S);
  84. S->used = 0;
  85. S->length = STRLEN;
  86. S->buffer = ALLOC(STRLEN + 1);
  87. return StringBuffer_append(S, "%s", s);
  88. }
  89. T StringBuffer_create(int hint) {
  90. T S;
  91. if (hint <= 0)
  92. THROW(AssertException, "Illegal hint value");
  93. NEW(S);
  94. S->used = 0;
  95. S->length = hint;
  96. S->buffer = ALLOC(hint + 1);
  97. *S->buffer = 0;
  98. return S;
  99. }
  100. void StringBuffer_free(T *S) {
  101. assert(S && *S);
  102. FREE((*S)->buffer);
  103. FREE(*S);
  104. }
  105. T StringBuffer_append(T S, const char *s, ...) {
  106. assert(S);
  107. if (s && *s) {
  108. va_list ap;
  109. va_start(ap, s);
  110. doAppend(S, s, ap);
  111. va_end(ap);
  112. }
  113. return S;
  114. }
  115. T StringBuffer_vappend(T S, const char *s, va_list ap) {
  116. assert(S);
  117. if (s && *s) {
  118. va_list ap_copy;
  119. va_copy(ap_copy, ap);
  120. doAppend(S, s, ap_copy);
  121. va_end(ap_copy);
  122. }
  123. return S;
  124. }
  125. int StringBuffer_length(T S) {
  126. assert(S);
  127. return S->used;
  128. }
  129. void StringBuffer_clear(T S) {
  130. assert(S);
  131. S->used = 0;
  132. *S->buffer = 0;
  133. }
  134. const char *StringBuffer_toString(T S) {
  135. assert(S);
  136. return S->buffer;
  137. }
  138. int StringBuffer_prepare4postgres(T S) {
  139. assert(S);
  140. return StringBuffer_prepareSQL(S, '$');
  141. }
  142. int StringBuffer_prepare4oracle(T S) {
  143. assert(S);
  144. return StringBuffer_prepareSQL(S, ':');
  145. }
  146. void StringBuffer_removeTrailingSemicolon(T S) {
  147. assert(S);
  148. while (S->used && ((S->buffer[S->used - 1] == ';') || isspace(S->buffer[S->used - 1])))
  149. S->buffer[--S->used] = 0;
  150. }
  151. #ifdef PACKAGE_PROTECTED
  152. #pragma GCC visibility pop
  153. #endif