[AArch64][GlobalISel] Add disjoint handling for add_and_or_is_add. (#123594)
[llvm-project.git] / libcxx / src / support / win32 / support.cpp
blob7ac508301b526ca970e0c0168f0ad9951fd32a91
1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include <cstdarg> // va_start, va_end
10 #include <cstddef> // size_t
11 #include <cstdio> // vsprintf, vsnprintf
12 #include <cstdlib> // malloc
13 #include <cstring> // strcpy, wcsncpy
14 #include <cwchar> // mbstate_t
16 // Returns >= 0: the number of wide characters found in the
17 // multi byte sequence src (of src_size_bytes), that fit in the buffer dst
18 // (of max_dest_chars elements size). The count returned excludes the
19 // null terminator. When dst is NULL, no characters are copied
20 // and no "out" parameters are updated.
21 // Returns (size_t) -1: an incomplete sequence encountered.
22 // Leaves *src pointing the next character to convert or NULL
23 // if a null character was converted from *src.
24 size_t mbsnrtowcs(wchar_t* __restrict dst,
25 const char** __restrict src,
26 size_t src_size_bytes,
27 size_t max_dest_chars,
28 mbstate_t* __restrict ps) {
29 const size_t terminated_sequence = static_cast<size_t>(0);
30 // const size_t invalid_sequence = static_cast<size_t>(-1);
31 const size_t incomplete_sequence = static_cast< size_t>(-2);
33 size_t dest_converted = 0;
34 size_t source_converted = 0;
35 size_t source_remaining = src_size_bytes;
36 size_t result = 0;
37 bool have_result = false;
39 // If dst is null then max_dest_chars should be ignored according to the
40 // standard. Setting max_dest_chars to a large value has this effect.
41 if (!dst)
42 max_dest_chars = static_cast<size_t>(-1);
44 while (source_remaining) {
45 if (dst && dest_converted >= max_dest_chars)
46 break;
47 // Converts one multi byte character.
48 // if result > 0, it's the size in bytes of that character.
49 // othewise if result is zero it indicates the null character has been found.
50 // otherwise it's an error and errno may be set.
51 size_t char_size = mbrtowc(dst ? dst + dest_converted : nullptr, *src + source_converted, source_remaining, ps);
52 // Don't do anything to change errno from here on.
53 if (char_size > 0) {
54 source_remaining -= char_size;
55 source_converted += char_size;
56 ++dest_converted;
57 continue;
59 result = char_size;
60 have_result = true;
61 break;
63 if (dst) {
64 if (have_result && result == terminated_sequence)
65 *src = nullptr;
66 else
67 *src += source_converted;
69 if (have_result && result != terminated_sequence && result != incomplete_sequence)
70 return static_cast<size_t>(-1);
72 return dest_converted;
75 // Converts max_source_chars from the wide character buffer pointer to by *src,
76 // into the multi byte character sequence buffer stored at dst which must be
77 // dst_size_bytes bytes in size.
78 // Returns >= 0: the number of bytes in the sequence
79 // converted from *src, excluding the null terminator.
80 // Returns size_t(-1) if an error occurs, also sets errno.
81 // If dst is NULL dst_size_bytes is ignored and no bytes are copied to dst
82 // and no "out" parameters are updated.
83 size_t wcsnrtombs(char* __restrict dst,
84 const wchar_t** __restrict src,
85 size_t max_source_chars,
86 size_t dst_size_bytes,
87 mbstate_t* __restrict ps) {
88 // const size_t invalid_sequence = static_cast<size_t>(-1);
90 size_t source_converted = 0;
91 size_t dest_converted = 0;
92 size_t dest_remaining = dst_size_bytes;
93 size_t char_size = 0;
94 const errno_t no_error = (errno_t)0;
95 errno_t result = (errno_t)0;
96 bool have_result = false;
97 bool terminator_found = false;
99 // If dst is null then dst_size_bytes should be ignored according to the
100 // standard. Setting dest_remaining to a large value has this effect.
101 if (!dst)
102 dest_remaining = static_cast<size_t>(-1);
104 while (source_converted != max_source_chars) {
105 if (!dest_remaining)
106 break;
107 wchar_t c = (*src)[source_converted];
108 if (dst)
109 result = wcrtomb_s(&char_size, dst + dest_converted, dest_remaining, c, ps);
110 else
111 result = wcrtomb_s(&char_size, nullptr, 0, c, ps);
112 // If result is zero there is no error and char_size contains the
113 // size of the multi-byte-sequence converted.
114 // Otherwise result indicates an errno type error.
115 if (result == no_error) {
116 if (c == L'\0') {
117 terminator_found = true;
118 break;
120 ++source_converted;
121 if (dst)
122 dest_remaining -= char_size;
123 dest_converted += char_size;
124 continue;
126 have_result = true;
127 break;
129 if (dst) {
130 if (terminator_found)
131 *src = nullptr;
132 else
133 *src = *src + source_converted;
135 if (have_result && result != no_error) {
136 errno = result;
137 return static_cast<size_t>(-1);
140 return dest_converted;