├── .gitignore
├── LICENSE
├── README.md
├── pawn.json
├── pawno
└── include
│ └── DeepL.inc
└── plugins
├── DeepL.def
├── DeepL.filters
├── DeepL.sln
├── DeepL.vcxproj
├── DeepL.vcxproj.filters
├── lib
├── json
│ ├── json11.cpp
│ └── json11.hpp
└── sdk
│ ├── amx
│ ├── amx.h
│ ├── getch.h
│ └── sclinux.h
│ ├── amxplugin.cpp
│ ├── plugin.h
│ └── plugincommon.h
├── makefile
└── src
├── cache.cpp
├── cache.h
├── deepl.cpp
├── deepl.h
├── main.cpp
├── main.h
├── natives.cpp
└── natives.h
/.gitignore:
--------------------------------------------------------------------------------
1 | # Linux stuff
2 | *.so
3 | *.o
4 |
5 | ## Ignore Visual Studio temporary files, build results, and
6 | ## files generated by popular Visual Studio add-ons.
7 |
8 | # User-specific files
9 | *.suo
10 | *.user
11 | *.sln.docstates
12 | *.db
13 | *.opendb
14 | *.amx
15 | rus.txt
16 |
17 | # Build results
18 | [Dd]ebug/
19 | [Dd]ebugPublic/
20 | [Rr]elease/
21 | x64/
22 | build/
23 | bld/
24 | [Bb]in/
25 | [Oo]bj/
26 |
27 | # MSTest test Results
28 | [Tt]est[Rr]esult*/
29 | [Bb]uild[Ll]og.*
30 |
31 | #NUNIT
32 | *.VisualState.xml
33 | TestResult.xml
34 |
35 | # Build Results of an ATL Project
36 | [Dd]ebugPS/
37 | [Rr]eleasePS/
38 | dlldata.c
39 |
40 | *_i.c
41 | *_p.c
42 | *_i.h
43 | *.ilk
44 | *.meta
45 | *.obj
46 | *.pch
47 | *.pdb
48 | *.pgc
49 | *.pgd
50 | *.rsp
51 | *.sbr
52 | *.tlb
53 | *.tli
54 | *.tlh
55 | *.tmp
56 | *.tmp_proj
57 | *.log
58 | *.vspscc
59 | *.vssscc
60 | .builds
61 | *.pidb
62 | *.svclog
63 | *.scc
64 |
65 | # Chutzpah Test files
66 | _Chutzpah*
67 |
68 | # Visual C++ cache files
69 | ipch/
70 | *.aps
71 | *.ncb
72 | *.opensdf
73 | *.sdf
74 | *.cachefile
75 |
76 | # Visual Studio profiler
77 | *.psess
78 | *.vsp
79 | *.vspx
80 |
81 | # TFS 2012 Local Workspace
82 | $tf/
83 |
84 | # Guidance Automation Toolkit
85 | *.gpState
86 |
87 | # ReSharper is a .NET coding add-in
88 | _ReSharper*/
89 | *.[Rr]e[Ss]harper
90 | *.DotSettings.user
91 |
92 | # JustCode is a .NET coding addin-in
93 | .JustCode
94 |
95 | # TeamCity is a build add-in
96 | _TeamCity*
97 |
98 | # DotCover is a Code Coverage Tool
99 | *.dotCover
100 |
101 | # NCrunch
102 | *.ncrunch*
103 | _NCrunch_*
104 | .*crunch*.local.xml
105 |
106 | # MightyMoose
107 | *.mm.*
108 | AutoTest.Net/
109 |
110 | # Web workbench (sass)
111 | .sass-cache/
112 |
113 | # Installshield output folder
114 | [Ee]xpress/
115 |
116 | # DocProject is a documentation generator add-in
117 | DocProject/buildhelp/
118 | DocProject/Help/*.HxT
119 | DocProject/Help/*.HxC
120 | DocProject/Help/*.hhc
121 | DocProject/Help/*.hhk
122 | DocProject/Help/*.hhp
123 | DocProject/Help/Html2
124 | DocProject/Help/html
125 |
126 | # Click-Once directory
127 | publish/
128 |
129 | # Publish Web Output
130 | *.[Pp]ublish.xml
131 | *.azurePubxml
132 |
133 | # NuGet Packages Directory
134 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line
135 | #packages/*
136 | ## TODO: If the tool you use requires repositories.config, also uncomment the next line
137 | #!packages/repositories.config
138 |
139 | # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets
140 | # This line needs to be after the ignore of the build folder (and the packages folder if the line above has been uncommented)
141 | !packages/build/
142 |
143 | # Windows Azure Build Output
144 | csx/
145 | *.build.csdef
146 |
147 | # Windows Store app package directory
148 | AppPackages/
149 |
150 | # Others
151 | sql/
152 | *.Cache
153 | ClientBin/
154 | [Ss]tyle[Cc]op.*
155 | ~$*
156 | *~
157 | *.dbmdl
158 | *.dbproj.schemaview
159 | *.pfx
160 | *.publishsettings
161 | node_modules/
162 |
163 | # RIA/Silverlight projects
164 | Generated_Code/
165 |
166 | # Backup & report files from converting an old project file to a newer
167 | # Visual Studio version. Backup files are not needed, because we have git ;-)
168 | _UpgradeReport_Files/
169 | Backup*/
170 | UpgradeLog*.XML
171 | UpgradeLog*.htm
172 |
173 | # SQL Server files
174 | *.mdf
175 | *.ldf
176 |
177 | # Business Intelligence projects
178 | *.rdl.data
179 | *.bim.layout
180 | *.bim_*.settings
181 |
182 | # Microsoft Fakes
183 | FakesAssemblies/
184 |
185 | # =========================
186 | # Windows detritus
187 | # =========================
188 |
189 | # Windows image file caches
190 | Thumbs.db
191 | ehthumbs.db
192 |
193 | # Folder config file
194 | Desktop.ini
195 |
196 | # Recycle Bin used on file shares
197 | $RECYCLE.BIN/
198 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2022 IS4
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | DeepL Plugin v1.3
2 | ==========
3 |
4 | This plugin adds integration for the [DeepL Translate API](https://developers.deepl.com/docs/api-reference/translate). To use the plugin, you have to provide your [DeepL authentication key](https://developers.deepl.com/docs/getting-started/auth#authentication).
5 |
6 | *There are no warranties nor support for the quality of the translation, which is handled purely by DeepL and system-defined locale conversions.*
7 |
8 | ## Usage
9 |
10 | Before requesting translation, call `DeepL_SetAuthKey` to set your authentication key:
11 | ```pawn
12 | DeepL_SetAuthKey("cbae67e8-63cd-4f7f-a0c9-a2a32905679d:fx"); // example key
13 | ```
14 |
15 | To request translation via the API, call `DeepL_Translate`:
16 | ```pawn
17 | native DeepL_Translate(
18 | const text[], // the text to translate
19 | const from[], // the source language and encoding
20 | const to[], // the target language and encoding
21 | const callback[] = #DeepL_OnTranslationDone, // the callback to invoke when translation is ready
22 | cookie = 0, // the cookie to pass to callback
23 | bool:preserve_formatting = true, // see the DeepL API for description of these parameters
24 | const tag_handling[] = "",
25 | const formality[] = "",
26 | const split_sentences[] = ""
27 | );
28 | ```
29 |
30 | The function returns `0` on success.
31 |
32 | The callback function is in this form:
33 | ```pawn
34 | forward bool:DeepL_OnTranslationDone(
35 | bool:success, // whether translation was produced or not
36 | result[], // if success, the translated text, otherwise the error message
37 | from[], // the detected source language
38 | cookie // cookie passed to DeepL_Translate
39 | );
40 | ```
41 |
42 | If the returned value is `true` and the text was successfully translated, the result is cached.
43 |
44 | ### Specifying language
45 |
46 | The value of `from` and `to` is in the form *language*:*locales*
, where *locales*
is a `|`-separated list of locale names (see [`std::locale`](https://en.cppreference.com/w/cpp/locale/locale/locale) for more description). If the first locale name is not found, it tries the second one, and so forth.
47 |
48 | On POSIX systems, you may use `locale -a` to list the existing locale names. On Unix, it is possible to define a custom locale using the [`localedef` command](https://man7.org/linux/man-pages/man1/localedef.1.html). For example, to define the locale `en_US.CP1250`, you could use `localedef -i en_US -f CP1250 'en_US.CP1250'` which you can then use as the argument in the form `"en:en_US.CP1250|.1250"`. On Windows, .*codepage*
can be used directly for a locale based on a particular codepage.
49 |
50 | The locales may be omitted altogether, in which case UTF-8 will be used for `text`/`result`.
51 |
52 | ### Caching
53 |
54 | Successful responses from DeepL are cached in the file `scriptfiles/deepl_cache.txt`. This file is composed of alternating key-value lines, where the key is formed from the API parameters, and value is the encoded JSON response.
55 |
56 | The cache file is written after every translation, when `true` is returned from the callback. It may also be modified freely to change the particular translations. If the file is modified on-the-fly while the server is running, call `DeepL_LoadCache` to reload it.
57 |
58 | ## Installation
59 | Download the latest [release](//github.com/IS4Code/Pawn-DeepL/releases/latest) for your platform to the "plugins" directory and add "DeepL" (or "DeepL.so" on Linux) to the `plugins` line in server.cfg.
60 |
61 | Include [DeepL.inc](pawno/include/DeepL.inc) in your Pawn program and you are done.
62 |
63 | ## Building
64 | Use Visual Studio to build the project on Windows, or `make` or `make static` on Linux. Requires GCC >= 4.9 and [cURL](https://curl.se/docs/install.html) to be installed.
65 |
--------------------------------------------------------------------------------
/pawn.json:
--------------------------------------------------------------------------------
1 | {
2 | "user": "IS4Code",
3 | "repo": "DeepL",
4 | "dependencies": ["sampctl/pawn-stdlib"],
5 | "resources": [
6 | {
7 | "name": "DeepL.dll",
8 | "platform": "windows",
9 | "archive": false
10 | },
11 | {
12 | "name": "DeepL.so",
13 | "platform": "linux",
14 | "archive": false
15 | }
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/pawno/include/DeepL.inc:
--------------------------------------------------------------------------------
1 | /** DeepL v1.3 by IS4 **/
2 | //github.com/IS4Code/Pawn-DeepL
3 |
4 | #if defined _inc_DeepL
5 | #undef _inc_DeepL
6 | #endif
7 | #if defined _DeepL_included
8 | #endinput
9 | #endif
10 | #define _DeepL_included
11 |
12 | forward bool:DeepL_OnTranslationDone(bool:success, result[], from[], cookie);
13 |
14 | native DeepL_SetAuthKey(const key[]);
15 | native DeepL_SetEndpoint(const endpoint_url[]);
16 | native DeepL_Translate(const text[], const from[], const to[], const callback[] = #DeepL_OnTranslationDone, cookie = 0, bool:preserve_formatting = true, const tag_handling[] = "", const formality[] = "", const split_sentences[] = "");
17 | native DeepL_LoadCache();
18 |
--------------------------------------------------------------------------------
/plugins/DeepL.def:
--------------------------------------------------------------------------------
1 | LIBRARY "DeepL"
2 |
3 | EXPORTS
4 | Supports
5 | Load
6 | Unload
7 | AmxLoad
8 | AmxUnload
9 | ProcessTick
--------------------------------------------------------------------------------
/plugins/DeepL.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | lib\subhook
6 |
7 |
8 | lib\sdk
9 |
10 |
11 | src
12 |
13 |
14 | src
15 |
16 |
17 | src
18 |
19 |
20 | src
21 |
22 |
23 | src
24 |
25 |
26 | src
27 |
28 |
29 | src\amx
30 |
31 |
32 | src\lua
33 |
34 |
35 | src\lua
36 |
37 |
38 | src\lua\interop
39 |
40 |
41 | src\lua\interop
42 |
43 |
44 | src\lua\interop
45 |
46 |
47 | src\lua\interop
48 |
49 |
50 | src\lua\interop
51 |
52 |
53 | src\lua\interop
54 |
55 |
56 | src\lua
57 |
58 |
59 | lib\lua
60 |
61 |
62 | lib\lua
63 |
64 |
65 | lib\lua
66 |
67 |
68 | lib\lua
69 |
70 |
71 | lib\lua
72 |
73 |
74 | lib\lua
75 |
76 |
77 | lib\lua
78 |
79 |
80 | lib\lua
81 |
82 |
83 | lib\lua
84 |
85 |
86 | lib\lua
87 |
88 |
89 | lib\lua
90 |
91 |
92 | lib\lua
93 |
94 |
95 | lib\lua
96 |
97 |
98 | lib\lua
99 |
100 |
101 | lib\lua
102 |
103 |
104 | lib\lua
105 |
106 |
107 | lib\lua
108 |
109 |
110 | lib\lua
111 |
112 |
113 | lib\lua
114 |
115 |
116 | lib\lua
117 |
118 |
119 | lib\lua
120 |
121 |
122 | lib\lua
123 |
124 |
125 | lib\lua
126 |
127 |
128 | lib\lua
129 |
130 |
131 | lib\lua
132 |
133 |
134 | lib\lua
135 |
136 |
137 | lib\lua
138 |
139 |
140 | lib\lua
141 |
142 |
143 | lib\lua
144 |
145 |
146 | lib\lua
147 |
148 |
149 | lib\lua
150 |
151 |
152 | lib\lua
153 |
154 |
155 | lib\lua
156 |
157 |
158 | src\lua\interop
159 |
160 |
161 | src\lua\interop
162 |
163 |
164 | src
165 |
166 |
167 |
168 |
169 | lib\subhook
170 |
171 |
172 | lib\subhook
173 |
174 |
175 | lib\subhook
176 |
177 |
178 | lib\subhook
179 |
180 |
181 | lib\subhook
182 |
183 |
184 | lib\subhook
185 |
186 |
187 | lib\sdk
188 |
189 |
190 | lib\sdk
191 |
192 |
193 | lib\sdk\amx
194 |
195 |
196 | lib\sdk\amx
197 |
198 |
199 | lib\sdk\amx
200 |
201 |
202 | src\fixes
203 |
204 |
205 | src
206 |
207 |
208 | src
209 |
210 |
211 | src
212 |
213 |
214 | src\utils
215 |
216 |
217 | src\utils
218 |
219 |
220 | src\utils
221 |
222 |
223 | src\utils
224 |
225 |
226 | src
227 |
228 |
229 | src
230 |
231 |
232 | src
233 |
234 |
235 | src\amx
236 |
237 |
238 | src\lua
239 |
240 |
241 | src\lua
242 |
243 |
244 | src\lua\interop
245 |
246 |
247 | src\lua\interop
248 |
249 |
250 | src\lua\interop
251 |
252 |
253 | src\lua\interop
254 |
255 |
256 | src\lua\interop
257 |
258 |
259 | src\lua\interop
260 |
261 |
262 | src\lua
263 |
264 |
265 | lib\lua
266 |
267 |
268 | lib\lua
269 |
270 |
271 | lib\lua
272 |
273 |
274 | lib\lua
275 |
276 |
277 | lib\lua
278 |
279 |
280 | lib\lua
281 |
282 |
283 | lib\lua
284 |
285 |
286 | lib\lua
287 |
288 |
289 | lib\lua
290 |
291 |
292 | lib\lua
293 |
294 |
295 | lib\lua
296 |
297 |
298 | lib\lua
299 |
300 |
301 | lib\lua
302 |
303 |
304 | lib\lua
305 |
306 |
307 | lib\lua
308 |
309 |
310 | lib\lua
311 |
312 |
313 | lib\lua
314 |
315 |
316 | lib\lua
317 |
318 |
319 | lib\lua
320 |
321 |
322 | lib\lua
323 |
324 |
325 | lib\lua
326 |
327 |
328 | lib\lua
329 |
330 |
331 | lib\lua
332 |
333 |
334 | lib\lua
335 |
336 |
337 | lib\lua
338 |
339 |
340 | lib\lua
341 |
342 |
343 | src\lua
344 |
345 |
346 | src\lua\interop
347 |
348 |
349 | src\lua\interop
350 |
351 |
352 | src
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 | {3d6a091a-259f-4fe8-8bba-120286323d40}
361 |
362 |
363 | {ea02da0c-7d5b-4184-a17e-c9362a2a0219}
364 |
365 |
366 | {d04663e9-3029-49cf-853e-feae3cd594d5}
367 |
368 |
369 | {7516e3ab-581e-47dc-b112-f524e53b8c77}
370 |
371 |
372 | {1013b1a8-51b7-4b2c-aa29-cc2e6607954b}
373 |
374 |
375 | {973f41a2-0716-4217-b2b2-ec5673be5f47}
376 |
377 |
378 | {470fb0f2-8ac6-4cf8-b645-a8820627a0a7}
379 |
380 |
381 | {abd01d7f-1955-4c11-b3f6-2d6a36909315}
382 |
383 |
384 | {d682c4ee-957c-49aa-ae1c-6d01519b1479}
385 |
386 |
387 | {e9e9cdfb-0e46-453d-8029-7abc274bb4a8}
388 |
389 |
390 | {fac941d1-b141-4cde-befa-8bb2283defbe}
391 |
392 |
393 |
--------------------------------------------------------------------------------
/plugins/DeepL.sln:
--------------------------------------------------------------------------------
1 | Microsoft Visual Studio Solution File, Format Version 12.00
2 | # Visual Studio 15
3 | VisualStudioVersion = 15.0.27004.2002
4 | MinimumVisualStudioVersion = 10.0.40219.1
5 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DeepL", "DeepL.vcxproj", "{2F8D97ED-64C2-4F78-A343-3F23C64D1AD5}"
6 | EndProject
7 | Global
8 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
9 | Debug|Any CPU = Debug|Any CPU
10 | Debug|Win32 = Debug|Win32
11 | Release|Any CPU = Release|Any CPU
12 | Release|Win32 = Release|Win32
13 | EndGlobalSection
14 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
15 | {2F8D97ED-64C2-4F78-A343-3F23C64D1AD5}.Debug|Any CPU.ActiveCfg = Debug|Win32
16 | {2F8D97ED-64C2-4F78-A343-3F23C64D1AD5}.Debug|Win32.ActiveCfg = Debug|Win32
17 | {2F8D97ED-64C2-4F78-A343-3F23C64D1AD5}.Debug|Win32.Build.0 = Debug|Win32
18 | {2F8D97ED-64C2-4F78-A343-3F23C64D1AD5}.Release|Any CPU.ActiveCfg = Release|Win32
19 | {2F8D97ED-64C2-4F78-A343-3F23C64D1AD5}.Release|Win32.ActiveCfg = Release|Win32
20 | {2F8D97ED-64C2-4F78-A343-3F23C64D1AD5}.Release|Win32.Build.0 = Release|Win32
21 | EndGlobalSection
22 | GlobalSection(SolutionProperties) = preSolution
23 | HideSolutionNode = FALSE
24 | EndGlobalSection
25 | GlobalSection(ExtensibilityGlobals) = postSolution
26 | SolutionGuid = {F3B8C0C8-8838-42EF-9075-40A3BC4DF3E6}
27 | EndGlobalSection
28 | EndGlobal
29 |
--------------------------------------------------------------------------------
/plugins/DeepL.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Release
6 | Win32
7 |
8 |
9 | Debug
10 | Win32
11 |
12 |
13 |
14 | {2F8D97ED-64C2-4F78-A343-3F23C64D1AD5}
15 | Win32Proj
16 | DeepL
17 | DeepL
18 | 10.0.16299.0
19 |
20 |
21 |
22 | DynamicLibrary
23 | false
24 | MultiByte
25 | v141
26 | true
27 |
28 |
29 | DynamicLibrary
30 | true
31 | MultiByte
32 | v141
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 | false
46 | bin\win32\Release\
47 | obj\win32\Release\
48 | DeepL
49 | .dll
50 | AllRules.ruleset
51 |
52 |
53 | C:\curl\builds\libcurl-vc-x86-release-static-ipv6-sspi-schannel\include\;$(VC_IncludePath);$(WindowsSDK_IncludePath);
54 | C:\curl\builds\libcurl-vc-x86-release-static-ipv6-sspi-schannel\lib\;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86
55 |
56 |
57 | true
58 | D:\Program Files\Rockstar Games\GTA San Andreas\Samp server\0.3.7\plugins\
59 | obj\win32\Debug\
60 | DeepL
61 | .dll
62 | AllRules.ruleset
63 |
64 |
65 | C:\curl\builds\libcurl-vc-x86-release-static-ipv6-sspi-schannel\include\;$(VC_IncludePath);$(WindowsSDK_IncludePath);
66 | C:\curl\builds\libcurl-vc-x86-release-static-ipv6-sspi-schannel\lib\;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86
67 |
68 |
69 |
70 | NotUsing
71 | Level3
72 | false
73 | HAVE_STDINT_H;_CRT_SECURE_NO_WARNINGS;NDEBUG;SAMPGDK_AMALGAMATION;SUBHOOK_IMPLEMENTATION;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)
74 | include;lib;src;%(AdditionalIncludeDirectories)
75 | MaxSpeed
76 | true
77 | true
78 | false
79 | Speed
80 | true
81 | true
82 | true
83 | AnySuitable
84 | true
85 | 1Byte
86 | true
87 | stdcpp14
88 |
89 |
90 | BOOST_ALL_NO_LIB;BOOST_CHRONO_HEADER_ONLY;_CRT_SECURE_NO_WARNINGS;NDEBUG;SAMPGDK_AMALGAMATION;%(PreprocessorDefinitions)
91 | include;lib;%(AdditionalIncludeDirectories)
92 |
93 |
94 | Windows
95 | false
96 | true
97 | true
98 | bin\win32\Release\DeepL.lib
99 | DeepL.def
100 | $(ProjectDir)bin\win32\Release\DeepL.dll
101 | libcurl_a.lib;Ws2_32.lib;Crypt32.lib;Wldap32.lib;Normaliz.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;psapi.lib;winmm.lib;Ws2_32.lib;%(AdditionalDependencies)
102 | false
103 | false
104 | true
105 |
106 |
107 |
108 |
109 | NotUsing
110 | Level3
111 | false
112 | HAVE_STDINT_H;_CRT_SECURE_NO_WARNINGS;SAMPGDK_AMALGAMATION;SUBHOOK_IMPLEMENTATION;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)
113 | include;lib;src;%(AdditionalIncludeDirectories)
114 | OldStyle
115 | $(OutDir)DeepL.pdb
116 | Disabled
117 | 1Byte
118 | stdcpp14
119 |
120 |
121 |
122 |
123 | BOOST_ALL_NO_LIB;BOOST_CHRONO_HEADER_ONLY;_CRT_SECURE_NO_WARNINGS;SAMPGDK_AMALGAMATION;%(PreprocessorDefinitions)
124 | include;lib;%(AdditionalIncludeDirectories)
125 |
126 |
127 | Windows
128 | true
129 | bin\win32\Debug\DeepL.lib
130 | DeepL.def
131 | true
132 | D:\Program Files\Rockstar Games\GTA San Andreas\Samp server\0.3.7\plugins\DeepL.dll
133 | libcurl_a.lib;Ws2_32.lib;Crypt32.lib;Wldap32.lib;Normaliz.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;Ws2_32.lib;%(AdditionalDependencies)
134 |
135 |
136 | msvcrt
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 |
--------------------------------------------------------------------------------
/plugins/DeepL.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | lib\sdk
6 |
7 |
8 | src
9 |
10 |
11 | src
12 |
13 |
14 | src
15 |
16 |
17 | lib\json
18 |
19 |
20 | src
21 |
22 |
23 |
24 |
25 | lib\sdk
26 |
27 |
28 | lib\sdk
29 |
30 |
31 | lib\sdk\amx
32 |
33 |
34 | lib\sdk\amx
35 |
36 |
37 | lib\sdk\amx
38 |
39 |
40 | src
41 |
42 |
43 | src
44 |
45 |
46 | src
47 |
48 |
49 | lib\json
50 |
51 |
52 | src
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 | {a4fd26cf-a2b4-4803-8d67-b7b0d036eb21}
61 |
62 |
63 | {e2d507f8-555b-42b7-adcf-ecafaa28b415}
64 |
65 |
66 | {072cd0b9-a015-41e5-bd5a-94e3e77f6ba3}
67 |
68 |
69 | {14346158-17c8-4f00-97a4-366965acac73}
70 |
71 |
72 | {fa08e708-8ba5-465e-ae6b-b4dc64697417}
73 |
74 |
75 |
--------------------------------------------------------------------------------
/plugins/lib/json/json11.cpp:
--------------------------------------------------------------------------------
1 | /* Copyright (c) 2013 Dropbox, Inc.
2 | *
3 | * Permission is hereby granted, free of charge, to any person obtaining a copy
4 | * of this software and associated documentation files (the "Software"), to deal
5 | * in the Software without restriction, including without limitation the rights
6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | * copies of the Software, and to permit persons to whom the Software is
8 | * furnished to do so, subject to the following conditions:
9 | *
10 | * The above copyright notice and this permission notice shall be included in
11 | * all copies or substantial portions of the Software.
12 | *
13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | * THE SOFTWARE.
20 | */
21 |
22 | #include "json11.hpp"
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 |
29 | namespace json11 {
30 |
31 | static const int max_depth = 200;
32 |
33 | using std::string;
34 | using std::vector;
35 | using std::map;
36 | using std::make_shared;
37 | using std::initializer_list;
38 | using std::move;
39 |
40 | /* Helper for representing null - just a do-nothing struct, plus comparison
41 | * operators so the helpers in JsonValue work. We can't use nullptr_t because
42 | * it may not be orderable.
43 | */
44 | struct NullStruct {
45 | bool operator==(NullStruct) const { return true; }
46 | bool operator<(NullStruct) const { return false; }
47 | };
48 |
49 | /* * * * * * * * * * * * * * * * * * * *
50 | * Serialization
51 | */
52 |
53 | static void dump(NullStruct, string &out) {
54 | out += "null";
55 | }
56 |
57 | static void dump(double value, string &out) {
58 | if (std::isfinite(value)) {
59 | char buf[32];
60 | snprintf(buf, sizeof buf, "%.17g", value);
61 | out += buf;
62 | } else {
63 | out += "null";
64 | }
65 | }
66 |
67 | static void dump(int value, string &out) {
68 | char buf[32];
69 | snprintf(buf, sizeof buf, "%d", value);
70 | out += buf;
71 | }
72 |
73 | static void dump(bool value, string &out) {
74 | out += value ? "true" : "false";
75 | }
76 |
77 | static void dump(const string &value, string &out) {
78 | out += '"';
79 | for (size_t i = 0; i < value.length(); i++) {
80 | const char ch = value[i];
81 | if (ch == '\\') {
82 | out += "\\\\";
83 | } else if (ch == '"') {
84 | out += "\\\"";
85 | } else if (ch == '\b') {
86 | out += "\\b";
87 | } else if (ch == '\f') {
88 | out += "\\f";
89 | } else if (ch == '\n') {
90 | out += "\\n";
91 | } else if (ch == '\r') {
92 | out += "\\r";
93 | } else if (ch == '\t') {
94 | out += "\\t";
95 | } else if (static_cast(ch) <= 0x1f) {
96 | char buf[8];
97 | snprintf(buf, sizeof buf, "\\u%04x", ch);
98 | out += buf;
99 | } else if (static_cast(ch) == 0xe2 && static_cast(value[i+1]) == 0x80
100 | && static_cast(value[i+2]) == 0xa8) {
101 | out += "\\u2028";
102 | i += 2;
103 | } else if (static_cast(ch) == 0xe2 && static_cast(value[i+1]) == 0x80
104 | && static_cast(value[i+2]) == 0xa9) {
105 | out += "\\u2029";
106 | i += 2;
107 | } else {
108 | out += ch;
109 | }
110 | }
111 | out += '"';
112 | }
113 |
114 | static void dump(const Json::array &values, string &out) {
115 | bool first = true;
116 | out += "[";
117 | for (const auto &value : values) {
118 | if (!first)
119 | out += ", ";
120 | value.dump(out);
121 | first = false;
122 | }
123 | out += "]";
124 | }
125 |
126 | static void dump(const Json::object &values, string &out) {
127 | bool first = true;
128 | out += "{";
129 | for (const auto &kv : values) {
130 | if (!first)
131 | out += ", ";
132 | dump(kv.first, out);
133 | out += ": ";
134 | kv.second.dump(out);
135 | first = false;
136 | }
137 | out += "}";
138 | }
139 |
140 | void Json::dump(string &out) const {
141 | m_ptr->dump(out);
142 | }
143 |
144 | /* * * * * * * * * * * * * * * * * * * *
145 | * Value wrappers
146 | */
147 |
148 | template
149 | class Value : public JsonValue {
150 | protected:
151 |
152 | // Constructors
153 | explicit Value(const T &value) : m_value(value) {}
154 | explicit Value(T &&value) : m_value(move(value)) {}
155 |
156 | // Get type tag
157 | Json::Type type() const override {
158 | return tag;
159 | }
160 |
161 | // Comparisons
162 | bool equals(const JsonValue * other) const override {
163 | return m_value == static_cast *>(other)->m_value;
164 | }
165 | bool less(const JsonValue * other) const override {
166 | return m_value < static_cast *>(other)->m_value;
167 | }
168 |
169 | const T m_value;
170 | void dump(string &out) const override { json11::dump(m_value, out); }
171 | };
172 |
173 | class JsonDouble final : public Value {
174 | double number_value() const override { return m_value; }
175 | int int_value() const override { return static_cast(m_value); }
176 | bool equals(const JsonValue * other) const override { return m_value == other->number_value(); }
177 | bool less(const JsonValue * other) const override { return m_value < other->number_value(); }
178 | public:
179 | explicit JsonDouble(double value) : Value(value) {}
180 | };
181 |
182 | class JsonInt final : public Value {
183 | double number_value() const override { return m_value; }
184 | int int_value() const override { return m_value; }
185 | bool equals(const JsonValue * other) const override { return m_value == other->number_value(); }
186 | bool less(const JsonValue * other) const override { return m_value < other->number_value(); }
187 | public:
188 | explicit JsonInt(int value) : Value(value) {}
189 | };
190 |
191 | class JsonBoolean final : public Value {
192 | bool bool_value() const override { return m_value; }
193 | public:
194 | explicit JsonBoolean(bool value) : Value(value) {}
195 | };
196 |
197 | class JsonString final : public Value {
198 | const string &string_value() const override { return m_value; }
199 | public:
200 | explicit JsonString(const string &value) : Value(value) {}
201 | explicit JsonString(string &&value) : Value(move(value)) {}
202 | };
203 |
204 | class JsonArray final : public Value {
205 | const Json::array &array_items() const override { return m_value; }
206 | const Json & operator[](size_t i) const override;
207 | public:
208 | explicit JsonArray(const Json::array &value) : Value(value) {}
209 | explicit JsonArray(Json::array &&value) : Value(move(value)) {}
210 | };
211 |
212 | class JsonObject final : public Value {
213 | const Json::object &object_items() const override { return m_value; }
214 | const Json & operator[](const string &key) const override;
215 | public:
216 | explicit JsonObject(const Json::object &value) : Value(value) {}
217 | explicit JsonObject(Json::object &&value) : Value(move(value)) {}
218 | };
219 |
220 | class JsonNull final : public Value {
221 | public:
222 | JsonNull() : Value({}) {}
223 | };
224 |
225 | /* * * * * * * * * * * * * * * * * * * *
226 | * Static globals - static-init-safe
227 | */
228 | struct Statics {
229 | const std::shared_ptr null = make_shared();
230 | const std::shared_ptr t = make_shared(true);
231 | const std::shared_ptr f = make_shared(false);
232 | const string empty_string;
233 | const vector empty_vector;
234 | const map empty_map;
235 | Statics() {}
236 | };
237 |
238 | static const Statics & statics() {
239 | static const Statics s {};
240 | return s;
241 | }
242 |
243 | static const Json & static_null() {
244 | // This has to be separate, not in Statics, because Json() accesses statics().null.
245 | static const Json json_null;
246 | return json_null;
247 | }
248 |
249 | /* * * * * * * * * * * * * * * * * * * *
250 | * Constructors
251 | */
252 |
253 | Json::Json() noexcept : m_ptr(statics().null) {}
254 | Json::Json(std::nullptr_t) noexcept : m_ptr(statics().null) {}
255 | Json::Json(double value) : m_ptr(make_shared(value)) {}
256 | Json::Json(int value) : m_ptr(make_shared(value)) {}
257 | Json::Json(bool value) : m_ptr(value ? statics().t : statics().f) {}
258 | Json::Json(const string &value) : m_ptr(make_shared(value)) {}
259 | Json::Json(string &&value) : m_ptr(make_shared(move(value))) {}
260 | Json::Json(const char * value) : m_ptr(make_shared(value)) {}
261 | Json::Json(const Json::array &values) : m_ptr(make_shared(values)) {}
262 | Json::Json(Json::array &&values) : m_ptr(make_shared(move(values))) {}
263 | Json::Json(const Json::object &values) : m_ptr(make_shared(values)) {}
264 | Json::Json(Json::object &&values) : m_ptr(make_shared(move(values))) {}
265 |
266 | /* * * * * * * * * * * * * * * * * * * *
267 | * Accessors
268 | */
269 |
270 | Json::Type Json::type() const { return m_ptr->type(); }
271 | double Json::number_value() const { return m_ptr->number_value(); }
272 | int Json::int_value() const { return m_ptr->int_value(); }
273 | bool Json::bool_value() const { return m_ptr->bool_value(); }
274 | const string & Json::string_value() const { return m_ptr->string_value(); }
275 | const vector & Json::array_items() const { return m_ptr->array_items(); }
276 | const map & Json::object_items() const { return m_ptr->object_items(); }
277 | const Json & Json::operator[] (size_t i) const { return (*m_ptr)[i]; }
278 | const Json & Json::operator[] (const string &key) const { return (*m_ptr)[key]; }
279 |
280 | double JsonValue::number_value() const { return 0; }
281 | int JsonValue::int_value() const { return 0; }
282 | bool JsonValue::bool_value() const { return false; }
283 | const string & JsonValue::string_value() const { return statics().empty_string; }
284 | const vector & JsonValue::array_items() const { return statics().empty_vector; }
285 | const map & JsonValue::object_items() const { return statics().empty_map; }
286 | const Json & JsonValue::operator[] (size_t) const { return static_null(); }
287 | const Json & JsonValue::operator[] (const string &) const { return static_null(); }
288 |
289 | const Json & JsonObject::operator[] (const string &key) const {
290 | auto iter = m_value.find(key);
291 | return (iter == m_value.end()) ? static_null() : iter->second;
292 | }
293 | const Json & JsonArray::operator[] (size_t i) const {
294 | if (i >= m_value.size()) return static_null();
295 | else return m_value[i];
296 | }
297 |
298 | /* * * * * * * * * * * * * * * * * * * *
299 | * Comparison
300 | */
301 |
302 | bool Json::operator== (const Json &other) const {
303 | if (m_ptr == other.m_ptr)
304 | return true;
305 | if (m_ptr->type() != other.m_ptr->type())
306 | return false;
307 |
308 | return m_ptr->equals(other.m_ptr.get());
309 | }
310 |
311 | bool Json::operator< (const Json &other) const {
312 | if (m_ptr == other.m_ptr)
313 | return false;
314 | if (m_ptr->type() != other.m_ptr->type())
315 | return m_ptr->type() < other.m_ptr->type();
316 |
317 | return m_ptr->less(other.m_ptr.get());
318 | }
319 |
320 | /* * * * * * * * * * * * * * * * * * * *
321 | * Parsing
322 | */
323 |
324 | /* esc(c)
325 | *
326 | * Format char c suitable for printing in an error message.
327 | */
328 | static inline string esc(char c) {
329 | char buf[12];
330 | if (static_cast(c) >= 0x20 && static_cast(c) <= 0x7f) {
331 | snprintf(buf, sizeof buf, "'%c' (%d)", c, c);
332 | } else {
333 | snprintf(buf, sizeof buf, "(%d)", c);
334 | }
335 | return string(buf);
336 | }
337 |
338 | static inline bool in_range(long x, long lower, long upper) {
339 | return (x >= lower && x <= upper);
340 | }
341 |
342 | namespace {
343 | /* JsonParser
344 | *
345 | * Object that tracks all state of an in-progress parse.
346 | */
347 | struct JsonParser final {
348 |
349 | /* State
350 | */
351 | const string &str;
352 | size_t i;
353 | string &err;
354 | bool failed;
355 | const JsonParse strategy;
356 |
357 | /* fail(msg, err_ret = Json())
358 | *
359 | * Mark this parse as failed.
360 | */
361 | Json fail(string &&msg) {
362 | return fail(move(msg), Json());
363 | }
364 |
365 | template
366 | T fail(string &&msg, const T err_ret) {
367 | if (!failed)
368 | err = std::move(msg);
369 | failed = true;
370 | return err_ret;
371 | }
372 |
373 | /* consume_whitespace()
374 | *
375 | * Advance until the current character is non-whitespace.
376 | */
377 | void consume_whitespace() {
378 | while (str[i] == ' ' || str[i] == '\r' || str[i] == '\n' || str[i] == '\t')
379 | i++;
380 | }
381 |
382 | /* consume_comment()
383 | *
384 | * Advance comments (c-style inline and multiline).
385 | */
386 | bool consume_comment() {
387 | bool comment_found = false;
388 | if (str[i] == '/') {
389 | i++;
390 | if (i == str.size())
391 | return fail("unexpected end of input after start of comment", false);
392 | if (str[i] == '/') { // inline comment
393 | i++;
394 | // advance until next line, or end of input
395 | while (i < str.size() && str[i] != '\n') {
396 | i++;
397 | }
398 | comment_found = true;
399 | }
400 | else if (str[i] == '*') { // multiline comment
401 | i++;
402 | if (i > str.size()-2)
403 | return fail("unexpected end of input inside multi-line comment", false);
404 | // advance until closing tokens
405 | while (!(str[i] == '*' && str[i+1] == '/')) {
406 | i++;
407 | if (i > str.size()-2)
408 | return fail(
409 | "unexpected end of input inside multi-line comment", false);
410 | }
411 | i += 2;
412 | comment_found = true;
413 | }
414 | else
415 | return fail("malformed comment", false);
416 | }
417 | return comment_found;
418 | }
419 |
420 | /* consume_garbage()
421 | *
422 | * Advance until the current character is non-whitespace and non-comment.
423 | */
424 | void consume_garbage() {
425 | consume_whitespace();
426 | if(strategy == JsonParse::COMMENTS) {
427 | bool comment_found = false;
428 | do {
429 | comment_found = consume_comment();
430 | if (failed) return;
431 | consume_whitespace();
432 | }
433 | while(comment_found);
434 | }
435 | }
436 |
437 | /* get_next_token()
438 | *
439 | * Return the next non-whitespace character. If the end of the input is reached,
440 | * flag an error and return 0.
441 | */
442 | char get_next_token() {
443 | consume_garbage();
444 | if (failed) return static_cast(0);
445 | if (i == str.size())
446 | return fail("unexpected end of input", static_cast(0));
447 |
448 | return str[i++];
449 | }
450 |
451 | /* encode_utf8(pt, out)
452 | *
453 | * Encode pt as UTF-8 and add it to out.
454 | */
455 | void encode_utf8(long pt, string & out) {
456 | if (pt < 0)
457 | return;
458 |
459 | if (pt < 0x80) {
460 | out += static_cast(pt);
461 | } else if (pt < 0x800) {
462 | out += static_cast((pt >> 6) | 0xC0);
463 | out += static_cast((pt & 0x3F) | 0x80);
464 | } else if (pt < 0x10000) {
465 | out += static_cast((pt >> 12) | 0xE0);
466 | out += static_cast(((pt >> 6) & 0x3F) | 0x80);
467 | out += static_cast((pt & 0x3F) | 0x80);
468 | } else {
469 | out += static_cast((pt >> 18) | 0xF0);
470 | out += static_cast(((pt >> 12) & 0x3F) | 0x80);
471 | out += static_cast(((pt >> 6) & 0x3F) | 0x80);
472 | out += static_cast((pt & 0x3F) | 0x80);
473 | }
474 | }
475 |
476 | /* parse_string()
477 | *
478 | * Parse a string, starting at the current position.
479 | */
480 | string parse_string() {
481 | string out;
482 | long last_escaped_codepoint = -1;
483 | while (true) {
484 | if (i == str.size())
485 | return fail("unexpected end of input in string", "");
486 |
487 | char ch = str[i++];
488 |
489 | if (ch == '"') {
490 | encode_utf8(last_escaped_codepoint, out);
491 | return out;
492 | }
493 |
494 | if (in_range(ch, 0, 0x1f))
495 | return fail("unescaped " + esc(ch) + " in string", "");
496 |
497 | // The usual case: non-escaped characters
498 | if (ch != '\\') {
499 | encode_utf8(last_escaped_codepoint, out);
500 | last_escaped_codepoint = -1;
501 | out += ch;
502 | continue;
503 | }
504 |
505 | // Handle escapes
506 | if (i == str.size())
507 | return fail("unexpected end of input in string", "");
508 |
509 | ch = str[i++];
510 |
511 | if (ch == 'u') {
512 | // Extract 4-byte escape sequence
513 | string esc = str.substr(i, 4);
514 | // Explicitly check length of the substring. The following loop
515 | // relies on std::string returning the terminating NUL when
516 | // accessing str[length]. Checking here reduces brittleness.
517 | if (esc.length() < 4) {
518 | return fail("bad \\u escape: " + esc, "");
519 | }
520 | for (size_t j = 0; j < 4; j++) {
521 | if (!in_range(esc[j], 'a', 'f') && !in_range(esc[j], 'A', 'F')
522 | && !in_range(esc[j], '0', '9'))
523 | return fail("bad \\u escape: " + esc, "");
524 | }
525 |
526 | long codepoint = strtol(esc.data(), nullptr, 16);
527 |
528 | // JSON specifies that characters outside the BMP shall be encoded as a pair
529 | // of 4-hex-digit \u escapes encoding their surrogate pair components. Check
530 | // whether we're in the middle of such a beast: the previous codepoint was an
531 | // escaped lead (high) surrogate, and this is a trail (low) surrogate.
532 | if (in_range(last_escaped_codepoint, 0xD800, 0xDBFF)
533 | && in_range(codepoint, 0xDC00, 0xDFFF)) {
534 | // Reassemble the two surrogate pairs into one astral-plane character, per
535 | // the UTF-16 algorithm.
536 | encode_utf8((((last_escaped_codepoint - 0xD800) << 10)
537 | | (codepoint - 0xDC00)) + 0x10000, out);
538 | last_escaped_codepoint = -1;
539 | } else {
540 | encode_utf8(last_escaped_codepoint, out);
541 | last_escaped_codepoint = codepoint;
542 | }
543 |
544 | i += 4;
545 | continue;
546 | }
547 |
548 | encode_utf8(last_escaped_codepoint, out);
549 | last_escaped_codepoint = -1;
550 |
551 | if (ch == 'b') {
552 | out += '\b';
553 | } else if (ch == 'f') {
554 | out += '\f';
555 | } else if (ch == 'n') {
556 | out += '\n';
557 | } else if (ch == 'r') {
558 | out += '\r';
559 | } else if (ch == 't') {
560 | out += '\t';
561 | } else if (ch == '"' || ch == '\\' || ch == '/') {
562 | out += ch;
563 | } else {
564 | return fail("invalid escape character " + esc(ch), "");
565 | }
566 | }
567 | }
568 |
569 | /* parse_number()
570 | *
571 | * Parse a double.
572 | */
573 | Json parse_number() {
574 | size_t start_pos = i;
575 |
576 | if (str[i] == '-')
577 | i++;
578 |
579 | // Integer part
580 | if (str[i] == '0') {
581 | i++;
582 | if (in_range(str[i], '0', '9'))
583 | return fail("leading 0s not permitted in numbers");
584 | } else if (in_range(str[i], '1', '9')) {
585 | i++;
586 | while (in_range(str[i], '0', '9'))
587 | i++;
588 | } else {
589 | return fail("invalid " + esc(str[i]) + " in number");
590 | }
591 |
592 | if (str[i] != '.' && str[i] != 'e' && str[i] != 'E'
593 | && (i - start_pos) <= static_cast(std::numeric_limits::digits10)) {
594 | return std::atoi(str.c_str() + start_pos);
595 | }
596 |
597 | // Decimal part
598 | if (str[i] == '.') {
599 | i++;
600 | if (!in_range(str[i], '0', '9'))
601 | return fail("at least one digit required in fractional part");
602 |
603 | while (in_range(str[i], '0', '9'))
604 | i++;
605 | }
606 |
607 | // Exponent part
608 | if (str[i] == 'e' || str[i] == 'E') {
609 | i++;
610 |
611 | if (str[i] == '+' || str[i] == '-')
612 | i++;
613 |
614 | if (!in_range(str[i], '0', '9'))
615 | return fail("at least one digit required in exponent");
616 |
617 | while (in_range(str[i], '0', '9'))
618 | i++;
619 | }
620 |
621 | return std::strtod(str.c_str() + start_pos, nullptr);
622 | }
623 |
624 | /* expect(str, res)
625 | *
626 | * Expect that 'str' starts at the character that was just read. If it does, advance
627 | * the input and return res. If not, flag an error.
628 | */
629 | Json expect(const string &expected, Json res) {
630 | assert(i != 0);
631 | i--;
632 | if (str.compare(i, expected.length(), expected) == 0) {
633 | i += expected.length();
634 | return res;
635 | } else {
636 | return fail("parse error: expected " + expected + ", got " + str.substr(i, expected.length()));
637 | }
638 | }
639 |
640 | /* parse_json()
641 | *
642 | * Parse a JSON object.
643 | */
644 | Json parse_json(int depth) {
645 | if (depth > max_depth) {
646 | return fail("exceeded maximum nesting depth");
647 | }
648 |
649 | char ch = get_next_token();
650 | if (failed)
651 | return Json();
652 |
653 | if (ch == '-' || (ch >= '0' && ch <= '9')) {
654 | i--;
655 | return parse_number();
656 | }
657 |
658 | if (ch == 't')
659 | return expect("true", true);
660 |
661 | if (ch == 'f')
662 | return expect("false", false);
663 |
664 | if (ch == 'n')
665 | return expect("null", Json());
666 |
667 | if (ch == '"')
668 | return parse_string();
669 |
670 | if (ch == '{') {
671 | map data;
672 | ch = get_next_token();
673 | if (ch == '}')
674 | return data;
675 |
676 | while (1) {
677 | if (ch != '"')
678 | return fail("expected '\"' in object, got " + esc(ch));
679 |
680 | string key = parse_string();
681 | if (failed)
682 | return Json();
683 |
684 | ch = get_next_token();
685 | if (ch != ':')
686 | return fail("expected ':' in object, got " + esc(ch));
687 |
688 | data[std::move(key)] = parse_json(depth + 1);
689 | if (failed)
690 | return Json();
691 |
692 | ch = get_next_token();
693 | if (ch == '}')
694 | break;
695 | if (ch != ',')
696 | return fail("expected ',' in object, got " + esc(ch));
697 |
698 | ch = get_next_token();
699 | }
700 | return data;
701 | }
702 |
703 | if (ch == '[') {
704 | vector data;
705 | ch = get_next_token();
706 | if (ch == ']')
707 | return data;
708 |
709 | while (1) {
710 | i--;
711 | data.push_back(parse_json(depth + 1));
712 | if (failed)
713 | return Json();
714 |
715 | ch = get_next_token();
716 | if (ch == ']')
717 | break;
718 | if (ch != ',')
719 | return fail("expected ',' in list, got " + esc(ch));
720 |
721 | ch = get_next_token();
722 | (void)ch;
723 | }
724 | return data;
725 | }
726 |
727 | return fail("expected value, got " + esc(ch));
728 | }
729 | };
730 | }//namespace {
731 |
732 | Json Json::parse(const string &in, string &err, JsonParse strategy) {
733 | JsonParser parser { in, 0, err, false, strategy };
734 | Json result = parser.parse_json(0);
735 |
736 | // Check for any trailing garbage
737 | parser.consume_garbage();
738 | if (parser.failed)
739 | return Json();
740 | if (parser.i != in.size())
741 | return parser.fail("unexpected trailing " + esc(in[parser.i]));
742 |
743 | return result;
744 | }
745 |
746 | // Documented in json11.hpp
747 | vector Json::parse_multi(const string &in,
748 | std::string::size_type &parser_stop_pos,
749 | string &err,
750 | JsonParse strategy) {
751 | JsonParser parser { in, 0, err, false, strategy };
752 | parser_stop_pos = 0;
753 | vector json_vec;
754 | while (parser.i != in.size() && !parser.failed) {
755 | json_vec.push_back(parser.parse_json(0));
756 | if (parser.failed)
757 | break;
758 |
759 | // Check for another object
760 | parser.consume_garbage();
761 | if (parser.failed)
762 | break;
763 | parser_stop_pos = parser.i;
764 | }
765 | return json_vec;
766 | }
767 |
768 | /* * * * * * * * * * * * * * * * * * * *
769 | * Shape-checking
770 | */
771 |
772 | bool Json::has_shape(const shape & types, string & err) const {
773 | if (!is_object()) {
774 | err = "expected JSON object, got " + dump();
775 | return false;
776 | }
777 |
778 | const auto& obj_items = object_items();
779 | for (auto & item : types) {
780 | const auto it = obj_items.find(item.first);
781 | if (it == obj_items.cend() || it->second.type() != item.second) {
782 | err = "bad type for " + item.first + " in " + dump();
783 | return false;
784 | }
785 | }
786 |
787 | return true;
788 | }
789 |
790 | } // namespace json11
791 |
--------------------------------------------------------------------------------
/plugins/lib/json/json11.hpp:
--------------------------------------------------------------------------------
1 | /* json11
2 | *
3 | * json11 is a tiny JSON library for C++11, providing JSON parsing and serialization.
4 | *
5 | * The core object provided by the library is json11::Json. A Json object represents any JSON
6 | * value: null, bool, number (int or double), string (std::string), array (std::vector), or
7 | * object (std::map).
8 | *
9 | * Json objects act like values: they can be assigned, copied, moved, compared for equality or
10 | * order, etc. There are also helper methods Json::dump, to serialize a Json to a string, and
11 | * Json::parse (static) to parse a std::string as a Json object.
12 | *
13 | * Internally, the various types of Json object are represented by the JsonValue class
14 | * hierarchy.
15 | *
16 | * A note on numbers - JSON specifies the syntax of number formatting but not its semantics,
17 | * so some JSON implementations distinguish between integers and floating-point numbers, while
18 | * some don't. In json11, we choose the latter. Because some JSON implementations (namely
19 | * Javascript itself) treat all numbers as the same type, distinguishing the two leads
20 | * to JSON that will be *silently* changed by a round-trip through those implementations.
21 | * Dangerous! To avoid that risk, json11 stores all numbers as double internally, but also
22 | * provides integer helpers.
23 | *
24 | * Fortunately, double-precision IEEE754 ('double') can precisely store any integer in the
25 | * range +/-2^53, which includes every 'int' on most systems. (Timestamps often use int64
26 | * or long long to avoid the Y2038K problem; a double storing microseconds since some epoch
27 | * will be exact for +/- 275 years.)
28 | */
29 |
30 | /* Copyright (c) 2013 Dropbox, Inc.
31 | *
32 | * Permission is hereby granted, free of charge, to any person obtaining a copy
33 | * of this software and associated documentation files (the "Software"), to deal
34 | * in the Software without restriction, including without limitation the rights
35 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
36 | * copies of the Software, and to permit persons to whom the Software is
37 | * furnished to do so, subject to the following conditions:
38 | *
39 | * The above copyright notice and this permission notice shall be included in
40 | * all copies or substantial portions of the Software.
41 | *
42 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
43 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
44 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
45 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
46 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
47 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
48 | * THE SOFTWARE.
49 | */
50 |
51 | #pragma once
52 |
53 | #include
54 | #include
55 | #include