forked from rurban/safeclib
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsafe_str_lib.h
871 lines (737 loc) · 40.7 KB
/
safe_str_lib.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
/*------------------------------------------------------------------
* safe_str_lib.h -- Safe C Library String APIs
*
* October 2008, Bo Berry
* September 2017, Reini Urban
* August 2020, Reini Urban
*
* Copyright (c) 2008-2011, 2013 by Cisco Systems, Inc.
* Copyright (c) 2017-2018, 2020 by Reini Urban
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*------------------------------------------------------------------
*/
#ifndef __SAFE_STR_LIB_H__
#define __SAFE_STR_LIB_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "safe_config.h"
#include "safe_lib_errno.h"
#include "safe_types.h"
#include "safe_compile.h"
#include <stdarg.h>
#ifndef __KERNEL__
#include <time.h>
#if defined HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#endif /* __KERNEL__ */
#ifndef SAFECLIB_DISABLE_WCHAR
#include <wchar.h>
#endif
#if defined _WIN32 && !defined(DISABLE_DLLIMPORT)
#undef EXTERN
#if defined(EXPORT) && defined(__SAFECLIB_PRIVATE_H__)
#define EXTERN extern __declspec(dllexport)
#else
#define EXTERN extern __declspec(dllimport)
#endif
#else
#define EXTERN extern
#endif
/**
* With this UCD version we generated our tables
*/
#define SAFECLIB_UNICODE_VERSION 15
/**
* The shortest string is a null string!!
*/
#define RSIZE_MIN_STR (1)
/** wide chars */
#define RSIZE_MAX_WSTR (RSIZE_MAX_STR / sizeof(wchar_t))
/** The makeup of a password */
#define SAFE_STR_MIN_LOWERCASE (2)
#define SAFE_STR_MIN_UPPERCASE (2)
#define SAFE_STR_MIN_NUMBERS (1)
#define SAFE_STR_MIN_SPECIALS (1)
#define SAFE_STR_PASSWORD_MIN_LENGTH (6)
#define SAFE_STR_PASSWORD_MAX_LENGTH (32)
EXTERN void abort_handler_s(const char *restrict msg, void *restrict ptr,
errno_t error)
#ifdef __GNUC__
__attribute__((noreturn))
#endif
;
EXTERN void ignore_handler_s(const char *restrict msg, void *restrict ptr,
errno_t error);
#define sl_default_handler ignore_handler_s
/* set string constraint handler */
EXTERN constraint_handler_t
set_str_constraint_handler_s(constraint_handler_t handler);
/* string concatenate */
#if !defined(TEST_MSVCRT)
EXTERN errno_t _strcat_s_chk(char *restrict dest, rsize_t dmax,
const char *restrict src, const size_t destbos)
BOS_CHK(dest) BOS_NULL(src);
#define strcat_s(dest, dmax, src) _strcat_s_chk(dest, dmax, src, BOS(dest))
/* string copy */
EXTERN errno_t _strcpy_s_chk(char *restrict dest, rsize_t dmax,
const char *restrict src, const size_t destbos)
BOS_CHK(dest) BOS_NULL(src);
#define strcpy_s(dest, dmax, src) _strcpy_s_chk(dest, dmax, src, BOS(dest))
#endif
/* fitted string concatenate */
EXTERN errno_t _strncat_s_chk(char *restrict dest, rsize_t dmax,
const char *restrict src, rsize_t slen,
const size_t destbos, const size_t srcbos)
BOS_ATTR((slen || dest || dmax) &&
(_BOS_NULL(dest) || _BOS_ZERO(dest, dmax)),
"empty dest or dmax")
BOS_ATTR((slen || dest || dmax) && _BOS_OVR(dest, dmax),
"dest overflow") BOS_OVR2_BUTZERO(src, slen);
#define strncat_s(dest, dmax, src, slen) \
_strncat_s_chk(dest, dmax, src, slen, BOS(dest), BOS(src))
/* fitted string copy */
EXTERN errno_t _strncpy_s_chk(char *restrict dest, rsize_t dmax,
const char *restrict src, rsize_t slen,
const size_t destbos, const size_t srcbos)
BOS_CHK(dest) BOS_OVR2_BUTZERO(src, slen);
#define strncpy_s(dest, dmax, src, slen) \
_strncpy_s_chk(dest, dmax, src, slen, BOS(dest), BOS(src))
/* string length */
EXTERN rsize_t _strnlen_s_chk(const char *str, rsize_t smax, size_t strbos)
BOS_CHK2(str, smax);
#define strnlen_s(str, smax) _strnlen_s_chk(str, smax, BOS(str))
/* string tokenizer */
EXTERN char *_strtok_s_chk(char *restrict dest, rsize_t *restrict dmaxp,
const char *restrict delim, char **restrict ptr,
const size_t destbos) BOS_OVR2_BUTNULL(dest, *dmaxp)
BOS_ATTR(dest &&_BOS_NULL(dmaxp), "empty dmax") BOS_NULL(delim)
BOS_NULL(ptr);
#if !(defined(_WIN32) && defined(HAVE_STRTOK_S))
/* they use:
char * strtok_s(char *_Str,const char *_Delim,char **_Context); */
#define strtok_s(dest, dmaxp, delim, ptr) \
_strtok_s_chk(dest, dmaxp, delim, ptr, BOS(dest))
#endif
/* secure stdio */
/* safe sprintf_s */
/* now __STDC_WANT_LIB_EXT1__ >= 1 compatible */
#if defined(SAFECLIB_HAVE_C99) && !defined(FOR_DOXYGEN)
EXTERN int _sprintf_s_chk(char *restrict dest, const rsize_t dmax,
const size_t destbos, const char *restrict fmt, ...)
__attribute_format__(printf,4,5) BOS_CHK(dest) BOS_FMT(fmt);
#define sprintf_s(dest, dmax, ...) \
_sprintf_s_chk(dest, dmax, BOS(dest), __VA_ARGS__)
#else
EXTERN int sprintf_s(char *restrict dest, rsize_t dmax,
const char *restrict fmt, ...)
__attribute_format__(printf,3,4) BOS_CHK(dest) BOS_FMT(fmt);
#endif
EXTERN int _vsprintf_s_chk(char *restrict dest, rsize_t dmax,
const size_t destbos, const char *restrict fmt,
va_list ap) BOS_CHK(dest) BOS_FMT(fmt);
#define vsprintf_s(dest, dmax, fmt, ap) \
_vsprintf_s_chk(dest, dmax, BOS(dest), fmt, ap)
/* truncating, no ESNOSPC */
#if defined(SAFECLIB_HAVE_C99) && !defined(TEST_MSVCRT) && !defined(FOR_DOXYGEN)
EXTERN int _snprintf_s_chk(char *restrict dest, rsize_t dmax,
const size_t destbos, const char *restrict fmt, ...)
__attribute_format__(printf,4,5) BOS_CHK(dest) BOS_FMT(fmt);
#define snprintf_s(dest, dmax, ...) \
_snprintf_s_chk(dest, dmax, BOS(dest), __VA_ARGS__)
#else
EXTERN int snprintf_s(char *restrict dest, rsize_t dmax,
const char *restrict fmt, ...)
__attribute_format__(printf,3,4) BOS_CHK(dest) BOS_FMT(fmt);
#endif
EXTERN int _vsnprintf_s_chk(char *restrict dest, rsize_t dmax,
const size_t destbos, const char *restrict fmt,
va_list ap) BOS_CHK(dest) BOS_FMT(fmt);
#if !(defined(_WIN32) && defined(HAVE_VSNPRINTF_S))
/* they use:
int vsnprintf_s(char *_DstBuf, size_t _DstSize, size_t _MaxCount,
const char *_Format, va_list _ArgList); */
#define vsnprintf_s(dest, dmax, fmt, ap) \
_vsnprintf_s_chk(dest, dmax, BOS(dest), fmt, ap)
#endif
/* Note: there is no __vsscanf_chk yet. Unchecked */
EXTERN int sscanf_s(const char *restrict buffer, const char *restrict fmt, ...)
__attribute_format__(scanf,2,3) BOS_NULL(buffer) BOS_FMT(fmt);
#ifndef __KERNEL__
EXTERN int fscanf_s(FILE *restrict stream, const char *restrict fmt, ...)
__attribute_format__(scanf,2,3) BOS_NULL(stream) BOS_FMT(fmt);
#endif /* __KERNEL__ */
EXTERN int scanf_s(const char *restrict fmt, ...)
__attribute_format__(scanf,1,2) BOS_FMT(fmt);
EXTERN int vscanf_s(const char *restrict fmt, va_list ap) BOS_FMT(fmt);
#ifndef __KERNEL__
EXTERN int vfscanf_s(FILE *restrict stream, const char *restrict fmt,
va_list ap) BOS_NULL(stream) BOS_FMT(fmt);
#endif /* __KERNEL__ */
EXTERN int vsscanf_s(const char *restrict dest, const char *restrict fmt,
va_list ap) BOS_NULL(dest) BOS_FMT(fmt);
EXTERN int printf_s(const char *restrict fmt, ...)
__attribute_format__(printf,1,2) BOS_FMT(fmt);
#ifndef __KERNEL__
EXTERN int fprintf_s(FILE *restrict stream, const char *restrict fmt, ...)
__attribute_format__(printf,2,3) BOS_FMT(fmt);
#endif /* __KERNEL__ */
EXTERN int vprintf_s(const char *restrict fmt, va_list ap) BOS_FMT(fmt);
#ifndef __KERNEL__
EXTERN int vfprintf_s(FILE *restrict stream, const char *restrict fmt,
va_list arg) BOS_FMT(fmt);
#endif /* __KERNEL__ */
EXTERN errno_t _strerror_s_chk(char *dest, rsize_t dmax, errno_t errnum,
const size_t destbos) BOS_CHK(dest);
#define strerror_s(dest, dmax, errnum) \
_strerror_s_chk(dest, dmax, errnum, BOS(dest))
EXTERN size_t strerrorlen_s(errno_t errnum);
/* for the other safe IO funcs see safe_lib.h */
#ifndef SAFECLIB_DISABLE_EXTENSIONS
/* improved strcpy */
EXTERN char *_stpcpy_s_chk(char *restrict dest, rsize_t dmax,
const char *restrict src, errno_t *restrict errp,
const size_t destbos, const size_t srcbos)
BOS_CHK(dest) BOS_NULL(src) BOS_NULL(errp);
#define stpcpy_s(dest, dmax, src, errp) \
_stpcpy_s_chk(dest, dmax, src, errp, BOS(dest), BOS(src))
EXTERN char *_stpncpy_s_chk(char *restrict dest, rsize_t dmax,
const char *restrict src, rsize_t slen,
errno_t *restrict errp,
const size_t destbos, const size_t srcbos)
BOS_CHK(dest) BOS_CHK2(src, slen) BOS_NULL(errp);
#define stpncpy_s(dest, dmax, src, slen, errp) \
_stpncpy_s_chk(dest, dmax, src, slen, errp, BOS(dest), BOS(src))
/* string compare */
EXTERN errno_t _strcmp_s_chk(const char *dest, rsize_t dmax, const char *src,
int *resultp, const size_t destbos,
const size_t srcbos) BOS_CHK(dest) BOS_NULL(src)
BOS_NULL(resultp);
#define strcmp_s(dest, dmax, src, resultp) \
_strcmp_s_chk(dest, dmax, src, resultp, BOS(dest), BOS(src))
/* string compare case-insensitive */
EXTERN errno_t _strcasecmp_s_chk(const char *dest, rsize_t dmax,
const char *src, int *resultp,
const size_t destbos) BOS_CHK(dest)
BOS_NULL(src) BOS_NULL(resultp);
#define strcasecmp_s(dest, dmax, src, resultp) \
_strcasecmp_s_chk(dest, dmax, src, resultp, BOS(dest))
/* natural order string compare */
EXTERN errno_t _strnatcmp_s_chk(const char *dest, rsize_t dmax, const char *src,
const int fold_case, int *resultp,
const size_t destbos, const size_t srcbos)
BOS_CHK(dest) BOS_NULL(src) BOS_NULL(resultp);
#define strnatcmp_s(dest, dmax, src, resultp) \
_strnatcmp_s_chk(dest, dmax, src, 0, resultp, BOS(dest), BOS(src))
#define strnatcasecmp_s(dest, dmax, src, resultp) \
_strnatcasecmp_s_chk(dest, dmax, src, 1, resultp, BOS(dest), BOS(src))
/* find a substring - case insensitive */
EXTERN errno_t _strcasestr_s_chk(char *dest, rsize_t dmax, const char *src,
rsize_t slen, char **substring,
const size_t destbos, const size_t srcbos)
BOS_CHK(dest) BOS_CHK2(src, slen) BOS_NULL(substring);
#define strcasestr_s(dest, dmax, src, slen, substring) \
_strcasestr_s_chk(dest, dmax, src, slen, substring, BOS(dest), BOS(src))
/* fixed field string compare */
EXTERN errno_t _strcmpfld_s_chk(const char *dest, rsize_t dmax, const char *src,
int *resultp, const size_t destbos)
BOS_CHK(dest) BOS_NULL(src) BOS_NULL(resultp);
#define strcmpfld_s(dest, dmax, src, resultp) \
_strcmpfld_s_chk(dest, dmax, src, resultp, BOS(dest))
/* fixed char array copy */
EXTERN errno_t _strcpyfld_s_chk(char *dest, const rsize_t dmax, const char *src,
rsize_t slen, const size_t destbos)
BOS_CHK_BUTZERO(dest, slen) BOS_OVR2_BUTZERO(src, slen)
VAL_OVR2(slen, dmax);
#define strcpyfld_s(dest, dmax, src, slen) \
_strcpyfld_s_chk(dest, dmax, src, slen, BOS(dest))
/* copy from a null terminated string to fixed char array */
EXTERN errno_t _strcpyfldin_s_chk(char *dest, rsize_t dmax, const char *src,
rsize_t slen, const size_t destbos)
BOS_CHK_BUTZERO(dest, slen) BOS_OVR2_BUTZERO(src, slen)
VAL_OVR2(slen, dmax);
#define strcpyfldin_s(dest, dmax, src, slen) \
_strcpyfldin_s_chk(dest, dmax, src, slen, BOS(dest))
/* copy from a char array to null terminated string */
EXTERN errno_t _strcpyfldout_s_chk(char *dest, rsize_t dmax, const char *src,
rsize_t slen, const size_t destbos)
BOS_CHK_BUTZERO(dest, slen) BOS_OVR2_BUTZERO(src, slen)
VAL_OVR2(slen, dmax);
#define strcpyfldout_s(dest, dmax, src, slen) \
_strcpyfldout_s_chk(dest, dmax, src, slen, BOS(dest))
/* computes excluded prefix length */
EXTERN errno_t _strcspn_s_chk(const char *dest, rsize_t dmax, const char *src,
rsize_t slen, rsize_t *countp,
const size_t destbos, const size_t srcbos)
BOS_CHK(dest) BOS_OVR2(src, slen) BOS_NULL(countp);
#define strcspn_s(dest, dmax, src, slen, countp) \
_strcspn_s_chk(dest, dmax, src, slen, countp, BOS(dest), BOS(src))
/* returns a pointer to the first occurrence of c in dest */
EXTERN errno_t _strfirstchar_s_chk(char *dest, rsize_t dmax, char c,
char **firstp, const size_t destbos)
BOS_CHK(dest) BOS_NULL(firstp);
#define strfirstchar_s(dest, dmax, c, firstp) \
_strfirstchar_s_chk(dest, dmax, c, firstp, BOS(dest))
/* returns index of first difference */
EXTERN errno_t _strfirstdiff_s_chk(const char *dest, rsize_t dmax,
const char *src, rsize_t *resultp,
const size_t destbos) BOS_CHK(dest)
BOS_NULL(src) BOS_NULL(resultp);
#define strfirstdiff_s(dest, dmax, src, resultp) \
_strfirstdiff_s_chk(dest, dmax, src, resultp, BOS(dest))
/* validate alphanumeric string */
EXTERN bool _strisalphanumeric_s_chk(const char *dest, rsize_t dmax,
const size_t destbos) BOS_CHK2(dest, dmax);
#define strisalphanumeric_s(dest, dmax) \
_strisalphanumeric_s_chk(dest, dmax, BOS(dest))
/* validate ascii string */
EXTERN bool _strisascii_s_chk(const char *dest, rsize_t dmax,
const size_t destbos) BOS_CHK2(dest, dmax);
#define strisascii_s(dest, dmax) _strisascii_s_chk(dest, dmax, BOS(dest))
/* validate string of digits */
EXTERN bool _strisdigit_s_chk(const char *dest, rsize_t dmax,
const size_t destbos) BOS_CHK2(dest, dmax);
#define strisdigit_s(dest, dmax) _strisdigit_s_chk(dest, dmax, BOS(dest))
/* validate hex string */
EXTERN bool _strishex_s_chk(const char *dest, rsize_t dmax,
const size_t destbos) BOS_CHK2(dest, dmax);
#define strishex_s(dest, dmax) _strishex_s_chk(dest, dmax, BOS(dest))
/* validate lower case */
EXTERN bool _strislowercase_s_chk(const char *dest, rsize_t dmax,
const size_t destbos) BOS_CHK2(dest, dmax);
#define strislowercase_s(dest, dmax) \
_strislowercase_s_chk(dest, dmax, BOS(dest))
/* validate mixed case */
EXTERN bool _strismixedcase_s_chk(const char *dest, rsize_t dmax,
const size_t destbos) BOS_CHK2(dest, dmax);
#define strismixedcase_s(dest, dmax) \
_strismixedcase_s_chk(dest, dmax, BOS(dest))
/* validate password */
EXTERN bool _strispassword_s_chk(const char *dest, rsize_t dmax,
const size_t destbos) BOS_CHK2(dest, dmax);
#define strispassword_s(dest, dmax) _strispassword_s_chk(dest, dmax, BOS(dest))
/* validate upper case */
EXTERN bool _strisuppercase_s_chk(const char *dest, rsize_t dmax,
const size_t destbos) BOS_CHK2(dest, dmax);
#define strisuppercase_s(dest, dmax) \
_strisuppercase_s_chk(dest, dmax, BOS(dest))
/* returns a pointer to the last occurrence of c in s1 */
EXTERN errno_t _strlastchar_s_chk(char *dest, rsize_t dmax, char c,
char **lastp, const size_t destbos)
BOS_CHK(dest) BOS_NULL(lastp);
#define strlastchar_s(dest, dmax, c, lastp) \
_strlastchar_s_chk(dest, dmax, c, lastp, BOS(dest))
/* returns index of last difference */
EXTERN errno_t _strlastdiff_s_chk(const char *dest, rsize_t dmax,
const char *src, rsize_t *resultp,
const size_t destbos) BOS_CHK(dest)
BOS_NULL(src) BOS_NULL(resultp);
#define strlastdiff_s(dest, dmax, src, resultp) \
_strlastdiff_s_chk(dest, dmax, src, resultp, BOS(dest))
/* left justify */
EXTERN errno_t _strljustify_s_chk(char *dest, rsize_t dmax,
const size_t destbos) BOS_CHK(dest);
#define strljustify_s(dest, dmax) _strljustify_s_chk(dest, dmax, BOS(dest))
/* string terminate */
EXTERN rsize_t _strnterminate_s_chk(char *dest, rsize_t dmax,
const size_t destbos) BOS_CHK2(dest, dmax);
#define strnterminate_s(dest, dmax) _strnterminate_s_chk(dest, dmax, BOS(dest))
/* get pointer to first occurrence from set of char */
EXTERN errno_t _strpbrk_s_chk(char *dest, rsize_t dmax, char *src, rsize_t slen,
char **firstp, const size_t destbos,
const size_t srcbos) BOS_CHK(dest)
BOS_OVR2(src, slen) BOS_NULL(firstp);
#define strpbrk_s(dest, dmax, src, slen, firstp) \
_strpbrk_s_chk(dest, dmax, src, slen, firstp, BOS(dest), BOS(src))
EXTERN errno_t _strfirstsame_s_chk(const char *dest, rsize_t dmax,
const char *src, rsize_t *resultp,
const size_t destbos) BOS_CHK(dest)
BOS_NULL(src) BOS_NULL(resultp);
#define strfirstsame_s(dest, dmax, src, resultp) \
_strfirstsame_s_chk(dest, dmax, src, resultp, BOS(dest))
EXTERN errno_t _strlastsame_s_chk(const char *dest, rsize_t dmax,
const char *src, rsize_t *resultp,
const size_t destbos) BOS_CHK(dest)
BOS_NULL(src) BOS_NULL(resultp);
#define strlastsame_s(dest, dmax, src, resultp) \
_strlastsame_s_chk(dest, dmax, src, resultp, BOS(dest))
/* searches for a prefix */
EXTERN errno_t _strprefix_s_chk(const char *dest, rsize_t dmax, const char *src,
const size_t destbos) BOS_CHK(dest)
BOS_NULL(src);
#define strprefix_s(dest, dmax, src) \
_strprefix_s_chk(dest, dmax, src, BOS(dest))
/* removes leading and trailing white space */
EXTERN errno_t _strremovews_s_chk(char *dest, rsize_t dmax,
const size_t destbos) BOS_CHK(dest);
#define strremovews_s(dest, dmax) _strremovews_s_chk(dest, dmax, BOS(dest))
/* computes inclusive prefix length */
EXTERN errno_t _strspn_s_chk(const char *dest, rsize_t dmax, const char *src,
rsize_t slen, rsize_t *countp,
const size_t destbos, const size_t srcbos)
BOS_CHK(dest) BOS_CHK2(src, slen) BOS_NULL(countp);
#define strspn_s(dest, dmax, src, slen, countp) \
_strspn_s_chk(dest, dmax, src, slen, countp, BOS(dest), BOS(src))
/* find a substring */
EXTERN errno_t _strstr_s_chk(char *dest, rsize_t dmax, const char *src,
rsize_t slen, char **substringp,
const size_t destbos, const size_t srcbos)
BOS_CHK(dest) BOS_OVR2(src, slen) BOS_NULL(substringp);
#define strstr_s(dest, dmax, src, slen, substringp) \
_strstr_s_chk(dest, dmax, src, slen, substringp, BOS(dest), BOS(src))
/* find a character */
EXTERN errno_t _strchr_s_chk(const char *restrict dest, rsize_t dmax,
const int ch, char **restrict resultp,
const size_t destbos) BOS_CHK(dest)
VAL_OVR2(ch, 255) BOS_NULL(resultp);
#define strchr_s(dest, dmax, ch, resultp) \
_strchr_s_chk(dest, dmax, ch, resultp, BOS(dest))
EXTERN errno_t _strrchr_s_chk(const char *restrict dest, rsize_t dmax,
const int ch, char **restrict resultp,
const size_t destbos) BOS_CHK(dest)
VAL_OVR2(ch, 255) BOS_NULL(resultp) BOS_ATTR(!*dest, "empty *dest");
#define strrchr_s(dest, dmax, ch, resultp) \
_strrchr_s_chk(dest, dmax, ch, resultp, BOS(dest))
/* convert string to lowercase.
mingw string_s.h: _strlwr_s */
EXTERN errno_t _strtolowercase_s_chk(char *dest, rsize_t dmax,
const size_t destbos) BOS_CHK2(dest, dmax);
#define strtolowercase_s(dest, dmax) \
_strtolowercase_s_chk(dest, dmax, BOS(dest))
/* convert string to uppercase
mingw string_s.h: _strupr_s */
EXTERN errno_t _strtouppercase_s_chk(char *dest, rsize_t dmax,
const size_t destbos) BOS_CHK2(dest, dmax);
#define strtouppercase_s(dest, dmax) \
_strtouppercase_s_chk(dest, dmax, BOS(dest))
#define strlwr_s(str, slen) strtolowercase_s((str), (slen))
#define strupr_s(str, slen) strtouppercase_s((str), (slen))
/* zero an entire string with nulls.
mingw string_s.h has: _strset_s */
EXTERN errno_t _strzero_s_chk(char *dest, rsize_t dmax, const size_t destbos)
BOS_CHK(dest);
#define strzero_s(dest, dmax) _strzero_s_chk(dest, dmax, BOS(dest))
EXTERN errno_t _strcoll_s_chk(const char *restrict dest, rsize_t dmax,
const char *restrict src, int *resultp,
const size_t destbos) BOS_CHK(dest) BOS_NULL(src)
BOS_NULL(resultp);
#define strcoll_s(dest, dmax, src, resultp) \
_strcoll_s_chk(dest, dmax, src, resultp, BOS(dest))
/* Derived from windows extensions sec_api/string_s.h
defined(MINGW_HAS_SECURE_API) */
EXTERN errno_t _strset_s_chk(char *restrict dest, rsize_t dmax, int value,
const size_t destbos) BOS_CHK(dest)
VAL_OVR2(value, 255);
#define strset_s(dest, dmax, value) _strset_s_chk(dest, dmax, value, BOS(dest))
EXTERN errno_t _strnset_s_chk(char *restrict dest, rsize_t dmax, int value,
rsize_t n, const size_t destbos) BOS_CHK(dest)
BOS_OVR2_BUTZERO(dest, n) VAL_OVR2(value, 255) VAL_OVR2_BUTZERO(n, dmax);
#define strnset_s(dest, dmax, value, n) \
_strnset_s_chk(dest, dmax, value, n, BOS(dest))
#endif /* SAFECLIB_DISABLE_EXTENSIONS */
#ifndef SAFECLIB_DISABLE_WCHAR
/* is c99
EXTERN wchar_t*
wcsstr(wchar_t *restrict dest, const wchar_t *restrict src);
*/
/* multibyte wchar */
EXTERN errno_t _mbstowcs_s_chk(size_t *restrict retvalp, wchar_t *restrict dest,
rsize_t dmax, const char *restrict src,
rsize_t len, const size_t destbos)
BOS_NULL(retvalp)
BOS_ATTR(!_BOS_NULL(dest) && _BOS_ZERO(dest, dmax), "empty dmax")
BOS_ATTR(!_BOS_NULL(dest) && _BOSW_OVR(dest, dmax), "dest overflow")
BOS_ATTR(!_BOS_NULL(dest) && (void *)dest == (void *)src,
"dest overlap") BOS_CHK2(src, len);
#define mbstowcs_s(retvalp, dest, dmax, src, len) \
_mbstowcs_s_chk(retvalp, dest, dmax, src, len, BOS(dest))
EXTERN errno_t _mbsrtowcs_s_chk(size_t *restrict retvalp,
wchar_t *restrict dest, rsize_t dmax,
const char **restrict srcp, rsize_t len,
mbstate_t *restrict ps, const size_t destbos)
BOS_NULL(retvalp) BOS_NULL(srcp) BOS_NULL(ps)
BOS_ATTR(!_BOS_NULL(dest) && _BOS_ZERO(dest, dmax), "empty dmax")
BOS_ATTR(!_BOS_NULL(dest) && _BOSW_OVR(dest, dmax), "dest overflow")
BOS_ATTR(!_BOS_NULL(dest) && (char *)dest == *srcp,
"dest overlap") BOS_CHK2(*srcp, len)
BOS_ATTR(dmax &&len > dmax, "len overflow >dmax");
#define mbsrtowcs_s(retvalp, dest, dmax, srcp, len, ps) \
_mbsrtowcs_s_chk(retvalp, dest, dmax, srcp, len, ps, BOS(dest))
EXTERN errno_t _wcsrtombs_s_chk(size_t *restrict retvalp, char *restrict dest,
rsize_t dmax, const wchar_t **restrict srcp,
rsize_t len, mbstate_t *restrict ps,
const size_t destbos) BOS_NULL(retvalp)
BOS_NULL(ps) BOS_ATTR(!_BOS_NULL(dest) && !dmax, "empty dmax")
BOS_ATTR(!_BOS_NULL(dest) && _BOS_OVR(dest, dmax), "dest overflow")
BOS_ATTR(!_BOS_NULL(dest) && (void *)dest == (void *)srcp,
"dest overlap") BOS_NULL(srcp) BOSW_CHK2(*srcp, len)
BOS_ATTR(dmax &&len > dmax, "len overflow >dmax");
#define wcsrtombs_s(retvalp, dest, dmax, srcp, len, ps) \
_wcsrtombs_s_chk(retvalp, dest, dmax, srcp, len, ps, BOS(dest))
EXTERN errno_t _wcstombs_s_chk(size_t *restrict retvalp, char *restrict dest,
rsize_t dmax, const wchar_t *restrict src,
rsize_t len, const size_t destbos)
BOS_NULL(retvalp) BOS_CHK(dest) BOSW_CHK2(src, len)
BOS_ATTR(dmax &&len > dmax, "len overflow >dmax");
#define wcstombs_s(retvalp, dest, dmax, src, len) \
_wcstombs_s_chk(retvalp, dest, dmax, src, len, BOS(dest))
EXTERN errno_t _wcrtomb_s_chk(size_t *restrict retvalp, char *restrict dest,
rsize_t dmax, wchar_t wc, mbstate_t *restrict ps,
const size_t destbos) BOS_NULL(retvalp)
BOS_CHK(dest) BOS_NULL(ps) VAL_OVR2(wc, 0x10ffff);
#define wcrtomb_s(retvalp, dest, dmax, wc, ps) \
_wcrtomb_s_chk(retvalp, dest, dmax, wc, ps, BOS(dest))
EXTERN errno_t _wctomb_s_chk(int *restrict retvalp, char *restrict dest,
rsize_t dmax, wchar_t wc, const size_t destbos)
BOS_NULL(retvalp)
BOS_ATTR(!_BOS_NULL(dest) &&
(!dmax || dmax > RSIZE_MAX_STR || _BOS_OVR(dest, dmax)),
"dest overflow or empty") VAL_OVR2(wc, 0x10ffff);
#define wctomb_s(retvalp, dest, dmax, wc) \
_wctomb_s_chk(retvalp, dest, dmax, wc, BOS(dest))
EXTERN size_t _wcsnlen_s_chk(const wchar_t *str, size_t smax, size_t srcbos)
BOSW_CHK2(str, smax);
#define wcsnlen_s(str, smax) _wcsnlen_s_chk(str, smax, BOS(str))
EXTERN errno_t _wcscpy_s_chk(wchar_t *restrict dest, rsize_t dmax,
const wchar_t *restrict src, const size_t destbos)
BOSW_CHK(dest) BOS_NULL(src);
#define wcscpy_s(dest, dmax, src) _wcscpy_s_chk(dest, dmax, src, BOS(dest))
EXTERN errno_t _wcsncpy_s_chk(wchar_t *restrict dest, rsize_t dmax,
const wchar_t *restrict src, rsize_t slen,
const size_t destbos, const size_t srcbos)
BOSW_CHK(dest) BOSW_OVR2(src, slen);
#define wcsncpy_s(dest, dmax, src, slen) \
_wcsncpy_s_chk(dest, dmax, src, slen, BOS(dest), BOS(src))
EXTERN errno_t _wcscat_s_chk(wchar_t *restrict dest, rsize_t dmax,
const wchar_t *restrict src, const size_t destbos)
BOSW_CHK(dest) BOS_NULL(src);
#define wcscat_s(dest, dmax, src) _wcscat_s_chk(dest, dmax, src, BOS(dest))
EXTERN errno_t _wcsncat_s_chk(wchar_t *restrict dest, rsize_t dmax,
const wchar_t *restrict src, rsize_t slen,
const size_t destbos, const size_t srcbos)
BOS_ATTR(slen && (_BOS_NULL(dest) || _BOS_ZERO(dest, dmax) || !dmax),
"empty dest or dmax")
BOS_ATTR(slen &&_BOSW_OVR(dest, dmax), "dest overflow")
BOS_ATTR(!slen && !_BOS_NULL(dest), "empty slen")
BOS_ATTR(slen && (_BOSW_OVR(src, slen) || _BOS_NULL(src)),
"src overflow or empty");
#define wcsncat_s(dest, dmax, src, slen) \
_wcsncat_s_chk(dest, dmax, src, slen, BOS(dest), BOS(src))
EXTERN wchar_t *_wcstok_s_chk(wchar_t *restrict dest, rsize_t *restrict dmaxp,
const wchar_t *restrict delim,
wchar_t **restrict ptr, const size_t destbos)
BOS_ATTR(_BOS_NULL(dmaxp) || !*dmaxp, "empty dmax")
BOSW_OVR2_BUTNULL(dest, *dmaxp) BOS_NULL(delim) BOS_NULL(ptr);
#if !(defined(_WIN32) && defined(HAVE_WCSTOK_S))
/* they use a buggy:
wchar_t* wcstok_s(wchar_t *_Str, const wchar_t *_Delim, wchar_t **_Context); */
#define wcstok_s(dest, dmaxp, delim, ptr) \
_wcstok_s_chk(dest, dmaxp, delim, ptr, BOS(dest))
#endif
#if defined(SAFECLIB_HAVE_C99) && !defined(TEST_MSVCRT)
EXTERN int _swprintf_s_chk(wchar_t *restrict dest, rsize_t dmax,
const size_t destbos, const wchar_t *restrict fmt,
...)
__attribute_format_wprintf(4,5) BOSW_CHK(dest) BOS_FMT(fmt);
#define swprintf_s(dest, dmax, ...) \
_swprintf_s_chk(dest, dmax, BOS(dest), __VA_ARGS__)
#else
EXTERN int swprintf_s(wchar_t *restrict dest, rsize_t dmax,
const wchar_t *restrict fmt, ...)
__attribute_format_wprintf(3,4) BOSW_CHK(dest) BOS_FMT(fmt);
#endif
EXTERN int _vswprintf_s_chk(wchar_t *restrict dest, rsize_t dmax,
const size_t destbos, const wchar_t *restrict fmt,
va_list ap) BOSW_CHK(dest) BOS_FMT(fmt);
#define vswprintf_s(dest, dmax, fmt, ap) \
_vswprintf_s_chk(dest, dmax, BOS(dest), fmt, ap)
/* truncating, no ESNOSPC */
#if defined(SAFECLIB_HAVE_C99) && !defined(TEST_MSVCRT) && !defined(FOR_DOXYGEN)
EXTERN int _snwprintf_s_chk(wchar_t *restrict dest, rsize_t dmax,
const size_t destbos, const wchar_t *restrict fmt,
...)
__attribute_format_wprintf(4,5) BOSW_CHK(dest) BOS_FMT(fmt);
#define snwprintf_s(dest, dmax, ...) \
_snwprintf_s_chk(dest, dmax, BOS(dest), __VA_ARGS__)
#else
EXTERN int snwprintf_s(wchar_t *restrict dest, rsize_t dmax,
const wchar_t *restrict fmt, ...)
__attribute_format_wprintf(3,4) BOSW_CHK(dest) BOS_FMT(fmt);
#endif
EXTERN int _vsnwprintf_s_chk(wchar_t *restrict dest, rsize_t dmax,
const size_t destbos, const wchar_t *restrict fmt,
va_list ap) BOSW_CHK(dest) BOS_FMT(fmt);
#define vsnwprintf_s(dest, dmax, fmt, ap) \
_vsnwprintf_s_chk(dest, dmax, BOS(dest), fmt, ap)
EXTERN int wprintf_s(const wchar_t *restrict fmt, ...)
__attribute_format_wprintf(1,2) BOS_FMT(fmt);
EXTERN int vwprintf_s(const wchar_t *restrict fmt, va_list ap) BOS_FMT(fmt);
#ifndef __KERNEL__
EXTERN int fwprintf_s(FILE *restrict stream, const wchar_t *restrict fmt, ...)
__attribute_format_wprintf(2,3) BOS_NULL(stream) BOS_FMT(fmt);
EXTERN int vfwprintf_s(FILE *restrict stream, const wchar_t *restrict fmt,
va_list ap) BOS_NULL(stream) BOS_FMT(fmt);
#endif /* __KERNEL__ */
EXTERN int swscanf_s(const wchar_t *restrict src, const wchar_t *restrict fmt,
...) __attribute_format_wscanf(2,3) BOS_NULL(src) BOS_FMT(fmt);
EXTERN int vswscanf_s(const wchar_t *restrict src, const wchar_t *restrict fmt,
va_list ap) BOS_NULL(src) BOS_FMT(fmt);
EXTERN int wscanf_s(const wchar_t *restrict fmt, ...)
__attribute_format_wscanf(1,2) BOS_FMT(fmt);
EXTERN int vwscanf_s(const wchar_t *restrict fmt, va_list ap) BOS_FMT(fmt);
#ifndef __KERNEL__
EXTERN int fwscanf_s(FILE *restrict stream, const wchar_t *restrict fmt, ...)
__attribute_format_wscanf(2,3) BOS_NULL(stream) BOS_FMT(fmt);
EXTERN int vfwscanf_s(FILE *restrict stream, const wchar_t *restrict fmt,
va_list ap) BOS_NULL(stream) BOS_FMT(fmt);
#endif /* __KERNEL__ */
#ifndef SAFECLIB_DISABLE_EXTENSIONS
/* search wide substring */
EXTERN errno_t _wcsstr_s_chk(wchar_t *restrict dest, rsize_t dmax,
const wchar_t *restrict src, rsize_t slen,
wchar_t **restrict substringp,
const size_t destbos, const size_t srcbos)
BOSW_CHK(dest) BOSW_OVR2(src, slen) BOS_NULL(substringp);
#define wcsstr_s(dest, dmax, src, slen, substringp) \
_wcsstr_s_chk(dest, dmax, src, slen, substringp, BOS(dest), BOS(src))
/* compare */
EXTERN errno_t _wcscmp_s_chk(const wchar_t *restrict dest, rsize_t dmax,
const wchar_t *restrict src, rsize_t smax,
int *resultp, const size_t destbos,
const size_t srcbos) BOSW_CHK(dest)
BOSW_CHK2(src, smax) BOS_NULL(resultp);
#define wcscmp_s(dest, dmax, src, smax, resultp) \
_wcscmp_s_chk(dest, dmax, src, smax, resultp, BOS(dest), BOS(src))
EXTERN errno_t _wcsncmp_s_chk(const wchar_t *restrict dest, rsize_t dmax,
const wchar_t *restrict src, rsize_t smax,
rsize_t count, int *resultp, const size_t destbos,
const size_t srcbos) BOSW_CHK(dest)
BOSW_CHK2(src, smax) BOS_NULL(resultp);
#define wcsncmp_s(dest, dmax, src, smax, count, resultp) \
_wcsncmp_s_chk(dest, dmax, src, smax, count, resultp, BOS(dest), BOS(src))
/* compare case-folded */
EXTERN errno_t _wcsicmp_s_chk(const wchar_t *restrict dest, rsize_t dmax,
const wchar_t *restrict src, rsize_t smax,
int *resultp, const size_t destbos,
const size_t srcbos) BOSW_CHK(dest)
BOSW_CHK2(src, smax) BOS_NULL(resultp);
#define wcsicmp_s(dest, dmax, src, smax, resultp) \
_wcsicmp_s_chk(dest, dmax, src, smax, resultp, BOS(dest), BOS(src))
/* natural sort-order */
EXTERN errno_t _wcsnatcmp_s_chk(const wchar_t *restrict dest, rsize_t dmax,
const wchar_t *restrict src, rsize_t smax,
const int fold_case, int *resultp,
const size_t destbos, const size_t srcbos)
BOSW_CHK(dest) BOSW_CHK2(src, smax) BOS_NULL(resultp);
#define wcsnatcmp_s(dest, dmax, src, smax, resultp) \
_wcsnatcmp_s_chk(dest, dmax, src, smax, 0, resultp, BOS(dest), BOS(src))
#define wcsnaticmp_s(dest, dmax, src, smax, resultp) \
_wcsnatcmp_s_chk(dest, dmax, src, smax, 1, resultp, BOS(dest), BOS(src))
EXTERN errno_t _wcsset_s_chk(wchar_t *restrict dest, rsize_t dmax,
const wchar_t value, const size_t destbos)
BOSW_CHK(dest) VAL_OVR2(value, 0x10ffff);
#define wcsset_s(dest, dmax, value) _wcsset_s_chk(dest, dmax, value, BOS(dest))
EXTERN errno_t _wcsnset_s_chk(wchar_t *restrict dest, rsize_t dmax,
const wchar_t value, size_t n,
const size_t destbos) BOSW_CHK(dest)
VAL_OVR2(value, 0x10ffff);
#define wcsnset_s(dest, dmax, value, n) \
_wcsnset_s_chk(dest, dmax, value, n, BOS(dest))
EXTERN errno_t _wcscoll_s_chk(const wchar_t *restrict dest, rsize_t dmax,
const wchar_t *restrict src, rsize_t smax,
int *resultp, const size_t destbos,
const size_t srcbos) BOSW_CHK(dest)
BOSW_CHK2(src, smax) BOS_NULL(resultp);
#define wcscoll_s(dest, dmax, src, smax, resultp) \
_wcscoll_s_chk(dest, dmax, src, smax, resultp, BOS(dest), BOS(src))
/* simple char-wise folding */
EXTERN errno_t _wcslwr_s_chk(wchar_t *restrict src, rsize_t slen,
const size_t srcbos) BOSW_OVR2_BUTZERO(src, slen);
#define wcslwr_s(src, slen) _wcslwr_s_chk(src, slen, BOS(src))
EXTERN errno_t _wcsupr_s_chk(wchar_t *restrict src, rsize_t slen,
const size_t srcbos) BOSW_OVR2_BUTZERO(src, slen);
#define wcsupr_s(src, slen) _wcsupr_s_chk(src, slen, BOS(src))
/* is a wide upper character which folds to multiple lowercase chars? how
* many */
EXTERN int iswfc(const uint32_t wc) VAL_OVR2(wc, 0x10ffff);
/* full foldcase a single upper char to mult. lower chars */
EXTERN int _towfc_s_chk(wchar_t *restrict dest, rsize_t dmax,
const uint32_t src, const size_t destbos) BOSW_CHK(dest)
BOS_ATTR(dmax < 4, "dmax underflow <4");
#define towfc_s(dest, dmax, src) _towfc_s_chk(dest, dmax, src, BOS(dest))
/* full foldcase + NFD normalization */
EXTERN errno_t _wcsfc_s_chk(wchar_t *restrict dest, rsize_t dmax,
const wchar_t *restrict src, rsize_t *restrict lenp,
const size_t destbos) BOSW_CHK(dest) BOS_NULL(src);
#define wcsfc_s(dest, dmax, src, lenp) \
_wcsfc_s_chk(dest, dmax, src, lenp, BOS(dest))
/* Normalize to FCD/pre-NFKD */
EXTERN errno_t _wcsnorm_decompose_s_chk(wchar_t *restrict dest, rsize_t dmax,
const wchar_t *restrict src,
rsize_t *restrict lenp,
const bool iscompat,
const size_t destbos) BOSW_CHK(dest)
BOS_NULL(src);
#define wcsnorm_decompose_s(dest, dmax, src, lenp, iscompat) \
_wcsnorm_decompose_s_chk(dest, dmax, src, lenp, iscompat, BOS(dest))
/* Normalize to NCD/NFKD */
EXTERN errno_t _wcsnorm_reorder_s_chk(wchar_t *restrict dest, rsize_t dmax,
const wchar_t *restrict src,
const rsize_t len, const size_t destbos)
BOSW_CHK(dest) BOSW_OVR2(src, len);
#define wcsnorm_reorder_s(dest, dmax, src, len) \
_wcsnorm_reorder_s_chk(dest, dmax, src, len, BOS(dest))
/* Normalize to NFC/NFKC */
EXTERN errno_t _wcsnorm_compose_s_chk(wchar_t *restrict dest, rsize_t dmax,
const wchar_t *restrict src,
rsize_t *restrict lenp, bool iscontig,
const size_t destbos) BOSW_CHK(dest)
BOS_NULL(src) BOS_NULL(lenp);
#define wcsnorm_compose_s(dest, dmax, src, lenp, iscontig) \
_wcsnorm_compose_s_chk(dest, dmax, src, lenp, iscontig, BOS(dest))
enum wcsnorm_mode {
WCSNORM_NFD = 0,
WCSNORM_NFC = 1, /* default */
WCSNORM_FCD = 2, /* not reordered */
WCSNORM_FCC = 3, /* contiguous composition only */
WCSNORM_NFKD = 4, /* compat. OPTIONAL with --enable-norm-compat */
WCSNORM_NFKC = 5 /* compat. OPTIONAL with --enable-norm-compat */
};
typedef enum wcsnorm_mode wcsnorm_mode_t;
/* Normalize to NFC (default), NFD nfc=0.
experim. nfc>1: FCD, FCC */
EXTERN errno_t _wcsnorm_s_chk(wchar_t *restrict dest, rsize_t dmax,
const wchar_t *restrict src,
const wcsnorm_mode_t mode, rsize_t *restrict lenp,
const size_t destbos) BOSW_CHK(dest)
BOS_NULL(src);
#define wcsnorm_s(dest, dmax, src, mode, lenp) \
_wcsnorm_s_chk(dest, dmax, src, mode, lenp, BOS(dest))
#endif /* SAFECLIB_DISABLE_EXTENSIONS */
#endif /* SAFECLIB_DISABLE_WCHAR */
#ifdef __cplusplus
}
#endif
#endif /* __SAFE_STR_LIB_H__ */