Line data Source code
1 : /**
2 : Copyright (c) 2024 Stappler LLC <admin@stappler.dev>
3 :
4 : Permission is hereby granted, free of charge, to any person obtaining a copy
5 : of this software and associated documentation files (the "Software"), to deal
6 : in the Software without restriction, including without limitation the rights
7 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 : copies of the Software, and to permit persons to whom the Software is
9 : furnished to do so, subject to the following conditions:
10 :
11 : The above copyright notice and this permission notice shall be included in
12 : all copies or substantial portions of the Software.
13 :
14 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 : THE SOFTWARE.
21 : **/
22 :
23 : #include "SPWasm.h"
24 : #include "SPString.h"
25 :
26 : namespace stappler::wasm {
27 :
28 175 : static uint32_t StapplerCoreItoaU8(wasm_exec_env_t exec_env, int64_t val, char *buf, uint32_t bufLen) {
29 175 : return string::_itoa(val, buf, bufLen);
30 : }
31 :
32 0 : static uint32_t StapplerCoreItoaU16(wasm_exec_env_t exec_env, int64_t val, char16_t *buf, uint32_t bufLen) {
33 0 : return string::_itoa(val, buf, bufLen);
34 : }
35 :
36 175 : static uint32_t StapplerCoreItoaLen(wasm_exec_env_t exec_env, int64_t val) {
37 175 : return string::_itoa_len(val);
38 : }
39 :
40 0 : static uint32_t StapplerCoreDtoaU8(wasm_exec_env_t exec_env, double val, char *buf, uint32_t bufLen) {
41 0 : return string::_dtoa(val, buf, bufLen);
42 : }
43 :
44 0 : static uint32_t StapplerCoreDtoaU16(wasm_exec_env_t exec_env, double val, char16_t *buf, uint32_t bufLen) {
45 0 : return string::_dtoa(val, buf, bufLen);
46 : }
47 :
48 0 : static uint32_t StapplerCoreDtoaLen(wasm_exec_env_t exec_env, double val) {
49 0 : return string::_dtoa_len(val);
50 : }
51 :
52 25 : static void StapplerCoreToUtf16(wasm_exec_env_t exec_env, char *ptr, uint32_t size, ListOutput *outputData) {
53 25 : auto env = ExecEnv::get(exec_env);
54 25 : auto sourceString = StringView(ptr, size);
55 :
56 25 : const auto outSize = string::getUtf16Length(sourceString);
57 :
58 25 : char16_t *outStringBuffer = nullptr;
59 25 : auto outOffset = env->allocate(outSize * sizeof(char16_t), &outStringBuffer);
60 :
61 25 : auto targetBuf = outStringBuffer;
62 :
63 25 : uint8_t offset = 0;
64 25 : auto sourcePtr = sourceString.data();
65 25 : auto end = sourcePtr + sourceString.size();
66 500 : while (sourcePtr < end) {
67 475 : auto c = unicode::utf8Decode32(sourcePtr, offset);
68 475 : targetBuf += unicode::utf16EncodeBuf(targetBuf, c);
69 475 : sourcePtr += offset;
70 : }
71 :
72 25 : outputData->ptr = outOffset;
73 25 : outputData->len = outSize;
74 25 : }
75 :
76 25 : static void StapplerCoreToUtf8(wasm_exec_env_t exec_env, char16_t *ptr, uint32_t size, ListOutput *outputData) {
77 25 : auto env = ExecEnv::get(exec_env);
78 25 : auto sourceString = WideStringView(ptr, size);
79 :
80 25 : const auto outSize = string::getUtf8Length(sourceString);
81 :
82 25 : char *outStringBuffer = nullptr;
83 25 : auto outOffset = env->allocate(outSize * sizeof(char), &outStringBuffer);
84 :
85 25 : auto targetBuf = outStringBuffer;
86 :
87 : uint8_t offset;
88 25 : auto sourcePtr = sourceString.data();
89 25 : auto end = sourcePtr + sourceString.size();
90 500 : while (sourcePtr < end) {
91 475 : auto c = unicode::utf16Decode32(sourcePtr, offset);
92 475 : targetBuf += unicode::utf8EncodeBuf(targetBuf, c);
93 475 : sourcePtr += offset;
94 : }
95 :
96 25 : outputData->ptr = outOffset;
97 25 : outputData->len = outSize;
98 25 : }
99 :
100 : template <typename Char>
101 75 : static void StapplerCoreConvertCase(wasm_exec_env_t exec_env, Char *ptr, uint32_t size, ListOutput *outputData,
102 : const Callback<std::basic_string<Char>(StringViewBase<Char>)> &cb) {
103 75 : auto env = ExecEnv::get(exec_env);
104 75 : auto sourceString = StringViewBase<Char>(ptr, size);
105 :
106 75 : auto outString = cb(sourceString);
107 :
108 75 : char *outStringBuffer = nullptr;
109 75 : auto outOffset = env->allocate(outString.size() * sizeof(Char), &outStringBuffer);
110 :
111 75 : memcpy(outStringBuffer, outString.data(), outString.size() * sizeof(Char));
112 :
113 75 : outputData->ptr = outOffset;
114 75 : outputData->len = outString.size();
115 75 : }
116 :
117 25 : static void StapplerCoreToUpperU8(wasm_exec_env_t exec_env, char *ptr, uint32_t size, ListOutput *target) {
118 25 : StapplerCoreConvertCase<char>(exec_env, ptr, size, target, [] (StringView str) {
119 25 : return platform::toupper<Interface>(str);
120 : });
121 25 : }
122 :
123 25 : static void StapplerCoreToLowerU8(wasm_exec_env_t exec_env, char *ptr, uint32_t size, ListOutput *target) {
124 25 : StapplerCoreConvertCase<char>(exec_env, ptr, size, target, [] (StringView str) {
125 25 : return platform::tolower<Interface>(str);
126 : });
127 25 : }
128 :
129 25 : static void StapplerCoreToTitleU8(wasm_exec_env_t exec_env, char *ptr, uint32_t size, ListOutput *target) {
130 25 : StapplerCoreConvertCase<char>(exec_env, ptr, size, target, [] (StringView str) {
131 25 : return platform::totitle<Interface>(str);
132 : });
133 25 : }
134 :
135 0 : static void StapplerCoreToUpperU16(wasm_exec_env_t exec_env, char16_t *ptr, uint32_t size, ListOutput *target) {
136 0 : StapplerCoreConvertCase<char16_t>(exec_env, ptr, size, target, [] (WideStringView str) {
137 0 : return platform::toupper<Interface>(str);
138 : });
139 0 : }
140 :
141 0 : static void StapplerCoreToLowerU16(wasm_exec_env_t exec_env, char16_t *ptr, uint32_t size, ListOutput *target) {
142 0 : StapplerCoreConvertCase<char16_t>(exec_env, ptr, size, target, [] (WideStringView str) {
143 0 : return platform::tolower<Interface>(str);
144 : });
145 0 : }
146 :
147 0 : static void StapplerCoreToTitleU16(wasm_exec_env_t exec_env, char16_t *ptr, uint32_t size, ListOutput *target) {
148 0 : StapplerCoreConvertCase<char16_t>(exec_env, ptr, size, target, [] (WideStringView str) {
149 0 : return platform::totitle<Interface>(str);
150 : });
151 0 : }
152 :
153 25 : static uint64_t StapplerCoreTimeNow(wasm_exec_env_t exec_env) {
154 25 : return Time::now().toMicros();
155 : }
156 :
157 175 : static uint32_t StapplerCoreTimeToHttp(wasm_exec_env_t exec_env, uint64_t t, char *buf, uint32_t size) {
158 175 : if (size < 30) {
159 0 : return 0;
160 : }
161 :
162 175 : sp_time_exp_t xt(t);
163 175 : return xt.encodeRfc822(buf);
164 : }
165 :
166 0 : static uint32_t StapplerCoreTimeToAtomXml(wasm_exec_env_t exec_env, uint64_t t, char *buf, uint32_t size) {
167 0 : if (size < 21) {
168 0 : return 0;
169 : }
170 :
171 0 : sp_time_exp_t xt(t, false);
172 0 : return xt.encodeIso8601(buf, 0);
173 : }
174 :
175 0 : static uint32_t StapplerCoreTimeToCTime(wasm_exec_env_t exec_env, uint64_t t, char *buf, uint32_t size) {
176 0 : if (size < 25) {
177 0 : return 0;
178 : }
179 :
180 0 : sp_time_exp_t xt(t, true);
181 0 : return xt.encodeCTime(buf);
182 : }
183 :
184 0 : static uint32_t StapplerCoreTimeToIso8601(wasm_exec_env_t exec_env, uint64_t t, uint32_t precision, char *buf, uint32_t size) {
185 0 : if (size < 22 + precision) {
186 0 : return 0;
187 : }
188 :
189 0 : sp_time_exp_t xt(t, true);
190 0 : return xt.encodeIso8601(buf, precision);
191 : }
192 :
193 0 : static uint32_t StapplerCoreTimeToFormat(wasm_exec_env_t exec_env, uint64_t t, char *fmt, uint32_t fmtLen, char *buf, uint32_t bufLen) {
194 0 : return Time(t).encodeToFormat(buf, bufLen, fmt);
195 : }
196 :
197 : static NativeSymbol stapper_core_symbols[] = {
198 : NativeSymbol{"itoa-u8", (void *)&StapplerCoreItoaU8, "(I*~)i", NULL},
199 : NativeSymbol{"itoa-u16", (void *)&StapplerCoreItoaU16, "(I*~)i", NULL},
200 : NativeSymbol{"itoa-len", (void *)&StapplerCoreItoaLen, "(I)i", NULL},
201 :
202 : NativeSymbol{"dtoa-u8", (void *)&StapplerCoreDtoaU8, "(F*~)i", NULL},
203 : NativeSymbol{"dtoa-u16", (void *)&StapplerCoreDtoaU16, "(F*~)i", NULL},
204 : NativeSymbol{"dtoa-len", (void *)&StapplerCoreDtoaLen, "(F)i", NULL},
205 :
206 : NativeSymbol{"to-utf16", (void *)&StapplerCoreToUtf16, "(*~*)", NULL},
207 : NativeSymbol{"to-utf8", (void *)&StapplerCoreToUtf8, "(*i*)", NULL},
208 :
209 : NativeSymbol{"toupper-u8", (void *)&StapplerCoreToUpperU8, "(*~*)", NULL},
210 : NativeSymbol{"tolower-u8", (void *)&StapplerCoreToLowerU8, "(*~*)", NULL},
211 : NativeSymbol{"totitle-u8", (void *)&StapplerCoreToTitleU8, "(*~*)", NULL},
212 :
213 : NativeSymbol{"toupper-u16", (void *)&StapplerCoreToUpperU16, "(*i*)", NULL},
214 : NativeSymbol{"tolower-u16", (void *)&StapplerCoreToLowerU16, "(*i*)", NULL},
215 : NativeSymbol{"totitle-u16", (void *)&StapplerCoreToTitleU16, "(*i*)", NULL},
216 :
217 : NativeSymbol{"time-now", (void *)&StapplerCoreTimeNow, "()I", NULL},
218 : NativeSymbol{"time-to-http", (void *)&StapplerCoreTimeToHttp, "(I*~)i", NULL},
219 : NativeSymbol{"time-to-atom-xml", (void *)&StapplerCoreTimeToAtomXml, "((I*~)i", NULL},
220 : NativeSymbol{"time-to-rfc822", (void *)&StapplerCoreTimeToHttp, "(I*~)i", NULL},
221 : NativeSymbol{"time-to-ctime", (void *)&StapplerCoreTimeToCTime, "((I*~)i", NULL},
222 : NativeSymbol{"time-to-iso8601", (void *)&StapplerCoreTimeToIso8601, "((Ii*~)i", NULL},
223 : NativeSymbol{"time-to-format", (void *)&StapplerCoreTimeToFormat, "((I*~*~)i", NULL},
224 : };
225 :
226 : static NativeModule s_coreModule("stappler:wasm/core", stapper_core_symbols, sizeof(stapper_core_symbols) / sizeof(NativeSymbol));
227 :
228 : }
|