Qore Programming Language  0.9.16
qore_string_private.h
1 /* -*- mode: c++; indent-tabs-mode: nil -*- */
2 /*
3  qore_string_private.h
4 
5  QoreString private implementation
6 
7  Qore Programming Language
8 
9  Copyright (C) 2003 - 2019 Qore Technologies, s.r.o.
10 
11  Permission is hereby granted, free of charge, to any person obtaining a
12  copy of this software and associated documentation files (the "Software"),
13  to deal in the Software without restriction, including without limitation
14  the rights to use, copy, modify, merge, publish, distribute, sublicense,
15  and/or sell copies of the Software, and to permit persons to whom the
16  Software is furnished to do so, subject to the following conditions:
17 
18  The above copyright notice and this permission notice shall be included in
19  all copies or substantial portions of the Software.
20 
21  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27  DEALINGS IN THE SOFTWARE.
28 
29  Note that the Qore library is released under a choice of three open-source
30  licenses: MIT (as above), LGPL 2+, or GPL 2+; see README-LICENSE for more
31  information.
32 */
33 
34 #ifndef QORE_QORE_STRING_PRIVATE_H
35 #define QORE_QORE_STRING_PRIVATE_H
36 
37 #include <vector>
38 
39 #define MAX_INT_STRING_LEN 48
40 #define MAX_BIGINT_STRING_LEN 48
41 #define MAX_FLOAT_STRING_LEN 48
42 #define STR_CLASS_BLOCK (0x10 * 4)
43 #define STR_CLASS_EXTRA (0x10 * 3)
44 
45 #define MIN_SPRINTF_BUFSIZE 64
46 
47 #define QUS_PATH 0
48 #define QUS_QUERY 1
49 #define QUS_FRAGMENT 2
50 
51 typedef std::vector<int> intvec_t;
52 
53 hashdecl qore_string_private {
54 private:
55 
56 public:
57  qore_size_t len = 0;
58  qore_size_t allocated = 0;
59  char* buf = nullptr;
60  const QoreEncoding* charset = nullptr;
61 
62  DLLLOCAL qore_string_private() {
63  }
64 
65  DLLLOCAL qore_string_private(const qore_string_private &p) {
66  allocated = p.len + STR_CLASS_EXTRA;
67  allocated = (allocated / 0x10 + 1) * 0x10; // use complete cache line
68  buf = (char*)malloc(sizeof(char) * allocated);
69  len = p.len;
70  if (len)
71  memcpy(buf, p.buf, len);
72  buf[len] = '\0';
73  charset = p.getEncoding();
74  }
75 
76  DLLLOCAL ~qore_string_private() {
77  if (buf)
78  free(buf);
79  }
80 
81  DLLLOCAL void check_char(qore_size_t i) {
82  if (i >= allocated) {
83  qore_size_t d = i >> 2;
84  allocated = i + (d < STR_CLASS_BLOCK ? STR_CLASS_BLOCK : d);
85  allocated = (allocated / 0x10 + 1) * 0x10; // use complete cache line
86  buf = (char*)realloc(buf, allocated * sizeof(char));
87  }
88  }
89 
90  DLLLOCAL qore_size_t check_offset(qore_offset_t offset) {
91  if (offset < 0) {
92  offset = len + offset;
93  return offset < 0 ? 0 : offset;
94  }
95 
96  return ((qore_size_t)offset > len) ? len : offset;
97  }
98 
99  DLLLOCAL void check_offset(qore_offset_t offset, qore_offset_t num, qore_size_t &n_offset, qore_size_t &n_num) {
100  n_offset = check_offset(offset);
101 
102  if (num < 0) {
103  num = len + num - n_offset;
104  if (num < 0)
105  n_num = 0;
106  else
107  n_num = num;
108  return;
109  }
110  n_num = num;
111  }
112 
113  // NOTE: this is purely byte oriented - no character semantics here
114  DLLLOCAL qore_offset_t find(char c, qore_offset_t pos = 0) {
115  if (pos < 0) {
116  pos = len + pos;
117  if (pos < 0)
118  pos = 0;
119  }
120  else if (pos > 0 && pos > (qore_offset_t)len)
121  return -1;
122  const char* p;
123  if (!(p = strchr(buf + pos, c)))
124  return -1;
125  return (qore_offset_t)(p - buf);
126  }
127 
128  // NOTE: this is purely byte oriented - no character semantics here
129  DLLLOCAL qore_offset_t rfind(char c, qore_offset_t pos = -1) {
130  if (pos < 0) {
131  pos = len + pos;
132  if (pos < 0)
133  return -1;
134  }
135  else if (pos > 0 && pos > (qore_offset_t)len)
136  pos = len - 1;
137 
138  const char* p = buf + pos;
139  while (p >= buf) {
140  if (*p == c)
141  return (qore_offset_t)(p - buf);
142  --p;
143  }
144  return -1;
145  }
146 
147  // NOTE: this is purely byte oriented - no character semantics here
148  DLLLOCAL qore_offset_t findAny(const char* str, qore_offset_t pos = 0) {
149  if (pos < 0) {
150  pos = len + pos;
151  if (pos < 0)
152  pos = 0;
153  }
154  else if (pos > 0 && pos > (qore_offset_t)len)
155  return -1;
156  const char* p;
157  if (!(p = strstr(buf + pos, str)))
158  return -1;
159  return (qore_offset_t)(p - buf);
160  }
161 
162  // NOTE: this is purely byte oriented - no character semantics here
163  DLLLOCAL qore_offset_t rfindAny(const char* str, qore_offset_t pos = -1) {
164  if (pos < 0) {
165  pos = len + pos;
166  if (pos < 0)
167  return -1;
168  }
169  else if (pos > 0 && pos > (qore_offset_t)len)
170  pos = len - 1;
171 
172  const char* p = buf + pos;
173  while (p >= buf) {
174  for (const char* t = str; *t; ++t) {
175  if (*p == *t)
176  return (qore_offset_t)(p - buf);
177  }
178  --p;
179  }
180  return -1;
181  }
182 
183  DLLLOCAL static qore_offset_t index_simple(const char* haystack, size_t hlen, const char* needle, size_t nlen,
184  qore_offset_t pos = 0) {
185  const char* start = haystack + pos;
186  void* ptr = q_memmem(start, hlen - pos, needle, nlen);
187  if (!ptr) {
188  return -1;
189  }
190  return reinterpret_cast<const char*>(ptr) - start + pos;
191  }
192 
193  DLLLOCAL qore_offset_t index(const QoreString &orig_needle, qore_offset_t pos, ExceptionSink *xsink) const {
194  assert(xsink);
195  TempEncodingHelper needle(orig_needle, getEncoding(), xsink);
196  if (!needle)
197  return -1;
198 
199  // do simple index
200  if (!getEncoding()->isMultiByte()) {
201  if (pos < 0) {
202  pos = len + pos;
203  if (pos < 0) {
204  pos = 0;
205  }
206  } else if (pos >= (qore_offset_t)len) {
207  return -1;
208  }
209 
210  return index_simple(buf, len, needle->c_str(), needle->size(), pos);
211  }
212 
213  // do multibyte index()
214  if (findByteOffset(pos, xsink))
215  return -1;
216  if (pos < 0)
217  pos = 0;
218  else if (pos >= (qore_offset_t)len)
219  return -1;
220 
221  qore_offset_t ind = index_simple(buf + pos, len - pos, needle->c_str(), needle->size());
222  if (ind != -1) {
223  ind = getEncoding()->getCharPos(buf, buf + pos + ind, xsink);
224  if (*xsink)
225  return -1;
226  }
227 
228  return ind;
229  }
230 
231  DLLLOCAL qore_offset_t bindex(const QoreString &needle, qore_offset_t pos) const {
232  if (needle.strlen() + pos > len)
233  return -1;
234 
235  return bindex(needle.getBuffer(), pos);
236  }
237 
238  DLLLOCAL qore_offset_t bindex(const std::string &needle, qore_offset_t pos) const {
239  if (needle.size() + pos > len)
240  return -1;
241 
242  return bindex(needle.c_str(), pos);
243  }
244 
245  DLLLOCAL qore_offset_t bindex(const char *needle, qore_offset_t pos) const {
246  if (pos < 0) {
247  pos = len + pos;
248  if (pos < 0) {
249  pos = 0;
250  }
251  } else if (pos >= (qore_offset_t)len) {
252  return -1;
253  }
254 
255  return index_simple(buf, len, needle, strlen(needle), pos);
256  }
257 
258  // finds the last occurrence of needle in haystack at or before position pos
259  // pos must be a non-negative valid byte offset in haystack
260  DLLLOCAL static qore_offset_t rindex_simple(const char* haystack, qore_size_t hlen, const char* needle,
261  qore_size_t nlen, qore_offset_t pos = -1) {
262  if (pos < 0) {
263  pos = hlen + pos;
264  if (pos < 0) {
265  return -1;
266  }
267  } else if (pos >= hlen) {
268  pos = hlen - 1;
269  }
270 
271  assert(pos < hlen);
272  void* ptr = q_memrmem(haystack, pos + 1, needle, nlen);
273  if (!ptr) {
274  return -1;
275  }
276  return static_cast<qore_offset_t>(reinterpret_cast<const char*>(ptr) - reinterpret_cast<const char*>(haystack));
277  }
278 
279  // start is a byte offset that has to point to the start of a valid character
280  DLLLOCAL int findByteOffset(qore_offset_t& pos, ExceptionSink* xsink, qore_size_t start = 0) const {
281  assert(xsink);
282  assert(getEncoding()->isMultiByte());
283  if (!pos)
284  return 0;
285  // get positive character offset if negative
286  if (pos < 0) {
287  // get the length of the string in characters
288  qore_size_t clen = getEncoding()->getLength(buf + start, buf + len, xsink);
289  if (*xsink)
290  return -1;
291  pos = clen + pos;
292  }
293  // now get the byte position from this character offset
294  pos = getEncoding()->getByteLen(buf + start, buf + len, pos, xsink);
295  return *xsink ? -1 : 0;
296  }
297 
298  DLLLOCAL qore_offset_t rindex(const QoreString &orig_needle, qore_offset_t pos, ExceptionSink *xsink) const {
299  assert(xsink);
300  TempEncodingHelper needle(orig_needle, getEncoding(), xsink);
301  if (!needle)
302  return -1;
303 
304  if (!getEncoding()->isMultiByte()) {
305  if (pos < 0) {
306  pos = len + pos;
307  if (pos < 0)
308  return -1;
309  }
310 
311  return rindex_simple(buf, len, needle->c_str(), needle->size(), pos);
312  }
313 
314  // do multi-byte rindex
315  if (findByteOffset(pos, xsink))
316  return -1;
317  if (pos < 0)
318  return -1;
319 
320  // get byte rindex position
321  qore_offset_t ind = rindex_simple(buf, len, needle->c_str(), needle->size(), pos);
322 
323  // calculate character position from byte position
324  if (ind && ind != -1) {
325  ind = getEncoding()->getCharPos(buf, buf + ind, xsink);
326  if (*xsink)
327  return 0;
328  }
329 
330  return ind;
331  }
332 
333  DLLLOCAL qore_offset_t brindex(const QoreString &needle, qore_offset_t pos) const {
334  return brindex(needle.getBuffer(), needle.strlen(), pos);
335  }
336 
337  DLLLOCAL qore_offset_t brindex(const std::string &needle, qore_offset_t pos) const {
338  return brindex(needle.c_str(), needle.size(), pos);
339  }
340 
341  DLLLOCAL qore_offset_t brindex(const char *needle, qore_size_t needle_len, qore_offset_t pos) const {
342  if (needle_len + pos > len)
343  return -1;
344 
345  if (pos < 0)
346  pos = len + pos;
347 
348  if (pos < 0)
349  return -1;
350 
351  return rindex_simple(buf, len, needle, needle_len, pos);
352  }
353 
354  DLLLOCAL bool isDataPrintableAscii() const {
355  for (qore_size_t i = 0; i < len; ++i) {
356  if (buf[i] < 32 || buf[i] > 126)
357  return false;
358  }
359  return true;
360  }
361 
362  DLLLOCAL bool isDataAscii() const {
363  for (qore_size_t i = 0; i < len; ++i) {
364  if ((unsigned char)(buf[i]) > 127)
365  return false;
366  }
367  return true;
368  }
369 
370  DLLLOCAL void concat_intern(const char* p, qore_size_t plen) {
371  assert(p);
372  assert(plen);
373  check_char(len + plen);
374  memcpy(buf + len, p, plen);
375  len += plen;
376  buf[len] = '\0';
377  }
378 
379  DLLLOCAL void concat_simple(const qore_string_private& str, qore_offset_t pos) {
380  if (pos < 0) {
381  pos = str.len + pos;
382  if (pos < 0)
383  pos = 0;
384  }
385  else if (pos >= (qore_offset_t)str.len)
386  return;
387 
388  concat_intern(str.buf + pos, str.len - pos);
389  }
390 
391  DLLLOCAL int concat(const qore_string_private& str, qore_offset_t pos, ExceptionSink* xsink) {
392  assert(str.getEncoding() == getEncoding());
393 
394  if (!getEncoding()->isMultiByte()) {
395  concat_simple(str, pos);
396  return 0;
397  }
398 
399  // find byte positions from character positions
400  if (pos) {
401  if (str.findByteOffset(pos, xsink))
402  return -1;
403  if (pos < 0)
404  pos = 0;
405  else if (pos > (qore_offset_t)str.len)
406  return 0;
407  }
408 
409  concat_intern(str.buf + pos, str.len - pos);
410  return 0;
411  }
412 
413  DLLLOCAL void concat_simple(const qore_string_private& str, qore_offset_t pos, qore_offset_t plen) {
414  if (pos < 0) {
415  pos = str.len + pos;
416  if (pos < 0)
417  pos = 0;
418  }
419  else if (pos >= (qore_offset_t)str.len)
420  return;
421 
422  if (plen < 0) {
423  plen = str.len + plen;
424  if (plen <= 0)
425  return;
426  }
427  else if (plen > (qore_offset_t)str.len)
428  plen = str.len;
429 
430  concat_intern(str.buf + pos, plen);
431  }
432 
433  DLLLOCAL int concat(const qore_string_private& str, qore_offset_t pos, qore_offset_t plen, ExceptionSink* xsink) {
434  assert(str.getEncoding() == getEncoding());
435  assert(plen);
436 
437  if (!getEncoding()->isMultiByte()) {
438  concat_simple(str, pos);
439  return 0;
440  }
441 
442  // find byte positions from character positions
443  if (pos) {
444  if (str.findByteOffset(pos, xsink))
445  return -1;
446  if (pos < 0)
447  pos = 0;
448  else if (pos > (qore_offset_t)str.len)
449  return 0;
450  }
451 
452  // find the byte position from the starting byte
453  if (str.findByteOffset(plen, xsink, pos))
454  return -1;
455  if (plen <= 0)
456  return 0;
457  if (plen > (qore_offset_t)str.len)
458  plen = str.len;
459 
460  concat_intern(str.buf + pos, plen);
461  return 0;
462  }
463 
464  DLLLOCAL qore_offset_t getByteOffset(qore_size_t i, ExceptionSink* xsink) const {
465  assert(xsink);
466  qore_size_t rc;
467  if (i) {
468  rc = getEncoding()->getByteLen(buf, buf + len, i, xsink);
469  if (*xsink)
470  return -1;
471  }
472  else
473  rc = 0;
474  return rc > len ? -1 : (qore_offset_t)rc;
475  }
476 
477  DLLLOCAL void concat(char c) {
478  if (allocated) {
479  buf[len] = c;
480  check_char(++len);
481  buf[len] = '\0';
482  return;
483  }
484  // allocate new string buffer
485  allocated = STR_CLASS_BLOCK;
486  len = 1;
487  buf = (char*)malloc(sizeof(char) * allocated);
488  buf[0] = c;
489  buf[1] = '\0';
490  }
491 
492  DLLLOCAL void concat(const qore_string_private* str) {
493  assert(!str || (str->charset == charset) || !str->charset);
494 
495  // if it's not a null string
496  if (str && str->len) {
497  // if priv->buffer needs to be resized
498  check_char(str->len + len + STR_CLASS_EXTRA);
499  // concatenate new string
500  memcpy(buf + len, str->buf, str->len);
501  len += str->len;
502  buf[len] = '\0';
503  }
504  }
505 
506  DLLLOCAL void concat(const char *str) {
507  // if it's not a null string
508  if (str) {
509  qore_size_t i = 0;
510  // iterate through new string
511  while (str[i]) {
512  // if priv->buffer needs to be resized
513  check_char(len);
514  // concatenate one character at a time
515  buf[len++] = str[i++];
516  }
517  // see if priv->buffer needs to be resized for '\0'
518  check_char(len);
519  // terminate string
520  buf[len] = '\0';
521  }
522  }
523 
524  DLLLOCAL int concat(const QoreString* str, ExceptionSink* xsink);
525 
526  // return 0 for success
527  DLLLOCAL int vsprintf(const char *fmt, va_list args) {
528  size_t fmtlen = ::strlen(fmt);
529  // ensure minimum space is free
530  if ((allocated - len - fmtlen) < MIN_SPRINTF_BUFSIZE) {
531  allocated += fmtlen + MIN_SPRINTF_BUFSIZE;
532  allocated = (allocated / 0x10 + 1) * 0x10; // use complete cache line
533  // resize buffer
534  buf = (char*)realloc(buf, allocated * sizeof(char));
535  }
536  // set free buffer size
537  qore_offset_t free = allocated - len;
538 
539  // copy formatted string to buffer
540  int i = ::vsnprintf(buf + len, free, fmt, args);
541 
542 #ifdef HPUX
543  // vsnprintf failed but didn't tell us how big the buffer should be
544  if (i < 0) {
545  //printf("DEBUG: vsnprintf() failed: i=%d allocated=" QSD " len=" QSD " buf=%p fmtlen=" QSD " (new=i+%d = %d)\n", i, allocated, len, buf, fmtlen, STR_CLASS_EXTRA, i + STR_CLASS_EXTRA);
546  // resize buffer
547  allocated += STR_CLASS_EXTRA;
548  allocated = (allocated / 0x10 + 1) * 0x10; // use complete cache line
549  buf = (char*)realloc(buf, sizeof(char) * allocated);
550  *(buf + len) = '\0';
551  return -1;
552  }
553 #else
554  if (i >= free) {
555  //printf("DEBUG: vsnprintf() failed: i=%d allocated=" QSD " len=" QSD " buf=%p fmtlen=" QSD " (new=i+%d = %d)\n", i, allocated, len, buf, fmtlen, STR_CLASS_EXTRA, i + STR_CLASS_EXTRA);
556  // resize buffer
557  allocated = len + i + STR_CLASS_EXTRA;
558  allocated = (allocated / 0x10 + 1) * 0x10; // use complete cache line
559  buf = (char*)realloc(buf, sizeof(char) * allocated);
560  *(buf + len) = '\0';
561  return -1;
562  }
563 #endif
564 
565  len += i;
566  return 0;
567  }
568 
569  DLLLOCAL int sprintf(const char *fmt, ...) {
570  va_list args;
571  while (true) {
572  va_start(args, fmt);
573  int rc = vsprintf(fmt, args);
574  va_end(args);
575  if (!rc)
576  break;
577  }
578  return 0;
579  }
580 
581  DLLLOCAL void concatUTF8FromUnicode(unsigned code);
582 
583  DLLLOCAL int concatUnicode(unsigned code, ExceptionSink *xsink) {
584  assert(xsink);
585  if (getEncoding() == QCS_UTF8) {
586  concatUTF8FromUnicode(code);
587  return 0;
588  }
589 
590  QoreString tmp(QCS_UTF8);
591  tmp.concatUTF8FromUnicode(code);
592  TempString ns(tmp.convertEncoding(getEncoding(), xsink));
593  if (*xsink)
594  return -1;
595  concat(ns->priv);
596  return 0;
597  }
598 
599  DLLLOCAL int trimLeading(ExceptionSink* xsink, const intvec_t& vec);
600  DLLLOCAL int trimLeading(ExceptionSink* xsink, const qore_string_private* chars);
601  DLLLOCAL int trimTrailing(ExceptionSink* xsink, const intvec_t& vec);
602  DLLLOCAL int trimTrailing(ExceptionSink* xsink, const qore_string_private* chars);
603 
604  DLLLOCAL void terminate(size_t size);
605 
606  DLLLOCAL int concatUnicode(unsigned code);
607 
608  DLLLOCAL int concatDecodeUriIntern(ExceptionSink* xsink, const qore_string_private& str, bool detect_query = false);
609 
610  DLLLOCAL int concatEncodeUriRequest(ExceptionSink* xsink, const qore_string_private& str);
611 
612  DLLLOCAL unsigned int getUnicodePointFromBytePos(qore_size_t offset, unsigned& len, ExceptionSink* xsink) const;
613 
614  DLLLOCAL int concatEncode(ExceptionSink* xsink, const QoreString& str, unsigned code = CE_XHTML);
615  DLLLOCAL int concatDecode(ExceptionSink* xsink, const QoreString& str, unsigned code = CD_ALL);
616 
617  DLLLOCAL int getUnicodeCharArray(intvec_t& vec, ExceptionSink* xsink) const {
618  size_t j = 0;
619  while (j < len) {
620  unsigned clen;
621  int c = getUnicodePointFromBytePos((qore_offset_t)j, clen, xsink);
622  if (*xsink)
623  return -1;
624  vec.push_back(c);
625  j += clen;
626  }
627  return 0;
628  }
629 
630  DLLLOCAL int allocate(unsigned requested_size) {
631  if ((unsigned)allocated >= requested_size)
632  return 0;
633  requested_size = (requested_size / 0x10 + 1) * 0x10; // fill complete cache line
634  char* aux = (char*)realloc(buf, requested_size * sizeof(char));
635  if (!aux) {
636  assert(false);
637  // FIXME: std::bad_alloc() should be thrown here;
638  return -1;
639  }
640  buf = aux;
641  allocated = requested_size;
642  return 0;
643  }
644 
645  DLLLOCAL const QoreEncoding* getEncoding() const {
646  return charset ? charset : QCS_USASCII;
647  }
648 
649  DLLLOCAL size_t getCharWidth(ExceptionSink* xsink) const;
650 
651  DLLLOCAL static bool inVector(int c, const intvec_t& vec) {
652  for (unsigned j = 0; j < vec.size(); ++j) {
653  if ((int)vec[j] == c)
654  return true;
655  }
656  return false;
657  }
658 
659  DLLLOCAL static qore_string_private* get(QoreString& str) {
660  return str.priv;
661  }
662 
663  DLLLOCAL static int getHex(const char*& p) {
664  if (*p == '%' && isxdigit(*(p + 1)) && isxdigit(*(p + 2))) {
665  char x[3] = { *(p + 1), *(p + 2), '\0' };
666  p += 3;
667  return strtol(x, 0, 16);
668  }
669  return -1;
670  }
671 
672  DLLLOCAL static int convert_encoding_intern(const char* src, qore_size_t src_len, const QoreEncoding* from, QoreString& targ, const QoreEncoding* nccs, ExceptionSink* xsink);
673 };
674 
675 #endif
qore_offset_t
intptr_t qore_offset_t
used for offsets that could be negative
Definition: common.h:76
q_memrmem
DLLEXPORT void * q_memrmem(const void *big, size_t big_len, const void *little, size_t little_len)
finds a memory sequence in a larger memory sequence searching from the end of the sequence
qore_size_t
size_t qore_size_t
used for sizes (same range as a pointer)
Definition: common.h:73
QoreString
Qore's string type supported by the QoreEncoding class.
Definition: QoreString.h:81
TempString
class used to hold a possibly temporary QoreString pointer, stack only, cannot be dynamically allocat...
Definition: QoreString.h:966
q_memmem
DLLEXPORT void * q_memmem(const void *big, size_t big_len, const void *little, size_t little_len)
finds a memory sequence in a larger memory sequence
QCS_USASCII
const DLLEXPORT QoreEncoding * QCS_USASCII
ascii encoding
Definition: QoreEncoding.h:249
QCS_UTF8
const DLLEXPORT QoreEncoding * QCS_UTF8
UTF-8 multi-byte encoding (only UTF-8 and UTF-16 are multi-byte encodings)
Definition: QoreEncoding.h:250
QoreString::getBuffer
const DLLEXPORT char * getBuffer() const
returns the string's buffer; this data should not be changed
ExceptionSink
container for holding Qore-language exception information and also for registering a "thread_exit" ca...
Definition: ExceptionSink.h:48
TempEncodingHelper
use this class to manage strings where the character encoding must be specified and may be different ...
Definition: QoreString.h:1025
QoreString::strlen
DLLEXPORT qore_size_t strlen() const
returns number of bytes in the string (not including the null pointer)
QoreEncoding
defines string encoding functions in Qore
Definition: QoreEncoding.h:83
QoreString::priv
hashdecl qore_string_private * priv
the private implementation of QoreString
Definition: QoreString.h:917