/src/dcmtk/ofstd/libsrc/ofstring.cc
Line | Count | Source |
1 | | /* |
2 | | * |
3 | | * Copyright (C) 1997-2023, OFFIS e.V. |
4 | | * All rights reserved. See COPYRIGHT file for details. |
5 | | * |
6 | | * This software and supporting documentation were developed by |
7 | | * |
8 | | * OFFIS e.V. |
9 | | * R&D Division Health |
10 | | * Escherweg 2 |
11 | | * D-26121 Oldenburg, Germany |
12 | | * |
13 | | * |
14 | | * Module: ofstd |
15 | | * |
16 | | * Author: Andrew Hewett |
17 | | * |
18 | | * Purpose: A simple string class |
19 | | * |
20 | | */ |
21 | | |
22 | | |
23 | | /* |
24 | | ** A simple string class |
25 | | ** - for OFFIS projects when an ANSI string class is not always available |
26 | | ** - based on the ANSI-C++ specifications |
27 | | ** - this implementation is intended to be slow but reliable |
28 | | ** - it is known to be slow but is it reliable? |
29 | | */ |
30 | | |
31 | | #include "dcmtk/config/osconfig.h" /* include OS specific configuration first */ |
32 | | |
33 | | #ifndef HAVE_STL_STRING |
34 | | |
35 | | #include "dcmtk/ofstd/ofstring.h" |
36 | | #include "dcmtk/ofstd/ofcast.h" |
37 | | #include "dcmtk/ofstd/ofbmanip.h" |
38 | | #include "dcmtk/ofstd/oftypes.h" |
39 | | #include "dcmtk/ofstd/ofstd.h" |
40 | | #include "dcmtk/ofstd/ofdiag.h" |
41 | | |
42 | | static const char* verify_string(const char *s) |
43 | 138 | { |
44 | 138 | if (s == NULL) |
45 | 0 | { |
46 | | #ifdef DEBUG |
47 | | fprintf(stderr, "WARNING: OFString constructed from NULL, this is deprecated.\n"); |
48 | | #endif |
49 | 0 | #ifdef USE_NULL_SAFE_OFSTRING |
50 | 0 | s = ""; |
51 | 0 | #endif |
52 | 0 | } |
53 | 138 | return s; |
54 | 138 | } |
55 | | |
56 | | /* |
57 | | ** Constructors |
58 | | */ |
59 | | |
60 | | OFString::OFString() |
61 | 117 | : theCString(NULL), theSize(0), theCapacity(0) |
62 | 117 | { |
63 | 117 | reserve(1); |
64 | 117 | } |
65 | | |
66 | | OFString::OFString(const OFString& str, size_t pos, size_t n) |
67 | 238 | : theCString(NULL), theSize(0), theCapacity(0) |
68 | 238 | { |
69 | 238 | this->assign(str, pos, n); |
70 | 238 | } |
71 | | |
72 | | OFString::OFString (const char* s, size_t n) |
73 | 0 | : theCString(NULL), theSize(0), theCapacity(0) |
74 | 0 | { |
75 | 0 | s = verify_string(s); |
76 | 0 | if (n == OFString_npos) { |
77 | 0 | n = strlen(s); |
78 | 0 | } |
79 | 0 | reserve(n); |
80 | 0 | OFBitmanipTemplate<char>::copyMem(s, this->theCString, n); |
81 | 0 | this->theCString[n] = '\0'; |
82 | 0 | this->theSize = n; |
83 | 0 | } |
84 | | |
85 | | OFString::OFString (const char* s) |
86 | 138 | : theCString(NULL), theSize(0), theCapacity(0) |
87 | 138 | { |
88 | 138 | s = verify_string(s); |
89 | 138 | const size_t n = strlen(s); |
90 | 138 | reserve(n); |
91 | | // Because we used strlen() to figure out the length we can use strlcpy() |
92 | | // since there won't be any '\0' bytes in the string. |
93 | | // The amount of memory allocated is always theCapacity+1 |
94 | | // because one extra byte is always allocated for the eos zero byte. |
95 | 138 | OFStandard::strlcpy(this->theCString, s, this->theCapacity+1); |
96 | 138 | this->theSize = n; |
97 | 138 | } |
98 | | |
99 | | |
100 | | OFString::OFString (size_t rep, char c) |
101 | 30 | : theCString(NULL), theSize(0), theCapacity(0) |
102 | 30 | { |
103 | 30 | reserve(rep); |
104 | 60 | for (size_t i = 0; i < rep; i++) { |
105 | 30 | this->theCString[i] = c; |
106 | 30 | } |
107 | 30 | this->theCString[rep] = '\0'; |
108 | 30 | this->theSize = rep; |
109 | 30 | } |
110 | | |
111 | | /* |
112 | | ** Destructor |
113 | | */ |
114 | | |
115 | | OFString::~OFString() |
116 | 256 | { |
117 | 256 | if (theCString) { |
118 | 256 | delete[] theCString; |
119 | 256 | theCString = NULL; |
120 | 256 | } |
121 | 256 | } |
122 | | |
123 | | /* |
124 | | ** Operator = |
125 | | */ |
126 | | |
127 | | OFString& |
128 | | OFString::operator= (const OFString& rhs) |
129 | 3 | { |
130 | 3 | this->assign(rhs); |
131 | 3 | return *this; |
132 | 3 | } |
133 | | |
134 | | OFString& |
135 | | OFString::operator= (const char* s) |
136 | 0 | { |
137 | 0 | this->assign(s); |
138 | 0 | return *this; |
139 | 0 | } |
140 | | |
141 | | OFString& |
142 | | OFString::operator= (char s) |
143 | 0 | { |
144 | 0 | this->assign(1, s); |
145 | 0 | return *this; |
146 | 0 | } |
147 | | |
148 | | /* |
149 | | ** Operator += |
150 | | */ |
151 | | |
152 | | OFString& |
153 | | OFString::operator+= (const OFString& rhs) |
154 | 0 | { |
155 | 0 | return this->append(rhs); |
156 | 0 | } |
157 | | |
158 | | OFString& |
159 | | OFString::operator+= (const char* s) |
160 | 0 | { |
161 | 0 | return this->append(s); |
162 | 0 | } |
163 | | |
164 | | OFString& |
165 | | OFString::operator+= (char s) |
166 | 24 | { |
167 | 24 | return this->append(1, s); |
168 | 24 | } |
169 | | |
170 | | /* |
171 | | ** Append |
172 | | */ |
173 | | |
174 | | OFString& |
175 | | OFString::append (const OFString& str, size_t pos, size_t n) |
176 | 56 | { |
177 | 56 | OFString b(str, pos, n); |
178 | 56 | this->reserve(this->size() + b.size()); |
179 | | // We can't use strcat() because some string could contain NULL bytes |
180 | | // We need size() + 1 so that the EOS mark is copied over, too |
181 | 56 | OFBitmanipTemplate<char>::copyMem(b.theCString, this->theCString + this->size(), b.size() + 1); |
182 | 56 | this->theSize += b.size(); |
183 | | |
184 | 56 | return *this; |
185 | 56 | } |
186 | | |
187 | | OFString& |
188 | | OFString::append (const char* s, size_t n) |
189 | 0 | { |
190 | 0 | OFString str(s, n); |
191 | 0 | return this->append(str); |
192 | 0 | } |
193 | | |
194 | | OFString& |
195 | | OFString::append (const char* s) |
196 | 0 | { |
197 | 0 | OFString str(s); |
198 | 0 | return this->append(str); |
199 | 0 | } |
200 | | |
201 | | OFString& |
202 | | OFString::append (size_t rep, char c) |
203 | 24 | { |
204 | 24 | OFString str(rep, c); |
205 | 24 | return this->append(str); |
206 | 24 | } |
207 | | |
208 | | /* |
209 | | ** Assign |
210 | | */ |
211 | | |
212 | | OFString& |
213 | | OFString::assign (const OFString& str, size_t pos, size_t n) |
214 | 276 | { |
215 | 276 | OFSTRING_OUTOFRANGE(pos > str.size()); |
216 | 276 | const size_t remain = (str.size() - pos); |
217 | 276 | if ((n == OFString_npos) || (n > remain)) { |
218 | 241 | n = remain; |
219 | 241 | } |
220 | 276 | if (n > 0) { |
221 | 180 | this->reserve(n); |
222 | | // Someone could try to assign a string to itself, but strncpy() must |
223 | | // not be called on overlapping memory areas, therefore, we use moveMem(). |
224 | 180 | OFBitmanipTemplate<char>::moveMem(str.theCString + pos, this->theCString, n); |
225 | 180 | this->theCString[n] = '\0'; |
226 | 180 | this->theSize = n; |
227 | 180 | } else { |
228 | 96 | this->reserve(1); |
229 | | /* assign an empty string */ |
230 | 96 | this->theCString[0] = '\0'; |
231 | 96 | this->theSize = 0; |
232 | 96 | } |
233 | 276 | return *this; |
234 | 276 | } |
235 | | |
236 | | OFString& |
237 | | OFString::assign (const OFString& str) |
238 | 35 | { |
239 | 35 | return assign(str, 0, OFString_npos); |
240 | 35 | } |
241 | | |
242 | | OFString& |
243 | | OFString::assign (const char* s, size_t n) |
244 | 0 | { |
245 | 0 | OFString str(s, n); |
246 | 0 | return this->assign(str); |
247 | 0 | } |
248 | | |
249 | | OFString& |
250 | | OFString::assign (const char* s) |
251 | 0 | { |
252 | 0 | OFString str(s); |
253 | 0 | return this->assign(str); |
254 | 0 | } |
255 | | |
256 | | OFString& |
257 | | OFString::assign (const char* s, const char *e) |
258 | 0 | { |
259 | 0 | OFString str(s, e - s); |
260 | 0 | return this->assign(str); |
261 | 0 | } |
262 | | |
263 | | OFString& |
264 | | OFString::assign (size_t rep, char c) |
265 | 0 | { |
266 | 0 | OFString str(rep, c); |
267 | 0 | return this->assign(str); |
268 | 0 | } |
269 | | |
270 | | /* |
271 | | ** Insert |
272 | | */ |
273 | | |
274 | | OFString& |
275 | | OFString::insert (size_t pos1, const OFString& str, size_t pos2, size_t n) |
276 | 0 | { |
277 | 0 | OFString i(str, pos2, n); |
278 | 0 | OFString a(*this, OFstatic_cast(size_t, 0), pos1); |
279 | 0 | OFString b(*this, pos1); |
280 | 0 | return this->assign(a).append(i).append(b); |
281 | 0 | } |
282 | | |
283 | | OFString& |
284 | | OFString::insert (size_t pos, const char* s, size_t n) |
285 | 0 | { |
286 | 0 | OFString str(s, n); |
287 | 0 | return this->insert(pos, str); |
288 | 0 | } |
289 | | |
290 | | OFString& |
291 | | OFString::insert (size_t pos, const char* s) |
292 | 0 | { |
293 | 0 | OFString str(s); |
294 | 0 | return this->insert(pos, str); |
295 | 0 | } |
296 | | |
297 | | OFString& |
298 | | OFString::insert (size_t pos, size_t rep, char s) |
299 | 0 | { |
300 | 0 | OFString str(rep, s); |
301 | 0 | return this->insert(pos, str); |
302 | 0 | } |
303 | | |
304 | | /* |
305 | | ** Erase |
306 | | */ |
307 | | OFString& |
308 | | OFString::erase (size_t pos, size_t n) |
309 | 32 | { |
310 | 32 | OFString a(*this, 0, pos); |
311 | 32 | OFString b; |
312 | 32 | if (n != OFString_npos) { |
313 | 0 | b.assign(*this, pos + n, OFString_npos); |
314 | 0 | } |
315 | 32 | return this->assign(a).append(b); |
316 | 32 | } |
317 | | |
318 | | /* |
319 | | ** Replace |
320 | | */ |
321 | | |
322 | | OFString& |
323 | | OFString::replace (size_t pos1, size_t n1, const OFString& str, |
324 | | size_t pos2, size_t n2) |
325 | 0 | { |
326 | 0 | OFString a(*this, OFstatic_cast(size_t, 0), pos1); |
327 | 0 | OFString b; |
328 | 0 | if ((n1 < OFString_npos) && ((pos1 + n1) < this->size())) { |
329 | 0 | b.assign(*this, pos1 + n1, OFString_npos); |
330 | 0 | } |
331 | 0 | OFString i(str, pos2, n2); |
332 | 0 | return this->assign(a).append(i).append(b); |
333 | 0 | } |
334 | | |
335 | | OFString& |
336 | | OFString::replace (size_t pos, size_t n, const char* s, size_t n2) |
337 | 0 | { |
338 | 0 | OFString str(s, n2); |
339 | 0 | return this->replace(pos, n, str); |
340 | 0 | } |
341 | | |
342 | | OFString& |
343 | | OFString::replace (size_t pos, size_t n, const char* s) |
344 | 0 | { |
345 | 0 | OFString str(s); |
346 | 0 | return this->replace(pos, n, str); |
347 | 0 | } |
348 | | |
349 | | OFString& |
350 | | OFString::replace (size_t pos, size_t n, size_t rep, char s) |
351 | 0 | { |
352 | 0 | OFString str(rep, s); |
353 | 0 | return this->replace(pos, n, str); |
354 | 0 | } |
355 | | |
356 | | |
357 | | /* |
358 | | ** Data |
359 | | */ |
360 | | |
361 | | const char* |
362 | | OFString::data () const |
363 | 0 | { |
364 | 0 | return (this->size() != 0) ? this->c_str() : ""; |
365 | 0 | } |
366 | | |
367 | | |
368 | | /* |
369 | | ** Resize |
370 | | */ |
371 | | |
372 | | void |
373 | | OFString::resize (size_t n, char c) |
374 | 18 | { |
375 | 18 | OFSTRING_LENGTHERROR(n == OFString_npos); |
376 | | |
377 | 18 | reserve(n); |
378 | 18 | const size_t len = this->size(); |
379 | 18 | if (n <= len) { |
380 | 42 | for (size_t i = n; i < len; i++) { |
381 | 24 | this->theCString[i] = '\0'; |
382 | 24 | } |
383 | 18 | } else { |
384 | 0 | for (size_t i = len; i < n; i++) { |
385 | 0 | this->theCString[i] = c; |
386 | 0 | } |
387 | 0 | this->theCString[n] = '\0'; |
388 | 0 | } |
389 | 18 | this->theSize = n; |
390 | 18 | } |
391 | | |
392 | | /* |
393 | | ** Reserve |
394 | | */ |
395 | | |
396 | | void |
397 | | OFString::reserve (size_t res_arg) |
398 | 635 | { |
399 | 635 | if (res_arg == OFString_npos) { |
400 | 0 | res_arg = 0; /* let at least space for eos get reserved */ |
401 | 0 | } |
402 | 635 | res_arg++; /* add space for eos */ |
403 | 635 | if (this->theCapacity < res_arg) { |
404 | 576 | char* newstr = new char[res_arg]; |
405 | 576 | if (newstr) { |
406 | 576 | size_t usedSpace = 0; |
407 | 576 | this->theCapacity = res_arg - 1; /* not the eos */ |
408 | 576 | if (this->size() > 0) { |
409 | 12 | const size_t len = size(); |
410 | | // copyMem() because theCString could have null bytes |
411 | 12 | OFBitmanipTemplate<char>::copyMem(this->theCString, newstr, len); |
412 | 12 | usedSpace = len; |
413 | 12 | } |
414 | | // suppress spurious gcc 12 warning |
415 | 576 | #include DCMTK_DIAGNOSTIC_PUSH |
416 | 576 | #include DCMTK_DIAGNOSTIC_IGNORE_STRINGOP_OVERFLOW |
417 | 576 | OFBitmanipTemplate<char>::zeroMem(newstr + usedSpace, res_arg - usedSpace); |
418 | 576 | #include DCMTK_DIAGNOSTIC_POP |
419 | 576 | char* oldstr = this->theCString; |
420 | 576 | this->theCString = newstr; |
421 | 576 | delete[] oldstr; |
422 | 576 | } else { |
423 | 0 | OFSTRING_MEMORYALLOCERROR(newstr); |
424 | 0 | } |
425 | 576 | } |
426 | 635 | } |
427 | | |
428 | | /* |
429 | | ** Copy |
430 | | */ |
431 | | |
432 | | size_t |
433 | | OFString::copy (char* s, size_t n, size_t pos) const |
434 | 0 | { |
435 | 0 | OFString sub(this->substr(pos, n)); |
436 | 0 | const size_t result = sub.size(); |
437 | | |
438 | | // The string could have NULL bytes so no strncpy() |
439 | 0 | OFBitmanipTemplate<char>::copyMem(sub.theCString, s, result); |
440 | 0 | return result; |
441 | 0 | } |
442 | | |
443 | | /* |
444 | | ** Substr |
445 | | */ |
446 | | |
447 | | OFString |
448 | | OFString::substr (size_t pos, size_t n) const |
449 | 0 | { |
450 | 0 | OFString sub; |
451 | 0 | return sub.assign(*this, pos, n); |
452 | 0 | } |
453 | | |
454 | | /* |
455 | | ** Swap |
456 | | */ |
457 | | |
458 | | void |
459 | | OFString::swap(OFString& s) |
460 | 0 | { |
461 | 0 | char* tmpCString = s.theCString; |
462 | 0 | s.theCString = this->theCString; |
463 | 0 | this->theCString = tmpCString; |
464 | |
|
465 | 0 | size_t tmpSize = s.theSize; |
466 | 0 | s.theSize = this->theSize; |
467 | 0 | this->theSize = tmpSize; |
468 | |
|
469 | 0 | size_t tmpCapacity = s.theCapacity; |
470 | 0 | s.theCapacity = this->theCapacity; |
471 | 0 | this->theCapacity = tmpCapacity; |
472 | 0 | } |
473 | | |
474 | | /* |
475 | | ** Compare |
476 | | */ |
477 | | |
478 | | int |
479 | | OFString::compare (const OFString& str) const |
480 | 267 | { |
481 | 267 | const size_t this_size = this->size(); |
482 | 267 | const size_t str_size = str.size(); |
483 | 267 | const size_t rlen = (this_size < str_size) ? this_size : str_size; |
484 | | // Our string could contain null bytes and thus we can't use strncmp() |
485 | 267 | int result = memcmp(this->theCString, str.theCString, rlen); |
486 | 267 | if (result == 0) { |
487 | 3 | result = this_size < str_size ? -1 : this_size > str_size ? 1 : 0; |
488 | 3 | } |
489 | 267 | return result; |
490 | 267 | } |
491 | | |
492 | | int |
493 | | OFString::compare (size_t pos1, size_t n1, const OFString& str) const |
494 | 0 | { |
495 | 0 | return OFString(*this, pos1, n1).compare(str); |
496 | 0 | } |
497 | | |
498 | | int |
499 | | OFString::compare (size_t pos1, size_t n1, const OFString& str, |
500 | | size_t pos2, size_t n2) const |
501 | 0 | { |
502 | 0 | return OFString(*this, pos1, n1).compare(OFString(str, pos2, n2)); |
503 | 0 | } |
504 | | |
505 | | int |
506 | | OFString::compare (const char* s) const |
507 | 0 | { |
508 | 0 | return this->compare(OFString(s)); |
509 | 0 | } |
510 | | |
511 | | int |
512 | | OFString::compare (size_t pos1, size_t n1, |
513 | | const char* s, size_t n2) const |
514 | 0 | { |
515 | 0 | return OFString(*this, pos1, n1).compare(OFString(s, n2)); |
516 | 0 | } |
517 | | |
518 | | /* |
519 | | ** Find |
520 | | */ |
521 | | |
522 | | size_t |
523 | | OFString::find (const OFString& pattern, size_t pos) const |
524 | 0 | { |
525 | | /* determine string length only once */ |
526 | 0 | const size_t this_size = this->size(); |
527 | 0 | const size_t pattern_size = pattern.size(); |
528 | 0 | if ((this_size == 0) || (pattern_size == 0) || (pos == OFString_npos)) { |
529 | 0 | return OFString_npos; |
530 | 0 | } |
531 | 0 | for (size_t i = pos; i < this_size; i++) { |
532 | | /* is there enough space for the pattern? */ |
533 | 0 | if ((i + pattern_size) > this_size) { |
534 | 0 | return OFString_npos; |
535 | 0 | } |
536 | 0 | int match = 1; /* assume there is a match */ |
537 | 0 | for (size_t j = 0; (j < pattern_size) && match; j++) { |
538 | 0 | if (this->at(i + j) != pattern[j]) { |
539 | 0 | match = 0; |
540 | 0 | } |
541 | 0 | } |
542 | 0 | if (match) { |
543 | 0 | return i; |
544 | 0 | } |
545 | 0 | } |
546 | 0 | return OFString_npos; |
547 | 0 | } |
548 | | |
549 | | size_t |
550 | | OFString::find (const char* pattern, size_t pos, size_t n) const |
551 | 0 | { |
552 | 0 | OFString str(pattern, n); |
553 | 0 | return this->find(str, pos); |
554 | 0 | } |
555 | | |
556 | | size_t |
557 | | OFString::find (const char* pattern, size_t pos) const |
558 | 0 | { |
559 | 0 | OFString str(pattern); |
560 | 0 | return this->find(str, pos); |
561 | 0 | } |
562 | | |
563 | | size_t |
564 | | OFString::find (char pattern, size_t pos) const |
565 | 0 | { |
566 | 0 | size_t i = pos; |
567 | 0 | const size_t this_size = this->size(); |
568 | 0 | while ((i < this_size) && (this->at(i) != pattern)) |
569 | 0 | i++; |
570 | 0 | return (i < this_size) ? i : OFString_npos; |
571 | 0 | } |
572 | | |
573 | | /* |
574 | | ** Rfind |
575 | | */ |
576 | | |
577 | | size_t |
578 | | OFString::rfind (const OFString& pattern, size_t pos) const |
579 | 0 | { |
580 | | /* determine string length only once */ |
581 | 0 | const size_t this_size = this->size(); |
582 | 0 | const size_t pattern_size = pattern.size(); |
583 | 0 | if ((this_size == 0) || (pattern_size == 0) || (this_size < pattern_size)) { |
584 | 0 | return OFString_npos; |
585 | 0 | } |
586 | 0 | OFintptr_t above = ((this_size - pattern_size) < pos) ? (this_size - pattern_size) : pos; |
587 | 0 | for (OFintptr_t i = above; i >= 0; --i) { |
588 | 0 | int match = 1; /* assume there is a match */ |
589 | 0 | for (size_t j = 0; (j < pattern_size) && match; ++j) { |
590 | 0 | if (this->at(i + j) != pattern[j]) { |
591 | 0 | match = 0; |
592 | 0 | } |
593 | 0 | } |
594 | 0 | if (match) { |
595 | 0 | return OFstatic_cast(size_t, i); // if i were < 0, the for-loop would've been already left. |
596 | 0 | } |
597 | 0 | } |
598 | 0 | return OFString_npos; |
599 | 0 | } |
600 | | |
601 | | size_t |
602 | | OFString::rfind (const char* pattern, size_t pos, size_t n) const |
603 | 0 | { |
604 | 0 | OFString str(pattern, n); |
605 | 0 | return this->rfind(str, pos); |
606 | 0 | } |
607 | | |
608 | | size_t |
609 | | OFString::rfind (const char* pattern, size_t pos) const |
610 | 0 | { |
611 | 0 | OFString str(pattern); |
612 | 0 | return this->rfind(str, pos); |
613 | 0 | } |
614 | | |
615 | | size_t |
616 | | OFString::rfind (char pattern, size_t pos) const |
617 | 0 | { |
618 | 0 | OFString str(1, pattern); |
619 | 0 | return this->rfind(str, pos); |
620 | 0 | } |
621 | | |
622 | | /* |
623 | | ** Find_first_of |
624 | | */ |
625 | | |
626 | | size_t |
627 | | OFString::find_first_of (const OFString& str, size_t pos) const |
628 | 0 | { |
629 | | /* determine string length only once */ |
630 | 0 | const size_t this_size = this->size(); |
631 | 0 | const size_t str_size = str.size(); |
632 | 0 | if ((this_size == 0) || (str_size == 0) || (pos == OFString_npos)) { |
633 | 0 | return OFString_npos; |
634 | 0 | } |
635 | 0 | for (size_t i = pos; i < this_size; i++) { |
636 | 0 | for (size_t j = 0; j < str_size; j++) { |
637 | 0 | if (this->at(i) == str[j]) { |
638 | 0 | return i; |
639 | 0 | } |
640 | 0 | } |
641 | 0 | } |
642 | 0 | return OFString_npos; |
643 | 0 | } |
644 | | |
645 | | size_t |
646 | | OFString::find_first_of (const char* s, size_t pos, size_t n) const |
647 | 0 | { |
648 | 0 | OFString str(s, n); |
649 | 0 | return this->find_first_of(str, pos); |
650 | 0 | } |
651 | | |
652 | | size_t |
653 | | OFString::find_first_of (const char* s, size_t pos) const |
654 | 0 | { |
655 | 0 | OFString str(s); |
656 | 0 | return this->find_first_of(str, pos); |
657 | 0 | } |
658 | | |
659 | | size_t |
660 | | OFString::find_first_of (char s, size_t pos) const |
661 | 0 | { |
662 | 0 | OFString str(1, s); |
663 | 0 | return this->find_first_of(str, pos); |
664 | 0 | } |
665 | | |
666 | | /* |
667 | | ** Find_last_of |
668 | | */ |
669 | | |
670 | | size_t |
671 | | OFString::find_last_of (const OFString& str, size_t pos) const |
672 | 6 | { |
673 | | /* determine string length only once */ |
674 | 6 | const size_t this_size = this->size(); |
675 | 6 | const size_t str_size = str.size(); |
676 | 6 | if ((this_size == 0) || (str_size == 0)) { |
677 | 0 | return OFString_npos; |
678 | 0 | } |
679 | 6 | if ((pos == OFString_npos) || (pos > this_size)) { |
680 | 0 | pos = this_size; |
681 | 0 | } |
682 | 36 | for (int i = OFstatic_cast(int, pos - 1); i >= 0; i--) { |
683 | 63 | for (size_t j = 0; j < str_size; j++) { |
684 | 33 | if (this->at(i) == str[j]) { |
685 | 3 | return i; |
686 | 3 | } |
687 | 33 | } |
688 | 33 | } |
689 | 3 | return OFString_npos; |
690 | 6 | } |
691 | | |
692 | | size_t |
693 | | OFString::find_last_of (const char* s, size_t pos, size_t n) const |
694 | 0 | { |
695 | 0 | OFString str(s, n); |
696 | 0 | return this->find_last_of(str, pos); |
697 | 0 | } |
698 | | |
699 | | size_t |
700 | | OFString::find_last_of (const char* s, size_t pos) const |
701 | 0 | { |
702 | 0 | OFString str(s); |
703 | 0 | return this->find_last_of(str, pos); |
704 | 0 | } |
705 | | |
706 | | size_t |
707 | | OFString::find_last_of (char s, size_t pos) const |
708 | 6 | { |
709 | 6 | OFString str(1, s); |
710 | 6 | return this->find_last_of(str, pos); |
711 | 6 | } |
712 | | |
713 | | /* |
714 | | ** Find_first_not_of |
715 | | */ |
716 | | |
717 | | size_t |
718 | | OFString::find_first_not_of (const OFString& str, size_t pos) const |
719 | 0 | { |
720 | | /* determine string length only once */ |
721 | 0 | const size_t this_size = this->size(); |
722 | 0 | const size_t str_size = str.size(); |
723 | 0 | if ((this_size == 0) || (str_size == 0) || (pos == OFString_npos)) { |
724 | 0 | return OFString_npos; |
725 | 0 | } |
726 | 0 | for (size_t i = pos; i < this_size; i++) { |
727 | 0 | if (str.find(this->at(i)) == OFString_npos) |
728 | 0 | return i; |
729 | 0 | } |
730 | 0 | return OFString_npos; |
731 | 0 | } |
732 | | |
733 | | size_t |
734 | | OFString::find_first_not_of (const char* s, size_t pos, size_t n) const |
735 | 0 | { |
736 | 0 | OFString str(s, n); |
737 | 0 | return this->find_first_not_of(str, pos); |
738 | 0 | } |
739 | | |
740 | | size_t |
741 | | OFString::find_first_not_of (const char* s, size_t pos) const |
742 | 0 | { |
743 | 0 | OFString str(s); |
744 | 0 | return this->find_first_not_of(str, pos); |
745 | 0 | } |
746 | | |
747 | | size_t |
748 | | OFString::find_first_not_of (char s, size_t pos) const |
749 | 0 | { |
750 | 0 | OFString str(1, s); |
751 | 0 | return this->find_first_not_of(str, pos); |
752 | 0 | } |
753 | | |
754 | | /* |
755 | | ** Find_last_not_of |
756 | | */ |
757 | | |
758 | | size_t |
759 | | OFString::find_last_not_of (const OFString& str, size_t pos) const |
760 | 0 | { |
761 | | /* determine string length only once */ |
762 | 0 | const size_t this_size = this->size(); |
763 | 0 | const size_t str_size = str.size(); |
764 | 0 | if ((this_size == 0) || (str_size == 0)) { |
765 | 0 | return OFString_npos; |
766 | 0 | } |
767 | 0 | if (pos == OFString_npos) { |
768 | 0 | pos = this_size; |
769 | 0 | } |
770 | 0 | for (int i = OFstatic_cast(int, pos - 1); i >= 0; i--) { |
771 | 0 | if (str.find(this->at(i)) == OFString_npos) |
772 | 0 | return i; |
773 | 0 | } |
774 | 0 | return OFString_npos; |
775 | 0 | } |
776 | | |
777 | | size_t |
778 | | OFString::find_last_not_of (const char* s, size_t pos, size_t n) const |
779 | 0 | { |
780 | 0 | OFString str(s, n); |
781 | 0 | return this->find_last_not_of(str, pos); |
782 | 0 | } |
783 | | |
784 | | size_t |
785 | | OFString::find_last_not_of (const char* s, size_t pos) const |
786 | 0 | { |
787 | 0 | OFString str(s); |
788 | 0 | return this->find_last_not_of(str, pos); |
789 | 0 | } |
790 | | |
791 | | size_t |
792 | | OFString::find_last_not_of (char s, size_t pos) const |
793 | 0 | { |
794 | 0 | OFString str(1, s); |
795 | 0 | return this->find_last_not_of(str, pos); |
796 | 0 | } |
797 | | |
798 | | /* |
799 | | ** Operator << |
800 | | */ |
801 | | |
802 | | STD_NAMESPACE ostream& operator<< (STD_NAMESPACE ostream& o, const OFString& s) |
803 | 0 | { |
804 | 0 | return o.write (s.c_str(), s.size()); |
805 | 0 | } |
806 | | |
807 | | /* |
808 | | ** Operator >> |
809 | | */ |
810 | | |
811 | | STD_NAMESPACE istream& operator>> (STD_NAMESPACE istream& i, OFString& s) |
812 | 0 | { |
813 | | // suppress spurious gcc 12 warning |
814 | 0 | #include DCMTK_DIAGNOSTIC_PUSH |
815 | 0 | #include DCMTK_DIAGNOSTIC_IGNORE_STRINGOP_OVERFLOW |
816 | 0 | s.resize(0); |
817 | 0 | #include DCMTK_DIAGNOSTIC_POP |
818 | 0 | char c = '\0'; |
819 | 0 | size_t n = s.max_size(); |
820 | 0 | if (i.width() > 0) { |
821 | 0 | n = OFstatic_cast(size_t, i.width()); |
822 | 0 | } |
823 | | // skip white space before word |
824 | 0 | i.get(c); |
825 | 0 | while (i.good() && isspace(OFstatic_cast(unsigned char, c))) { |
826 | 0 | i.get(c); |
827 | 0 | } |
828 | | // get the word |
829 | 0 | while (i.good() && !isspace(OFstatic_cast(unsigned char, c)) && n--) { |
830 | 0 | s += c; |
831 | 0 | i.get(c); |
832 | 0 | } |
833 | 0 | if (isspace(OFstatic_cast(unsigned char, c))) { |
834 | 0 | i.putback(c); |
835 | 0 | } |
836 | 0 | i.width(0); |
837 | 0 | return i; |
838 | 0 | } |
839 | | |
840 | | /* |
841 | | ** Operator + |
842 | | */ |
843 | | |
844 | | OFString operator+ (const OFString& lhs, const OFString& rhs) |
845 | 0 | { |
846 | 0 | OFString s(lhs); |
847 | 0 | s += rhs; |
848 | 0 | return s; |
849 | 0 | } |
850 | | |
851 | | OFString operator+ (const char* lhs, const OFString& rhs) |
852 | 0 | { |
853 | 0 | OFString s(lhs); |
854 | 0 | s += rhs; |
855 | 0 | return s; |
856 | 0 | } |
857 | | |
858 | | OFString operator+ (char lhs, const OFString& rhs) |
859 | 0 | { |
860 | 0 | OFString s(1, lhs); |
861 | 0 | s += rhs; |
862 | 0 | return s; |
863 | 0 | } |
864 | | |
865 | | OFString operator+ (const OFString& lhs, const char* rhs) |
866 | 0 | { |
867 | 0 | OFString s(lhs); |
868 | 0 | s += rhs; |
869 | 0 | return s; |
870 | 0 | } |
871 | | |
872 | | OFString operator+ (const OFString& lhs, char rhs) |
873 | 0 | { |
874 | 0 | OFString s(lhs); |
875 | 0 | s += rhs; |
876 | 0 | return s; |
877 | 0 | } |
878 | | |
879 | | /* |
880 | | ** Operator == |
881 | | */ |
882 | | |
883 | | OFBool operator== (const OFString& lhs, const OFString& rhs) |
884 | 156 | { |
885 | 156 | return (lhs.compare(rhs) == 0) ? OFTrue : OFFalse; |
886 | 156 | } |
887 | | |
888 | | OFBool operator== (const char* lhs, const OFString& rhs) |
889 | 0 | { |
890 | 0 | OFString slhs(lhs); |
891 | 0 | return (slhs == rhs); |
892 | 0 | } |
893 | | |
894 | | OFBool operator== (char lhs, const OFString& rhs) |
895 | 0 | { |
896 | 0 | OFString slhs(1, lhs); |
897 | 0 | return (slhs == rhs); |
898 | 0 | } |
899 | | |
900 | | OFBool operator== (const OFString& lhs, const char* rhs) |
901 | 0 | { |
902 | 0 | OFString srhs(rhs); |
903 | 0 | return (lhs == srhs); |
904 | 0 | } |
905 | | |
906 | | OFBool operator== (const OFString& lhs, char rhs) |
907 | 0 | { |
908 | 0 | OFString srhs(1, rhs); |
909 | 0 | return (lhs == srhs); |
910 | 0 | } |
911 | | |
912 | | /* |
913 | | ** Operator < |
914 | | */ |
915 | | |
916 | | OFBool operator< (const OFString& lhs, const OFString& rhs) |
917 | 111 | { |
918 | 111 | return (lhs.compare(rhs) < 0) ? OFTrue : OFFalse; |
919 | 111 | } |
920 | | |
921 | | OFBool operator< (const char* lhs, const OFString& rhs) |
922 | 0 | { |
923 | 0 | OFString slhs(lhs); |
924 | 0 | return (slhs < rhs); |
925 | 0 | } |
926 | | |
927 | | OFBool operator< (char lhs, const OFString& rhs) |
928 | 0 | { |
929 | 0 | OFString slhs(1, lhs); |
930 | 0 | return (slhs < rhs); |
931 | 0 | } |
932 | | |
933 | | OFBool operator< (const OFString& lhs, const char* rhs) |
934 | 0 | { |
935 | 0 | OFString srhs(rhs); |
936 | 0 | return (lhs < srhs); |
937 | 0 | } |
938 | | |
939 | | OFBool operator< (const OFString& lhs, char rhs) |
940 | 0 | { |
941 | 0 | OFString srhs(1, rhs); |
942 | 0 | return (lhs < srhs); |
943 | 0 | } |
944 | | |
945 | | /* |
946 | | ** Operator <= |
947 | | */ |
948 | | |
949 | | OFBool operator<= (const OFString& lhs, const OFString& rhs) |
950 | 0 | { |
951 | 0 | return (!(rhs < lhs)); |
952 | 0 | } |
953 | | |
954 | | OFBool operator<= (const char* lhs, const OFString& rhs) |
955 | 0 | { |
956 | 0 | return (!(rhs < lhs)); |
957 | 0 | } |
958 | | |
959 | | OFBool operator<= (char lhs, const OFString& rhs) |
960 | 0 | { |
961 | 0 | return (!(rhs < lhs)); |
962 | 0 | } |
963 | | |
964 | | OFBool operator<= (const OFString& lhs, const char* rhs) |
965 | 0 | { |
966 | 0 | return (!(rhs < lhs)); |
967 | 0 | } |
968 | | |
969 | | OFBool operator<= (const OFString& lhs, char rhs) |
970 | 0 | { |
971 | 0 | return (!(rhs < lhs)); |
972 | 0 | } |
973 | | |
974 | | /* |
975 | | ** Operator != |
976 | | */ |
977 | | |
978 | | OFBool operator!= (const OFString& lhs, const OFString& rhs) |
979 | 0 | { |
980 | 0 | return (!(lhs == rhs)); |
981 | 0 | } |
982 | | |
983 | | OFBool operator!= (const char* lhs, const OFString& rhs) |
984 | 0 | { |
985 | 0 | return (!(lhs == rhs)); |
986 | 0 | } |
987 | | |
988 | | OFBool operator!= (char lhs, const OFString& rhs) |
989 | 0 | { |
990 | 0 | return (!(lhs == rhs)); |
991 | 0 | } |
992 | | |
993 | | OFBool operator!= (const OFString& lhs, const char* rhs) |
994 | 0 | { |
995 | 0 | return (!(lhs == rhs)); |
996 | 0 | } |
997 | | |
998 | | OFBool operator!= (const OFString& lhs, char rhs) |
999 | 0 | { |
1000 | 0 | return (!(lhs == rhs)); |
1001 | 0 | } |
1002 | | |
1003 | | /* |
1004 | | ** Operator > |
1005 | | */ |
1006 | | |
1007 | | OFBool operator> (const OFString& lhs, const OFString& rhs) |
1008 | 111 | { |
1009 | 111 | return (rhs < lhs); |
1010 | 111 | } |
1011 | | |
1012 | | OFBool operator> (const char* lhs, const OFString& rhs) |
1013 | 0 | { |
1014 | 0 | return (rhs < lhs); |
1015 | 0 | } |
1016 | | |
1017 | | OFBool operator> (char lhs, const OFString& rhs) |
1018 | 0 | { |
1019 | 0 | return (rhs < lhs); |
1020 | 0 | } |
1021 | | |
1022 | | OFBool operator> (const OFString& lhs, const char* rhs) |
1023 | 0 | { |
1024 | 0 | return (rhs < lhs); |
1025 | 0 | } |
1026 | | |
1027 | | OFBool operator> (const OFString& lhs, char rhs) |
1028 | 0 | { |
1029 | 0 | return (rhs < lhs); |
1030 | 0 | } |
1031 | | |
1032 | | /* |
1033 | | ** Operator >= |
1034 | | */ |
1035 | | |
1036 | | OFBool operator>= (const OFString& lhs, const OFString& rhs) |
1037 | 0 | { |
1038 | 0 | return (!(lhs < rhs)); |
1039 | 0 | } |
1040 | | |
1041 | | OFBool operator>= (const char* lhs, const OFString& rhs) |
1042 | 0 | { |
1043 | 0 | return (!(lhs < rhs)); |
1044 | 0 | } |
1045 | | |
1046 | | OFBool operator>= (char lhs, const OFString& rhs) |
1047 | 0 | { |
1048 | 0 | return (!(lhs < rhs)); |
1049 | 0 | } |
1050 | | |
1051 | | OFBool operator>= (const OFString& lhs, const char* rhs) |
1052 | 0 | { |
1053 | 0 | return (!(lhs < rhs)); |
1054 | 0 | } |
1055 | | |
1056 | | OFBool operator>= (const OFString& lhs, char rhs) |
1057 | 0 | { |
1058 | 0 | return (!(lhs < rhs)); |
1059 | 0 | } |
1060 | | |
1061 | | #else /* HAVE_STL_STRING */ |
1062 | | |
1063 | | int ofstring_cc_dummy_to_keep_linker_from_moaning = 0; |
1064 | | |
1065 | | #endif |