@fugood/llama.node 0.0.1-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (204) hide show
  1. package/CMakeLists.txt +85 -0
  2. package/README.md +56 -0
  3. package/bin/darwin/arm64/llama-node.node +0 -0
  4. package/bin/darwin/x64/llama-node.node +0 -0
  5. package/bin/linux/arm64/llama-node.node +0 -0
  6. package/bin/linux/x64/llama-node.node +0 -0
  7. package/bin/win32/arm64/llama-node.node +0 -0
  8. package/bin/win32/arm64/node.lib +0 -0
  9. package/bin/win32/x64/llama-node.node +0 -0
  10. package/bin/win32/x64/node.lib +0 -0
  11. package/lib/binding.js +13 -0
  12. package/lib/binding.ts +57 -0
  13. package/lib/index.js +24 -0
  14. package/lib/index.ts +13 -0
  15. package/package.json +65 -0
  16. package/src/addons.cpp +506 -0
  17. package/src/llama.cpp/CMakeLists.txt +1320 -0
  18. package/src/llama.cpp/build.zig +172 -0
  19. package/src/llama.cpp/cmake/FindSIMD.cmake +100 -0
  20. package/src/llama.cpp/common/CMakeLists.txt +87 -0
  21. package/src/llama.cpp/common/base64.hpp +392 -0
  22. package/src/llama.cpp/common/common.cpp +2949 -0
  23. package/src/llama.cpp/common/common.h +324 -0
  24. package/src/llama.cpp/common/console.cpp +501 -0
  25. package/src/llama.cpp/common/console.h +19 -0
  26. package/src/llama.cpp/common/grammar-parser.cpp +440 -0
  27. package/src/llama.cpp/common/grammar-parser.h +29 -0
  28. package/src/llama.cpp/common/json-schema-to-grammar.cpp +764 -0
  29. package/src/llama.cpp/common/json-schema-to-grammar.h +4 -0
  30. package/src/llama.cpp/common/json.hpp +24766 -0
  31. package/src/llama.cpp/common/log.h +724 -0
  32. package/src/llama.cpp/common/ngram-cache.cpp +282 -0
  33. package/src/llama.cpp/common/ngram-cache.h +94 -0
  34. package/src/llama.cpp/common/sampling.cpp +353 -0
  35. package/src/llama.cpp/common/sampling.h +147 -0
  36. package/src/llama.cpp/common/stb_image.h +8396 -0
  37. package/src/llama.cpp/common/train.cpp +1513 -0
  38. package/src/llama.cpp/common/train.h +233 -0
  39. package/src/llama.cpp/examples/CMakeLists.txt +52 -0
  40. package/src/llama.cpp/examples/baby-llama/CMakeLists.txt +5 -0
  41. package/src/llama.cpp/examples/baby-llama/baby-llama.cpp +1640 -0
  42. package/src/llama.cpp/examples/batched/CMakeLists.txt +5 -0
  43. package/src/llama.cpp/examples/batched/batched.cpp +262 -0
  44. package/src/llama.cpp/examples/batched-bench/CMakeLists.txt +5 -0
  45. package/src/llama.cpp/examples/batched-bench/batched-bench.cpp +261 -0
  46. package/src/llama.cpp/examples/beam-search/CMakeLists.txt +5 -0
  47. package/src/llama.cpp/examples/beam-search/beam-search.cpp +188 -0
  48. package/src/llama.cpp/examples/benchmark/CMakeLists.txt +6 -0
  49. package/src/llama.cpp/examples/benchmark/benchmark-matmult.cpp +275 -0
  50. package/src/llama.cpp/examples/convert-llama2c-to-ggml/CMakeLists.txt +5 -0
  51. package/src/llama.cpp/examples/convert-llama2c-to-ggml/convert-llama2c-to-ggml.cpp +936 -0
  52. package/src/llama.cpp/examples/embedding/CMakeLists.txt +5 -0
  53. package/src/llama.cpp/examples/embedding/embedding.cpp +211 -0
  54. package/src/llama.cpp/examples/eval-callback/CMakeLists.txt +9 -0
  55. package/src/llama.cpp/examples/eval-callback/eval-callback.cpp +195 -0
  56. package/src/llama.cpp/examples/export-lora/CMakeLists.txt +5 -0
  57. package/src/llama.cpp/examples/export-lora/export-lora.cpp +462 -0
  58. package/src/llama.cpp/examples/finetune/CMakeLists.txt +5 -0
  59. package/src/llama.cpp/examples/finetune/finetune.cpp +1861 -0
  60. package/src/llama.cpp/examples/gbnf-validator/CMakeLists.txt +5 -0
  61. package/src/llama.cpp/examples/gbnf-validator/gbnf-validator.cpp +132 -0
  62. package/src/llama.cpp/examples/gguf/CMakeLists.txt +5 -0
  63. package/src/llama.cpp/examples/gguf/gguf.cpp +256 -0
  64. package/src/llama.cpp/examples/gguf-split/CMakeLists.txt +5 -0
  65. package/src/llama.cpp/examples/gguf-split/gguf-split.cpp +553 -0
  66. package/src/llama.cpp/examples/gritlm/CMakeLists.txt +5 -0
  67. package/src/llama.cpp/examples/gritlm/gritlm.cpp +215 -0
  68. package/src/llama.cpp/examples/imatrix/CMakeLists.txt +5 -0
  69. package/src/llama.cpp/examples/imatrix/imatrix.cpp +655 -0
  70. package/src/llama.cpp/examples/infill/CMakeLists.txt +5 -0
  71. package/src/llama.cpp/examples/infill/infill.cpp +767 -0
  72. package/src/llama.cpp/examples/jeopardy/questions.txt +100 -0
  73. package/src/llama.cpp/examples/llama-bench/CMakeLists.txt +5 -0
  74. package/src/llama.cpp/examples/llama-bench/llama-bench.cpp +1286 -0
  75. package/src/llama.cpp/examples/llama.android/app/src/main/cpp/CMakeLists.txt +50 -0
  76. package/src/llama.cpp/examples/llama.android/app/src/main/cpp/llama-android.cpp +443 -0
  77. package/src/llama.cpp/examples/llava/CMakeLists.txt +37 -0
  78. package/src/llama.cpp/examples/llava/clip.cpp +2027 -0
  79. package/src/llama.cpp/examples/llava/clip.h +85 -0
  80. package/src/llama.cpp/examples/llava/llava-cli.cpp +309 -0
  81. package/src/llama.cpp/examples/llava/llava.cpp +426 -0
  82. package/src/llama.cpp/examples/llava/llava.h +50 -0
  83. package/src/llama.cpp/examples/llava/requirements.txt +3 -0
  84. package/src/llama.cpp/examples/lookahead/CMakeLists.txt +5 -0
  85. package/src/llama.cpp/examples/lookahead/lookahead.cpp +485 -0
  86. package/src/llama.cpp/examples/lookup/CMakeLists.txt +23 -0
  87. package/src/llama.cpp/examples/lookup/lookup-create.cpp +41 -0
  88. package/src/llama.cpp/examples/lookup/lookup-merge.cpp +47 -0
  89. package/src/llama.cpp/examples/lookup/lookup-stats.cpp +160 -0
  90. package/src/llama.cpp/examples/lookup/lookup.cpp +258 -0
  91. package/src/llama.cpp/examples/main/CMakeLists.txt +5 -0
  92. package/src/llama.cpp/examples/main/main.cpp +957 -0
  93. package/src/llama.cpp/examples/main-cmake-pkg/CMakeLists.txt +33 -0
  94. package/src/llama.cpp/examples/parallel/CMakeLists.txt +5 -0
  95. package/src/llama.cpp/examples/parallel/parallel.cpp +427 -0
  96. package/src/llama.cpp/examples/passkey/CMakeLists.txt +5 -0
  97. package/src/llama.cpp/examples/passkey/passkey.cpp +302 -0
  98. package/src/llama.cpp/examples/perplexity/CMakeLists.txt +5 -0
  99. package/src/llama.cpp/examples/perplexity/perplexity.cpp +1943 -0
  100. package/src/llama.cpp/examples/quantize/CMakeLists.txt +6 -0
  101. package/src/llama.cpp/examples/quantize/quantize.cpp +423 -0
  102. package/src/llama.cpp/examples/quantize-stats/CMakeLists.txt +6 -0
  103. package/src/llama.cpp/examples/quantize-stats/quantize-stats.cpp +424 -0
  104. package/src/llama.cpp/examples/retrieval/CMakeLists.txt +5 -0
  105. package/src/llama.cpp/examples/retrieval/retrieval.cpp +350 -0
  106. package/src/llama.cpp/examples/save-load-state/CMakeLists.txt +5 -0
  107. package/src/llama.cpp/examples/save-load-state/save-load-state.cpp +246 -0
  108. package/src/llama.cpp/examples/server/CMakeLists.txt +40 -0
  109. package/src/llama.cpp/examples/server/bench/requirements.txt +2 -0
  110. package/src/llama.cpp/examples/server/httplib.h +9465 -0
  111. package/src/llama.cpp/examples/server/server.cpp +3826 -0
  112. package/src/llama.cpp/examples/server/tests/requirements.txt +6 -0
  113. package/src/llama.cpp/examples/server/utils.hpp +653 -0
  114. package/src/llama.cpp/examples/simple/CMakeLists.txt +5 -0
  115. package/src/llama.cpp/examples/simple/simple.cpp +183 -0
  116. package/src/llama.cpp/examples/speculative/CMakeLists.txt +5 -0
  117. package/src/llama.cpp/examples/speculative/speculative.cpp +614 -0
  118. package/src/llama.cpp/examples/sycl/CMakeLists.txt +9 -0
  119. package/src/llama.cpp/examples/sycl/ls-sycl-device.cpp +13 -0
  120. package/src/llama.cpp/examples/tokenize/CMakeLists.txt +5 -0
  121. package/src/llama.cpp/examples/tokenize/tokenize.cpp +42 -0
  122. package/src/llama.cpp/examples/train-text-from-scratch/CMakeLists.txt +5 -0
  123. package/src/llama.cpp/examples/train-text-from-scratch/train-text-from-scratch.cpp +1252 -0
  124. package/src/llama.cpp/ggml-alloc.c +985 -0
  125. package/src/llama.cpp/ggml-alloc.h +76 -0
  126. package/src/llama.cpp/ggml-backend-impl.h +141 -0
  127. package/src/llama.cpp/ggml-backend.c +2099 -0
  128. package/src/llama.cpp/ggml-backend.h +233 -0
  129. package/src/llama.cpp/ggml-common.h +1853 -0
  130. package/src/llama.cpp/ggml-cuda.h +43 -0
  131. package/src/llama.cpp/ggml-impl.h +265 -0
  132. package/src/llama.cpp/ggml-kompute.cpp +2006 -0
  133. package/src/llama.cpp/ggml-kompute.h +46 -0
  134. package/src/llama.cpp/ggml-metal.h +66 -0
  135. package/src/llama.cpp/ggml-mpi.c +216 -0
  136. package/src/llama.cpp/ggml-mpi.h +39 -0
  137. package/src/llama.cpp/ggml-opencl.cpp +2301 -0
  138. package/src/llama.cpp/ggml-opencl.h +36 -0
  139. package/src/llama.cpp/ggml-quants.c +12678 -0
  140. package/src/llama.cpp/ggml-quants.h +133 -0
  141. package/src/llama.cpp/ggml-sycl.cpp +17882 -0
  142. package/src/llama.cpp/ggml-sycl.h +49 -0
  143. package/src/llama.cpp/ggml-vulkan-shaders.hpp +69849 -0
  144. package/src/llama.cpp/ggml-vulkan.cpp +6442 -0
  145. package/src/llama.cpp/ggml-vulkan.h +29 -0
  146. package/src/llama.cpp/ggml.c +21819 -0
  147. package/src/llama.cpp/ggml.h +2403 -0
  148. package/src/llama.cpp/llama.cpp +17468 -0
  149. package/src/llama.cpp/llama.h +1117 -0
  150. package/src/llama.cpp/pocs/CMakeLists.txt +12 -0
  151. package/src/llama.cpp/pocs/vdot/CMakeLists.txt +9 -0
  152. package/src/llama.cpp/pocs/vdot/q8dot.cpp +172 -0
  153. package/src/llama.cpp/pocs/vdot/vdot.cpp +310 -0
  154. package/src/llama.cpp/prompts/LLM-questions.txt +49 -0
  155. package/src/llama.cpp/prompts/alpaca.txt +1 -0
  156. package/src/llama.cpp/prompts/assistant.txt +31 -0
  157. package/src/llama.cpp/prompts/chat-with-baichuan.txt +4 -0
  158. package/src/llama.cpp/prompts/chat-with-bob.txt +7 -0
  159. package/src/llama.cpp/prompts/chat-with-qwen.txt +1 -0
  160. package/src/llama.cpp/prompts/chat-with-vicuna-v0.txt +7 -0
  161. package/src/llama.cpp/prompts/chat-with-vicuna-v1.txt +7 -0
  162. package/src/llama.cpp/prompts/chat.txt +28 -0
  163. package/src/llama.cpp/prompts/dan-modified.txt +1 -0
  164. package/src/llama.cpp/prompts/dan.txt +1 -0
  165. package/src/llama.cpp/prompts/mnemonics.txt +93 -0
  166. package/src/llama.cpp/prompts/parallel-questions.txt +43 -0
  167. package/src/llama.cpp/prompts/reason-act.txt +18 -0
  168. package/src/llama.cpp/requirements/requirements-convert-hf-to-gguf.txt +3 -0
  169. package/src/llama.cpp/requirements/requirements-convert-llama-ggml-to-gguf.txt +1 -0
  170. package/src/llama.cpp/requirements/requirements-convert-lora-to-ggml.txt +2 -0
  171. package/src/llama.cpp/requirements/requirements-convert-persimmon-to-gguf.txt +2 -0
  172. package/src/llama.cpp/requirements/requirements-convert.txt +5 -0
  173. package/src/llama.cpp/requirements.txt +12 -0
  174. package/src/llama.cpp/scripts/gen-build-info-cpp.cmake +24 -0
  175. package/src/llama.cpp/scripts/xxd.cmake +16 -0
  176. package/src/llama.cpp/sgemm.cpp +999 -0
  177. package/src/llama.cpp/sgemm.h +12 -0
  178. package/src/llama.cpp/tests/CMakeLists.txt +78 -0
  179. package/src/llama.cpp/tests/get-model.cpp +21 -0
  180. package/src/llama.cpp/tests/get-model.h +2 -0
  181. package/src/llama.cpp/tests/test-autorelease.cpp +24 -0
  182. package/src/llama.cpp/tests/test-backend-ops.cpp +2266 -0
  183. package/src/llama.cpp/tests/test-c.c +7 -0
  184. package/src/llama.cpp/tests/test-chat-template.cpp +107 -0
  185. package/src/llama.cpp/tests/test-double-float.cpp +57 -0
  186. package/src/llama.cpp/tests/test-grad0.cpp +1606 -0
  187. package/src/llama.cpp/tests/test-grammar-integration.cpp +243 -0
  188. package/src/llama.cpp/tests/test-grammar-parser.cpp +250 -0
  189. package/src/llama.cpp/tests/test-json-schema-to-grammar.cpp +899 -0
  190. package/src/llama.cpp/tests/test-llama-grammar.cpp +402 -0
  191. package/src/llama.cpp/tests/test-model-load-cancel.cpp +27 -0
  192. package/src/llama.cpp/tests/test-opt.cpp +181 -0
  193. package/src/llama.cpp/tests/test-quantize-fns.cpp +185 -0
  194. package/src/llama.cpp/tests/test-quantize-perf.cpp +363 -0
  195. package/src/llama.cpp/tests/test-rope.cpp +221 -0
  196. package/src/llama.cpp/tests/test-sampling.cpp +301 -0
  197. package/src/llama.cpp/tests/test-tokenizer-0-falcon.cpp +187 -0
  198. package/src/llama.cpp/tests/test-tokenizer-0-llama.cpp +190 -0
  199. package/src/llama.cpp/tests/test-tokenizer-1-bpe.cpp +123 -0
  200. package/src/llama.cpp/tests/test-tokenizer-1-llama.cpp +111 -0
  201. package/src/llama.cpp/unicode-data.cpp +1651 -0
  202. package/src/llama.cpp/unicode-data.h +16 -0
  203. package/src/llama.cpp/unicode.cpp +277 -0
  204. package/src/llama.cpp/unicode.h +28 -0
@@ -0,0 +1,392 @@
1
+ /*
2
+ This is free and unencumbered software released into the public domain.
3
+
4
+ Anyone is free to copy, modify, publish, use, compile, sell, or
5
+ distribute this software, either in source code form or as a compiled
6
+ binary, for any purpose, commercial or non-commercial, and by any
7
+ means.
8
+
9
+ In jurisdictions that recognize copyright laws, the author or authors
10
+ of this software dedicate any and all copyright interest in the
11
+ software to the public domain. We make this dedication for the benefit
12
+ of the public at large and to the detriment of our heirs and
13
+ successors. We intend this dedication to be an overt act of
14
+ relinquishment in perpetuity of all present and future rights to this
15
+ software under copyright law.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20
+ IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21
+ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23
+ OTHER DEALINGS IN THE SOFTWARE.
24
+
25
+ For more information, please refer to <http://unlicense.org>
26
+ */
27
+
28
+ #ifndef PUBLIC_DOMAIN_BASE64_HPP_
29
+ #define PUBLIC_DOMAIN_BASE64_HPP_
30
+
31
+ #include <cstdint>
32
+ #include <iterator>
33
+ #include <stdexcept>
34
+ #include <string>
35
+
36
+ class base64_error : public std::runtime_error
37
+ {
38
+ public:
39
+ using std::runtime_error::runtime_error;
40
+ };
41
+
42
+ class base64
43
+ {
44
+ public:
45
+ enum class alphabet
46
+ {
47
+ /** the alphabet is detected automatically */
48
+ auto_,
49
+ /** the standard base64 alphabet is used */
50
+ standard,
51
+ /** like `standard` except that the characters `+` and `/` are replaced by `-` and `_` respectively*/
52
+ url_filename_safe
53
+ };
54
+
55
+ enum class decoding_behavior
56
+ {
57
+ /** if the input is not padded, the remaining bits are ignored */
58
+ moderate,
59
+ /** if a padding character is encounter decoding is finished */
60
+ loose
61
+ };
62
+
63
+ /**
64
+ Encodes all the elements from `in_begin` to `in_end` to `out`.
65
+
66
+ @warning The source and destination cannot overlap. The destination must be able to hold at least
67
+ `required_encode_size(std::distance(in_begin, in_end))`, otherwise the behavior depends on the output iterator.
68
+
69
+ @tparam Input_iterator the source; the returned elements are cast to `std::uint8_t` and should not be greater than
70
+ 8 bits
71
+ @tparam Output_iterator the destination; the elements written to it are from the type `char`
72
+ @param in_begin the beginning of the source
73
+ @param in_end the ending of the source
74
+ @param out the destination iterator
75
+ @param alphabet which alphabet should be used
76
+ @returns the iterator to the next element past the last element copied
77
+ @throws see `Input_iterator` and `Output_iterator`
78
+ */
79
+ template<typename Input_iterator, typename Output_iterator>
80
+ static Output_iterator encode(Input_iterator in_begin, Input_iterator in_end, Output_iterator out,
81
+ alphabet alphabet = alphabet::standard)
82
+ {
83
+ constexpr auto pad = '=';
84
+ const char* alpha = alphabet == alphabet::url_filename_safe
85
+ ? "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
86
+ : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
87
+
88
+ while (in_begin != in_end) {
89
+ std::uint8_t i0 = 0, i1 = 0, i2 = 0;
90
+
91
+ // first character
92
+ i0 = static_cast<std::uint8_t>(*in_begin);
93
+ ++in_begin;
94
+
95
+ *out = alpha[i0 >> 2 & 0x3f];
96
+ ++out;
97
+
98
+ // part of first character and second
99
+ if (in_begin != in_end) {
100
+ i1 = static_cast<std::uint8_t>(*in_begin);
101
+ ++in_begin;
102
+
103
+ *out = alpha[((i0 & 0x3) << 4) | (i1 >> 4 & 0x0f)];
104
+ ++out;
105
+ } else {
106
+ *out = alpha[(i0 & 0x3) << 4];
107
+ ++out;
108
+
109
+ // last padding
110
+ *out = pad;
111
+ ++out;
112
+
113
+ // last padding
114
+ *out = pad;
115
+ ++out;
116
+
117
+ break;
118
+ }
119
+
120
+ // part of second character and third
121
+ if (in_begin != in_end) {
122
+ i2 = static_cast<std::uint8_t>(*in_begin);
123
+ ++in_begin;
124
+
125
+ *out = alpha[((i1 & 0xf) << 2) | (i2 >> 6 & 0x03)];
126
+ ++out;
127
+ } else {
128
+ *out = alpha[(i1 & 0xf) << 2];
129
+ ++out;
130
+
131
+ // last padding
132
+ *out = pad;
133
+ ++out;
134
+
135
+ break;
136
+ }
137
+
138
+ // rest of third
139
+ *out = alpha[i2 & 0x3f];
140
+ ++out;
141
+ }
142
+
143
+ return out;
144
+ }
145
+ /**
146
+ Encodes a string.
147
+
148
+ @param str the string that should be encoded
149
+ @param alphabet which alphabet should be used
150
+ @returns the encoded base64 string
151
+ @throws see base64::encode()
152
+ */
153
+ static std::string encode(const std::string& str, alphabet alphabet = alphabet::standard)
154
+ {
155
+ std::string result;
156
+
157
+ result.reserve(required_encode_size(str.length()) + 1);
158
+
159
+ encode(str.begin(), str.end(), std::back_inserter(result), alphabet);
160
+
161
+ return result;
162
+ }
163
+ /**
164
+ Encodes a char array.
165
+
166
+ @param buffer the char array
167
+ @param size the size of the array
168
+ @param alphabet which alphabet should be used
169
+ @returns the encoded string
170
+ */
171
+ static std::string encode(const char* buffer, std::size_t size, alphabet alphabet = alphabet::standard)
172
+ {
173
+ std::string result;
174
+
175
+ result.reserve(required_encode_size(size) + 1);
176
+
177
+ encode(buffer, buffer + size, std::back_inserter(result), alphabet);
178
+
179
+ return result;
180
+ }
181
+ /**
182
+ Decodes all the elements from `in_begin` to `in_end` to `out`. `in_begin` may point to the same location as `out`,
183
+ in other words: inplace decoding is possible.
184
+
185
+ @warning The destination must be able to hold at least `required_decode_size(std::distance(in_begin, in_end))`,
186
+ otherwise the behavior depends on the output iterator.
187
+
188
+ @tparam Input_iterator the source; the returned elements are cast to `char`
189
+ @tparam Output_iterator the destination; the elements written to it are from the type `std::uint8_t`
190
+ @param in_begin the beginning of the source
191
+ @param in_end the ending of the source
192
+ @param out the destination iterator
193
+ @param alphabet which alphabet should be used
194
+ @param behavior the behavior when an error was detected
195
+ @returns the iterator to the next element past the last element copied
196
+ @throws base64_error depending on the set behavior
197
+ @throws see `Input_iterator` and `Output_iterator`
198
+ */
199
+ template<typename Input_iterator, typename Output_iterator>
200
+ static Output_iterator decode(Input_iterator in_begin, Input_iterator in_end, Output_iterator out,
201
+ alphabet alphabet = alphabet::auto_,
202
+ decoding_behavior behavior = decoding_behavior::moderate)
203
+ {
204
+ //constexpr auto pad = '=';
205
+ std::uint8_t last = 0;
206
+ auto bits = 0;
207
+
208
+ while (in_begin != in_end) {
209
+ auto c = *in_begin;
210
+ ++in_begin;
211
+
212
+ if (c == '=') {
213
+ break;
214
+ }
215
+
216
+ auto part = _base64_value(alphabet, c);
217
+
218
+ // enough bits for one byte
219
+ if (bits + 6 >= 8) {
220
+ *out = (last << (8 - bits)) | (part >> (bits - 2));
221
+ ++out;
222
+
223
+ bits -= 2;
224
+ } else {
225
+ bits += 6;
226
+ }
227
+
228
+ last = part;
229
+ }
230
+
231
+ // check padding
232
+ if (behavior != decoding_behavior::loose) {
233
+ while (in_begin != in_end) {
234
+ auto c = *in_begin;
235
+ ++in_begin;
236
+
237
+ if (c != '=') {
238
+ throw base64_error("invalid base64 character.");
239
+ }
240
+ }
241
+ }
242
+
243
+ return out;
244
+ }
245
+ /**
246
+ Decodes a string.
247
+
248
+ @param str the base64 encoded string
249
+ @param alphabet which alphabet should be used
250
+ @param behavior the behavior when an error was detected
251
+ @returns the decoded string
252
+ @throws see base64::decode()
253
+ */
254
+ static std::string decode(const std::string& str, alphabet alphabet = alphabet::auto_,
255
+ decoding_behavior behavior = decoding_behavior::moderate)
256
+ {
257
+ std::string result;
258
+
259
+ result.reserve(max_decode_size(str.length()));
260
+
261
+ decode(str.begin(), str.end(), std::back_inserter(result), alphabet, behavior);
262
+
263
+ return result;
264
+ }
265
+ /**
266
+ Decodes a string.
267
+
268
+ @param buffer the base64 encoded buffer
269
+ @param size the size of the buffer
270
+ @param alphabet which alphabet should be used
271
+ @param behavior the behavior when an error was detected
272
+ @returns the decoded string
273
+ @throws see base64::decode()
274
+ */
275
+ static std::string decode(const char* buffer, std::size_t size, alphabet alphabet = alphabet::auto_,
276
+ decoding_behavior behavior = decoding_behavior::moderate)
277
+ {
278
+ std::string result;
279
+
280
+ result.reserve(max_decode_size(size));
281
+
282
+ decode(buffer, buffer + size, std::back_inserter(result), alphabet, behavior);
283
+
284
+ return result;
285
+ }
286
+ /**
287
+ Decodes a string inplace.
288
+
289
+ @param[in,out] str the base64 encoded string
290
+ @param alphabet which alphabet should be used
291
+ @param behavior the behavior when an error was detected
292
+ @throws base64::decode_inplace()
293
+ */
294
+ static void decode_inplace(std::string& str, alphabet alphabet = alphabet::auto_,
295
+ decoding_behavior behavior = decoding_behavior::moderate)
296
+ {
297
+ str.resize(decode(str.begin(), str.end(), str.begin(), alphabet, behavior) - str.begin());
298
+ }
299
+ /**
300
+ Decodes a char array inplace.
301
+
302
+ @param[in,out] str the string array
303
+ @param size the length of the array
304
+ @param alphabet which alphabet should be used
305
+ @param behavior the behavior when an error was detected
306
+ @returns the pointer to the next element past the last element decoded
307
+ @throws base64::decode_inplace()
308
+ */
309
+ static char* decode_inplace(char* str, std::size_t size, alphabet alphabet = alphabet::auto_,
310
+ decoding_behavior behavior = decoding_behavior::moderate)
311
+ {
312
+ return decode(str, str + size, str, alphabet, behavior);
313
+ }
314
+ /**
315
+ Returns the required decoding size for a given size. The value is calculated with the following formula:
316
+
317
+ $$
318
+ \lceil \frac{size}{4} \rceil \cdot 3
319
+ $$
320
+
321
+ @param size the size of the encoded input
322
+ @returns the size of the resulting decoded buffer; this the absolute maximum
323
+ */
324
+ static std::size_t max_decode_size(std::size_t size) noexcept
325
+ {
326
+ return (size / 4 + (size % 4 ? 1 : 0)) * 3;
327
+ }
328
+ /**
329
+ Returns the required encoding size for a given size. The value is calculated with the following formula:
330
+
331
+ $$
332
+ \lceil \frac{size}{3} \rceil \cdot 4
333
+ $$
334
+
335
+ @param size the size of the decoded input
336
+ @returns the size of the resulting encoded buffer
337
+ */
338
+ static std::size_t required_encode_size(std::size_t size) noexcept
339
+ {
340
+ return (size / 3 + (size % 3 ? 1 : 0)) * 4;
341
+ }
342
+
343
+ private:
344
+ static std::uint8_t _base64_value(alphabet& alphabet, char c)
345
+ {
346
+ if (c >= 'A' && c <= 'Z') {
347
+ return c - 'A';
348
+ } else if (c >= 'a' && c <= 'z') {
349
+ return c - 'a' + 26;
350
+ } else if (c >= '0' && c <= '9') {
351
+ return c - '0' + 52;
352
+ }
353
+
354
+ // comes down to alphabet
355
+ if (alphabet == alphabet::standard) {
356
+ if (c == '+') {
357
+ return 62;
358
+ } else if (c == '/') {
359
+ return 63;
360
+ }
361
+ } else if (alphabet == alphabet::url_filename_safe) {
362
+ if (c == '-') {
363
+ return 62;
364
+ } else if (c == '_') {
365
+ return 63;
366
+ }
367
+ } // auto detect
368
+ else {
369
+ if (c == '+') {
370
+ alphabet = alphabet::standard;
371
+
372
+ return 62;
373
+ } else if (c == '/') {
374
+ alphabet = alphabet::standard;
375
+
376
+ return 63;
377
+ } else if (c == '-') {
378
+ alphabet = alphabet::url_filename_safe;
379
+
380
+ return 62;
381
+ } else if (c == '_') {
382
+ alphabet = alphabet::url_filename_safe;
383
+
384
+ return 63;
385
+ }
386
+ }
387
+
388
+ throw base64_error("invalid base64 character.");
389
+ }
390
+ };
391
+
392
+ #endif // !PUBLIC_DOMAIN_BASE64_HPP_