Qore Programming Language 2.1.1
Loading...
Searching...
No Matches
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 - 2024 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
51typedef std::vector<int> intvec_t;
52
53hashdecl qore_string_private {
54public:
55 size_t len = 0;
56 size_t allocated = 0;
57 char* buf = nullptr;
58 const QoreEncoding* encoding = nullptr;
59
60 DLLLOCAL qore_string_private() {
61 }
62
63 DLLLOCAL qore_string_private(const qore_string_private &p) {
64 allocated = p.len + STR_CLASS_EXTRA;
65 allocated = (allocated / 0x10 + 1) * 0x10; // use complete cache line
66 buf = (char*)malloc(sizeof(char) * allocated);
67 len = p.len;
68 if (len)
69 memcpy(buf, p.buf, len);
70 buf[len] = '\0';
71 encoding = p.getEncoding();
72 }
73
74 DLLLOCAL ~qore_string_private() {
75 if (buf) {
76 free(buf);
77 }
78 }
79
80 DLLLOCAL void check_char(size_t i) {
81 if (i >= allocated) {
82 size_t d = i >> 2;
83 allocated = i + (d < STR_CLASS_BLOCK ? STR_CLASS_BLOCK : d);
84 allocated = (allocated / 0x10 + 1) * 0x10; // use complete cache line
85 buf = (char*)realloc(buf, allocated * sizeof(char));
86 }
87 }
88
89 DLLLOCAL size_t check_offset(qore_offset_t offset) {
90 if (offset < 0) {
91 offset = len + offset;
92 return offset < 0 ? 0 : offset;
93 }
94
95 return ((size_t)offset > len) ? len : offset;
96 }
97
98 DLLLOCAL void check_offset(qore_offset_t offset, qore_offset_t num, size_t &n_offset, size_t &n_num) {
99 n_offset = check_offset(offset);
100
101 if (num < 0) {
102 num = len + num - n_offset;
103 if (num < 0)
104 n_num = 0;
105 else
106 n_num = num;
107 return;
108 }
109 n_num = num;
110 }
111
112 // NOTE: this is purely byte oriented - no character semantics here
113 DLLLOCAL qore_offset_t find(char c, qore_offset_t pos = 0) {
114 if (pos < 0) {
115 pos = len + pos;
116 if (pos < 0)
117 pos = 0;
118 } else if (pos > 0 && pos > (qore_offset_t)len)
119 return -1;
120 const char* p;
121 if (!(p = strchr(buf + pos, c)))
122 return -1;
123 return (qore_offset_t)(p - buf);
124 }
125
126 // NOTE: this is purely byte oriented - no character semantics here
127 DLLLOCAL qore_offset_t rfind(char c, qore_offset_t pos = -1) {
128 if (pos < 0) {
129 pos = len + pos;
130 if (pos < 0)
131 return -1;
132 } else if (pos > 0 && pos > (qore_offset_t)len)
133 pos = len - 1;
134
135 const char* p = buf + pos;
136 while (p >= buf) {
137 if (*p == c)
138 return (qore_offset_t)(p - buf);
139 --p;
140 }
141 return -1;
142 }
143
144 // NOTE: this is purely byte oriented - no character semantics here
145 DLLLOCAL qore_offset_t findAny(const char* str, qore_offset_t pos = 0) {
146 if (pos < 0) {
147 pos = len + pos;
148 if (pos < 0)
149 pos = 0;
150 } else if (pos > 0 && pos > (qore_offset_t)len)
151 return -1;
152 const char* p;
153 if (!(p = strstr(buf + pos, str)))
154 return -1;
155 return (qore_offset_t)(p - buf);
156 }
157
158 // NOTE: this is purely byte oriented - no character semantics here
159 DLLLOCAL qore_offset_t rfindAny(const char* str, qore_offset_t pos = -1) {
160 if (pos < 0) {
161 pos = len + pos;
162 if (pos < 0)
163 return -1;
164 } else if (pos > 0 && pos > (qore_offset_t)len)
165 pos = len - 1;
166
167 const char* p = buf + pos;
168 while (p >= buf) {
169 for (const char* t = str; *t; ++t) {
170 if (*p == *t)
171 return (qore_offset_t)(p - buf);
172 }
173 --p;
174 }
175 return -1;
176 }
177
178 DLLLOCAL static qore_offset_t index_simple(const char* haystack, size_t hlen, const char* needle, size_t nlen,
179 qore_offset_t pos = 0) {
180 const char* start = haystack + pos;
181 void* ptr = q_memmem(start, hlen - pos, needle, nlen);
182 if (!ptr) {
183 return -1;
184 }
185 return reinterpret_cast<const char*>(ptr) - start + pos;
186 }
187
188 DLLLOCAL qore_offset_t index(const QoreString &orig_needle, qore_offset_t pos, ExceptionSink *xsink) const {
189 assert(xsink);
190 TempEncodingHelper needle(orig_needle, getEncoding(), xsink);
191 if (!needle)
192 return -1;
193
194 // do simple index
195 if (!getEncoding()->isMultiByte()) {
196 if (pos < 0) {
197 pos = len + pos;
198 if (pos < 0) {
199 pos = 0;
200 }
201 } else if (pos >= (qore_offset_t)len) {
202 return -1;
203 }
204
205 return index_simple(buf, len, needle->c_str(), needle->size(), pos);
206 }
207
208 // do multibyte index()
209 if (findByteOffset(pos, xsink))
210 return -1;
211 if (pos < 0)
212 pos = 0;
213 else if (pos >= (qore_offset_t)len)
214 return -1;
215
216 qore_offset_t ind = index_simple(buf + pos, len - pos, needle->c_str(), needle->size());
217 if (ind != -1) {
218 ind = getEncoding()->getCharPos(buf, buf + pos + ind, xsink);
219 if (*xsink)
220 return -1;
221 }
222
223 return ind;
224 }
225
226 DLLLOCAL qore_offset_t bindex(const QoreString &needle, qore_offset_t pos) const {
227 if (needle.strlen() + pos > len)
228 return -1;
229
230 return bindex(needle.c_str(), pos, needle.size());
231 }
232
233 DLLLOCAL qore_offset_t bindex(const std::string &needle, qore_offset_t pos) const {
234 if (needle.size() + pos > len)
235 return -1;
236
237 return bindex(needle.c_str(), pos, needle.size());
238 }
239
240 DLLLOCAL qore_offset_t bindex(const char *needle, qore_offset_t pos, size_t nsize = 0) const {
241 if (pos < 0) {
242 pos = len + pos;
243 if (pos < 0) {
244 pos = 0;
245 }
246 } else if (pos >= (qore_offset_t)len) {
247 return -1;
248 }
249
250 if (!nsize) {
251 nsize = strlen(needle);
252 }
253 return index_simple(buf, len, needle, nsize, pos);
254 }
255
256 // finds the last occurrence of needle in haystack at or before position pos
257 // pos must be a non-negative valid byte offset in haystack
258 DLLLOCAL static qore_offset_t rindex_simple(const char* haystack, size_t hlen, const char* needle,
259 size_t nlen, qore_offset_t pos = -1) {
260 if (pos < 0) {
261 pos = hlen + pos;
262 if (pos < 0) {
263 return -1;
264 }
265 } else if (pos >= (qore_offset_t)hlen) {
266 pos = hlen - 1;
267 }
268
269 assert(pos < (qore_offset_t)hlen);
270 void* ptr = q_memrmem(haystack, pos + 1, needle, nlen);
271 if (!ptr) {
272 return -1;
273 }
274 return static_cast<qore_offset_t>(reinterpret_cast<const char*>(ptr) -
275 reinterpret_cast<const char*>(haystack));
276 }
277
278 // start is a byte offset that has to point to the start of a valid character
279 DLLLOCAL int findByteOffset(qore_offset_t& pos, ExceptionSink* xsink, size_t start = 0) const {
280 assert(xsink);
281 assert(getEncoding()->isMultiByte());
282 if (!pos)
283 return 0;
284 // get positive character offset if negative
285 if (pos < 0) {
286 // get the length of the string in characters
287 size_t clen = getEncoding()->getLength(buf + start, buf + len, xsink);
288 if (*xsink)
289 return -1;
290 pos = clen + pos;
291 }
292 // now get the byte position from this character offset
293 pos = getEncoding()->getByteLen(buf + start, buf + len, pos, xsink);
294 return *xsink ? -1 : 0;
295 }
296
297 DLLLOCAL qore_offset_t rindex(const QoreString &orig_needle, qore_offset_t pos, ExceptionSink *xsink) const {
298 assert(xsink);
299 TempEncodingHelper needle(orig_needle, getEncoding(), xsink);
300 if (!needle)
301 return -1;
302
303 if (!getEncoding()->isMultiByte()) {
304 if (pos < 0) {
305 pos = len + pos;
306 if (pos < 0)
307 return -1;
308 }
309
310 return rindex_simple(buf, len, needle->c_str(), needle->size(), pos);
311 }
312
313 // do multi-byte rindex
314 if (findByteOffset(pos, xsink))
315 return -1;
316 if (pos < 0)
317 return -1;
318
319 // get byte rindex position
320 qore_offset_t ind = rindex_simple(buf, len, needle->c_str(), needle->size(), pos);
321
322 // calculate character position from byte position
323 if (ind && ind != -1) {
324 ind = getEncoding()->getCharPos(buf, buf + ind, xsink);
325 if (*xsink)
326 return 0;
327 }
328
329 return ind;
330 }
331
332 DLLLOCAL qore_offset_t brindex(const QoreString &needle, qore_offset_t pos) const {
333 return brindex(needle.getBuffer(), needle.strlen(), pos);
334 }
335
336 DLLLOCAL qore_offset_t brindex(const std::string &needle, qore_offset_t pos) const {
337 return brindex(needle.c_str(), needle.size(), pos);
338 }
339
340 DLLLOCAL qore_offset_t brindex(const char *needle, size_t needle_len, qore_offset_t pos) const {
341 if (pos < 0)
342 pos = len + pos;
343
344 if (pos >= (qore_offset_t)len) {
345 pos = len - 1;
346 }
347
348 if (pos < 0) {
349 if (pos == -1 && !len && !needle_len) {
350 return 0;
351 }
352 return -1;
353 }
354
355 if (needle_len + (len - pos) > len)
356 return -1;
357
358 return rindex_simple(buf, len, needle, needle_len, pos);
359 }
360
361 DLLLOCAL bool startsWith(const char* str, size_t ssize) const {
362 return !strncmp(str, buf, ssize);
363 }
364
365 DLLLOCAL bool endsWith(const char* str, size_t ssize) const {
366 if (ssize > len) {
367 return false;
368 }
369 return !strncmp(str, buf + len - ssize, ssize);
370 }
371
372 DLLLOCAL bool isDataPrintableAscii() const {
373 for (size_t i = 0; i < len; ++i) {
374 if (buf[i] < 32 || buf[i] > 126)
375 return false;
376 }
377 return true;
378 }
379
380 DLLLOCAL bool isDataAscii() const {
381 for (size_t i = 0; i < len; ++i) {
382 if ((unsigned char)(buf[i]) > 127)
383 return false;
384 }
385 return true;
386 }
387
388 DLLLOCAL void concat_intern(const char* p, size_t plen) {
389 assert(p);
390 assert(plen);
391 check_char(len + plen);
392 memcpy(buf + len, p, plen);
393 len += plen;
394 buf[len] = '\0';
395 }
396
397 DLLLOCAL void concat_simple(const qore_string_private& str, qore_offset_t pos) {
398 if (pos < 0) {
399 pos = str.len + pos;
400 if (pos < 0)
401 pos = 0;
402 }
403 else if (pos >= (qore_offset_t)str.len)
404 return;
405
406 concat_intern(str.buf + pos, str.len - pos);
407 }
408
409 DLLLOCAL int concat(const qore_string_private& str, qore_offset_t pos, ExceptionSink* xsink) {
410 assert(str.getEncoding() == getEncoding());
411
412 if (!getEncoding()->isMultiByte()) {
413 concat_simple(str, pos);
414 return 0;
415 }
416
417 // find byte positions from character positions
418 if (pos) {
419 if (str.findByteOffset(pos, xsink))
420 return -1;
421 if (pos < 0)
422 pos = 0;
423 else if (pos > (qore_offset_t)str.len)
424 return 0;
425 }
426
427 concat_intern(str.buf + pos, str.len - pos);
428 return 0;
429 }
430
431 DLLLOCAL void concat_simple(const qore_string_private& str, qore_offset_t pos, qore_offset_t plen) {
432 if (pos < 0) {
433 pos = str.len + pos;
434 if (pos < 0)
435 pos = 0;
436 } else if (pos >= (qore_offset_t)str.len)
437 return;
438
439 if (plen < 0) {
440 plen = str.len + plen;
441 if (plen <= 0)
442 return;
443 } else if (plen > (qore_offset_t)str.len)
444 plen = str.len;
445
446 concat_intern(str.buf + pos, plen);
447 }
448
449 DLLLOCAL int concat(const qore_string_private& str, qore_offset_t pos, qore_offset_t plen, ExceptionSink* xsink) {
450 assert(str.getEncoding() == getEncoding());
451 assert(plen);
452
453 if (!getEncoding()->isMultiByte()) {
454 concat_simple(str, pos);
455 return 0;
456 }
457
458 // find byte positions from character positions
459 if (pos) {
460 if (str.findByteOffset(pos, xsink))
461 return -1;
462 if (pos < 0)
463 pos = 0;
464 else if (pos > (qore_offset_t)str.len)
465 return 0;
466 }
467
468 // find the byte position from the starting byte
469 if (str.findByteOffset(plen, xsink, pos))
470 return -1;
471 if (plen <= 0)
472 return 0;
473 if (plen > (qore_offset_t)str.len)
474 plen = str.len;
475
476 concat_intern(str.buf + pos, plen);
477 return 0;
478 }
479
480 DLLLOCAL qore_offset_t getByteOffset(size_t i, ExceptionSink* xsink) const {
481 assert(xsink);
482 size_t rc;
483 if (i) {
484 rc = getEncoding()->getByteLen(buf, buf + len, i, xsink);
485 if (*xsink)
486 return -1;
487 } else
488 rc = 0;
489 return rc > len ? -1 : (qore_offset_t)rc;
490 }
491
492 DLLLOCAL size_t removeBytes(size_t num) {
493 if (num >= len) {
494 clear();
495 return len;
496 }
497 memmove(buf, buf + num, len - num);
498 len -= num;
499 return num;
500 }
501
502 DLLLOCAL void clear() {
503 if (allocated) {
504 len = 0;
505 buf[0] = '\0';
506 }
507 }
508
509 DLLLOCAL void concat(char c) {
510 if (allocated) {
511 buf[len] = c;
512 check_char(++len);
513 buf[len] = '\0';
514 return;
515 }
516 // allocate new string buffer
517 allocated = STR_CLASS_BLOCK;
518 len = 1;
519 buf = (char*)malloc(sizeof(char) * allocated);
520 buf[0] = c;
521 buf[1] = '\0';
522 }
523
524 DLLLOCAL void concat(const qore_string_private* str) {
525 assert(!str || (str->encoding == encoding) || !str->encoding);
526
527 // if it's not a null string
528 if (str && str->len) {
529 // if priv->buffer needs to be resized
530 check_char(str->len + len + STR_CLASS_EXTRA);
531 // concatenate new string
532 memcpy(buf + len, str->buf, str->len);
533 len += str->len;
534 buf[len] = '\0';
535 }
536 }
537
538 DLLLOCAL void concat(const char *str) {
539 // if it's not a null string
540 if (str) {
541 size_t i = 0;
542 // iterate through new string
543 while (str[i]) {
544 // if priv->buffer needs to be resized
545 check_char(len);
546 // concatenate one character at a time
547 buf[len++] = str[i++];
548 }
549 // see if priv->buffer needs to be resized for '\0'
550 check_char(len);
551 // terminate string
552 buf[len] = '\0';
553 }
554 }
555
556 DLLLOCAL int concat(const QoreString* str, ExceptionSink* xsink);
557
558 // return 0 for success
559 DLLLOCAL int vsprintf(const char *fmt, va_list args) {
560 size_t fmtlen = ::strlen(fmt);
561 // ensure minimum space is free
562 if ((allocated - len - fmtlen) < MIN_SPRINTF_BUFSIZE) {
563 allocated += fmtlen + MIN_SPRINTF_BUFSIZE;
564 allocated = (allocated / 0x10 + 1) * 0x10; // use complete cache line
565 // resize buffer
566 buf = (char*)realloc(buf, allocated * sizeof(char));
567 }
568 // set free buffer size
569 qore_offset_t free = allocated - len;
570
571 // copy formatted string to buffer
572 int i = ::vsnprintf(buf + len, free, fmt, args);
573
574#ifdef HPUX
575 // vsnprintf failed but didn't tell us how big the buffer should be
576 if (i < 0) {
577 //printf("DEBUG: vsnprintf() failed: i=%d allocated=" QSD " len=" QSD " buf=%p fmtlen=" QSD
578 // " (new=i+%d = %d)\n", i, allocated, len, buf, fmtlen, STR_CLASS_EXTRA, i + STR_CLASS_EXTRA);
579 // resize buffer
580 allocated += STR_CLASS_EXTRA;
581 allocated = (allocated / 0x10 + 1) * 0x10; // use complete cache line
582 buf = (char*)realloc(buf, sizeof(char) * allocated);
583 *(buf + len) = '\0';
584 return -1;
585 }
586#else
587 if (i >= free) {
588 //printf("DEBUG: vsnprintf() failed: i=%d allocated=" QSD " len=" QSD " buf=%p fmtlen=" QSD
589 // " (new=i+%d = %d)\n", i, allocated, len, buf, fmtlen, STR_CLASS_EXTRA, i + STR_CLASS_EXTRA);
590 // resize buffer
591 allocated = len + i + STR_CLASS_EXTRA;
592 allocated = (allocated / 0x10 + 1) * 0x10; // use complete cache line
593 buf = (char*)realloc(buf, sizeof(char) * allocated);
594 *(buf + len) = '\0';
595 return -1;
596 }
597#endif
598
599 len += i;
600 return 0;
601 }
602
603 DLLLOCAL int sprintf(const char *fmt, ...) {
604 va_list args;
605 while (true) {
606 va_start(args, fmt);
607 int rc = vsprintf(fmt, args);
608 va_end(args);
609 if (!rc)
610 break;
611 }
612 return 0;
613 }
614
615 DLLLOCAL void concatUTF8FromUnicode(unsigned code);
616
617 DLLLOCAL int concatUnicode(unsigned code, ExceptionSink *xsink) {
618 assert(xsink);
619 if (getEncoding() == QCS_UTF8) {
620 concatUTF8FromUnicode(code);
621 return 0;
622 }
623
624 QoreString tmp(QCS_UTF8);
625 tmp.concatUTF8FromUnicode(code);
626 TempString ns(tmp.convertEncoding(getEncoding(), xsink));
627 if (*xsink)
628 return -1;
629 concat(ns->priv);
630 return 0;
631 }
632
633 DLLLOCAL void setRegexBaseOpts(QoreRegexBase& re, int opts);
634
635 DLLLOCAL void setRegexOpts(QoreRegexSubst& re, int opts);
636
637 DLLLOCAL void splice_simple(size_t offset, size_t length, QoreString* extract = nullptr);
638 DLLLOCAL void splice_simple(size_t offset, size_t length, const char* str, size_t str_len,
639 QoreString* extract = nullptr);
640 DLLLOCAL void splice_complex(qore_offset_t offset, ExceptionSink* xsink, QoreString* extract = nullptr);
641 DLLLOCAL void splice_complex(qore_offset_t offset, qore_offset_t length, ExceptionSink* xsink,
642 QoreString* extract = nullptr);
643 DLLLOCAL void splice_complex(qore_offset_t offset, qore_offset_t length, const QoreString* str,
644 ExceptionSink* xsink, QoreString* extract = nullptr);
645 DLLLOCAL int substr_simple(QoreString* str, qore_offset_t offset) const;
646 DLLLOCAL int substr_simple(QoreString* str, qore_offset_t offset, qore_offset_t length) const;
647 DLLLOCAL int substr_complex(QoreString* str, qore_offset_t offset, ExceptionSink* xsink) const;
648 DLLLOCAL int substr_complex(QoreString* str, qore_offset_t offset, qore_offset_t length,
649 ExceptionSink* xsink) const;
650
651 DLLLOCAL int trimLeading(ExceptionSink* xsink, const intvec_t& vec);
652 DLLLOCAL int trimLeading(ExceptionSink* xsink, const qore_string_private* chars);
653 DLLLOCAL int trimTrailing(ExceptionSink* xsink, const intvec_t& vec);
654 DLLLOCAL int trimTrailing(ExceptionSink* xsink, const qore_string_private* chars);
655
656 DLLLOCAL void terminate(size_t size);
657
658 DLLLOCAL int concatUnicode(unsigned code);
659
660 DLLLOCAL int concatDecodeUriIntern(ExceptionSink* xsink, const qore_string_private& str,
661 bool detect_query = false);
662
663 DLLLOCAL int concatEncodeUriRequest(ExceptionSink* xsink, const qore_string_private& str);
664
665 DLLLOCAL unsigned int getUnicodePointFromBytePos(size_t offset, unsigned& len, ExceptionSink* xsink) const;
666
667 DLLLOCAL int concatEncode(ExceptionSink* xsink, const QoreString& str, unsigned code = CE_XHTML);
668 DLLLOCAL int concatDecode(ExceptionSink* xsink, const QoreString& str, unsigned code = CD_ALL);
669
670 DLLLOCAL int getUnicodeCharArray(intvec_t& vec, ExceptionSink* xsink) const {
671 size_t j = 0;
672 while (j < len) {
673 unsigned clen;
674 int c = getUnicodePointFromBytePos((qore_offset_t)j, clen, xsink);
675 if (*xsink)
676 return -1;
677 vec.push_back(c);
678 j += clen;
679 }
680 return 0;
681 }
682
683 DLLLOCAL int allocate(unsigned requested_size) {
684 if ((unsigned)allocated >= requested_size)
685 return 0;
686 requested_size = (requested_size / 0x10 + 1) * 0x10; // fill complete cache line
687 char* aux = (char*)realloc(buf, requested_size * sizeof(char));
688 if (!aux) {
689 assert(false);
690 // FIXME: std::bad_alloc() should be thrown here;
691 return -1;
692 }
693 buf = aux;
694 allocated = requested_size;
695 return 0;
696 }
697
698 DLLLOCAL const QoreEncoding* getEncoding() const {
699 return encoding ? encoding : QCS_USASCII;
700 }
701
702 DLLLOCAL size_t getCharWidth(ExceptionSink* xsink) const;
703
704 DLLLOCAL void concatBase64(const char* bbuf, size_t size, size_t maxlinelen, bool url_encode = false);
705
706 DLLLOCAL static bool inVector(int c, const intvec_t& vec) {
707 for (unsigned j = 0; j < vec.size(); ++j) {
708 if ((int)vec[j] == c)
709 return true;
710 }
711 return false;
712 }
713
714 DLLLOCAL static qore_string_private* get(QoreString& str) {
715 return str.priv;
716 }
717
718 DLLLOCAL static int getHex(const char*& p) {
719 if (*p == '%' && isxdigit(*(p + 1)) && isxdigit(*(p + 2))) {
720 char x[3] = { *(p + 1), *(p + 2), '\0' };
721 p += 3;
722 return strtol(x, 0, 16);
723 }
724 return -1;
725 }
726
727 DLLLOCAL static int convert_encoding_intern(const char* src, size_t src_len, const QoreEncoding* from,
728 QoreString& targ, const QoreEncoding* nccs, ExceptionSink* xsink);
729};
730
731template <typename T>
732DLLLOCAL T* binary_to_string(BinaryNode* bin, const QoreEncoding* qe) {
734 if (!b) {
735 return nullptr;
736 }
737
738 if (b->empty()) {
739 return new QoreStringNode;
740 }
741
742 qore_string_private *p = new qore_string_private;
743 p->len = b->size() - 1;
744 p->buf = (char*)b->giveBuffer();
745 p->encoding = qe;
746
747 // free binary object
748 b = 0;
749
750 // check for null termination
751 if (p->buf[p->len]) {
752 ++p->len;
753 p->buf = (char*)realloc(p->buf, p->len + 1);
754 p->buf[p->len] = '\0';
755 }
756
757 p->allocated = p->len + 1;
758 return new T(p);
759}
760
761#endif
DLLEXPORT const QoreEncoding * QCS_UTF8
UTF-8 multi-byte encoding (only UTF-8 and UTF-16 are multi-byte encodings)
Definition QoreEncoding.h:247
DLLEXPORT const QoreEncoding * QCS_USASCII
ascii encoding
Definition QoreEncoding.h:246
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
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
holds arbitrary binary data
Definition BinaryNode.h:41
container for holding Qore-language exception information and also for registering a "thread_exit" ca...
Definition ExceptionSink.h:50
defines string encoding functions in Qore
Definition QoreEncoding.h:83
Qore's string type supported by the QoreEncoding class.
Definition QoreString.h:93
DLLEXPORT const char * c_str() const
returns the string's buffer; this data should not be changed
DLLEXPORT size_t strlen() const
returns number of bytes in the string (not including the null pointer)
DLLEXPORT const char * getBuffer() const
returns the string's buffer; this data should not be changed
DLLEXPORT size_t size() const
returns number of bytes in the string (not including the null pointer)
hashdecl qore_string_private * priv
the private implementation of QoreString
Definition QoreString.h:1100
Qore's string value type, reference counted, dynamically-allocated only.
Definition QoreStringNode.h:50
manages a reference count of a pointer to a class that takes a simple "deref()" call with no argument...
Definition ReferenceHolder.h:127
use this class to manage strings where the character encoding must be specified and may be different ...
Definition QoreString.h:1198
class used to hold a possibly temporary QoreString pointer, stack only, cannot be dynamically allocat...
Definition QoreString.h:1139
intptr_t qore_offset_t
used for offsets that could be negative
Definition common.h:82
#define CD_ALL
code for decoding everything
Definition QoreString.h:73
#define CE_XHTML
code for encoding XHTML entities
Definition QoreString.h:55