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