MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
BaseString.cpp
1 /*
2  Copyright (c) 2003, 2010, Oracle and/or its affiliates. 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 as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17 
18 /* -*- c-basic-offset: 4; -*- */
19 #include <ndb_global.h>
20 #include <BaseString.hpp>
21 #include "basestring_vsnprintf.h"
22 
24 {
25  m_chr = new char[1];
26  if (m_chr == NULL)
27  {
28  errno = ENOMEM;
29  m_len = 0;
30  return;
31  }
32  m_chr[0] = 0;
33  m_len = 0;
34 }
35 
36 BaseString::BaseString(const char* s)
37 {
38  if (s == NULL)
39  {
40  m_chr = NULL;
41  m_len = 0;
42  return;
43  }
44  const size_t n = strlen(s);
45  m_chr = new char[n + 1];
46  if (m_chr == NULL)
47  {
48  errno = ENOMEM;
49  m_len = 0;
50  return;
51  }
52  memcpy(m_chr, s, n + 1);
53  m_len = n;
54 }
55 
56 BaseString::BaseString(const char * s, size_t n)
57 {
58  if (s == NULL || n == 0)
59  {
60  m_chr = NULL;
61  m_len = 0;
62  return;
63  }
64  m_chr = new char[n + 1];
65  if (m_chr == NULL)
66  {
67  errno = ENOMEM;
68  m_len = 0;
69  return;
70  }
71  memcpy(m_chr, s, n);
72  m_chr[n] = 0;
73  m_len = n;
74 }
75 
77 {
78  const char* const s = str.m_chr;
79  const size_t n = str.m_len;
80  if (s == NULL)
81  {
82  m_chr = NULL;
83  m_len = 0;
84  return;
85  }
86  char* t = new char[n + 1];
87  if (t == NULL)
88  {
89  errno = ENOMEM;
90  m_chr = NULL;
91  m_len = 0;
92  return;
93  }
94  memcpy(t, s, n + 1);
95  m_chr = t;
96  m_len = n;
97 }
98 
100 {
101  delete[] m_chr;
102 }
103 
104 BaseString&
105 BaseString::assign(const char* s)
106 {
107  if (s == NULL)
108  {
109  if (m_chr)
110  delete[] m_chr;
111  m_chr = NULL;
112  m_len = 0;
113  return *this;
114  }
115  size_t n = strlen(s);
116  char* t = new char[n + 1];
117  if (t)
118  {
119  memcpy(t, s, n + 1);
120  }
121  else
122  {
123  errno = ENOMEM;
124  n = 0;
125  }
126  delete[] m_chr;
127  m_chr = t;
128  m_len = n;
129  return *this;
130 }
131 
132 BaseString&
133 BaseString::assign(const char* s, size_t n)
134 {
135  char* t = new char[n + 1];
136  if (t)
137  {
138  memcpy(t, s, n);
139  t[n] = 0;
140  }
141  else
142  {
143  errno = ENOMEM;
144  n = 0;
145  }
146  delete[] m_chr;
147  m_chr = t;
148  m_len = n;
149  return *this;
150 }
151 
152 BaseString&
153 BaseString::assign(const BaseString& str, size_t n)
154 {
155  if (n > str.m_len)
156  n = str.m_len;
157  return assign(str.m_chr, n);
158 }
159 
160 BaseString&
161 BaseString::append(const char* s)
162 {
163  if (s == NULL)
164  return *this;
165 
166  size_t n = strlen(s);
167  char* t = new char[m_len + n + 1];
168  if (t)
169  {
170  memcpy(t, m_chr, m_len);
171  memcpy(t + m_len, s, n + 1);
172  }
173  else
174  {
175  errno = ENOMEM;
176  m_len = 0;
177  n = 0;
178  }
179  delete[] m_chr;
180  m_chr = t;
181  m_len += n;
182  return *this;
183 }
184 
185 BaseString&
187  return appfmt("%c", c);
188 }
189 
190 BaseString&
192 {
193  return append(str.m_chr);
194 }
195 
196 BaseString&
198  const BaseString &separator) {
199  for(size_t i=0;i<vector.size(); i++) {
200  append(vector[i]);
201  if(i<vector.size()-1)
202  append(separator);
203  }
204  return *this;
205 }
206 
207 BaseString&
208 BaseString::assfmt(const char *fmt, ...)
209 {
210  char buf[1];
211  va_list ap;
212  int l;
213 
214  /* Figure out how long the formatted string will be. A small temporary
215  * buffer is used, because I don't trust all implementations to work
216  * when called as vsnprintf(NULL, 0, ...).
217  */
218  va_start(ap, fmt);
219  l = basestring_vsnprintf(buf, sizeof(buf), fmt, ap) + 1;
220  va_end(ap);
221  if(l > (int)m_len) {
222  char *t = new char[l];
223  if (t == NULL)
224  {
225  errno = ENOMEM;
226  return *this;
227  }
228  delete[] m_chr;
229  m_chr = t;
230  }
231  va_start(ap, fmt);
232  l = basestring_vsnprintf(m_chr, l, fmt, ap);
233  assert(l == (int)strlen(m_chr));
234  va_end(ap);
235  m_len = strlen(m_chr);
236  return *this;
237 }
238 
239 BaseString&
240 BaseString::appfmt(const char *fmt, ...)
241 {
242  char buf[1];
243  va_list ap;
244  int l;
245 
246  /* Figure out how long the formatted string will be. A small temporary
247  * buffer is used, because I don't trust all implementations to work
248  * when called as vsnprintf(NULL, 0, ...).
249  */
250  va_start(ap, fmt);
251  l = basestring_vsnprintf(buf, sizeof(buf), fmt, ap) + 1;
252  va_end(ap);
253  char *tmp = new char[l];
254  if (tmp == NULL)
255  {
256  errno = ENOMEM;
257  return *this;
258  }
259  va_start(ap, fmt);
260  basestring_vsnprintf(tmp, l, fmt, ap);
261  va_end(ap);
262  append(tmp);
263  delete[] tmp;
264  return *this;
265 }
266 
267 BaseString&
269 {
270  if (this != &str) {
271  this->assign(str);
272  }
273  return *this;
274 }
275 
276 int
278  const BaseString &separator,
279  int maxSize) const {
280  char *str = strdup(m_chr);
281  int i, start, len, num = 0;
282  len = strlen(str);
283  for(start = i = 0;
284  (i <= len) && ( (maxSize<0) || ((int)v.size()<=maxSize-1) );
285  i++) {
286  if(strchr(separator.c_str(), str[i]) || i == len) {
287  if(maxSize < 0 || (int)v.size() < maxSize-1)
288  str[i] = '\0';
289  v.push_back(BaseString(str+start));
290  num++;
291  start = i+1;
292  }
293  }
294  free(str);
295 
296  return num;
297 }
298 
299 ssize_t
300 BaseString::indexOf(char c) const {
301  char *p;
302  p = strchr(m_chr, c);
303  if(p == NULL)
304  return -1;
305  return (ssize_t)(p-m_chr);
306 }
307 
308 ssize_t
309 BaseString::lastIndexOf(char c) const {
310  char *p;
311  p = strrchr(m_chr, c);
312  if(p == NULL)
313  return -1;
314  return (ssize_t)(p-m_chr);
315 }
316 
318 BaseString::substr(ssize_t start, ssize_t stop) const {
319  if(stop < 0)
320  stop = length();
321  ssize_t len = stop-start;
322  if(len <= 0)
323  return BaseString("");
324  BaseString s;
325  s.assign(m_chr+start, len);
326  return s;
327 }
328 
329 static bool
330 iswhite(char c) {
331  switch(c) {
332  case ' ':
333  case '\t':
334  return true;
335  default:
336  return false;
337  }
338  /* NOTREACHED */
339 }
340 
341 char **
342 BaseString::argify(const char *argv0, const char *src) {
343  Vector<char *> vargv;
344 
345  if(argv0 != NULL)
346  {
347  char *t = strdup(argv0);
348  if (t == NULL)
349  {
350  errno = ENOMEM;
351  return NULL;
352  }
353  if (vargv.push_back(t))
354  {
355  free(t);
356  return NULL;
357  }
358  }
359 
360  char *tmp = new char[strlen(src)+1];
361  if (tmp == NULL)
362  {
363  for(size_t i = 0; i < vargv.size(); i++)
364  free(vargv[i]);
365  errno = ENOMEM;
366  return NULL;
367  }
368  char *dst = tmp;
369  const char *end = src + strlen(src);
370  /* Copy characters from src to destination, while compacting them
371  * so that all whitespace is compacted and replaced by a NUL-byte.
372  * At the same time, add pointers to strings in the vargv vector.
373  * When whitespace is detected, the characters '"' and '\' are honored,
374  * to make it possible to give arguments containing whitespace.
375  * The semantics of '"' and '\' match that of most Unix shells.
376  */
377  while(src < end && *src) {
378  /* Skip initial whitespace */
379  while(src < end && *src && iswhite(*src))
380  src++;
381 
382  char *begin = dst;
383  while(src < end && *src) {
384  /* Handle '"' quotation */
385  if(*src == '"') {
386  src++;
387  while(src < end && *src && *src != '"') {
388  if(*src == '\\')
389  src++;
390  *dst++ = *src++;
391  }
392  src++;
393  if(src >= end)
394  goto end;
395  }
396 
397  /* Handle '\' */
398  if(*src == '\\')
399  src++;
400  else if(iswhite(*src))
401  break;
402 
403  /* Actually copy characters */
404  *dst++ = *src++;
405  }
406 
407  /* Make sure the string is properly terminated */
408  *dst++ = '\0';
409  src++;
410 
411  {
412  char *t = strdup(begin);
413  if (t == NULL)
414  {
415  delete[] tmp;
416  for(size_t i = 0; i < vargv.size(); i++)
417  free(vargv[i]);
418  errno = ENOMEM;
419  return NULL;
420  }
421  if (vargv.push_back(t))
422  {
423  free(t);
424  delete[] tmp;
425  for(size_t i = 0; i < vargv.size(); i++)
426  free(vargv[i]);
427  return NULL;
428  }
429  }
430  }
431  end:
432 
433  delete[] tmp;
434  if (vargv.push_back(NULL))
435  {
436  for(size_t i = 0; i < vargv.size(); i++)
437  free(vargv[i]);
438  return NULL;
439  }
440 
441  /* Convert the C++ Vector into a C-vector of strings, suitable for
442  * calling execv().
443  */
444  char **argv = (char **)malloc(sizeof(*argv) * (vargv.size()));
445  if(argv == NULL)
446  {
447  for(size_t i = 0; i < vargv.size(); i++)
448  free(vargv[i]);
449  errno = ENOMEM;
450  return NULL;
451  }
452 
453  for(size_t i = 0; i < vargv.size(); i++){
454  argv[i] = vargv[i];
455  }
456 
457  return argv;
458 }
459 
460 BaseString&
461 BaseString::trim(const char * delim){
462  trim(m_chr, delim);
463  m_len = strlen(m_chr);
464  return * this;
465 }
466 
467 char*
468 BaseString::trim(char * str, const char * delim){
469  int len = strlen(str) - 1;
470  for(; len > 0 && strchr(delim, str[len]); len--)
471  ;
472 
473  int pos = 0;
474  for(; pos <= len && strchr(delim, str[pos]); pos++)
475  ;
476 
477  if(pos > len){
478  str[0] = 0;
479  return 0;
480  } else {
481  memmove(str, &str[pos], len - pos + 1);
482  str[len-pos+1] = 0;
483  }
484 
485  return str;
486 }
487 
488 int
489 BaseString::vsnprintf(char *str, size_t size, const char *format, va_list ap)
490 {
491  return(basestring_vsnprintf(str, size, format, ap));
492 }
493 
494 int
495 BaseString::snprintf(char *str, size_t size, const char *format, ...)
496 {
497  va_list ap;
498  va_start(ap, format);
499  int ret= basestring_vsnprintf(str, size, format, ap);
500  va_end(ap);
501  return(ret);
502 }
503 
505 BaseString::getText(unsigned size, const Uint32 data[])
506 {
507  BaseString to;
508  char * buf = (char*)malloc(32*size+1);
509  if (buf)
510  {
511  BitmaskImpl::getText(size, data, buf);
512  to.append(buf);
513  free(buf);
514  }
515  return to;
516 }
517 
519 BaseString::getPrettyText(unsigned size, const Uint32 data[])
520 {
521  const char* delimiter = "";
522  unsigned found = 0;
523  const unsigned MAX_BITS = sizeof(Uint32) * 8 * size;
524  BaseString to;
525  for (unsigned i = 0; i < MAX_BITS; i++)
526  {
527  if (BitmaskImpl::get(size, data, i))
528  {
529  to.appfmt("%s%d", delimiter, i);
530  found++;
531  if (found < BitmaskImpl::count(size, data) - 1)
532  delimiter = ", ";
533  else
534  delimiter = " and ";
535  }
536  }
537  return to;
538 }
539 
541 BaseString::getPrettyTextShort(unsigned size, const Uint32 data[])
542 {
543  const char* delimiter = "";
544  const unsigned MAX_BITS = sizeof(Uint32) * 8 * size;
545  BaseString to;
546  for (unsigned i = 0; i < MAX_BITS; i++)
547  {
548  if (BitmaskImpl::get(size, data, i))
549  {
550  to.appfmt("%s%d", delimiter, i);
551  delimiter = ",";
552  }
553  }
554  return to;
555 }
556 
557 const void*
558 BaseString_get_key(const void* key, size_t* key_length)
559 {
560  const BaseString* str = (const BaseString*)key;
561  *key_length = str->length();
562  return str->c_str();
563 }
564 
565 #ifdef TEST_BASE_STRING
566 
567 #include <NdbTap.hpp>
568 
569 TAPTEST(BaseString)
570 {
571  BaseString s("abc");
572  BaseString t(s);
573  s.assign("def");
574  t.append("123");
575  OK(s == "def");
576  OK(t == "abc123");
577  s.assign("");
578  t.assign("");
579  for (unsigned i = 0; i < 1000; i++) {
580  s.append("xyz");
581  t.assign(s);
582  OK(strlen(t.c_str()) % 3 == 0);
583  }
584 
585  {
586  BaseString s(":123:abc:;:foo:");
588  OK(s.split(v, ":;") == 7);
589 
590  OK(v[0] == "");
591  OK(v[1] == "123");
592  OK(v[2] == "abc");
593  OK(v[3] == "");
594  OK(v[4] == "");
595  OK(v[5] == "foo");
596  OK(v[6] == "");
597  }
598 
599  {
600  BaseString s(":123:abc:foo:bar");
602  OK(s.split(v, ":;", 4) == 4);
603 
604  OK(v[0] == "");
605  OK(v[1] == "123");
606  OK(v[2] == "abc");
607  OK(v[3] == "foo:bar");
608 
609  BaseString n;
610  n.append(v, "()");
611  OK(n == "()123()abc()foo:bar");
612  n = "";
613  n.append(v);
614  OK(n == " 123 abc foo:bar");
615  }
616 
617  {
618  OK(BaseString("hamburger").substr(4,2) == "");
619  OK(BaseString("hamburger").substr(3) == "burger");
620  OK(BaseString("hamburger").substr(4,8) == "urge");
621  OK(BaseString("smiles").substr(1,5) == "mile");
622  OK(BaseString("012345").indexOf('2') == 2);
623  OK(BaseString("hej").indexOf('X') == -1);
624  }
625 
626  {
627  OK(BaseString(" 1").trim(" ") == "1");
628  OK(BaseString("1 ").trim(" ") == "1");
629  OK(BaseString(" 1 ").trim(" ") == "1");
630  OK(BaseString("abc\t\n\r kalleabc\t\r\n").trim("abc\t\r\n ") == "kalle");
631  OK(BaseString(" ").trim(" ") == "");
632  }
633 
634  // Tests for BUG#38662
635  BaseString s2(NULL);
636  BaseString s3;
637  BaseString s4("elf");
638 
639  OK(s3.append((const char*)NULL) == "");
640  OK(s4.append((const char*)NULL) == "elf");
641  OK(s4.append(s3) == "elf");
642  OK(s4.append(s2) == "elf");
643  OK(s4.append(s4) == "elfelf");
644 
645  OK(s3.assign((const char*)NULL).c_str() == NULL);
646  OK(s4.assign((const char*)NULL).c_str() == NULL);
647  OK(s4.assign(s4).c_str() == NULL);
648 
649  //tests for Bug #45733 Cluster with more than 4 storage node
650  for(int i=0;i<20;i++)
651  {
652 #define BIG_ASSFMT_OK(X) do{u_int x=(X);OK(s2.assfmt("%*s",x,"Z").length() == x);}while(0)
653  BIG_ASSFMT_OK(8);
654  BIG_ASSFMT_OK(511);
655  BIG_ASSFMT_OK(512);
656  BIG_ASSFMT_OK(513);
657  BIG_ASSFMT_OK(1023);
658  BIG_ASSFMT_OK(1024);
659  BIG_ASSFMT_OK(1025);
660  BIG_ASSFMT_OK(20*1024*1024);
661  }
662 
663  return 1; // OK
664 }
665 
666 #endif
667 
668 template class Vector<BaseString>;