opennurbs_string.h
1 /* $NoKeywords: $ */
2 /*
3 //
4 // Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved.
5 // OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert
6 // McNeel & Associates.
7 //
8 // THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
9 // ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
10 // MERCHANTABILITY ARE HEREBY DISCLAIMED.
11 //
12 // For complete openNURBS copyright information see <http://www.opennurbs.org>.
13 //
14 ////////////////////////////////////////////////////////////////
15 */
16 
17 #if !defined(ON_STRING_INC_)
18 #define ON_STRING_INC_
19 
20 
21 /*
22 Description:
23  Sort an index array.
24 Parameters
25  method - [in]
26  ON::sort_algorithm::quick_sort (best in general) or ON::sort_algorithm::heap_sort.
27  Use ON::sort_algorithm::heap_sort only after doing meaningful performance
28  testing using optimized release builds that demonstrate
29  ON::sort_algorithm::heap_sort is significantly better.
30  index - [out]
31  Pass in an array of count integers. The returned
32  index[] is a permutation of (0,1,..,count-1)
33  such that compare(B[index[i]],B[index[i+1]) <= 0
34  where B[i] = base + i*sizeof_element
35  base - [in]
36  array of count elements
37  count - [in]
38  number of elements in the index[] and base[] arrays
39  sizeof_element - [in]
40  number of bytes between consecutive elements in the
41  base[] array.
42  compare - [in]
43  Comparison function a la qsort().
44 */
45 ON_DECL
46 void ON_Sort(
47  ON::sort_algorithm method,
48  int* index,
49  const void* base,
50  size_t count,
51  size_t sizeof_element,
52  int (*compare)(const void*,const void*) // int compar(const void*,const void*)
53  );
54 
55 ON_DECL
56 void ON_Sort(
57  ON::sort_algorithm method,
58  unsigned int* index,
59  const void* base,
60  size_t count,
61  size_t sizeof_element,
62  int(*compare)(const void*, const void*) // int compar(const void*,const void*)
63  );
64 
65 
66 /*
67 Description:
68  Sort an index array using a compare function
69  that takes an additional pointer that can be used to
70  pass extra informtation.
71 Parameters
72  method - [in]
73  ON::sort_algorithm::quick_sort (best in general) or ON::sort_algorithm::heap_sort.
74  Use ON::sort_algorithm::heap_sort only after doing meaningful performance
75  testing using optimized release builds that demonstrate
76  ON::sort_algorithm::heap_sort is significantly better.
77  index - [out]
78  Pass in an array of count integers. The returned
79  index[] is a permutation of (0,1,..,count-1)
80  such that compare(B[index[i]],B[index[i+1]) <= 0
81  where B[i] = base + i*sizeof_element
82  base - [in]
83  array of count elements
84  count - [in]
85  number of elements in the index[] and base[] arrays
86  sizeof_element - [in]
87  number of bytes between consecutive elements in the
88  base[] array.
89  compare - [in]
90  Comparison function a la qsort(). The context parameter
91  is pass as the third argument.
92  context - [in]
93  pointer passed as the third argument to compare().
94 */
95 ON_DECL
96 void ON_Sort(
97  ON::sort_algorithm method,
98  int* index,
99  const void* base,
100  size_t count,
101  size_t sizeof_element,
102  int (*compare)(const void*,const void*,void*), // int compar(const void* a,const void* b, void* ptr)
103  void* context
104  );
105 
106 ON_DECL
107 void ON_Sort(
108  ON::sort_algorithm method,
109  unsigned int* index,
110  const void* base,
111  size_t count,
112  size_t sizeof_element,
113  int(*compare)(const void*, const void*, void*), // int compar(const void* a,const void* b, void* ptr)
114  void* context
115  );
116 
117 /*
118 Description:
119  Various sorts. When in doubt, use ON_qsort().
120  ON_qsort - quick sort.
121  ON_hsort = hearp sort.
122 Parameters
123  base - [in]
124  array of count elements
125  count - [in]
126  number of elements in the index[] and base[] arrays
127  sizeof_element - [in]
128  number of bytes between consecutive elements in the
129  base[] array.
130  compare - [in]
131  Comparison function a la qsort(). The context parameter
132  is pass as the third argument.
133  context - [in]
134  pointer passed as the third argument to compare().
135 Remarks:
136  As a rule, use quick sort unless extensive tests in your case
137  prove that heap sort is faster.
138 
139  This implementation of quick sort is generally faster than
140  heap sort, even when the input arrays are nearly sorted.
141  The only common case when heap sort is faster occurs when
142  the arrays are strictly "chevron" (3,2,1,2,3) or "carat"
143  (1,2,3,2,1) ordered, and in these cases heap sort is about
144  50% faster. If the "chevron" or "caret" ordered arrays
145  have a little randomness added, the two algorithms have
146  the same speed.
147 */
148 ON_DECL
149 void ON_hsort(
150  void* base,
151  size_t count,
152  size_t sizeof_element,
153  int (*compare)(const void*,const void*)
154  );
155 
156 ON_DECL
157 void ON_qsort(
158  void* base,
159  size_t count,
160  size_t sizeof_element,
161  int (*compare)(const void*,const void*)
162  );
163 
164 ON_DECL
165 void ON_hsort(
166  void* base,
167  size_t count,
168  size_t sizeof_element,
169  int (*compare)(void*,const void*,const void*),
170  void* context
171  );
172 
173 ON_DECL
174 void ON_qsort(
175  void* base,
176  size_t count,
177  size_t sizeof_element,
178  int (*compare)(void*,const void*,const void*),
179  void* context
180  );
181 
182 /*
183 Description:
184  Sort an array of doubles in increasing order in place.
185 Parameters:
186  sort_algorithm - [in]
187  ON::sort_algorithm::quick_sort (best in general) or ON::sort_algorithm::heap_sort
188  Use ON::sort_algorithm::heap_sort only if you have done extensive testing with
189  optimized release builds and are confident heap sort is
190  significantly faster in your case.
191  a - [in / out]
192  The values in a[] are sorted so that a[i] <= a[i+1].
193  a[] cannot contain NaNs.
194  nel - [in]
195  length of array a[]
196 */
197 ON_DECL
198 void ON_SortDoubleArray(
199  ON::sort_algorithm sort_algorithm,
200  double* a,
201  size_t nel
202  );
203 
204 
205 /*
206 Description:
207  Sort an array of doubles in increasing order in place.
208 Parameters:
209  a - [in / out]
210  The values in a[] are sorted so that a[i] <= a[i+1].
211  a[] cannot contain NaNs.
212  nel - [in]
213  length of array a[]
214 */
215 ON_DECL
216 void ON_SortDoubleArrayIncreasing(
217  double* a,
218  size_t nel
219  );
220 
221 /*
222 Description:
223  Sort an array of doubles in increasing order in place.
224 Parameters:
225  a - [in / out]
226  The values in a[] are sorted so that a[i] >= a[i+1].
227  a[] cannot contain NaNs.
228  nel - [in]
229  length of array a[]
230 */
231 ON_DECL
232 void ON_SortDoubleArrayDecreasing(
233  double* a,
234  size_t nel
235  );
236 
237 /*
238 Description:
239  Sort an array of ints in place.
240 Parameters:
241  sort_algorithm - [in]
242  ON::sort_algorithm::quick_sort (best in general) or ON::sort_algorithm::heap_sort
243  Use ON::sort_algorithm::heap_sort only if you have done extensive testing with
244  optimized release builds and are confident heap sort is
245  significantly faster in your case.
246  a - [in / out]
247  The values in a[] are sorted so that a[i] <= a[i+1].
248  nel - [in]
249  length of array a[]
250 */
251 ON_DECL
252 void ON_SortIntArray(
253  ON::sort_algorithm sort_algorithm,
254  int* a,
255  size_t nel
256  );
257 
258 /*
259 Description:
260  Sort an array of unsigned ints in place.
261 Parameters:
262  sort_algorithm - [in]
263  ON::sort_algorithm::quick_sort (best in general) or ON::sort_algorithm::heap_sort
264  Use ON::sort_algorithm::heap_sort only if you have done extensive testing with
265  optimized release builds and are confident heap sort is
266  significantly faster in your case.
267  a - [in / out]
268  The values in a[] are sorted so that a[i] <= a[i+1].
269  nel - [in]
270  length of array a[]
271 */
272 ON_DECL
273 void ON_SortUnsignedIntArray(
274  ON::sort_algorithm sort_algorithm,
275  unsigned int* a,
276  size_t nel
277  );
278 
279 /*
280 Description:
281  Sort an array of unsigned 64-bit ints in place.
282 Parameters:
283  sort_algorithm - [in]
284  ON::sort_algorithm::quick_sort (best in general) or ON::sort_algorithm::heap_sort
285  Use ON::sort_algorithm::heap_sort only if you have done extensive testing with
286  optimized release builds and are confident heap sort is
287  significantly faster in your case.
288  a - [in / out]
289  The values in a[] are sorted so that a[i] <= a[i+1].
290  nel - [in]
291  length of array a[]
292 */
293 ON_DECL
294 void ON_SortUINT64Array(
295  ON::sort_algorithm sort_algorithm,
296  ON__UINT64* a,
297  size_t nel
298 );
299 
300 
301 
302 /*
303 Description:
304  Sort an array of unsigned null terminated char strings in place.
305 Parameters:
306  sort_algorithm - [in]
307  ON::sort_algorithm::quick_sort (best in general) or ON::sort_algorithm::heap_sort
308  Use ON::sort_algorithm::heap_sort only if you have done extensive testing with
309  optimized release builds and are confident heap sort is
310  significantly faster in your case.
311  a - [in / out]
312  The values in a[] are sorted so that strcmp(a[i],a[i+1]) <= 0.
313  nel - [in]
314  length of array a[]
315 */
316 ON_DECL
317 void ON_SortStringArray(
318  ON::sort_algorithm sort_algorithm,
319  char** a,
320  size_t nel
321  );
322 
323 ON_DECL
324 const int* ON_BinarySearchIntArray(
325  int key,
326  const int* base,
327  size_t nel
328  );
329 
330 ON_DECL
331 const unsigned int* ON_BinarySearchUnsignedIntArray(
332  unsigned int key,
333  const unsigned int* base,
334  size_t nel
335  );
336 
337 ON_DECL
338 const void* ON_BinarySearchArrayForUnsingedInt(
339  unsigned int key,
340  const void* base,
341  size_t count,
342  size_t sizeof_element,
343  size_t key_offset
344  );
345 
346 ON_DECL
347 const double* ON_BinarySearchDoubleArray(
348  double key,
349  const double* base,
350  size_t nel
351  );
352 
353 /*
354  This class is intended to be used to determine if a file's
355  contents have changed.
356 */
357 class ON_CLASS ON_CheckSum
358 {
359 public:
360  ON_CheckSum();
361  ~ON_CheckSum();
362 
363  static const ON_CheckSum UnsetCheckSum;
364 
365  // zeros all fields.
366  void Zero();
367 
368  /*
369  Returns:
370  True if checksum is set.
371  */
372  bool IsSet() const;
373 
374  // C++ default operator=, operator==,
375  // and copy constructor work fine.
376 
377  /*
378  Descripton:
379  Set check sum values for a buffer
380  Parameters:
381  size - [in]
382  number of bytes in buffer
383  buffer - [in]
384  time - [in]
385  last modified time in seconds since Jan 1, 1970, UCT
386  Returns:
387  True if checksum is set.
388  */
389  bool SetBufferCheckSum(
390  size_t size,
391  const void* buffer,
392  time_t time
393  );
394 
395  /*
396  Descripton:
397  Set check sum values for a file.
398  Parameters:
399  fp - [in] pointer to a file opened with ON:FileOpen(...,"rb")
400  Returns:
401  True if checksum is set.
402  */
403  bool SetFileCheckSum(
404  FILE* fp
405  );
406 
407  /*
408  Descripton:
409  Set check sum values for a file.
410  Parameters:
411  filename - [in] name of file.
412  Returns:
413  True if checksum is set.
414  */
415  bool SetFileCheckSum(
416  const wchar_t* filename
417  );
418 
419  /*
420  Description:
421  Test buffer to see if it has a matching checksum.
422  Paramters:
423  size - [in] size in bytes
424  buffer - [in]
425  Returns:
426  True if the buffer has a matching checksum.
427  */
428  bool CheckBuffer(
429  size_t size,
430  const void* buffer
431  ) const;
432 
433  /*
434  Description:
435  Test buffer to see if it has a matching checksum.
436  Paramters:
437  fp - [in] pointer to file opened with ON::OpenFile(...,"rb")
438  bSkipTimeCheck - [in] if true, the time of last
439  modification is not checked.
440  Returns:
441  True if the file has a matching checksum.
442  */
443  bool CheckFile(
444  FILE* fp,
445  bool bSkipTimeCheck = false
446  ) const;
447 
448  /*
449  Description:
450  Test buffer to see if it has a matching checksum.
451  Paramters:
452  filename - [in]
453  bSkipTimeCheck - [in] if true, the time of last
454  modification is not checked.
455  Returns:
456  True if the file has a matching checksum.
457  */
458  bool CheckFile(
459  const wchar_t* filename,
460  bool bSkipTimeCheck = false
461  ) const;
462 
463  bool Write(class ON_BinaryArchive&) const;
464  bool Read(class ON_BinaryArchive&);
465 
466  void Dump(class ON_TextLog&) const;
467 
468 public:
469  size_t m_size; // bytes in the file.
470  time_t m_time; // last modified time in seconds since Jan 1, 1970, UCT
471  ON__UINT32 m_crc[8]; // crc's
472 };
473 
474 
475 /*
476 Description:
477  Get the length of a UTF-8 encoded char string.
478 Parameters:
479  string - [in]
480  null terminated char string.
481 Returns:
482  Number of nonzero char elements before the null terminator.
483  If string is nullptr, then 0 is returned.
484 */
485 ON_DECL
486 int ON_StringLengthUTF8(
487  const char* string
488  );
489 
490 /*
491 Description:
492  Get the length of a UTF-16 encoded ON__UINT16 string.
493 Parameters:
494  string - [in]
495  null terminated ON__UINT16 string.
496 Returns:
497  Number of nonzero ON__UINT16 elements before the null terminator.
498  If string is nullptr, then 0 is returned.
499 */
500 ON_DECL
501 int ON_StringLengthUTF16(
502  const ON__UINT16* string
503  );
504 
505 /*
506 Description:
507  Get the length of a UTF-32 encoded ON__UINT32 string.
508 Parameters:
509  string - [in]
510  null terminated ON__UINT32 string.
511 Returns:
512  Number of nonzero ON__UINT32 elements before the null terminator.
513  If string is nullptr, then 0 is returned.
514 */
515 ON_DECL
516 int ON_StringLengthUTF32(
517  const ON__UINT32* string
518  );
519 
520 /*
521 Description:
522  Get the length of a wchar_t string.
523 Parameters:
524  string - [in]
525  null terminated wchar_t string.
526 Returns:
527  Number of nonzero wchar_t elements before the null terminator.
528  If string is nullptr, then 0 is returned.
529 */
530 ON_DECL
531 int ON_StringLengthWideChar(
532  const wchar_t* string
533  );
534 
535 /*
536 Description:
537  Get the length of a UTF-8 encoded char string.
538 Parameters:
539  string - [in]
540  null terminated char string.
541  string_capacity - [in]
542  maximum number of string[] elements to test.
543 Returns:
544  If string is nullptr or string_capacity <=0, then 0 is returned.
545  If a null terminator is not found, then string_capacity is returned.
546  Otherwise, the number of nonzero char elements before the null terminator is returned.
547 */
548 ON_DECL
549 int ON_StringLengthUTF8(
550  const char* string,
551  size_t string_capacity
552  );
553 
554 /*
555 Description:
556  Get the length of a UTF-16 encoded ON__UINT16 string.
557 Parameters:
558  string - [in]
559  null terminated ON__UINT16 string.
560  string_capacity - [in]
561  maximum number of string[] elements to test.
562 Returns:
563  If string is nullptr or string_capacity <=0, then 0 is returned.
564  If a null terminator is not found, then string_capacity is returned.
565  Otherwise, the number of nonzero char elements before the null terminator is returned.
566 */
567 ON_DECL
568 int ON_StringLengthUTF16(
569  const ON__UINT16* string,
570  size_t string_capacity
571  );
572 
573 /*
574 Description:
575  Get the length of a UTF-32 encoded ON__UINT32 string.
576 Parameters:
577  string - [in]
578  null terminated ON__UINT32 string.
579  string_capacity - [in]
580  maximum number of string[] elements to test.
581 Returns:
582  If string is nullptr or string_capacity <=0, then 0 is returned.
583  If a null terminator is not found, then string_capacity is returned.
584  Otherwise, the number of nonzero char elements before the null terminator is returned.
585 */
586 ON_DECL
587 int ON_StringLengthUTF32(
588  const ON__UINT32* string,
589  size_t string_capacity
590  );
591 
592 /*
593 Description:
594  Get the length of a wchar_t string.
595 Parameters:
596  string - [in]
597  null terminated wchar_t string.
598  string_capacity - [in]
599  maximum number of string[] elements to test.
600 Returns:
601  If string is nullptr or string_capacity <=0, then 0 is returned.
602  If a null terminator is not found, then string_capacity is returned.
603  Otherwise, the number of nonzero char elements before the null terminator is returned.
604 */
605 ON_DECL
606 int ON_StringLengthWideChar(
607  const wchar_t* string,
608  size_t string_capacity
609  );
610 
611 /*
612 Description:
613  Compare of UTF-8 encoded char strings element by element.
614 Parameters:
615  string1 - [in]
616  element_count1 - [in]
617  If element_count1 < 0, then string1 must be null terminated and element_count1
618  will be set to the length of string1.
619  If element_count1 >= 0, then that number of elements are compared in string1[].
620  string2 - [in]
621  element_count2 - [in]
622  If element_count2 < 0, then string2 must be null terminated and element_count2
623  will be set to the length of string2.
624  If element_count2 >= 0, then that number of elements are compared in string2[].
625  bOrdinalIgnoreCase - [in]
626  If bOrdinalIgnoreCase, then letters with a capital and small codepoint value <= 127
627  are compared using the smallest codepoint value. This amounts to converting the
628  letters a-z to A-Z before comparing.
629 Returns:
630  0: the strings are the same
631  <0: string1 < string2
632  >0: string1 > string2
633 Remarks:
634  1) If linguistic issues are important, then this function is not appropriate.
635  2) nullptr values are handled.
636  3) There are lists of Unicode code point values such that the results of
637  ON_StringCompareOrdinalUTF8, ON_StringCompareOrdinalUTF16 and ON_StringCompareOrdinalUTF32
638  are different when applied to UTF-8, UTF-16 and UTF-32 encodings.
639  4) This function does not compare Unicode code point values the strings have eny elements with values > 127.
640 */
641 ON_DECL
642 int ON_StringCompareOrdinalUTF8(
643  const char* string1,
644  int element_count1,
645  const char* string2,
646  int element_count2,
647  bool bOrdinalIgnoreCase
648  );
649 
650 /*
651 Description:
652  Compare of UTF-16 encoded ON__UINT16 strings element by element.
653 Parameters:
654  string1 - [in]
655  element_count1 - [in]
656  If element_count1 < 0, then string1 must be null terminated and element_count1
657  will be set to the length of string1.
658  If element_count1 >= 0, then that number of elements are compared in string1[].
659  string2 - [in]
660  element_count2 - [in]
661  If element_count2 < 0, then string2 must be null terminated and element_count2
662  will be set to the length of string2.
663  If element_count2 >= 0, then that number of elements are compared in string2[].
664  bOrdinalIgnoreCase - [in]
665  If bOrdinalIgnoreCase, then letters with a capital and small codepoint value <= 127
666  are compared using the smallest codepoint value. This amounts to converting the
667  letters a-z to A-Z before comparing.
668 Returns:
669  0: the strings are the same
670  <0: string1 < string2
671  >0: string1 > string2
672 Remarks:
673  1) If linguistic issues are important, then this function is not appropriate.
674  2) nullptr values are handled.
675  3) There are lists of Unicode code point values such that the results of
676  ON_StringCompareOrdinalUTF8, ON_StringCompareOrdinalUTF16 and ON_StringCompareOrdinalUTF32
677  are different when applied to UTF-8, UTF-16 and UTF-32 encodings.
678  4) This function does not compare Unicode code point values if the strings have any surrogate pairs.
679 */
680 ON_DECL
681 int ON_StringCompareOrdinalUTF16(
682  const ON__UINT16* string1,
683  int element_count1,
684  const ON__UINT16* string2,
685  int element_count2,
686  bool bOrdinalIgnoreCase
687  );
688 
689 /*
690 Description:
691  Compare of UTF-32 encoded ON__UINT32 strings element by element.
692 Parameters:
693  string1 - [in]
694  element_count1 - [in]
695  If element_count1 < 0, then string1 must be null terminated and element_count1
696  will be set to the length of string1.
697  If element_count1 >= 0, then that number of elements are compared in string1[].
698  string2 - [in]
699  element_count2 - [in]
700  If element_count2 < 0, then string2 must be null terminated and element_count2
701  will be set to the length of string2.
702  If element_count2 >= 0, then that number of elements are compared in string2[].
703  bOrdinalIgnoreCase - [in]
704  If bOrdinalIgnoreCase, then letters with a capital and small codepoint value <= 127
705  are compared using the smallest codepoint value. This amounts to converting the
706  letters a-z to A-Z before comparing.
707 Returns:
708  0: the strings are the same
709  <0: string1 < string2
710  >0: string1 > string2
711 Remarks:
712  1) If linguistic issues are important, then this function is not appropriate.
713  2) nullptr values are handled.
714  3) There are lists of Unicode code point values such that the results of
715  ON_StringCompareOrdinalUTF8, ON_StringCompareOrdinalUTF16 and ON_StringCompareOrdinalUTF32
716  are different when applied to UTF-8, UTF-16 and UTF-32 encodings.
717 */
718 ON_DECL
719 int ON_StringCompareOrdinalUTF32(
720  const ON__UINT32* string1,
721  int element_count1,
722  const ON__UINT32* string2,
723  int element_count2,
724  bool bOrdinalIgnoreCase
725  );
726 
727 /*
728 Description:
729  Compare wchar_t strings element by element.
730 Parameters:
731  string1 - [in]
732  element_count1 - [in]
733  If element_count1 < 0, then string1 must be null terminated and element_count1
734  will be set to the length of string1.
735  If element_count1 >= 0, then that number of elements are compared in string1[].
736  string2 - [in]
737  element_count2 - [in]
738  If element_count2 < 0, then string2 must be null terminated and element_count2
739  will be set to the length of string2.
740  If element_count2 >= 0, then that number of elements are compared in string2[].
741  bOrdinalIgnoreCase - [in]
742  If bOrdinalIgnoreCase, then letters with a capital and small codepoint value <= 127
743  are compared using the smallest codepoint value. This amounts to converting the
744  letters a-z to A-Z before comparing.
745 Returns:
746  0: the strings are the same
747  <0: string1 < string2
748  >0: string1 > string2
749 Remarks:
750  1) If linguistic issues are important, then this function is not appropriate.
751  2) nullptr values are handled.
752  3) There are lists of Unicode code point values such that the results of
753  ON_StringCompareOrdinalUTF8, ON_StringCompareOrdinalUTF16 and ON_StringCompareOrdinalUTF32
754  are different when applied to UTF-8, UTF-16 and UTF-32 encodings.
755  4) This function assumes the sizeof(wchar_t) is 1, 2 or 4,
756  that 1 bytes wchar_t strings are UTF-8 encoded, 2 byte wchar_t strings are UTF-16 encoded
757  and 4 bytes wchar_t strings are UTF-32 encoded.
758 */
759 ON_DECL
760 int ON_StringCompareOrdinalWideChar(
761  const wchar_t* string1,
762  int element_count1,
763  const wchar_t* string2,
764  int element_count2,
765  bool bOrdinalIgnoreCase
766  );
767 
768 /////////////////////////////////////////////////////////////////////////////
769 //
770 // ON_String is a UTF-8 char string on all platforms
771 // ON_wString is a UTF-16 encoded wchar_t string on Windows platforms
772 // ON_wString is a UTF-32 encoded wchar_t string on Windows platforms
773 //
774 
775 class ON_CLASS ON_StringBuffer
776 {
777 public:
778  ON_StringBuffer();
781  char* stack_buffer,
782  size_t stack_buffer_capacity
783  );
784 
785  ~ON_StringBuffer();
786 
787  bool GrowBuffer(
788  size_t buffer_capacity
789  );
790 
791  char* m_buffer;
792  size_t m_buffer_capacity;
793 
794 private:
796  ON_StringBuffer& operator=(const ON_StringBuffer&);
797  char* m_heap_buffer;
798  size_t m_heap_buffer_capacity;
799 };
800 
801 class ON_CLASS ON_wStringBuffer
802 {
803 public:
805 
807  wchar_t* stack_buffer,
808  size_t stack_buffer_capacity
809  );
810 
811  ~ON_wStringBuffer();
812 
813  bool GrowBuffer(
814  size_t buffer_capacity
815  );
816 
817  wchar_t* m_buffer;
818  size_t m_buffer_capacity;
819 
820 private:
822  ON_wStringBuffer& operator=(const ON_wStringBuffer&);
823  wchar_t* m_heap_buffer;
824  size_t m_heap_buffer_capacity;
825 };
826 
827 ON_DECL
828 ON__UINT32 ON_UnicodeMapCodePointOrdinal(
829  ON_StringMapOrdinalType map_type,
830  ON__UINT32 unicode_code_point
831  );
832 
833 ON_DECL
834 ON__UINT32 ON_UnicodeMapCodePoint(
835  const ON_Locale& locale,
836  ON_StringMapType map_type,
837  ON__UINT32 unicode_code_point
838  );
839 
840 /*
841 Parameters:
842  sUTF8 - [in]
843  pointer to a UTF-8 encoded string.
844  element_count - [in]
845  number of char elements to parse.
846  if element_count < 0, then sUTF8 must be null terminated
847  mapping - [in]
848  mapping to apply to unicode code points
849 Returns:
850  A SHA-1 value of the sequence of unicode code points. This value is independent
851  of platform endian or UTF encoding.
852 */
853 const ON_SHA1_Hash ON_StringContentHash(
854  const char* sUTF8,
855  int element_count,
856  ON_StringMapOrdinalType mapping
857 );
858 
859 /*
860 Parameters:
861  sUTF8 - [in]
862  pointer to a UTF-8 encoded string.
863  element_count - [in]
864  number of char elements to parse.
865  if element_count < 0, then sUTF8 must be null terminated
866  mapping - [in]
867  mapping to apply to unicode code points
868 Returns:
869  A SHA-1 value of the sequence of unicode code points. This value is independent
870  of platform endian or UTF encoding.
871 */
872 const ON_SHA1_Hash ON_StringContentHash(
873  const wchar_t* sWideString,
874  int element_count,
875  ON_StringMapOrdinalType mapping
876 );
877 
878 class ON_CLASS ON_String
879 {
880 public:
881 
882 // Constructors
883  ON_String() ON_NOEXCEPT;
884  ON_String( const ON_String& );
885 
886  // ON_String::EmptyString has length 0.
887  // const char* s = ON_String::EmptyString sets s to "".
888  static const ON_String EmptyString;
889 
890  static const char Backspace; // Unicode BACKSPACE control U+0008
891  static const char Tab; // Unicode CHARACTER TABULATION control U+0009
892  static const char LineFeed; // Unicode LINE FEED control U+000A
893  static const char VerticalTab; // Unicode LINE TABULATION control U+000B
894  static const char FormFeed; // Unicode FORM FEED control U+000C
895  static const char CarriageReturn; // Unicode CHARACTER TABULATION control U+000D
896  static const char Escape; // Unicode CARRIAGE RETURN control U+001B
897  static const char Space; // Unicode SPACE U+0020
898  static const char Slash; // Unicode SOLIDUS U+002F
899  static const char Backslash; // Unicode REVERSE SOLIDUS U+005C
900  static const char Pipe; // Unicode VERTICAL LINE U+007C
901 
902 private:
903  // Use IsEmpty() or IsNotEmpty() when you want a bool
904  // to test for the empty string.
905  explicit operator bool() const { return IsNotEmpty(); }
906 public:
907 
908 #if defined(ON_HAS_RVALUEREF)
909  // Clone constructor
910  ON_String( ON_String&& ) ON_NOEXCEPT;
911 
912  // Clone Assignment operator
913  ON_String& operator=( ON_String&& ) ON_NOEXCEPT;
914 #endif
915 
916  ON_String( const char* );
917  ON_String( const char*, int /*length*/ ); // from substring
918  ON_String( char, int = 1 /* repeat count */ );
919 
920  ON_String( const unsigned char* );
921  ON_String( const unsigned char*, int /*length*/ ); // from substring
922  ON_String( unsigned char, int = 1 /* repeat count */ );
923 
924  // construct a UTF-8 string string from a UTF-16 string.
925  ON_String( const wchar_t* src ); // src = UTF-16 string
926  ON_String( const wchar_t* src, int length ); // from a UTF-16 substring
927  ON_String( const ON_wString& src ); // src = UTF-16 string
928 
929 #if defined(ON_RUNTIME_WIN)
930  // Windows support
931  bool LoadResourceString( HINSTANCE, UINT); // load from Windows string resource
932  // 2047 chars max
933 #endif
934 
935  void Create();
936  void Destroy(); // releases any memory and initializes to default empty string
937  void EmergencyDestroy();
938 
939  /*
940  Description:
941  Enables reference counting. I limited cases, this is useful
942  for large strings or strings that are frequently passed around.
943  Reference counted strings must be carefully managed in
944  when multi-threading is used.
945  Parameters:
946  If EnableReferenceCounting()
947  is not called, then the string will not be referanceThe default is to not use
948  reference counted strings.
949  */
950  void EnableReferenceCounting( bool bEnable );
951 
952  /*
953  Returns:
954  True if the string is reference counted.
955  */
956  bool IsReferenceCounted() const;
957 
958 
959  // Attributes & Operations
960 
961  /*
962  Returns:
963  number of nonzero elements in string.
964  */
965  int Length() const;
966 
967  /*
968  Returns:
969  number of nonzero elements in the string.
970  */
971  unsigned int UnsignedLength() const;
972 
973  /*
974  Returns:
975  number of nonzero elements in string before the first null terminator.
976  If string is nullptr, 0 is returned.
977  */
978  static int Length(
979  const char* string
980  );
981 
982  /*
983  Returns:
984  number of nonzero elements in string before the first null terminator.
985  If string is nullptr, 0 is returned.
986  */
987  static unsigned int UnsignedLength(
988  const char* string
989  );
990 
991  bool IsEmpty() const; // returns true if length == 0
992  bool IsNotEmpty() const; // returns true if length > 0
993  void Empty(); // sets length to zero - if possible, memory is retained
994 
995  char& operator[](int);
996  char operator[](int) const;
997  char GetAt(int) const;
998  void SetAt(int, char);
999  void SetAt(int, unsigned char);
1000 
1001  operator const char*() const;
1002 
1003  // overloaded assignment
1004  ON_String& operator=(const ON_String&);
1005  ON_String& operator=(char);
1006  ON_String& operator=(const char*);
1007  ON_String& operator=(unsigned char);
1008  ON_String& operator=(const unsigned char*);
1009  ON_String& operator=(const wchar_t* src); // src = Wide char string, result is a UTF-8 string
1010  ON_String& operator=(const ON_wString& src); // src = Wide char string, result is a UTF-8 string
1011 
1012  // operator+()
1013  ON_String operator+(const ON_String&) const;
1014  ON_String operator+(char) const;
1015  ON_String operator+(unsigned char) const;
1016  ON_String operator+(const char*) const;
1017  ON_String operator+(const unsigned char*) const;
1018 
1019  // string concatenation
1020  void Append( const char*, int ); // append specified number of characters
1021  void Append( const unsigned char*, int ); // append specified number of characters
1022  const ON_String& operator+=(const ON_String&);
1023  const ON_String& operator+=(char);
1024  const ON_String& operator+=(unsigned char);
1025  const ON_String& operator+=(const char*);
1026  const ON_String& operator+=(const unsigned char*);
1027 
1028  ON_DEPRECATED_MSG("Use CompareOrdinal(), ComparePath(), CompareAttributeName(), or a test that is linguistically apprropriate")
1029  int Compare( const char* ) const;
1030 
1031  ON_DEPRECATED_MSG("Use CompareOrdinal(), ComparePath(), CompareAttributeName(), or a test that is linguistically apprropriate")
1032  int Compare( const unsigned char* ) const;
1033 
1034  ON_DEPRECATED_MSG("Use CompareOrdinal(), ComparePath(), CompareAttributeName(), or a test that is linguistically apprropriate")
1035  int CompareNoCase( const char* ) const;
1036 
1037  ON_DEPRECATED_MSG("Use CompareOrdinal(), ComparePath(), CompareAttributeName(), or a test that is linguistically apprropriate")
1038  int CompareNoCase( const unsigned char* ) const;
1039 
1040  bool Equal(
1041  const ON_String& other_string,
1042  const class ON_Locale& locale,
1043  bool bIgnoreCase
1044  ) const;
1045 
1046  bool Equal(
1047  const char* other_string,
1048  const class ON_Locale& locale,
1049  bool bIgnoreCase
1050  ) const;
1051 
1052  static bool Equal(
1053  const char* string1,
1054  const char* string2,
1055  const class ON_Locale& locale,
1056  bool bIgnoreCase
1057  );
1058 
1059  static bool Equal(
1060  const char* string1,
1061  int element_count1,
1062  const char* string2,
1063  int element_count2,
1064  const class ON_Locale& locale,
1065  bool bOrdinalIgnoreCase
1066  );
1067 
1068  /*
1069  Description:
1070  Compare this string and other_string by normalizing (NFC)
1071  and using invariant culture ordering.
1072  Parameters:
1073  other_string - [in]
1074  bIgnoreCase - [in]
1075  Remarks:
1076  1) Ordinal compares are the fastest.
1077  2) Equal(...) is faster than Compare(...)
1078  */
1079  int Compare(
1080  const ON_String& other_string,
1081  const class ON_Locale& locale,
1082  bool bIgnoreCase
1083  ) const;
1084 
1085  int Compare(
1086  const char* other_string,
1087  const class ON_Locale& locale,
1088  bool bIgnoreCase
1089  ) const;
1090 
1091  /*
1092  Description:
1093  Compare string1 and string2 by normalizing (NFC) and using invariant culture ordering.
1094  Parameters:
1095  string1 - [in]
1096  string2 - [in]
1097  bIgnoreCase - [in]
1098  Remarks:
1099  1) Ordinal compares are the fastest.
1100  2) Equal(...) is faster than Compare(...)
1101  */
1102  static int Compare(
1103  const char* string1,
1104  const char* string2,
1105  const class ON_Locale& locale,
1106  bool bIgnoreCase
1107  );
1108 
1109  /*
1110  Description:
1111  Compare string1 and string2 by normalizing (NFC) and using invariant culture ordering.
1112  Parameters:
1113  string1 - [in]
1114  element_count1 - [in]
1115  The number of string1[] elements to compare.
1116  If element_count1 < 0, then string1 must be null terminated.
1117  string2 - [in]
1118  element_count2 - [in]
1119  The number of string2[] elements to compare.
1120  If element_count2 < 0, then string2 must be null terminated.
1121  locale - [in]
1122  Typically ON_Locale::Ordinal, ON_Locale::InvariantCulture, or
1123  ON_Locale::CurrentCulture.
1124  bIgnoreCase - [in]
1125  Remarks:
1126  1) Ordinal compares are the fastest.
1127  2) Equal(...) is faster than Compare(...)
1128  */
1129  static int Compare(
1130  const char* string1,
1131  int element_count1,
1132  const char* string2,
1133  int element_count2,
1134  const class ON_Locale& locale,
1135  bool bIgnoreCase
1136  );
1137 
1138  bool EqualOrdinal(
1139  const ON_String& other_string,
1140  bool bOrdinalIgnoreCase
1141  ) const;
1142 
1143  bool EqualOrdinal(
1144  const char* other_string,
1145  bool bOrdinalIgnoreCase
1146  ) const;
1147 
1148  static bool EqualOrdinal(
1149  const char* string1,
1150  const char* string2,
1151  bool bOrdinalIgnoreCase
1152  );
1153 
1154  static bool EqualOrdinal(
1155  const char* string1,
1156  int element_count1,
1157  const char* string2,
1158  int element_count2,
1159  bool bOrdinalIgnoreCase
1160  );
1161 
1162  /*
1163  Description:
1164  Compare this string and other_string unsigned byte by unsigned byte.
1165  Parameters:
1166  other_string - [in]
1167  bIgnoreCase - [in]
1168  Remarks:
1169  1) If the string is UTF-8 encoded and bOrdinalIgnoreCase is true, only
1170  small latin a - z and capital latin A - Z are considered equal. It is
1171  imposible to ignore case for any other values in an ordinal compare.
1172 
1173  2) If you are comparing file system paths, you should use ComparePath().
1174 
1175  3) If locale, linguistic issues, UTF-8 encoding issues or unicode normalization
1176  or collation issues need to be considered, then CompareOrdinal() is
1177  the wrong function to use.
1178  */
1179  int CompareOrdinal(
1180  const ON_String& other_string,
1181  bool bIgnoreCase
1182  ) const;
1183 
1184  int CompareOrdinal(
1185  const char* other_string,
1186  bool bIgnoreCase
1187  ) const;
1188 
1189  /*
1190  Description:
1191  Compare string1 and string2 unsigned byte by unsigned byte.
1192  Parameters:
1193  string1 - [in]
1194  string2 - [in]
1195  bIgnoreCase - [in]
1196  Remarks:
1197  1) If the string is UTF-8 encoded and bOrdinalIgnoreCase is true, only
1198  small latin a - z and capital latin A - Z are considered equal. It is
1199  imposible to ignore case for any other values in a UTF-8 ordinal compare.
1200 
1201  2) If you are comparing file system paths, you should use ComparePath().
1202 
1203  3) If locale, linguistic issues, UTF-8 encoding issues or unicode normalization
1204  or collation issues need to be considered, then CompareOrdinal() is
1205  the wrong function to use.
1206  */
1207  static int CompareOrdinal(
1208  const char* string1,
1209  const char* string2,
1210  bool bIgnoreCase
1211  );
1212 
1213  /*
1214  Description:
1215  Compare string1 and string2 unsigned byte by unsigned byte.
1216  Parameters:
1217  string1 - [in]
1218  element_count1 - [in]
1219  The number of elements in string1[] to compare.
1220  If element_count1 < 1, string1 must be null terminated and every element
1221  before the null terminator will be compared.
1222  string2 - [in]
1223  element_count2 - [in]
1224  The number of elements in string2[] to compare.
1225  If element_count2 < 1, string2 must be null terminated and every element
1226  before the null terminator will be compared.
1227  bOrdinalIgnoreCase - [in]
1228  If true, elements with values a-z are compared as if they had values A-Z.
1229  Remarks:
1230  1) If the string is UTF-8 encoded and bOrdinalIgnoreCase is true, only
1231  small latin a - z and capital latin A - Z are considered equal. It is
1232  imposible to ignore case for any other values in a UTF-8 ordinal compare.
1233 
1234  2) If you are comparing file system paths, you should use ComparePath().
1235 
1236  3) If locale, linguistic issues, UTF-8 encoding issues or unicode normalization
1237  or collation issues need to be considered, then CompareOrdinal() is
1238  the wrong function to use.
1239  */
1240  static int CompareOrdinal(
1241  const char* string1,
1242  int element_count1,
1243  const char* string2,
1244  int element_count2,
1245  bool bOrdinalIgnoreCase
1246  );
1247 
1248  /*
1249  Description:
1250  Compare this string and other_path as file system paths using
1251  appropriate tests for the current operating system.
1252  Parameters:
1253  other_path - [in]
1254  Remarks:
1255  1) Windows and UNIX directory separators (/ and \) are considered equal.
1256 
1257  2) Case is ignored when the file system is not case sensitive, like Windows.
1258 
1259  3) String normalization appropriate for the current operating system
1260  is performed.
1261  */
1262  int ComparePath(
1263  const char* other_path
1264  ) const;
1265 
1266  bool EqualPath(
1267  const char* other_path
1268  ) const;
1269 
1270  /*
1271  Description:
1272  Compare sPath1 and sPath2 as file system paths using
1273  appropriate tests for the current operating system.
1274  Parameters:
1275  path1 - [in]
1276  null terminated string
1277  path2 - [in]
1278  null terminated string
1279  Remarks:
1280  1) Windows and UNIX directory separators (/ and \) are considered equal.
1281 
1282  2) Case is ignored when the file system is not case sensitive, like Windows.
1283 
1284  3) String normalization appropriate for the current operating system
1285  is performed.
1286  */
1287  static int ComparePath(
1288  const char* path1,
1289  const char* path2
1290  );
1291 
1292  static bool EqualPath(
1293  const char* path1,
1294  const char* path2
1295  );
1296 
1297  /*
1298  Description:
1299  Compare sPath1 and sPath2 as file system paths using
1300  appropriate tests for the current operating system.
1301  Parameters:
1302  path1 - [in]
1303  maximum_element_count1 - [in]
1304  path2 - [in]
1305  maximum_element_count2 - [in]
1306  Remarks:
1307  1) Windows and UNIX directory separators (/ and \) are considered equal.
1308 
1309  2) Case is ignored when the file system is not case sensitive, like Windows.
1310 
1311  3) String normalization appropriate for the current operating system
1312  is performed.
1313  */
1314  static int ComparePath(
1315  const char* path1,
1316  int element_count1,
1317  const char* path2,
1318  int element_count2
1319  );
1320 
1321  static bool EqualPath(
1322  const char* path1,
1323  int element_count1,
1324  const char* path2,
1325  int element_count2
1326  );
1327 
1328  /*
1329  Description:
1330  Compare this string and other_name as a name attribute of an object
1331  like ON_3dmObjectAttributes.m_name, ON_Layer.m_name, and so on.
1332  These comparisons ignore case and use appropriate string normalization.
1333  Parameters:
1334  other_name - [in]
1335  null terminated string
1336  */
1337  int CompareAttributeName(
1338  const char* other_name
1339  ) const;
1340  bool EqualAttributeName(
1341  const char* other_name
1342  ) const;
1343 
1344  /*
1345  Description:
1346  Compare this string and other_name as a name attribute of an object
1347  like ON_3dmObjectAttributes.m_name, ON_Layer.m_name, and so on.
1348  These comparisons ignore case and use appropriate string normalization.
1349  Parameters:
1350  name1 - [in]
1351  null terminated string
1352  name2 - [in]
1353  null terminated string
1354  */
1355  static int CompareAttributeName(
1356  const char* name1,
1357  const char* name2
1358  );
1359  static bool EqualAttributeName(
1360  const char* name1,
1361  const char* name2
1362  );
1363 
1364  // Description:
1365  // Simple case sensitive wildcard matching. A question mark (?) in the
1366  // pattern matches a single character. An asterisk (*) in the pattern
1367  // mathes zero or more occurances of any character.
1368  //
1369  // Parameters:
1370  // pattern - [in] pattern string where ? and * are wild cards.
1371  //
1372  // Returns:
1373  // true if the string mathes the wild card pattern.
1374  bool WildCardMatch( const char* ) const;
1375  bool WildCardMatch( const unsigned char* ) const;
1376 
1377  // Description:
1378  // Simple case insensitive wildcard matching. A question mark (?) in the
1379  // pattern matches a single character. An asterisk (*) in the pattern
1380  // mathes zero or more occurances of any character.
1381  //
1382  // Parameters:
1383  // pattern - [in] pattern string where ? and * are wild cards.
1384  //
1385  // Returns:
1386  // true if the string mathes the wild card pattern.
1387  bool WildCardMatchNoCase( const char* ) const;
1388  bool WildCardMatchNoCase( const unsigned char* ) const;
1389 
1390  /*
1391  Description:
1392  Replace all substrings that match token1 with token2
1393  Parameters:
1394  token1 - [in]
1395  token2 - [in]
1396  Returns:
1397  Number of times token1 was replaced with token2.
1398  */
1399  int Replace( const char* token1, const char* token2 );
1400  int Replace( const unsigned char* token1, const unsigned char* token2 );
1401  int Replace(char utf8_single_byte_c1, char utf8_single_byte_c2);
1402  int Replace(unsigned char utf8_single_byte_c1, unsigned char utf8_single_byte_c2);
1403 
1404 
1405  // simple sub-string extraction
1406  ON_String Mid(
1407  int, // index of first char
1408  int // count
1409  ) const;
1410  ON_String Mid(
1411  int // index of first char
1412  ) const;
1413  ON_String Left(
1414  int // number of chars to keep
1415  ) const;
1416  ON_String Right(
1417  int // number of chars to keep
1418  ) const;
1419 
1420  /*
1421  Description:
1422  Map a single byte UTF-8 element to upper or lower case.
1423  Parameters:
1424  c - [in]
1425  If c is in the range A to Z or a to z, the map specified
1426  by map_type is applied. All other values of c are
1427  unchanged.
1428  Remarks:
1429  MapCharacterOrdinal is not appropriate for general string mapping.
1430  */
1431  static char MapCharacterOrdinal(
1432  ON_StringMapOrdinalType map_type,
1433  char c
1434  );
1435 
1436  ON_String MapStringOrdinal(
1437  ON_StringMapOrdinalType map_type
1438  ) const;
1439 
1440 
1441  /*
1442  Description:
1443  Map a wchar_t string.
1444  Parameters:
1445  map_type - [in]
1446  string - [in]
1447  element_count - [in]
1448  number of string[] elements to map.
1449  If element_count < 0, then ON_wString::Length(string) elements are mapped.
1450  mapped_string - [out]
1451  mapped_string_capacity - [in]
1452  number of available elements in mapped_string[].
1453  map_type - [in]
1454  Returns:
1455  Number of mapped_string[] elements that were mapped from string[].
1456 
1457  When the number of string[] input elements is >= mapped_string_capacity,
1458  mapped_string_capacity mapped_string[] elements are set and
1459  mapped_string_capacity is returned.
1460 
1461  When the return value is < mapped_string_capacity, a null terminator
1462  is appended after the last mapped element.
1463  */
1464  static int MapStringOrdinal(
1465  ON_StringMapOrdinalType map_type,
1466  const char* string,
1467  int element_count,
1468  char* mapped_string,
1469  int mapped_string_capacity
1470  );
1471 
1472  ON_String MapString(
1473  const class ON_Locale& locale,
1474  ON_StringMapType map_type
1475  ) const;
1476 
1477  static ON_String MapString(
1478  const class ON_Locale& locale,
1479  ON_StringMapType map_type,
1480  const char* string,
1481  int element_count
1482  );
1483 
1484  /*
1485  Description:
1486  Maps element_count elements of string[] to mapped_string[].
1487 
1488  Parameters:
1489  locale - [in]
1490  Locale to use when converting case. It is common to pass one of
1491  the preset locales ON_Locale::Ordinal, ON_Locale::InvariantCulture,
1492  or ON_Locale::m_CurrentCulture.
1493 
1494  map_type - [in]
1495  selects the mapping
1496 
1497  string - [in]
1498  input string to map.
1499 
1500  element_count - [in]
1501  The number of char elements to map from input string[].
1502 
1503  If element_count < 1, then string[] must be null terminated and
1504  ON_wString::Length(string)+1 elements are mapped.
1505  The +1 insures the output is null terminated.
1506 
1507  mapped_string - [out]
1508  The result of the mapping is returned in mapped_string[].
1509 
1510  mapped_string_capacity - [in]
1511  Number of char elements available in mapped_string[]
1512  or 0 to calculate the minimum number of elements needed
1513  for the mapping.
1514 
1515  Returns:
1516  If mapped_string_capacity > 0, then the number elements set in mapped_string[]
1517  is returned.
1518 
1519  If mapped_string_capacity == 0, then the number elements required to perform
1520  the mapping is returned.
1521 
1522  When there is room, mapped_string[] is null terminated.
1523 
1524  0: Failure.
1525  */
1526  static int MapString(
1527  const class ON_Locale& locale,
1528  ON_StringMapType map_type,
1529  const char* string,
1530  int element_count,
1531  char* mapped_string,
1532  int mapped_string_capacity
1533  );
1534 
1535  // upper/lower/reverse conversion
1536  /*ON_DEPRECATED */ void MakeUpper();
1537  /*ON_DEPRECATED */void MakeLower();
1538  void MakeUpperOrdinal();
1539  void MakeLowerOrdinal();
1540 
1541  const ON_SHA1_Hash ContentHash(
1542  ON_StringMapOrdinalType mapping
1543  ) const;
1544 
1545  ON_String Reverse() const;
1546 
1547  static char* Reverse(
1548  char* string,
1549  int element_count
1550  );
1551 
1552  void MakeReverse();
1553 
1554  void TrimLeft(const char* = nullptr);
1555  void TrimRight(const char* = nullptr);
1556  void TrimLeftAndRight(const char* = nullptr);
1557 
1558  // remove occurrences of chRemove
1559  int Remove(const char utf8_single_byte_c);
1560 
1561  // searching (return starting index, or -1 if not found)
1562  // look for a single character match
1563  int Find(
1564  char utf8_single_byte_c
1565  ) const;
1566  int Find(
1567  unsigned char utf8_single_byte_c
1568  ) const;
1569  int ReverseFind(
1570  char utf8_single_byte_c
1571  ) const;
1572  int ReverseFind(
1573  unsigned char utf8_single_byte_c
1574  ) const;
1575 
1576  // look for a specific sub-string
1577  int Find(
1578  const char*
1579  ) const;
1580  int Find(
1581  const unsigned char*
1582  ) const;
1583  int Find(
1584  const char*,
1585  int start_index
1586  ) const;
1587  int Find(
1588  const unsigned char*,
1589  int start_index
1590  ) const;
1591  int ReverseFind(
1592  const char*
1593  ) const;
1594  int ReverseFind(
1595  const unsigned char*
1596  ) const;
1597 
1598  // It is common to format single numbers into strings
1599  // and the FromNumber and FromDouble functions are
1600  // the fastest way to do this and provide consistent results.
1601  // They return a pointer to their buffer so the can be used
1602  // as function parameters.
1603  static const ON_String FromNumber(
1604  char n
1605  );
1606  static const ON_String FromNumber(
1607  unsigned char n
1608  );
1609  static const ON_String FromNumber(
1610  short n
1611  );
1612  static const ON_String FromNumber(
1613  unsigned short n
1614  );
1615  static const ON_String FromNumber(
1616  int n
1617  );
1618  static const ON_String FromNumber(
1619  unsigned int n
1620  );
1621  static const ON_String FromNumber(
1622  ON__INT64 n
1623  );
1624  static const ON_String FromNumber(
1625  ON__UINT64 n
1626  );
1627  static const ON_String FromNumber(
1628  double d // "%g" format
1629  );
1630  static const ON_String ApproximateFromNumber(
1631  double d // "%f" when possible, otherwise "%g"
1632  );
1633  static const ON_String PreciseFromNumber(
1634  double d // "%.17g"
1635  );
1636 
1637 
1638  /*
1639  Description:
1640  Each byte value is converted to 2 hexadecimal digits.
1641  Parameters:
1642  bytes - [in]
1643  list of byte values
1644  byte_count - [in]
1645  Number of byte values in bytes[] array.
1646  bCapitalDigits - [in]
1647  false: Use 0-9, a - b
1648  true: Use 0-9, A - F
1649  bReverse - [in]
1650  false:
1651  The digist in the string will be in the order
1652  bytes[0], bytes[1], ..., bytes[byte_count-1].
1653  true:
1654  The digist in the string will be in the order
1655  bytes[byte_count-1], ..., bytes[1], bytes[0].
1656  */
1657  static const ON_String HexadecimalFromBytes(
1658  const ON__UINT8* bytes,
1659  size_t byte_count,
1660  bool bCapitalDigits,
1661  bool bReverse
1662  );
1663 
1664  /*
1665  Parameters:
1666  format - [in]
1667  Format control.
1668  Positional paramters of the form %N$x where N >= 1 and x
1669  is the standard format specification are supported.
1670  Avoid using %S (capital S). See the Remarks for details.
1671  ... - [in]
1672  arguments for replacable items in the format string.
1673  Returns:
1674  True if successful.
1675  False if the string is too long or the format string is not valid.
1676  Remarks:
1677  When using Microsoft's compiler and other compilers that provide similar
1678  locale support, the locale is the invariant culture locale returned by
1679  ON_Locale::InvariantCulture::LocalePtr().
1680 
1681  The way Windows handles the %S (capital S) format parameter depends on locale
1682  and code page settings. It is strongly reccommended that you never use %S to
1683  include any string that may possibly contain elements with values > 127.
1684  The following examples illustrate a way to predictably use UTF-8 and wchar_t
1685  parameters in buffers of the other element type.
1686 
1687  const char* utf8_string = ...;
1688  // UNRELIABLE // ON_wString::Format(buffer,buffer_capacity,"%S",utf8_string);
1689  // The code below will treat utf8_string as a UTF-8 encoded string.
1690  wchar_t wchar_buffer[...];
1691  const size_t wchar_buffer_capacity= sizeof(buffer)/sizeof(buffer[0]);
1692  ON_wString::Format(wchar_buffer, wchar_buffer_capacity, "%s", ON_wString(utf8_string));
1693 
1694  const wchar_t* wide_string = ...;
1695  // UNRELIABLE // ON_wString::Format(buffer,buffer_capacity,"%S",char_string);
1696  // The code below will include wide_string as a UTF-8 encoded string.
1697  char char_buffer[...];
1698  const size_t char_buffer_capacity = sizeof(buffer)/sizeof(buffer[0]);
1699  ON_String::Format(char_buffer, char_buffer_capacity, "%s", ON_String(wide_string));
1700  */
1701  bool ON_VARGS_FUNC_CDECL Format(
1702  const char* format,
1703  ...
1704  );
1705 
1706  bool ON_VARGS_FUNC_CDECL Format(
1707  const unsigned char* format,
1708  ...
1709  );
1710 
1711  static const ON_wString ON_VARGS_FUNC_CDECL FormatToString(
1712  const char* format,
1713  ...
1714  );
1715 
1716  bool FormatVargs(
1717  const char* format,
1718  va_list args
1719  );
1720 
1721  bool FormatVargs(
1722  const unsigned char* format,
1723  va_list args
1724  );
1725 
1726  /*
1727  Description:
1728  A platform independent, secure, culture invariant way to format a char string.
1729  This function is provide to be used when it is critical that
1730  the formatting be platform independent, secure and culture invarient.
1731  Parameters:
1732  buffer - [out]
1733  not null
1734  buffer_capacity - [in]
1735  > 0
1736  Number of char elements in buffer.
1737  sFormat - [in]
1738  Avoid using %S (capital S). See the Remarks for details.
1739  ... - [in]
1740  Returns:
1741  >= 0:
1742  The number of char elements written to buffer[], not including the null terminator.
1743  A null terminator is always added (buffer[returned value] = 0).
1744  The last element of buffer[] is always set to zero (buffer[buffer_capacity-1] = 0).
1745  < 0: failure:
1746  If buffer is not null and buffer_capacity > 0, then buffer[0] = 0 and buffer[buffer_capacity-1] = 0;
1747  Remarks:
1748  The way Windows handles the %S (capital S) format parameter depends on locale
1749  and code page settings. It is strongly reccommended that you never use %S to
1750  include any string that may possibly contain elements with values > 127.
1751  The following examples illustrate a way to predictably use UTF-8 and wchar_t
1752  parameters in buffers of the other element type.
1753 
1754  const char* utf8_string = ...;
1755  // UNRELIABLE // ON_wString::Format(buffer,buffer_capacity,"%S",utf8_string);
1756  wchar_t wchar_buffer[...];
1757  const size_t wchar_buffer_capacity= sizeof(buffer)/sizeof(buffer[0]);
1758  ON_wString::Format(wchar_buffer, wchar_buffer_capacity, "%s", ON_wString(utf8_string));
1759 
1760  const wchar_t* wide_string = ...;
1761  // UNRELIABLE // ON_wString::Format(buffer,buffer_capacity,"%S",char_string);
1762  char char_buffer[...];
1763  const size_t char_buffer_capacity = sizeof(buffer)/sizeof(buffer[0]);
1764  ON_String::Format(char_buffer, char_buffer_capacity, "%s", ON_String(wide_string));
1765  */
1766  static int ON_VARGS_FUNC_CDECL FormatIntoBuffer(
1767  char* buffer,
1768  size_t buffer_capacity,
1769  const char* format,
1770  ...
1771  );
1772 
1773  static int ON_VARGS_FUNC_CDECL FormatIntoBuffer(
1774  ON_StringBuffer& buffer,
1775  const char* format,
1776  ...
1777  );
1778 
1779  static int FormatVargsIntoBuffer(
1780  char* buffer,
1781  size_t buffer_capacity,
1782  const char* format,
1783  va_list args
1784  );
1785 
1786  static int FormatVargsIntoBuffer(
1787  ON_StringBuffer& buffer,
1788  const char* format,
1789  va_list args
1790  );
1791 
1792  /*
1793  Returns:
1794  >= 0:
1795  Number of char elements in the formatted string, not including the null terminator.
1796  < 0:
1797  Invalid input
1798  */
1799  static int FormatVargsOutputCount(
1800  const char* format,
1801  va_list args
1802  );
1803 
1804  /*
1805  Parameters:
1806  format - [in]
1807  null terminated string to scan
1808  ... - [out]
1809  pointers to elements to assign.
1810  Returns:
1811  >= 0: number of fields successfully converted and assigned.
1812  <0: failure
1813  */
1814  int ON_VARGS_FUNC_CDECL Scan(
1815  const char* format,
1816  ...
1817  );
1818 
1819  int ON_VARGS_FUNC_CDECL Scan(
1820  const unsigned char* format,
1821  ...
1822  );
1823 
1824  static int ON_VARGS_FUNC_CDECL ScanBuffer(
1825  const char* buffer,
1826  const char* format,
1827  ...
1828  );
1829 
1830  static int ON_VARGS_FUNC_CDECL ScanBuffer(
1831  const unsigned char* buffer,
1832  const unsigned char* format,
1833  ...
1834  );
1835 
1836  static int ScanBufferVargs(
1837  const char* buffer,
1838  const char* format,
1839  va_list args
1840  );
1841 
1842  static int ScanBufferVargs(
1843  const unsigned char* buffer,
1844  const unsigned char* format,
1845  va_list args
1846  );
1847 
1848 
1849  /*
1850  Parameters:
1851  buffer - [in]
1852  decimal number
1853  Returns:
1854  not zero:
1855  pointer to the first character that was not scanned
1856  nullptr:
1857  failure
1858  */
1859  static const char* ToNumber(
1860  const char* buffer,
1861  char value_on_failure,
1862  char* value
1863  );
1864  static const char* ToNumber(
1865  const char* buffer,
1866  unsigned char value_on_failure,
1867  unsigned char* value
1868  );
1869  static const char* ToNumber(
1870  const char* buffer,
1871  short value_on_failure,
1872  short* value
1873  );
1874  static const char* ToNumber(
1875  const char* buffer,
1876  unsigned short value_on_failure,
1877  unsigned short* value
1878  );
1879  static const char* ToNumber(
1880  const char* buffer,
1881  int value_on_failure,
1882  int* value
1883  );
1884  static const char* ToNumber(
1885  const char* buffer,
1886  unsigned int value_on_failure,
1887  unsigned int* value
1888  );
1889  static const char* ToNumber(
1890  const char* buffer,
1891  ON__INT64 value_on_failure,
1892  ON__INT64* value
1893  );
1894  static const char* ToNumber(
1895  const char* buffer,
1896  ON__UINT64 value_on_failure,
1897  ON__UINT64* value
1898  );
1899  static const char* ToNumber(
1900  const char* buffer,
1901  double value_on_failure,
1902  double* value
1903  );
1904 
1905 
1906  // Low level access to string contents as character array
1907  char* ReserveArray(size_t); // make sure internal array has at least
1908  // the requested capacity.
1909  void ShrinkArray(); // shrink internal storage to minimum size
1910  char* SetLength(size_t); // set length (<=capacity)
1911  char* Array();
1912  const char* Array() const;
1913 
1914  /*
1915  Returns:
1916  Total number of bytes of memory used by this class.
1917  (For use in ON_Object::SizeOf() overrides.
1918  */
1919  unsigned int SizeOf() const;
1920 
1921  ON__UINT32 DataCRC(ON__UINT32 current_remainder) const;
1922 
1923  /*
1924  OBSOLETE - use ON_FileSystemPath::SplitPath
1925  */
1926  static void SplitPath(
1927  const char* path,
1928  ON_String* drive,
1929  ON_String* dir,
1930  ON_String* fname,
1931  ON_String* ext
1932  );
1933 
1934 public:
1935  ~ON_String();
1936 
1937 protected:
1938  // Implementation
1939  char* m_s; // pointer to ref counted string array
1940  // m_s - 12 bytes points at the string's ON_aStringHeader
1941 
1942  // implementation helpers
1943  struct ON_aStringHeader* Header() const;
1944  char* CreateArray(int);
1945  void CopyArray();
1946  void CopyToArray( const ON_String& );
1947  void CopyToArray( int, const char* );
1948  void CopyToArray( int, const unsigned char* );
1949  void CopyToArray( int, const wchar_t* );
1950  void AppendToArray( const ON_String& );
1951  void AppendToArray( int, const char* );
1952  void AppendToArray( int, const unsigned char* );
1953 };
1954 
1955 /*
1956 Returns:
1957  True if lhs and rhs are identical as arrays of char elements.
1958 */
1959 ON_DECL
1960 bool operator==( const ON_String& lhs, const ON_String& rhs );
1961 
1962 /*
1963 Returns:
1964  True if lhs and rhs are not identical as arrays of char elements.
1965 */
1966 ON_DECL
1967 bool operator!=(const ON_String& lhs, const ON_String& rhs);
1968 
1969 /*
1970 Returns:
1971  True if lhs is less than rhs as an array of unsigned bytes.
1972 */
1973 ON_DECL
1974 bool operator<(const ON_String& lhs, const ON_String& rhs);
1975 
1976 /*
1977 Returns:
1978  True if lhs is greater than rhs as an array of unsigned bytes.
1979 */
1980 ON_DECL
1981 bool operator>(const ON_String& lhs, const ON_String& rhs);
1982 
1983 /*
1984 Returns:
1985  True if lhs is less than or equal to rhs as an array of unsigned bytes.
1986 */
1987 ON_DECL
1988 bool operator<=(const ON_String& lhs, const ON_String& rhs);
1989 
1990 /*
1991 Returns:
1992  True if lhs is greater than or equal to rhs as an array of unsigned bytes.
1993 */
1994 ON_DECL
1995 bool operator>=(const ON_String& lhs, const ON_String& rhs);
1996 
1997 /*
1998 Returns:
1999  True if lhs and rhs are identical as arrays of char elements.
2000 */
2001 ON_DECL
2002 bool operator==( const ON_String& lhs, const char* rhs );
2003 
2004 /*
2005 Returns:
2006  True if lhs and rhs are not identical as arrays of char elements.
2007 */
2008 ON_DECL
2009 bool operator!=(const ON_String& lhs, const char* rhs);
2010 
2011 /*
2012 Returns:
2013  True if lhs is less than rhs as an array of unsigned bytes.
2014 */
2015 ON_DECL
2016 bool operator<(const ON_String& lhs, const char* rhs);
2017 
2018 /*
2019 Returns:
2020  True if lhs is greater than rhs as an array of unsigned bytes.
2021 */
2022 ON_DECL
2023 bool operator>(const ON_String& lhs, const char* rhs);
2024 
2025 /*
2026 Returns:
2027  True if lhs is less than or equal to rhs as an array of unsigned bytes.
2028 */
2029 ON_DECL
2030 bool operator<=(const ON_String& lhs, const char* rhs);
2032 /*
2033 Returns:
2034  True if lhs is greater than or equal to rhs as an array of unsigned bytes.
2035 */
2036 ON_DECL
2037 bool operator>=(const ON_String& lhs, const char* rhs);
2039 /*
2040 Returns:
2041  True if lhs and rhs are identical as arrays of char elements.
2042 */
2043 ON_DECL
2044 bool operator==( const char* lhs, const ON_String& rhs );
2045 
2046 /*
2047 Returns:
2048  True if lhs and rhs are not identical as arrays of char elements.
2049 */
2050 ON_DECL
2051 bool operator!=(const char* lhs, const ON_String& rhs);
2052 
2053 /*
2054 Returns:
2055  True if lhs is less than rhs as an array of unsigned bytes.
2056 */
2057 ON_DECL
2058 bool operator<(const char* lhs, const ON_String& rhs);
2059 
2060 /*
2061 Returns:
2062  True if lhs is greater than rhs as an array of unsigned bytes.
2063 */
2064 ON_DECL
2065 bool operator>(const char* lhs, const ON_String& rhs);
2066 
2067 /*
2068 Returns:
2069  True if lhs is less than or equal to rhs as an array of unsigned bytes.
2070 */
2071 ON_DECL
2072 bool operator<=(const char* lhs, const ON_String& rhs);
2073 
2074 /*
2075 Returns:
2076  True if lhs is greater than or equal to rhs as an array of unsigned bytes.
2077 */
2078 ON_DECL
2079 bool operator>=(const char* lhs, const ON_String& rhs);
2080 
2081 /////////////////////////////////////////////////////////////////////////////
2082 /////////////////////////////////////////////////////////////////////////////
2083 /////////////////////////////////////////////////////////////////////////////
2084 /////////////////////////////////////////////////////////////////////////////
2085 //
2086 // ON_wString
2087 //
2088 
2089 class ON_CLASS ON_wString
2090 {
2091 public:
2092 
2093  // ON_String::EmptyString has length 0.
2094  // const char* s = ON_String::EmptyString sets s to L"".
2095  static const ON_wString EmptyString;
2096 
2097  static const wchar_t Backspace; // Unicode BACKSPACE control U+0008
2098  static const wchar_t Tab; // Unicode CHARACTER TABULATION control U+0009
2099  static const wchar_t LineFeed; // Unicode LINE FEED control U+000A
2100  static const wchar_t VerticalTab; // Unicode LINE TABULATION control U+000B
2101  static const wchar_t FormFeed; // Unicode FORM FEED control U+000C
2102  static const wchar_t CarriageReturn; // Unicode CARRIAGE RETURN control U+000D
2103  static const wchar_t Escape; // Unicode CARRIAGE RETURN control U+001B
2104  static const wchar_t Space; // Unicode SPACE U+0020
2105  static const wchar_t Slash; // Unicode SOLIDUS U+002F
2106  static const wchar_t Backslash; // Unicode REVERSE SOLIDUS U+005C
2107  static const wchar_t Pipe; // Unicode VERTICAL LINE U+007C
2108 
2109 #if defined(ON_SIZEOF_WCHAR_T) && ON_SIZEOF_WCHAR_T >= 2
2110  // Never cast these values as "char"
2111  // The UTF-8 representation of any Unicode code point with value > 127
2112  // requires multiple bytes.
2113  static const wchar_t RadiusSymbol; // Unicode LATIN CAPITAL LETTER R U+0052
2114  static const wchar_t DegreeSymbol; // Unicode DEGREE SIGN U+00B0
2115  static const wchar_t PlusMinusSymbol; // Unicode PLUS-MINUS SIGN U+00B1
2116  static const wchar_t DiameterSymbol; // Unicode LATIN CAPITAL LETTER O WITH STROKE U+00D8
2117  static const wchar_t RecyclingSymbol; // Unicode UNIVERSAL RECYCLING SYMBOL U+2672 (decimal 9842)
2118  static const wchar_t ReplacementCharacter; // Unicode REPLACEMENT CHARACTER U+FFFD
2119  static const wchar_t NextLine; // Unicode NEXT LINE (NEL) U+0085
2120  static const wchar_t LineSeparator; // LINE SEPARATOR U+2028 unambiguous line separator
2121  static const wchar_t ParagraphSeparator; // PARAGRAPH SEPARATOR U+2028 unambiguous paragraph separator
2122  static const wchar_t NoBreakSpace; // NO-BREAK SPACE (NBSP)
2123  static const wchar_t NarrowNoBreakSpace; // NARROW NO-BREAK SPACE (NNBSP)
2124  static const wchar_t ZeroWidthSpace; // ZERO WIDTH SPACE (ZWSP)
2125 #endif
2126 
2127 private:
2128  // Use IsEmpty() or IsNotEmpty() when you want a bool
2129  // to test for the empty string.
2130  explicit operator bool() const { return IsNotEmpty(); }
2131 public:
2132 
2133 // Constructors
2134  ON_wString() ON_NOEXCEPT;
2135  ON_wString( const ON_wString& );
2136 
2137 #if defined(ON_HAS_RVALUEREF)
2138  // Clone constructor
2139  ON_wString( ON_wString&& ) ON_NOEXCEPT;
2140 
2141  // Clone Assignment operator
2142  ON_wString& operator=( ON_wString&& ) ON_NOEXCEPT;
2143 #endif
2144 
2145  ON_wString( const ON_String& src ); // src = UTF-8 string
2146 
2147  ON_wString( const char* src ); // src = nul; terminated UTF-8 string
2148  ON_wString( const char* src, int /*length*/ ); // from UTF-8 substring
2149  ON_wString( char, int = 1 /* repeat count */ );
2150 
2151  ON_wString( const unsigned char* src); // src = nul; terminated UTF-8 string
2152  ON_wString( const unsigned char*src, int /*length*/ ); // from UTF-8 substring
2153  ON_wString( unsigned char, int = 1 /* repeat count */ );
2154 
2155  ON_wString( const wchar_t* );
2156  ON_wString( const wchar_t*, int /*length*/ ); // from substring
2157  ON_wString( wchar_t, int = 1 /* repeat count */ );
2158 
2159 #if defined(ON_RUNTIME_WIN)
2160  // Windows support
2161  bool LoadResourceString(HINSTANCE, UINT); // load from string resource
2162  // 2047 characters max
2163 #endif
2164 
2165  void Create();
2166  void Destroy(); // releases any memory and initializes to default empty string
2167  void EmergencyDestroy();
2168 
2169  /*
2170  Description:
2171  Enables reference counting. I limited cases, this is useful
2172  for large strings or strings that are frequently passed around.
2173  Reference counted strings must be carefully managed in
2174  when multi-threading is used.
2175  Parameters:
2176  If EnableReferenceCounting()
2177  is not called, then the string will not be referanceThe default is to not use
2178  reference counted strings.
2179  */
2180  void EnableReferenceCounting( bool bEnable );
2181 
2182  /*
2183  Returns:
2184  True if the string is reference counted.
2185  */
2186  bool IsReferenceCounted() const;
2187 
2188  // Attributes & Operations
2189 
2190  /*
2191  Returns:
2192  number of nonzero elements in string.
2193  */
2194  int Length() const;
2195 
2196  /*
2197  Returns:
2198  number of nonzero elements in the string.
2199  */
2200  unsigned int UnsignedLength() const;
2201 
2202  /*
2203  Returns:
2204  number of nonzero elements in string before the first null terminator.
2205  If string is nullptr, 0 is returned.
2206  */
2207  static int Length(
2208  const wchar_t* string
2209  );
2210 
2211  /*
2212  Returns:
2213  number of nonzero elements in string before the first null terminator.
2214  If string is nullptr, 0 is returned.
2215  */
2216  static unsigned int UnsignedLength(
2217  const wchar_t* string
2218  );
2219 
2220  bool IsEmpty() const;
2221  bool IsNotEmpty() const; // returns true if length > 0
2222  void Empty(); // sets length to zero - if possible, memory is retained
2223 
2224  wchar_t& operator[](int);
2225  wchar_t operator[](int) const;
2226  wchar_t GetAt(int) const;
2227  void SetAt(int, char);
2228  void SetAt(int, unsigned char);
2229  void SetAt(int, wchar_t);
2230 
2231  operator const wchar_t*() const;
2232 
2233  // overloaded assignment
2234  const ON_wString& operator=(const ON_wString&);
2235  const ON_wString& operator=(const ON_String& src); // src = UTF-8 string
2236  const ON_wString& operator=(char);
2237  const ON_wString& operator=(const char* src); // src = UTF-8 string
2238  const ON_wString& operator=(unsigned char);
2239  const ON_wString& operator=(const unsigned char* src); // src = UTF-8 string
2240  const ON_wString& operator=(wchar_t);
2241  const ON_wString& operator=(const wchar_t*);
2242 
2243  // string concatenation
2244  void Append( const char* sUTF8, int ); // append specified number of elements from a UTF-8 string
2245  void Append( const unsigned char* sUTF8, int ); // append specified number of elements from a UTF-8 string
2246  void Append( const wchar_t*, int ); // append specified number of elements
2247  const ON_wString& operator+=(const ON_wString&);
2248  const ON_wString& operator+=(const ON_String& sUTF8); // append UTF-8 string
2249  const ON_wString& operator+=(char);
2250  const ON_wString& operator+=(unsigned char);
2251  const ON_wString& operator+=(wchar_t);
2252  const ON_wString& operator+=(const char* sUTF8); // append UTF-8 string
2253  const ON_wString& operator+=(const unsigned char* sUTF8); // append UTF-8 string
2254  const ON_wString& operator+=(const wchar_t*);
2255 
2256  // operator+()
2257  ON_wString operator+(const ON_wString&) const;
2258  ON_wString operator+(const ON_String& sUTF8) const; // concatinate with a UTF-8 string
2259  ON_wString operator+(char) const;
2260  ON_wString operator+(unsigned char) const;
2261  ON_wString operator+(wchar_t) const;
2262  ON_wString operator+(const char* sUTF8) const; // concatinate with a UTF-8 string
2263  ON_wString operator+(const unsigned char* sUTF8) const; // concatinate with a UTF-8 string
2264  ON_wString operator+(const wchar_t*) const;
2265 
2266  // Use CompareOrdinal(), ComparePath(), CompareAttributeName(), or a test that is linguistically apprropriate
2267  //ON_DEPRECATED // deprecation in progress
2268  int Compare( const wchar_t* ) const;
2269 
2270  // Use CompareOrdinal(), ComparePath(), CompareAttributeName(), or a test that is linguistically apprropriate
2271  // ON_DEPRECATED // deprecation in progress
2272  int CompareNoCase( const wchar_t* ) const;
2273 
2274  bool Equal(
2275  const ON_wString& other_string,
2276  const class ON_Locale& locale,
2277  bool bIgnoreCase
2278  ) const;
2279 
2280  bool Equal(
2281  const wchar_t* other_string,
2282  const class ON_Locale& locale,
2283  bool bIgnoreCase
2284  ) const;
2285 
2286  static bool Equal(
2287  const wchar_t* string1,
2288  const wchar_t* string2,
2289  const class ON_Locale& locale,
2290  bool bIgnoreCase
2291  );
2292 
2293  /*
2294  Description:
2295  Determine if string 1 and string2 are equal.
2296  Parameters:
2297  string1 - [in]
2298  element_count1 - [in]
2299  The number of string1[] elements to test.
2300  If element_count1 < 0, then string1 must nullptr or be null terminated.
2301  string2 - [in]
2302  element_count2 - [in]
2303  The number of string2[] elements to test.
2304  If element_count1 < 0, then string2 must nullptr or be null terminated.
2305  locale - [in]
2306  Typically ON_Locale::Ordinal, ON_Locale::InvariantCulture, or
2307  ON_Locale::CurrentCulture.
2308  bIgnoreCase - [in]
2309  Remarks:
2310  1) Ordinal compares are the fastest.
2311  2) Equal(...) is faster than Compare(...)
2312  */
2313  static bool Equal(
2314  const wchar_t* string1,
2315  int element_count1,
2316  const wchar_t* string2,
2317  int element_count2,
2318  const class ON_Locale& locale,
2319  bool bIgnoreCase
2320  );
2321 
2322  /*
2323  Description:
2324  Compare this string and other_string by normalizing (NFC)
2325  and using invariant culture ordering.
2326  Parameters:
2327  other_string - [in]
2328  bIgnoreCase - [in]
2329  Remarks:
2330  1) Ordinal compares are the fastest.
2331  2) Equal(...) is faster than Compare(...)
2332  */
2333  int Compare(
2334  const ON_wString& other_string,
2335  const class ON_Locale& locale,
2336  bool bIgnoreCase
2337  ) const;
2338 
2339  int Compare(
2340  const wchar_t* other_string,
2341  const class ON_Locale& locale,
2342  bool bIgnoreCase
2343  ) const;
2344 
2345  /*
2346  Description:
2347  Compare string1 and string2 by normalizing (NFC) and using invariant culture ordering.
2348  Parameters:
2349  string1 - [in]
2350  string2 - [in]
2351  bIgnoreCase - [in]
2352  Remarks:
2353  1) Ordinal compares are the fastest.
2354  2) Equal(...) is faster than Compare(...)
2355  */
2356  static int Compare(
2357  const wchar_t* string1,
2358  const wchar_t* string2,
2359  const class ON_Locale& locale,
2360  bool bIgnoreCase
2361  );
2362 
2363  /*
2364  Description:
2365  Compare string1 and string2 by normalizing (NFC) and using invariant culture ordering.
2366  Parameters:
2367  string1 - [in]
2368  element_count1 - [in]
2369  The number of string1[] elements to compare.
2370  If element_count1 < 0, then string1 must be null terminated.
2371  string2 - [in]
2372  element_count2 - [in]
2373  The number of string2[] elements to compare.
2374  If element_count2 < 0, then string2 must be null terminated.
2375  locale - [in]
2376  Typically ON_Locale::Ordinal, ON_Locale::InvariantCulture, or
2377  ON_Locale::CurrentCulture.
2378  bIgnoreCase - [in]
2379  Remarks:
2380  1) Ordinal compares are the fastest.
2381  2) Equal(...) is faster than Compare(...)
2382  */
2383  static int Compare(
2384  const wchar_t* string1,
2385  int element_count1,
2386  const wchar_t* string2,
2387  int element_count2,
2388  const class ON_Locale& locale,
2389  bool bIgnoreCase
2390  );
2391 
2392  bool EqualOrdinal(
2393  const ON_wString& other_string,
2394  bool bOrdinalIgnoreCase
2395  ) const;
2396 
2397  bool EqualOrdinal(
2398  const wchar_t* other_string,
2399  bool bOrdinalIgnoreCase
2400  ) const;
2401 
2402  static bool EqualOrdinal(
2403  const wchar_t* string1,
2404  const wchar_t* string2,
2405  bool bOrdinalIgnoreCase
2406  );
2407 
2408  static bool EqualOrdinal(
2409  const wchar_t* string1,
2410  int element_count1,
2411  const wchar_t* string2,
2412  int element_count2,
2413  bool bOrdinalIgnoreCase
2414  );
2415 
2416 
2417  /*
2418  Description:
2419  Compare this string and other_string wchar_t element by wchar_t element.
2420  Parameters:
2421  other_string - [in]
2422  bOrdinalIgnoreCase - [in]
2423  Remarks:
2424  1) If the string is UTF-8 encoded and bOrdinalIgnoreCase is true, only
2425  small latin a - z and capital latin A - Z are considered equal. It is
2426  imposible to ignore case for any other values in an ordinal compare.
2427 
2428  2) If you are comparing file system paths, you should use ComparePath().
2429 
2430  3) If locale, linguistic issues, UTF-8 encoding issues or unicode normalization
2431  or collation issues need to be considered, then CompareOrdinal() is
2432  the wrong function to use.
2433  */
2434  int CompareOrdinal(
2435  const ON_wString& other_string,
2436  bool bOrdinalIgnoreCase
2437  ) const;
2438 
2439  int CompareOrdinal(
2440  const wchar_t* other_string,
2441  bool bOrdinalIgnoreCase
2442  ) const;
2443 
2444  /*
2445  Description:
2446  Compare this string1 and string2 wchar_t element by wchar_t element.
2447  Parameters:
2448  string1 - [in]
2449  string2 - [in]
2450  bOrdinalIgnoreCase - [in]
2451  If true, elements with values a-z are compared as if they had values A-Z.
2452  Remarks:
2453  1) If the string is UTF-8 encoded and bOrdinalIgnoreCase is true, only
2454  small latin a - z and capital latin A - Z are considered equal. It is
2455  imposible to ignore case for any other values in an ordinal compare.
2456 
2457  2) If you are comparing file system paths, you should use ComparePath().
2458 
2459  3) If locale, linguistic issues, UTF-8 encoding issues or unicode normalization
2460  or collation issues need to be considered, then CompareOrdinal() is
2461  the wrong function to use.
2462  */
2463  static int CompareOrdinal(
2464  const wchar_t* string1,
2465  const wchar_t* string2,
2466  bool bOrdinalIgnoreCase
2467  );
2468 
2469  /*
2470  Description:
2471  Compare this string1 and string2 wchar_t element by wchar_t element.
2472  Parameters:
2473  string1 - [in]
2474  maximum_element_count1 - [in]
2475  maximum number of elements to compare
2476  string2 - [in]
2477  maximum_element_count2 - [in]
2478  maximum number of elements to compare
2479  bOrdinalIgnoreCase - [in]
2480  If true, elements with values a-z are compared as if they had values A-Z.
2481  Remarks:
2482  1) If the string is UTF-8 encoded and bOrdinalIgnoreCase is true, only
2483  small latin a - z and capital latin A - Z are considered equal. It is
2484  imposible to ignore case for any other values in an ordinal compare.
2485 
2486  2) If you are comparing file system paths, you should use ComparePath().
2487 
2488  3) If locale, linguistic issues, UTF-8 encoding issues or unicode normalization
2489  or collation issues need to be considered, then CompareOrdinal() is
2490  the wrong function to use.
2491  */
2492  static int CompareOrdinal(
2493  const wchar_t* string1,
2494  int element_count1,
2495  const wchar_t* string2,
2496  int element_count2,
2497  bool bOrdinalIgnoreCase
2498  );
2499 
2500  /*
2501  Description:
2502  Compare this string and other_path as file system paths using
2503  appropriate tests for the current operating system.
2504  Parameters:
2505  other_path - [in]
2506  null terminated string
2507  Remarks:
2508  1) Windows and UNIX directory separators (/ and \) are considered equal.
2509 
2510  2) Case is ignored when the file system is not case sensitive, like Windows.
2511 
2512  3) String normalization appropriate for the current operating system
2513  is performed.
2514  */
2515  int ComparePath(
2516  const wchar_t* other_path
2517  ) const;
2518  bool EqualPath(
2519  const wchar_t* other_path
2520  ) const;
2521 
2522  /*
2523  Description:
2524  Compare sPath1 and sPath2 as file system paths using
2525  appropriate tests for the current operating system.
2526  Parameters:
2527  path1 - [in]
2528  null terminated string
2529  path2 - [in]
2530  null terminated string
2531  Remarks:
2532  1) Windows and UNIX directory separators (/ and \) are considered equal.
2533 
2534  2) Case is ignored when the file system is not case sensitive, like Windows.
2535 
2536  3) String normalization appropriate for the current operating system
2537  is performed.
2538  */
2539  static int ComparePath(
2540  const wchar_t* path1,
2541  const wchar_t* path2
2542  );
2543  static bool EqualPath(
2544  const wchar_t* path1,
2545  const wchar_t* path2
2546  );
2547 
2548  /*
2549  Description:
2550  Compare sPath1 and sPath2 as file system paths using
2551  appropriate tests for the current operating system.
2552  Parameters:
2553  path1 - [in]
2554  maximum_element_count1 - [in]
2555  path2 - [in]
2556  maximum_element_count2 - [in]
2557  Remarks:
2558  1) Windows and UNIX directory separators (/ and \) are considered equal.
2559 
2560  2) Case is ignored when the file system is not case sensitive, like Windows.
2561 
2562  3) String normalization appropriate for the current operating system
2563  is performed.
2564  */
2565  static int ComparePath(
2566  const wchar_t* path1,
2567  int element_count1,
2568  const wchar_t* path2,
2569  int element_count2
2570  );
2571  static bool EqualPath(
2572  const wchar_t* path1,
2573  int element_count1,
2574  const wchar_t* path2,
2575  int element_count2
2576  );
2577 
2578  /*
2579  Description:
2580  Compare this string and other_name as a name attribute of an object
2581  like ON_3dmObjectAttributes.m_name, ON_Layer.m_name, and so on.
2582  These comparisons ignore case and use appropriate string normalization.
2583  Parameters:
2584  other_name - [in]
2585  null terminated string
2586  */
2587  int CompareAttributeName(
2588  const wchar_t* other_name
2589  ) const;
2590  bool EqualAttributeName(
2591  const wchar_t* other_name
2592  ) const;
2593 
2594  /*
2595  Description:
2596  Compare this string and other_name as a name attribute of an object
2597  like ON_3dmObjectAttributes.m_name, ON_Layer.m_name, and so on.
2598  These comparisons ignore case and use appropriate string normalization.
2599  Parameters:
2600  name1 - [in]
2601  null terminated string
2602  name2 - [in]
2603  null terminated string
2604  */
2605  static int CompareAttributeName(
2606  const wchar_t* name1,
2607  const wchar_t* name2
2608  );
2609  static bool EqualAttributeName(
2610  const wchar_t* name1,
2611  const wchar_t* name2
2612  );
2613 
2614 
2615  // Description:
2616  // Simple case sensitive wildcard matching. A question mark (?) in the
2617  // pattern matches a single character. An asterisk (*) in the pattern
2618  // mathes zero or more occurances of any character.
2619  //
2620  // Parameters:
2621  // pattern - [in] pattern string where ? and * are wild cards.
2622  //
2623  // Returns:
2624  // true if the string mathes the wild card pattern.
2625  bool WildCardMatch( const wchar_t* ) const;
2626 
2627  // Description:
2628  // Simple case insensitive wildcard matching. A question mark (?) in the
2629  // pattern matches a single character. An asterisk (*) in the pattern
2630  // mathes zero or more occurances of any character.
2631  //
2632  // Parameters:
2633  // pattern - [in] pattern string where ? and * are wild cards.
2634  //
2635  // Returns:
2636  // true if the string mathes the wild card pattern.
2637  bool WildCardMatchNoCase( const wchar_t* ) const;
2638 
2639  /*
2640  Description:
2641  Replace all substrings that match token1 with token2
2642  Parameters:
2643  token1 - [in]
2644  token2 - [in]
2645  Returns:
2646  Number of times toke1 was replaced with token2
2647  */
2648  int Replace( const wchar_t* token1, const wchar_t* token2 );
2649  int Replace( wchar_t token1, wchar_t token2 );
2650 
2651  /*
2652  Description:
2653  Replaces all characters in the string whose values are
2654  not '0-9', 'A-Z', or 'a-z' with a percent sign followed
2655  by a 2 digit hex value.
2656  */
2657  void UrlEncode();
2658 
2659  /*
2660  Description:
2661  Replaces all %xx where xx a two digit hexadecimal number,
2662  with a single character. Returns false if the orginal
2663  string contained
2664  */
2665  bool UrlDecode();
2666 
2667  /*
2668  Description:
2669  Replace all white-space characters with the token.
2670  If token is zero, the string will end up with
2671  internal 0's
2672  Parameters:
2673  token - [in]
2674  whitespace - [in] if not null, this is a 0 terminated
2675  string that lists the characters considered to be
2676  white space. If null, then (1,2,...,32,127) is used.
2677  Returns:
2678  Number of whitespace characters replaced.
2679  See Also:
2680  ON_wString::RemoveWhiteSpace
2681  */
2682  int ReplaceWhiteSpace( wchar_t token, const wchar_t* whitespace = 0 );
2683 
2684  /*
2685  Description:
2686  Removes all white-space characters with the token.
2687  Parameters:
2688  whitespace - [in] if not null, this is a 0 terminated
2689  string that lists the characters considered to be
2690  white space. If null, then (1,2,...,32,127) is used.
2691  Returns:
2692  Number of whitespace characters removed.
2693  See Also:
2694  ON_wString::ReplaceWhiteSpace
2695  */
2696  int RemoveWhiteSpace( const wchar_t* whitespace = 0 );
2697 
2698  /*
2699  Parameters:
2700  prefix - [in]
2701  locale - [in]
2702  When no local is available, pass ON_Locale::Ordinal.
2703  bIgnoreCase - [in]
2704  true to ignore case.
2705  Returns:
2706  If the string begins with prefix, the returned string has prefix removed.
2707  Otherwise the returned string is identical to the string.
2708  */
2709  const ON_wString RemovePrefix(
2710  const wchar_t* prefix,
2711  const class ON_Locale& locale,
2712  bool bIgnoreCase
2713  ) const;
2714 
2715  /*
2716  Parameters:
2717  suffix - [in]
2718  locale - [in]
2719  When no local is available, pass ON_Locale::Ordinal.
2720  bIgnoreCase - [in]
2721  true to ignore case.
2722  Returns:
2723  If the string ends with suffix, the returned string has suffix removed.
2724  Otherwise the returned string is identical to the string.
2725  */
2726  const ON_wString RemoveSuffix(
2727  const wchar_t* suffix,
2728  const class ON_Locale& locale,
2729  bool bIgnoreCase
2730  ) const;
2731 
2732  // simple sub-string extraction
2733  ON_wString Mid(
2734  int, // index of first char
2735  int // count
2736  ) const;
2737  ON_wString Mid(
2738  int // index of first char
2739  ) const;
2740  ON_wString Left(
2741  int // number of chars to keep
2742  ) const;
2743  ON_wString Right(
2744  int // number of chars to keep
2745  ) const;
2746  const ON_wString SubString(
2747  int start_index
2748  ) const;
2749  const ON_wString SubString(
2750  int start_index,
2751  int count
2752  ) const;
2753 
2754  /*
2755  Description:
2756  Map a single wchar_t element to upper or lower case.
2757  Parameters:
2758  c - [in]
2759  If sizeof(wchar_t) >= 2 and c is not a value used int surrogate pairs,
2760  the map specified by map_type is applied. If c is a value used in
2761  surrogate pairs, the value is not changed.
2762  Remarks:
2763  1) MapCharacterOrdinal is not appropriate for general string mapping
2764  because it does not correctly handle surrogate pairs.
2765  2) If sizeof(wchar_t) == sizeof(char), ON_String::MapCharacterOrdinal()
2766  and ON_wString::MapCharacterOrdinal() are identical.
2767  */
2768  static wchar_t MapCharacterOrdinal(
2769  ON_StringMapOrdinalType map_type,
2770  wchar_t c
2771  );
2772 
2773  ON_wString MapStringOrdinal(
2774  ON_StringMapOrdinalType map_type
2775  ) const;
2776 
2777  /*
2778  Description:
2779  Map a wchar_t string.
2780  Parameters:
2781  map_type - [in]
2782  string - [in]
2783  element_count - [in]
2784  number of string[] elements to map.
2785  If element_count < 0, then ON_wString::Length(string) elements are mapped.
2786  mapped_string - [out]
2787  mapped_string_capacity - [in]
2788  number of available elements in mapped_string[].
2789  mapped_string_capacity must be >= mapped_element_count where
2790  mapped_element_count = (element_count >= 0) element_count ? ON_wString::Length(string).
2791  map_type - [in]
2792  Returns:
2793  Number of mapped_string[] elements that were mapped from string[].
2794 
2795  When the return value is < mapped_string_capacity, a null terminator
2796  is appended after the last mapped element.
2797  */
2798  static int MapStringOrdinal(
2799  ON_StringMapOrdinalType map_type,
2800  const wchar_t* string,
2801  int element_count,
2802  wchar_t* mapped_string,
2803  int mapped_string_capacity
2804  );
2805 
2806  ON_wString MapString(
2807  const class ON_Locale& locale,
2808  ON_StringMapType map_type
2809  ) const;
2810 
2811  static ON_wString MapString(
2812  const class ON_Locale& locale,
2813  ON_StringMapType map_type,
2814  const wchar_t* string,
2815  int element_count
2816  );
2817 
2818  /*
2819  Description:
2820  Maps element_count elements of string[] to mapped_string[].
2821  Parameters:
2822  locale - [in]
2823  Locale to use when converting case. It is common to pass one of
2824  the preset locales ON_Locale::Ordinal, ON_Locale::InvariantCulture,
2825  or ON_Locale::m_CurrentCulture.
2826 
2827  map_type - [in]
2828  selects the mapping
2829 
2830  string - [in]
2831  input string to map.
2832 
2833  element_count - [in]
2834  The number of wchar_t elements to map from input string[].
2835 
2836  If element_count < 1, then string[] must be null terminated and
2837  ON_wString::Length(string)+1 elements are mapped.
2838  The +1 insures the output is null terminated.
2839 
2840  mapped_string - [out]
2841  The result of the mapping is returned in mapped_string[].
2842 
2843  mapped_string_capacity - [in]
2844  Number of wchar_t elements available in mapped_string[]
2845  or 0 to calculate the minimum number of elements needed
2846  for the mapping.
2847 
2848  Returns:
2849  If mapped_string_capacity > 0, then the number elements set in mapped_string[]
2850  is returned.
2851 
2852  If mapped_string_capacity == 0, then the number elements required to perform
2853  the mapping is returned.
2854 
2855  When there is room, mapped_string[] is null terminated.
2856 
2857  0: Failure.
2858  */
2859  static int MapString(
2860  const class ON_Locale& locale,
2861  ON_StringMapType map_type,
2862  const wchar_t* string,
2863  int element_count,
2864  wchar_t* mapped_string,
2865  int mapped_string_capacity
2866  );
2867 
2868  /*
2869  Returns:
2870  A platform independed SHA-1 of the string content. Independent of platform endian or platform wide string UTF encoding.
2871  */
2872  const ON_SHA1_Hash ContentHash(
2873  ON_StringMapOrdinalType mapping
2874  ) const;
2875 
2876 
2877  // upper/lower/reverse conversion
2878  /*ON_DEPRECATED */ void MakeUpper();
2879  /*ON_DEPRECATED */ void MakeLower();
2880 
2881  ON_wString Reverse() const;
2882 
2883  static wchar_t* Reverse(
2884  wchar_t* string,
2885  int element_count
2886  );
2887 
2888  void MakeUpperOrdinal();
2889  void MakeLowerOrdinal();
2890  void MakeReverse();
2891 
2892  /*
2893  Description:
2894  Removes leading elements from the string.
2895  Parameters:
2896  s - [in]
2897  All leading wchar_t elements with a value that it found in s[] are removed.
2898  If s is nullptr, All leading wchar_t element with a value between 1 and space are removed.
2899  */
2900  void TrimLeft(const wchar_t* s = nullptr);
2901 
2902  /*
2903  Description:
2904  Removes trailing elements from the string.
2905  Parameters:
2906  s - [in]
2907  All trailing wchar_t elements with a value that it found in s[] are removed.
2908  If s is nullptr, All trailing wchar_t elements with a value between 1 and space are removed.
2909  */
2910  void TrimRight(const wchar_t* s = nullptr);
2911 
2912  void TrimLeftAndRight(const wchar_t* s = nullptr);
2913 
2914  /*
2915  Description:
2916  Remove all occurrences of the input character.
2917  Parameters:
2918  c - [in]
2919  utf8_single_byte_ct must have a value between 0 and 0x7F.
2920  When w is a 2 byte UTF-16 wchar_t value (like Microsoft's wchar_t),
2921  it must be in the range 0 to 0xD7FF or 0xE000 to 0xFFFF.
2922  When w is a 4 byte UTF-32 wchar_t value (like Apple's wchar_t),
2923  it must be in the range 0 to 0xD7FF or 0xE000 to 0x10FFFF.
2924  Returns:
2925  Number of characters removed.
2926  */
2927  int Remove(
2928  char utf8_single_byte_c
2929  );
2930  int Remove(
2931  unsigned char utf8_single_byte_c
2932  );
2933  int Remove(
2934  wchar_t w
2935  );
2936 
2937  /*
2938  Description:
2939  Find the first occurrence of a character or substring.
2940  Parameters:
2941  utf8_single_byte_c - [in]
2942  utf8_single_byte_c must have a value between 0 and 0x7F.
2943  w - [in]
2944  When w is a 2 byte UTF-16 wchar_t value (like Microsoft's wchar_t),
2945  it must be in the range 0 to 0xD7FF or 0xE000 to 0xFFFF.
2946  When w is a 4 byte UTF-32 wchar_t value (like Apple's wchar_t),
2947  it must be in the range 0 to 0xD7FF or 0xE000 to 0x10FFFF.
2948  sTUF8 - [in]
2949  A null terminated UTF-8 string.
2950  wcharString - [in]
2951  A null terminated wchar_t string.
2952  start_index - [in]
2953  Index where search should begin.
2954  Returns:
2955  -1: invalid input or character is not in the string.
2956  >=0: Index of the first instance of the character.
2957  */
2958  int Find(
2959  char utf8_single_byte_c
2960  ) const;
2961  int Find(
2962  unsigned char utf8_single_byte_c
2963  ) const;
2964  int Find(
2965  wchar_t w
2966  ) const;
2967  int Find(
2968  const char* sUTF8
2969  ) const;
2970  int Find(
2971  const unsigned char* sUTF8
2972  ) const;
2973  int Find(
2974  const wchar_t* wcharString
2975  ) const;
2976  int Find(
2977  char utf8_single_byte_c,
2978  size_t start_index
2979  ) const;
2980  int Find(
2981  unsigned char utf8_single_byte_c,
2982  size_t start_index
2983  ) const;
2984  int Find(
2985  wchar_t w,
2986  size_t start_index
2987  ) const;
2988  int Find(
2989  wchar_t w,
2990  int start_index
2991  ) const;
2992  int Find(
2993  const char* sUTF8,
2994  size_t start_index
2995  ) const;
2996  int Find(
2997  const unsigned char* sUTF8,
2998  size_t start_index
2999  ) const;
3000  int Find(
3001  const wchar_t* wcharString,
3002  size_t start_index
3003  ) const;
3004  int Find(
3005  const wchar_t* wcharString,
3006  int start_index
3007  ) const;
3008  int FindOneOf(
3009  const wchar_t* character_set
3010  ) const;
3011 
3012 
3013  /*
3014  Description:
3015  Find the last occurrence of a character or substring.
3016  Parameters:
3017  utf8_single_byte_c - [in]
3018  utf8_single_byte_c must have a value between 0 and 0x7F.
3019  w - [in]
3020  When w is a 2 byte UTF-16 wchar_t value (like Microsoft's wchar_t),
3021  it must be in the range 0 to 0xD7FF or 0xE000 to 0xFFFF.
3022  When w is a 4 byte UTF-32 wchar_t value (like Apple's wchar_t),
3023  it must be in the range 0 to 0xD7FF or 0xE000 to 0x10FFFF.
3024  sUTF8 - [in]
3025  wideString - [in]
3026  Returns:
3027  -1: Invalid input or character or substring was not found.
3028  >=0: Index of the final occurrence of the character or substring.
3029  */
3030  int ReverseFind(
3031  char utf8_single_byte_c
3032  ) const;
3033  int ReverseFind(
3034  unsigned char utf8_single_byte_c
3035  ) const;
3036  int ReverseFind(
3037  wchar_t w
3038  ) const;
3039  int ReverseFind(
3040  const char* sUTF8
3041  ) const;
3042 
3043  int ReverseFind(
3044  const wchar_t* wideString
3045  ) const;
3046 
3047 
3048  // It is common to format single numbers into strings
3049  // and the FromNumber and FromDouble functions are
3050  // the fastest way to do this and provide consistent results.
3051  // They return a pointer to their buffer so the can be used
3052  // as function parameters.
3053  static const ON_wString FromNumber(
3054  char n
3055  );
3056  static const ON_wString FromNumber(
3057  unsigned char n
3058  );
3059  static const ON_wString FromNumber(
3060  short n
3061  );
3062  static const ON_wString FromNumber(
3063  unsigned short n
3064  );
3065  static const ON_wString FromNumber(
3066  int n
3067  );
3068  static const ON_wString FromNumber(
3069  unsigned int n
3070  );
3071  static const ON_wString FromNumber(
3072  ON__INT64 n
3073  );
3074  static const ON_wString FromNumber(
3075  ON__UINT64 n
3076  );
3077  static const ON_wString FromNumber(
3078  double d // "%g" format
3079  );
3080  static const ON_wString ApproximateFromNumber(
3081  double d // "%f" when possible, otherwise "%g"
3082  );
3083  static const ON_wString PreciseFromNumber(
3084  double d // "%.17g"
3085  );
3086 
3087  /*
3088  Description:
3089  Convert a list of Unicode code points into a wide string.
3090  Parameters:
3091  code_points - [in]
3092  array of Unicode code points
3093  code_point_count - [in]
3094  number of code points.
3095  -1 indicates code_points[] is terminated by a 0 value.
3096  error_code_point - [in]
3097  If error_code_point is a valid Unicode code point,
3098  then error_code_point will be used in place of invalid values in code_points[].
3099  Otherwise, conversion will terminate if code_points[] contains an invalid value.
3100  The values ON_UnicodeCodePoint::ON_ReplacementCharacter and
3101  ON_UnicodeCodePoint::ON_InvalidCodePoint are commonly used for this parameter.
3102  Returns:
3103  A wide string encoding of the Unicode code points.
3104  Remarks:
3105  If more control over the conversion process is required,
3106  then use ON_ConvertUTF32ToWideChar().
3107  */
3108  static const ON_wString FromUnicodeCodePoints(
3109  const ON__UINT32* code_points,
3110  int code_point_count,
3111  ON__UINT32 error_code_point
3112  );
3113 
3114  /*
3115  Description:
3116  Each byte value is converted to 2 hexadecimal digits.
3117  Parameters:
3118  bytes - [in]
3119  list of byte values
3120  byte_count - [in]
3121  Number of byte values in bytes[] array.
3122  bCapitalDigits - [in]
3123  false: Use 0-9, a - b
3124  true: Use 0-9, A - F
3125  bReverse - [in]
3126  false:
3127  The digist in the string will be in the order
3128  bytes[0], bytes[1], ..., bytes[byte_count-1].
3129  true:
3130  The digist in the string will be in the order
3131  bytes[byte_count-1], ..., bytes[1], bytes[0].
3132  */
3133  static const ON_wString HexadecimalFromBytes(
3134  const ON__UINT8* bytes,
3135  size_t byte_count,
3136  bool bCapitalDigits,
3137  bool bReverse
3138  );
3139 
3140 
3141  /*
3142  Parameters:
3143  format - [in]
3144  Format control.
3145  Positional paramters of the form %N$x where N >= 1 and x
3146  is the standard format specification are supported.
3147  Avoid using %S (capital S). See the Remarks for details.
3148  ... - [in]
3149  arguments for replacable items in the format string.
3150  Returns:
3151  True if successful.
3152  False if the string is too long or the format string is not valid.
3153  Remarks:
3154  When using Microsoft's compiler and other compilers that provide similar
3155  locale support, the locale is the invariant culture locale returned by
3156  ON_Locale::InvariantCulture::LocalePtr().
3157 
3158  The way Windows handles the %S (capital S) format parameter depends on locale
3159  and code page settings. It is strongly reccommended that you never use %S to
3160  include any string that may possibly contain elements with values > 127.
3161  The following examples illustrate a way to predictably use UTF-8 and wchar_t
3162  parameters in buffers of the other element type.
3163 
3164  const char* utf8_string = ...;
3165  // UNRELIABLE // ON_wString::Format(buffer,buffer_capacity,"%S",utf8_string);
3166  // The code below will treat utf8_string as a UTF-8 encoded string.
3167  wchar_t wchar_buffer[...];
3168  const size_t wchar_buffer_capacity= sizeof(buffer)/sizeof(buffer[0]);
3169  ON_wString::Format(wchar_buffer, wchar_buffer_capacity, "%s", ON_wString(utf8_string));
3170 
3171  const wchar_t* wide_string = ...;
3172  // UNRELIABLE // ON_wString::Format(buffer,buffer_capacity,"%S",char_string);
3173  // The code below will include wide_string as a UTF-8 encoded string.
3174  char char_buffer[...];
3175  const size_t char_buffer_capacity = sizeof(buffer)/sizeof(buffer[0]);
3176  ON_String::Format(char_buffer, char_buffer_capacity, "%s", ON_String(wide_string));
3177  */
3178  bool ON_VARGS_FUNC_CDECL Format(
3179  const wchar_t* format,
3180  ...
3181  );
3182 
3183  static const ON_wString ON_VARGS_FUNC_CDECL FormatToString(
3184  const wchar_t* format,
3185  ...
3186  );
3187 
3188  bool FormatVargs(
3189  const wchar_t* format,
3190  va_list args
3191  );
3192 
3193  /*
3194  Description:
3195  A platform independent, secure, culture invariant way to format a wchar_t string
3196  with support for positional format parameters.
3197  This function is provide to be used when it is critical that
3198  the formatting be platform independent, secure and culture invarient.
3199  Parameters:
3200  buffer - [out]
3201  not null
3202  buffer_capacity - [in]
3203  > 0
3204  Number of wchar_t elements in buffer.
3205  format - [in]
3206  Avoid using %S (capital S). See the Remarks for details.
3207  ... - [in]
3208  Returns:
3209  >= 0:
3210  The number of wchar_t elements written to buffer[], not including the null terminator.
3211  A null terminator is always added (buffer[returned value] = 0).
3212  The last element of buffer[] is always set to zero (buffer[buffer_capacity-1] = 0).
3213  < 0: failure:
3214  If buffer is not null and buffer_capacity > 0, then buffer[0] = 0 and buffer[buffer_capacity-1] = 0;
3215  Remarks:
3216  The way Windows handles the %S (capital S) format parameter depends on locale
3217  and code page settings. It is strongly reccommended that you never use %S to
3218  include any string that may possibly contain elements with values > 127.
3219  The following examples illustrate a way to predictably use UTF-8 and wchar_t
3220  parameters in buffers of the other element type.
3221 
3222  const char* utf8_string = ...;
3223  // UNRELIABLE // ON_wString::Format(buffer,buffer_capacity,"%S",utf8_string);
3224  wchar_t wchar_buffer[...];
3225  const size_t wchar_buffer_capacity= sizeof(buffer)/sizeof(buffer[0]);
3226  ON_wString::Format(wchar_buffer, wchar_buffer_capacity, "%s", ON_wString(utf8_string));
3227 
3228  const wchar_t* wide_string = ...;
3229  // UNRELIABLE // ON_wString::Format(buffer,buffer_capacity,"%S",char_string);
3230  char char_buffer[...];
3231  const size_t char_buffer_capacity = sizeof(buffer)/sizeof(buffer[0]);
3232  ON_String::Format(char_buffer, char_buffer_capacity, "%s", ON_String(wide_string));
3233  */
3234  static int ON_VARGS_FUNC_CDECL FormatIntoBuffer(
3235  wchar_t* buffer,
3236  size_t buffer_capacity,
3237  const wchar_t* format,
3238  ...
3239  );
3240 
3241  static int ON_VARGS_FUNC_CDECL FormatIntoBuffer(
3242  ON_wStringBuffer& buffer,
3243  const wchar_t* format,
3244  ...
3245  );
3246 
3247  static int FormatVargsIntoBuffer(
3248  ON_wStringBuffer& buffer,
3249  const wchar_t* format,
3250  va_list args
3251  );
3252 
3253  static int FormatVargsIntoBuffer(
3254  wchar_t* buffer,
3255  size_t buffer_capacity,
3256  const wchar_t* format,
3257  va_list args
3258  );
3259 
3260  /*
3261  Returns:
3262  >= 0:
3263  Number of char elements in the formatted string, not including the null terminator.
3264  < 0:
3265  Invalid input
3266  */
3267  static int FormatVargsOutputCount(
3268  const wchar_t* format,
3269  va_list args
3270  );
3271 
3272  /*
3273  Parameters:
3274  format - [in]
3275  null terminated string to scan
3276  ... - [out]
3277  pointers to elements to assign.
3278  Returns:
3279  >= 0: number of fields successfully converted and assigned.
3280  <0: failure
3281  */
3282  int ON_VARGS_FUNC_CDECL Scan(
3283  const wchar_t* format,
3284  ...
3285  ) const;
3286 
3287  static int ON_VARGS_FUNC_CDECL ScanBuffer(
3288  const wchar_t* buffer,
3289  const wchar_t* format,
3290  ...
3291  );
3292 
3293  static int ScanBufferVargs(
3294  const wchar_t* buffer,
3295  const wchar_t* format,
3296  va_list args
3297  );
3298 
3299  /*
3300  Returns:
3301  not zero:
3302  pointer to the first character that was not scanned
3303  nullptr:
3304  failure
3305  */
3306  static const wchar_t* ToNumber(
3307  const wchar_t* buffer,
3308  char value_on_failure,
3309  char* value
3310  );
3311  static const wchar_t* ToNumber(
3312  const wchar_t* buffer,
3313  unsigned char value_on_failure,
3314  unsigned char* value
3315  );
3316  static const wchar_t* ToNumber(
3317  const wchar_t* buffer,
3318  short value_on_failure,
3319  short* value
3320  );
3321  static const wchar_t* ToNumber(
3322  const wchar_t* buffer,
3323  unsigned short value_on_failure,
3324  unsigned short* value
3325  );
3326  static const wchar_t* ToNumber(
3327  const wchar_t* buffer,
3328  int value_on_failure,
3329  int* value
3330  );
3331  static const wchar_t* ToNumber(
3332  const wchar_t* buffer,
3333  unsigned int value_on_failure,
3334  unsigned int* value
3335  );
3336  static const wchar_t* ToNumber(
3337  const wchar_t* buffer,
3338  ON__INT64 value_on_failure,
3339  ON__INT64* value
3340  );
3341  static const wchar_t* ToNumber(
3342  const wchar_t* buffer,
3343  ON__UINT64 value_on_failure,
3344  ON__UINT64* value
3345  );
3346  static const wchar_t* ToNumber(
3347  const wchar_t* buffer,
3348  double value_on_failure,
3349  double* value
3350  );
3351 
3352 
3353  // Low level access to string contents as character array
3354  wchar_t* ReserveArray(size_t); // make sure internal array has at least
3355  // the requested capacity.
3356  void ShrinkArray(); // shrink internal storage to minimum size
3357  wchar_t* SetLength(size_t); // set length (<=capacity)
3358  wchar_t* Array();
3359  const wchar_t* Array() const;
3360 
3361  /*
3362  Returns:
3363  Total number of bytes of memory used by this class.
3364  (For use in ON_Object::SizeOf() overrides.
3365  */
3366  unsigned int SizeOf() const;
3367 
3368  /*
3369  Returns:
3370  CRC of the string.
3371  */
3372  ON__UINT32 DataCRC(ON__UINT32 current_remainder) const;
3373 
3374  /*
3375  Returns:
3376  CRC of the lower case version of the string. Useful
3377  for case insensitive CRCs and hash codes.
3378  */
3379  ON__UINT32 DataCRCLower(ON__UINT32 current_remainder) const;
3380 
3381  /*
3382  OBSOLETE - Use ON_FileSystemPath::SplitPath
3383  */
3384  static void SplitPath(
3385  const char* path,
3386  ON_wString* drive,
3387  ON_wString* dir,
3388  ON_wString* fname,
3389  ON_wString* ext
3390  );
3391 
3392  static void SplitPath(
3393  const wchar_t* path,
3394  ON_wString* drive,
3395  ON_wString* dir,
3396  ON_wString* fname,
3397  ON_wString* ext
3398  );
3399 
3400 public:
3401  ~ON_wString();
3402 
3403 protected:
3404  // Implementation
3405  wchar_t* m_s; // pointer to ref counted string array
3406  // m_s - 12 bytes points at the string's ON_wStringHeader
3407 
3408  // implementation helpers
3409  struct ON_wStringHeader* Header() const;
3410  wchar_t* CreateArray(int);
3411  void CopyArray();
3412  void CopyToArray( const ON_wString& );
3413  void CopyToArray( int, const char* );
3414  void CopyToArray( int, const unsigned char* );
3415  void CopyToArray( int, const wchar_t* );
3416  void AppendToArray( const ON_wString& );
3417  void AppendToArray( int, const char* );
3418  void AppendToArray( int, const unsigned char* );
3419  void AppendToArray( int, const wchar_t* );
3420 };
3421 
3422 /*
3423 Returns:
3424  True if lhs and rhs are identical as arrays of wchar_t elements.
3425 */
3426 ON_DECL
3427 bool operator==( const ON_wString& lhs, const ON_wString& rhs );
3428 
3429 /*
3430 Returns:
3431  True if lhs and rhs are not identical as arrays of wchar_t elements.
3432 */
3433 ON_DECL
3434 bool operator!=(const ON_wString& lhs, const ON_wString& rhs);
3435 
3436 /*
3437 Returns:
3438  True if lhs is less than rhs as an array of wchar_t elements.
3439 */
3440 ON_DECL
3441 bool operator<(const ON_wString& lhs, const ON_wString& rhs);
3442 
3443 /*
3444 Returns:
3445  True if lhs is greater than rhs as an array of wchar_t elements.
3446 */
3447 ON_DECL
3448 bool operator>(const ON_wString& lhs, const ON_wString& rhs);
3449 
3450 /*
3451 Returns:
3452  True if lhs is less than or equal to rhs as an array of wchar_t elements.
3453 */
3454 ON_DECL
3455 bool operator<=(const ON_wString& lhs, const ON_wString& rhs);
3456 
3457 /*
3458 Returns:
3459  True if lhs is greater than or equal to rhs as an array of wchar_t elements.
3460 */
3461 ON_DECL
3462 bool operator>=(const ON_wString& lhs, const ON_wString& rhs);
3463 
3464 /*
3465 Returns:
3466  True if lhs and rhs are identical as arrays of wchar_t elements.
3467 */
3468 ON_DECL
3469 bool operator==( const ON_wString& lhs, const wchar_t* rhs );
3470 
3471 /*
3472 Returns:
3473  True if lhs and rhs are not identical as arrays of wchar_t elements.
3474 */
3475 ON_DECL
3476 bool operator!=(const ON_wString& lhs, const wchar_t* rhs);
3477 
3478 /*
3479 Returns:
3480  True if lhs is less than rhs as an array of wchar_t elements.
3481 */
3482 ON_DECL
3483 bool operator<(const ON_wString& lhs, const wchar_t* rhs);
3484 
3485 /*
3486 Returns:
3487  True if lhs is greater than rhs as an array of wchar_t elements.
3488 */
3489 ON_DECL
3490 bool operator>(const ON_wString& lhs, const wchar_t* rhs);
3491 
3492 /*
3493 Returns:
3494  True if lhs is less than or equal to rhs as an array of wchar_t elements.
3495 */
3496 ON_DECL
3497 bool operator<=(const ON_wString& lhs, const wchar_t* rhs);
3498 
3499 /*
3500 Returns:
3501  True if lhs is greater than or equal to rhs as an array of wchar_t elements.
3502 */
3503 ON_DECL
3504 bool operator>=(const ON_wString& lhs, const wchar_t* rhs);
3505 
3506 /*
3507 Returns:
3508  True if lhs and rhs are identical as arrays of wchar_t elements.
3509 */
3510 ON_DECL
3511 bool operator==( const wchar_t* lhs, const ON_wString& rhs );
3512 
3513 /*
3514 Returns:
3515  True if lhs and rhs are not identical as arrays of wchar_t elements.
3516 */
3517 ON_DECL
3518 bool operator!=(const wchar_t* lhs, const ON_wString& rhs);
3519 
3520 /*
3521 Returns:
3522  True if lhs is less than rhs as an array of wchar_t elements.
3523 */
3524 ON_DECL
3525 bool operator<(const wchar_t* lhs, const ON_wString& rhs);
3526 
3527 /*
3528 Returns:
3529  True if lhs is greater than rhs as an array of wchar_t elements.
3530 */
3531 ON_DECL
3532 bool operator>(const wchar_t* lhs, const ON_wString& rhs);
3533 
3534 /*
3535 Returns:
3536  True if lhs is less than or equal to rhs as an array of wchar_t elements.
3537 */
3538 ON_DECL
3539 bool operator<=(const wchar_t* lhs, const ON_wString& rhs);
3540 
3541 /*
3542 Returns:
3543  True if lhs is greater than or equal to rhs as an array of wchar_t elements.
3544 */
3545 ON_DECL
3546 bool operator>=(const wchar_t* lhs, const ON_wString& rhs);
3547 
3548 /*
3549 Description:
3550  An ON_NameHash is designed to help search for and compare attribute names
3551  like the ON_ModelComponent.Name() value.
3552 
3553  If a name is wchar_t encoded as wide_char_name and UTF-8 encoded as utf8_name,
3554  then ON_NameHash(wide_char_name) == ON_NameHash(utf8_name).
3555 
3556  Set:
3557  bool bEqualNameHash = ON_NameHash::Create(parent_id1,name1) == ON_NameHash::Create(parent_id2,name2);
3558  bool bEqualParentId = (parent_id1 == parent_id2)
3559  bool bEqualAttributeName = ON_String::EqualAttributeName(name1,name2);
3560 
3561  If (bEqualParentId && bEqualAttributeName) is true, then bEqualNameHash is true.
3562  If bEqualParentId is false, then bEqualNameHash is false.
3563  With probablity 1-epsilon, if bEqualAttributeName is false, then bEqualNameHash is false,
3564  where epsilon is an extremely tiny number.
3565 */
3566 class ON_CLASS ON_NameHash
3567 {
3568 public:
3569  /*
3570  Default conststruction creates ON_NameHash::UnsetNameHash.
3571  */
3572  ON_NameHash() = default;
3573  ~ON_NameHash() = default;
3574  ON_NameHash(const ON_NameHash&) = default;
3575  ON_NameHash& operator=(const ON_NameHash&) = default;
3576 
3577  static const ON_NameHash EmptyNameHash;
3578  static const ON_NameHash UnsetNameHash;
3579 
3580  /*
3581  Returns:
3582  True if the hash is for a valid non-empty name.
3583  */
3584  bool IsValidAndNotEmpty() const;
3585 
3586  /*
3587  Returns:
3588  True if the hash is for an empty name.
3589  */
3590  bool IsEmptyNameHash() const;
3591 
3592  /*
3593  Returns:
3594  True if the hash is for an invalid name.
3595  */
3596  bool IsInvalidNameHash() const;
3597 
3598  /*
3599  Returns:
3600  True if the hash is not empty and was set by calling CreateFilePathHash().
3601  */
3602  bool IsFilePathHash() const;
3603 
3604  /*
3605  Returns:
3606  True if hash is set and case is ignored
3607  */
3608  bool IgnoreCase() const;
3609 
3610  /*
3611  Returns:
3612  ON_NameHash::EmptyNameHash if name is empty.
3613  ON_NameHash::UnsetNameHash if name is not valid.
3614  */
3615  static ON_NameHash Create(
3616  const ON_wString& name
3617  );
3618  static ON_NameHash Create(
3619  const wchar_t* name
3620  );
3621  static ON_NameHash Create(
3622  size_t length,
3623  const wchar_t* name
3624  );
3625  static ON_NameHash Create(
3626  const ON_String& utf8_name
3627  );
3628  static ON_NameHash Create(
3629  const char* utf8_name
3630  );
3631  static ON_NameHash Create(
3632  size_t length,
3633  const char* utf8_name
3634  );
3635 
3636  static ON_NameHash Create(
3637  const ON_UUID& parent_id,
3638  const ON_wString& name
3639  );
3640  static ON_NameHash Create(
3641  const ON_UUID& parent_id,
3642  const wchar_t* name
3643  );
3644  static ON_NameHash Create(
3645  const ON_UUID& parent_id,
3646  size_t length,
3647  const wchar_t* name
3648  );
3649  static ON_NameHash Create(
3650  const ON_UUID& parent_id,
3651  const ON_String& name
3652  );
3653  static ON_NameHash Create(
3654  const ON_UUID& parent_id,
3655  const char* utf8_name
3656  );
3657  static ON_NameHash Create(
3658  const ON_UUID& parent_id,
3659  size_t length,
3660  const char* utf8_name
3661  );
3662 
3663  static ON_NameHash Create(
3664  const ON_wString& name,
3665  bool bIgnoreCase
3666  );
3667  static ON_NameHash Create(
3668  const wchar_t* name,
3669  bool bIgnoreCase
3670  );
3671  static ON_NameHash Create(
3672  size_t length,
3673  const wchar_t* name,
3674  bool bIgnoreCase
3675  );
3676  static ON_NameHash Create(
3677  const ON_String& name,
3678  bool bIgnoreCase
3679  );
3680  static ON_NameHash Create(
3681  const char* utf8_name,
3682  bool bIgnoreCase
3683  );
3684  static ON_NameHash Create(
3685  size_t length,
3686  const char* utf8_name,
3687  bool bIgnoreCase
3688  );
3689  static ON_NameHash Create(
3690  const ON_UUID& parent_id,
3691  const ON_wString& name,
3692  bool bIgnoreCase
3693  );
3694  static ON_NameHash Create(
3695  const ON_UUID& parent_id,
3696  const wchar_t* name,
3697  bool bIgnoreCase
3698  );
3699  static ON_NameHash Create(
3700  const ON_UUID& parent_id,
3701  size_t length,
3702  const wchar_t* name,
3703  bool bIgnoreCase
3704  );
3705  static ON_NameHash Create(
3706  const ON_UUID& parent_id,
3707  const ON_String& utf8_name,
3708  bool bIgnoreCase
3709  );
3710  static ON_NameHash Create(
3711  const ON_UUID& parent_id,
3712  const char* utf8_name,
3713  bool bIgnoreCase
3714  );
3715  static ON_NameHash Create(
3716  const ON_UUID& parent_id,
3717  size_t length,
3718  const char* utf8_name,
3719  bool bIgnoreCase
3720  );
3721 
3722  static ON_NameHash CreateIdAndEmptyName(
3723  const ON_UUID& parent_id
3724  );
3725 
3726  static ON_NameHash CreateIdAndUnsetName(
3727  const ON_UUID& parent_id
3728  );
3729 
3730  static ON_NameHash CreateFilePathHash(
3731  const class ON_FileReference& file_reference
3732  );
3733 
3734  static ON_NameHash CreateFilePathHash(
3735  const wchar_t* file_path
3736  );
3737 
3738  static ON_NameHash CreateFilePathHash(
3739  const char* file_path
3740  );
3741 
3742  static int CompareNameSHA1(
3743  const ON_NameHash& a,
3744  const ON_NameHash& b
3745  );
3746 
3747  static int CompareNameSHA1Ptr(
3748  const ON_NameHash* a,
3749  const ON_NameHash* b
3750  );
3751 
3752  static int CompareParentId(
3753  const ON_NameHash& a,
3754  const ON_NameHash& b
3755  );
3756 
3757  static int CompareParentIdPtr(
3758  const ON_NameHash* a,
3759  const ON_NameHash* b
3760  );
3761 
3762  /*
3763  Description:
3764  Compares id, then length, then SHA-1 digest.
3765  */
3766  static int Compare(
3767  const ON_NameHash& a,
3768  const ON_NameHash& b
3769  );
3770 
3771  /*
3772  Description:
3773  Compares id, then length, then SHA-1 digest.
3774  */
3775  static int ComparePtr(
3776  const ON_NameHash* a,
3777  const ON_NameHash* b
3778  );
3780  // Number of UTf-32 code point values in mapped name.
3781  // (0 for file path hashes)
3782  ON__UINT32 MappedNameCodePointCount() const;
3783 
3784  // SHA-1 hash of mapped name
3785  ON_SHA1_Hash MappedNameSha1Hash() const;
3786 
3787  // 32 bit hash of id and mapped name
3788  ON__UINT32 DataCRC(ON__UINT32 current_remainder) const;
3790  // 32 bit hash of id
3791  ON__UINT32 IdCRC(ON__UINT32 current_remainder) const;
3793  // 32 bit hash of id and mapped name
3794  ON__UINT32 NameCRC(ON__UINT32 current_remainder) const;
3796  ON_UUID ParentId() const;
3797 
3798 private:
3799 
3800  enum : unsigned int
3801  {
3802  flags_length_mask = 0x0FFFFFFF,
3803  flags_case_sensitive = 0x80000000,
3804  flags_file_path = 0xFFFFFFFF
3805  };
3806  // m_flags = 0xFFFFFFFFU -> Hash is a file path hash
3807  // m_flags != 0
3808  // m_flags &0x0FFFFFFF = number of unicode (UTF-32) code points in name
3809  // m_flags &0x80000000 = 0 to ignore case, !=0 if case sensitive hash
3810  ON__UINT32 m_flags = 0;
3811 
3812  // m_sha1_hash = SHA-1 hash of ordinal minimum mapped unicode (UTF-32) code points
3813  // If the name is empty, m_length = 0 and m_sha1_hash = ON_SHA1_Hash::EmptyContentHash.
3814  // If the name is not valid, m_length = 0 and m_sha1_hash = ON_SHA1_Hash::ZeroDigest.
3815  ON_SHA1_Hash m_sha1_hash = ON_SHA1_Hash::ZeroDigest;
3816 
3817  // When names appear in a tree structure, m_parent_id identifies the
3818  // parent node.
3819  ON_UUID m_parent_id = ON_nil_uuid;
3820 
3821 public:
3822  /*
3823  Description:
3824  Internal_CreateFromDotNet() is public for technical reasons. It is used
3825  in Rhino Common p-invoke code that provides a .NET interface to the
3826  services ON_NameHash provided by the ON_NameHash class.
3827  This function should be ignored and never called from ordinary C++ code.
3828  If you choose to ignore the preceding admonition, you will have to read
3829  the source code for information about how this function works.
3830  */
3831  static ON_NameHash Internal_DotNetInterfaceSet(
3832  const ON_UUID&,
3833  const ON_SHA1_Hash&,
3834  const ON__UINT32
3835  );
3836 
3837  ON__UINT32 Internal_DotNetInterfaceGetFlags() const;
3838 };
3839 
3840 /*
3841 Compares id, then length, then SHA-1 digest
3842 */
3843 ON_DECL
3844 bool operator==(
3845  const ON_NameHash& a,
3846  const ON_NameHash& b
3847  );
3848 
3849 /*
3850 Compares id, then length, then SHA-1 digest
3851 */
3852 ON_DECL
3853 bool operator!=(
3854  const ON_NameHash& a,
3855  const ON_NameHash& b
3856  );
3857 
3858 /*
3859 Compares id, then length, then SHA-1 digest
3860 */
3861 ON_DECL
3862 bool operator<(
3863  const ON_NameHash& a,
3864  const ON_NameHash& b
3865  );
3866 
3867 /*
3868 Compares id, then length, then SHA-1 digest
3869 */
3870 ON_DECL
3871 bool operator<=(
3872  const ON_NameHash& a,
3873  const ON_NameHash& b
3874  );
3875 
3876 /*
3877 Compares id, then length, then SHA-1 digest
3878 */
3879 ON_DECL
3880 bool operator>(
3881  const ON_NameHash& a,
3882  const ON_NameHash& b
3883  );
3884 
3885 /*
3886 Compares id, then length, then SHA-1 digest
3887 */
3888 ON_DECL
3889 bool operator>=(
3890  const ON_NameHash& a,
3891  const ON_NameHash& b
3892  );
3893 
3894 class ON_CLASS ON_UnitSystem
3895 {
3896 public:
3897  // Default construction sets this to ON_UnitSystem::Meters
3898  ON_UnitSystem() = default;
3899 
3900  ~ON_UnitSystem() = default;
3901  ON_UnitSystem(const ON_UnitSystem&) = default;
3902  ON_UnitSystem& operator=(const ON_UnitSystem&) = default;
3903 
3904 public:
3905  ON_UnitSystem(
3906  ON::LengthUnitSystem length_unit_system
3907  );
3908 
3909  ON_UnitSystem& operator=(
3910  ON::LengthUnitSystem length_unit_system
3911  );
3912 
3913  /*
3914  Parameters:
3915  custom_unit_name - [in]
3916  length unit name (no spaces)
3917  meters_per_custom_unit - [in]
3918  a positive number
3919  Example:
3920  // 1 League = 5556 meters
3921  const ON_UnitSystem Leagues = ON_UnitSystem::CreateCustomUnitSystem(L"Leagues", 1.0/5556.0);
3922  */
3923  static ON_UnitSystem CreateCustomUnitSystem(
3924  const wchar_t* custom_unit_name,
3925  double meters_per_custom_unit
3926  );
3927 
3928 public:
3929  // unit system = ON::LengthUnitSystem::None. Scale to or from any valid unit = 1
3930  static const ON_UnitSystem None;
3931 
3932  static const ON_UnitSystem Angstroms;
3933  static const ON_UnitSystem Nanometers;
3934  static const ON_UnitSystem Microns;
3935 
3936  // unit system = ON::LengthUnitSystem::Millimeters and meters/unit = 0.001 exactly
3937  static const ON_UnitSystem Millimeters;
3938 
3939  static const ON_UnitSystem Centimeters;
3940  static const ON_UnitSystem Decimeters;
3941 
3942  // unit system = ON::LengthUnitSystem::Meters and meters/unit = 1
3943  static const ON_UnitSystem Meters;
3944  static const ON_UnitSystem Dekameters;
3945  static const ON_UnitSystem Hectometers;
3946  static const ON_UnitSystem Kilometers;
3947  static const ON_UnitSystem Megameters;
3948  static const ON_UnitSystem Gigameters;
3949  static const ON_UnitSystem Microinches;
3950  static const ON_UnitSystem Mils;
3951 
3952  // unit system = ON::LengthUnitSystem::Inches and meters/unit = 0.0254 exactly
3953  static const ON_UnitSystem Inches;
3954 
3955  // unit system = ON::LengthUnitSystem::Feet and meters/unit = 0.3048 exactly
3956  static const ON_UnitSystem Feet;
3957 
3958  static const ON_UnitSystem Yards;
3959  static const ON_UnitSystem Miles;
3960  static const ON_UnitSystem PrinterPoints;
3961  static const ON_UnitSystem PrinterPicas;
3962  static const ON_UnitSystem NauticalMiles;
3963  static const ON_UnitSystem AstronomicalUnits;
3964  static const ON_UnitSystem LightYears;
3965  static const ON_UnitSystem Parsecs;
3966 
3967  // unit system = ON::LengthUnitSystem::Unset and meters/unit = ON_DBL_QNAN
3968  static const ON_UnitSystem Unset;
3969 
3970 
3971 
3972 public:
3973  bool operator==(const ON_UnitSystem&) const;
3974  bool operator!=(const ON_UnitSystem&) const;
3975 
3976  /*
3977  Returns
3978  true if m_unit_system is a valid ON::LengthUnitSystem enum value,
3979  which may be ON::LengthUnitSystem::None. If m_unit_system is
3980  ON::LengthUnitSystem::CustomUnits, then IsValid() returns true
3981  if m_custom_unit_scale > 0.0 and false otherwise.
3982  The value of m_custom_unit_name is not tested.
3983  See Also:
3984  IsSet()
3985  */
3986  bool IsValid() const;
3987 
3988  bool Read( class ON_BinaryArchive& );
3989  bool Write( class ON_BinaryArchive& ) const;
3990  void Dump( class ON_TextLog& ) const;
3991 
3992  /*
3993  Returns
3994  true If the unit system is valid and set to something beside
3995  ON::no_unit_systm;
3996  */
3997  bool IsSet() const;
3998 
3999  /*
4000  Returns
4001  true If the unit system is ON::LengthUnitSystem::CustomUnits
4002  */
4003  bool IsCustomUnitSystem() const;
4004 
4005  void SetUnitSystem(
4006  ON::LengthUnitSystem us
4007  );
4008 
4009  /*
4010  Parameters:
4011  custom_unit_name - [in]
4012  length unit name (no spaces)
4013  meters_per_custom_unit - [in]
4014  a positive number
4015  Example:
4016  // 1 League = 5556 meters
4017  ON_UnitSystem Leagues;
4018  Leagues.SetCustomUnitSystem( L"Leagues", 1.0/5556.0);
4019  // or
4020  ON_UnitSystem Leagues = ON_UnitSystem::CreateCustomUnitSystem(L"Leagues", 1.0/5556.0);
4021  */
4022  void SetCustomUnitSystem(
4023  const wchar_t* custom_unit_name,
4024  double meters_per_custom_unit
4025  );
4026 
4027  /*
4028  Description:
4029  Changes the unit system to custom units and sets the custom unit scale.
4030  Remarks:
4031  Avoid using this function. Use SetCustomUnitSystem() or SetUnitSystem()
4032  instead.
4033  */
4034  void SetCustomUnitSystemName(
4035  const wchar_t* custom_unit_name
4036  );
4037 
4038  /*
4039  Description:
4040  Changes the unit system to custom units and sets the custom unit scale.
4041  Remarks:
4042  Avoid using this function. Use SetCustomUnitSystem() or SetUnitSystem()
4043  instead.
4044  */
4045  void SetCustomUnitSystemScale(
4046  double meters_per_custom_unit
4047  );
4048 
4049  double MetersPerUnit() const;
4050  ON::LengthUnitSystem UnitSystem() const;
4051  const ON_wString& UnitSystemName() const;
4052 
4053 
4054 private:
4055  ON::LengthUnitSystem m_unit_system = ON::LengthUnitSystem::Meters;
4056  unsigned int m_reserved = 0;
4057 
4058  // The m_custom_unit_... settings apply when m_unit_system = ON::LengthUnitSystem::CustomUnits
4059  double m_meters_per_unit = 1.0; // 1 meter = m_custom_unit_scale custom units
4060  ON_wString m_custom_unit_name; // name of custom units
4061 };
4062 #endif
ON_UUID is a 16 byte universally unique identifier.
Definition: opennurbs_uuid.h:32
Definition: opennurbs_sha1.h:19
Definition: opennurbs_string.h:2020
Definition: opennurbs_string.h:753
Definition: opennurbs_string.h:852
Definition: opennurbs_string.h:779
An ON_NameHash is designed to help search for and compare attribute names like the ON_ModelComponent...
Definition: opennurbs_string.h:3434
Definition: opennurbs_string.h:3739
Definition: opennurbs_textlog.h:20
Definition: opennurbs_archive.h:1783
Definition: opennurbs_string.h:341
Definition: opennurbs_locale.h:32
static const ON_SHA1_Hash ZeroDigest
Definition: opennurbs_sha1.h:22
Definition: opennurbs_file_utilities.h:1125