├── .gitignore ├── LICENSE ├── README.md ├── docs ├── dochack.js ├── index.html └── nimdoc.out.css ├── sqliteral.nim └── sqliteral.nimble /.gitignore: -------------------------------------------------------------------------------- 1 | nim.cfg 2 | /tests -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Olli Niinivaara 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 | # SQLiteral 2 | A high level SQLite API for Nim 3 | 4 | Supports multi-threading, prepared statements, proper typing, 5 | zero-copy data paths, debugging, optimizing, backups, and more... 6 | 7 | ## Documentation 8 | 9 | http://olliNiinivaara.github.io/SQLiteral/ 10 | 11 | ## 5.0.1 Release notes (2025-02-13) 12 | * `withRow` template fix by removing a superfluous `dirty` pragma 13 | 14 | ## 5.0.0 Release notes (2024-12-22) 15 | * statements from more than one enum list can be used 16 | * a statement is prepared automatically on first use 17 | * all used statements are finalized automatically on close 18 | * only the Nim default memory managers (ARC and ORC family) are supported 19 | * errors that are not sqlite errors are logged with error code 10000 20 | * failing to close raises an SQLError 21 | * json_extract, json_patch, json_valid, and json_tree procs removed as too high level (esp. now that multiple statement lists are supported) 22 | 23 | ## Example 24 | 25 | ```nim 26 | import sqliteral 27 | const Schema = "CREATE TABLE IF NOT EXISTS Example(string TEXT NOT NULL)" 28 | type SqlStatements = enum 29 | Upsert = """INSERT INTO Example(rowid, string) VALUES(1, ?) 30 | ON CONFLICT(rowid) DO UPDATE SET string = ?""" 31 | SelectAll = "SELECT string FROM Example" 32 | var db: SQLiteral 33 | 34 | proc operate(i: string) = 35 | let view: DbValue = i.toDb(3, 7) # zero-copy view into string 36 | db.transaction: db.exec(Upsert, view, view) 37 | for row in db.rows(SelectAll): echo row.getCString(0) 38 | 39 | db.openDatabase("example.db", Schema) 40 | var input = "012INPUT89" 41 | operate(input) 42 | db.close() 43 | ``` 44 | -------------------------------------------------------------------------------- /docs/dochack.js: -------------------------------------------------------------------------------- 1 | /* Generated by the Nim Compiler v2.2.0 */ 2 | var framePtr = null; 3 | var excHandler = 0; 4 | var lastJSError = null; 5 | var NTI33554466 = {size: 0,kind: 1,base: null,node: null,finalizer: null}; 6 | var NTI687865870 = {size: 0, kind: 18, base: null, node: null, finalizer: null}; 7 | var NTI33554435 = {size: 0,kind: 31,base: null,node: null,finalizer: null}; 8 | var NTI922746959 = {size: 0,kind: 31,base: null,node: null,finalizer: null}; 9 | var NTI922746965 = {size: 0, kind: 18, base: null, node: null, finalizer: null}; 10 | var NTI134217745 = {size: 0, kind: 17, base: null, node: null, finalizer: null}; 11 | var NTI134217749 = {size: 0, kind: 17, base: null, node: null, finalizer: null}; 12 | var NTI134217751 = {size: 0, kind: 17, base: null, node: null, finalizer: null}; 13 | var NTI33555167 = {size: 0, kind: 17, base: null, node: null, finalizer: null}; 14 | var NTI33555175 = {size: 0, kind: 22, base: null, node: null, finalizer: null}; 15 | var NTI33554449 = {size: 0,kind: 28,base: null,node: null,finalizer: null}; 16 | var NTI33554450 = {size: 0,kind: 29,base: null,node: null,finalizer: null}; 17 | var NTI33555174 = {size: 0, kind: 22, base: null, node: null, finalizer: null}; 18 | var NTI33555171 = {size: 0, kind: 17, base: null, node: null, finalizer: null}; 19 | var NTI33555172 = {size: 0, kind: 17, base: null, node: null, finalizer: null}; 20 | var NTI134217741 = {size: 0, kind: 17, base: null, node: null, finalizer: null}; 21 | var NTI134217743 = {size: 0, kind: 17, base: null, node: null, finalizer: null}; 22 | var NNI134217743 = {kind: 2, len: 0, offset: 0, typ: null, name: null, sons: []}; 23 | NTI134217743.node = NNI134217743; 24 | var NNI134217741 = {kind: 2, len: 0, offset: 0, typ: null, name: null, sons: []}; 25 | NTI134217741.node = NNI134217741; 26 | var NNI33555172 = {kind: 2, len: 0, offset: 0, typ: null, name: null, sons: []}; 27 | NTI33555172.node = NNI33555172; 28 | NTI33555174.base = NTI33555171; 29 | NTI33555175.base = NTI33555171; 30 | var NNI33555171 = {kind: 2, len: 5, offset: 0, typ: null, name: null, sons: [{kind: 1, offset: "parent", len: 0, typ: NTI33555174, name: "parent", sons: null}, 31 | {kind: 1, offset: "name", len: 0, typ: NTI33554450, name: "name", sons: null}, 32 | {kind: 1, offset: "message", len: 0, typ: NTI33554449, name: "msg", sons: null}, 33 | {kind: 1, offset: "trace", len: 0, typ: NTI33554449, name: "trace", sons: null}, 34 | {kind: 1, offset: "up", len: 0, typ: NTI33555175, name: "up", sons: null}]}; 35 | NTI33555171.node = NNI33555171; 36 | var NNI33555167 = {kind: 2, len: 0, offset: 0, typ: null, name: null, sons: []}; 37 | NTI33555167.node = NNI33555167; 38 | NTI33555171.base = NTI33555167; 39 | NTI33555172.base = NTI33555171; 40 | NTI134217741.base = NTI33555172; 41 | NTI134217743.base = NTI134217741; 42 | var NNI134217751 = {kind: 2, len: 0, offset: 0, typ: null, name: null, sons: []}; 43 | NTI134217751.node = NNI134217751; 44 | NTI134217751.base = NTI33555172; 45 | var NNI134217749 = {kind: 2, len: 0, offset: 0, typ: null, name: null, sons: []}; 46 | NTI134217749.node = NNI134217749; 47 | NTI134217749.base = NTI33555172; 48 | var NNI134217745 = {kind: 2, len: 0, offset: 0, typ: null, name: null, sons: []}; 49 | NTI134217745.node = NNI134217745; 50 | NTI134217745.base = NTI33555172; 51 | var NNI922746965 = {kind: 2, len: 2, offset: 0, typ: null, name: null, sons: [{kind: 1, offset: "a", len: 0, typ: NTI922746959, name: "a", sons: null}, 52 | {kind: 1, offset: "b", len: 0, typ: NTI33554435, name: "b", sons: null}]}; 53 | NTI922746965.node = NNI922746965; 54 | var NNI687865870 = {kind: 2, len: 2, offset: 0, typ: null, name: null, sons: [{kind: 1, offset: "Field0", len: 0, typ: NTI33554435, name: "Field0", sons: null}, 55 | {kind: 1, offset: "Field1", len: 0, typ: NTI33554466, name: "Field1", sons: null}]}; 56 | NTI687865870.node = NNI687865870; 57 | 58 | function mnewString(len_p0) { 59 | var result = new Array(len_p0); 60 | for (var i = 0; i < len_p0; i++) {result[i] = 0;} 61 | return result; 62 | 63 | 64 | 65 | } 66 | 67 | function toJSStr(s_p0) { 68 | var result_33556911 = null; 69 | 70 | var res_33556965 = newSeq__system_u2508((s_p0).length); 71 | var i_33556966 = 0; 72 | var j_33556967 = 0; 73 | Label1: { 74 | Label2: while (true) { 75 | if (!(i_33556966 < (s_p0).length)) break Label2; 76 | var c_33556968 = s_p0[i_33556966]; 77 | if ((c_33556968 < 128)) { 78 | res_33556965[j_33556967] = String.fromCharCode(c_33556968); 79 | i_33556966 += 1; 80 | } 81 | else { 82 | var helper_33556994 = newSeq__system_u2508(0); 83 | Label3: { 84 | Label4: while (true) { 85 | if (!true) break Label4; 86 | var code_33556995 = c_33556968.toString(16); 87 | if ((((code_33556995) == null ? 0 : (code_33556995).length) == 1)) { 88 | helper_33556994.push("%0");; 89 | } 90 | else { 91 | helper_33556994.push("%");; 92 | } 93 | 94 | helper_33556994.push(code_33556995);; 95 | i_33556966 += 1; 96 | if ((((s_p0).length <= i_33556966) || (s_p0[i_33556966] < 128))) { 97 | break Label3; 98 | } 99 | 100 | c_33556968 = s_p0[i_33556966]; 101 | } 102 | }; 103 | ++excHandler; 104 | try { 105 | res_33556965[j_33556967] = decodeURIComponent(helper_33556994.join("")); 106 | --excHandler; 107 | } catch (EXCEPTION) { 108 | var prevJSError = lastJSError; 109 | lastJSError = EXCEPTION; 110 | --excHandler; 111 | res_33556965[j_33556967] = helper_33556994.join(""); 112 | lastJSError = prevJSError; 113 | } finally { 114 | } 115 | } 116 | 117 | j_33556967 += 1; 118 | } 119 | }; 120 | if (res_33556965.length < j_33556967) { for (var i = res_33556965.length ; i < j_33556967 ; ++i) res_33556965.push(null); } 121 | else { res_33556965.length = j_33556967; }; 122 | result_33556911 = res_33556965.join(""); 123 | 124 | return result_33556911; 125 | 126 | } 127 | 128 | function raiseException(e_p0, ename_p1) { 129 | e_p0.name = ename_p1; 130 | if ((excHandler == 0)) { 131 | unhandledException(e_p0); 132 | } 133 | 134 | throw e_p0; 135 | 136 | 137 | } 138 | 139 | function addInt(a_p0, b_p1) { 140 | var result = a_p0 + b_p1; 141 | checkOverflowInt(result); 142 | return result; 143 | 144 | 145 | 146 | } 147 | 148 | function chckRange(i_p0, a_p1, b_p2) { 149 | var result_33557358 = 0; 150 | 151 | BeforeRet: { 152 | if (((a_p1 <= i_p0) && (i_p0 <= b_p2))) { 153 | result_33557358 = i_p0; 154 | break BeforeRet; 155 | } 156 | else { 157 | raiseRangeError(); 158 | } 159 | 160 | }; 161 | 162 | return result_33557358; 163 | 164 | } 165 | 166 | function setConstr() { 167 | var result = {}; 168 | for (var i = 0; i < arguments.length; ++i) { 169 | var x = arguments[i]; 170 | if (typeof(x) == "object") { 171 | for (var j = x[0]; j <= x[1]; ++j) { 172 | result[j] = true; 173 | } 174 | } else { 175 | result[x] = true; 176 | } 177 | } 178 | return result; 179 | 180 | 181 | 182 | } 183 | var ConstSet1 = setConstr(17, 16, 4, 18, 27, 19, 23, 22, 21); 184 | 185 | function nimCopy(dest_p0, src_p1, ti_p2) { 186 | var result_33557318 = null; 187 | 188 | switch (ti_p2.kind) { 189 | case 21: 190 | case 22: 191 | case 23: 192 | case 5: 193 | if (!(isFatPointer__system_u2866(ti_p2))) { 194 | result_33557318 = src_p1; 195 | } 196 | else { 197 | result_33557318 = [src_p1[0], src_p1[1]]; 198 | } 199 | 200 | break; 201 | case 19: 202 | if (dest_p0 === null || dest_p0 === undefined) { 203 | dest_p0 = {}; 204 | } 205 | else { 206 | for (var key in dest_p0) { delete dest_p0[key]; } 207 | } 208 | for (var key in src_p1) { dest_p0[key] = src_p1[key]; } 209 | result_33557318 = dest_p0; 210 | 211 | break; 212 | case 18: 213 | case 17: 214 | if (!((ti_p2.base == null))) { 215 | result_33557318 = nimCopy(dest_p0, src_p1, ti_p2.base); 216 | } 217 | else { 218 | if ((ti_p2.kind == 17)) { 219 | result_33557318 = (dest_p0 === null || dest_p0 === undefined) ? {m_type: ti_p2} : dest_p0; 220 | } 221 | else { 222 | result_33557318 = (dest_p0 === null || dest_p0 === undefined) ? {} : dest_p0; 223 | } 224 | } 225 | nimCopyAux(result_33557318, src_p1, ti_p2.node); 226 | break; 227 | case 4: 228 | case 16: 229 | if(ArrayBuffer.isView(src_p1)) { 230 | if(dest_p0 === null || dest_p0 === undefined || dest_p0.length != src_p1.length) { 231 | dest_p0 = new src_p1.constructor(src_p1); 232 | } else { 233 | dest_p0.set(src_p1, 0); 234 | } 235 | result_33557318 = dest_p0; 236 | } else { 237 | if (src_p1 === null) { 238 | result_33557318 = null; 239 | } 240 | else { 241 | if (dest_p0 === null || dest_p0 === undefined || dest_p0.length != src_p1.length) { 242 | dest_p0 = new Array(src_p1.length); 243 | } 244 | result_33557318 = dest_p0; 245 | for (var i = 0; i < src_p1.length; ++i) { 246 | result_33557318[i] = nimCopy(result_33557318[i], src_p1[i], ti_p2.base); 247 | } 248 | } 249 | } 250 | 251 | break; 252 | case 24: 253 | case 27: 254 | if (src_p1 === null) { 255 | result_33557318 = null; 256 | } 257 | else { 258 | if (dest_p0 === null || dest_p0 === undefined || dest_p0.length != src_p1.length) { 259 | dest_p0 = new Array(src_p1.length); 260 | } 261 | result_33557318 = dest_p0; 262 | for (var i = 0; i < src_p1.length; ++i) { 263 | result_33557318[i] = nimCopy(result_33557318[i], src_p1[i], ti_p2.base); 264 | } 265 | } 266 | 267 | break; 268 | case 28: 269 | if (src_p1 !== null) { 270 | result_33557318 = src_p1.slice(0); 271 | } 272 | 273 | break; 274 | default: 275 | result_33557318 = src_p1; 276 | break; 277 | } 278 | 279 | return result_33557318; 280 | 281 | } 282 | 283 | function chckIndx(i_p0, a_p1, b_p2) { 284 | var result_33557353 = 0; 285 | 286 | BeforeRet: { 287 | if (((a_p1 <= i_p0) && (i_p0 <= b_p2))) { 288 | result_33557353 = i_p0; 289 | break BeforeRet; 290 | } 291 | else { 292 | raiseIndexError(i_p0, a_p1, b_p2); 293 | } 294 | 295 | }; 296 | 297 | return result_33557353; 298 | 299 | } 300 | 301 | function makeNimstrLit(c_p0) { 302 | var result = []; 303 | for (var i = 0; i < c_p0.length; ++i) { 304 | result[i] = c_p0.charCodeAt(i); 305 | } 306 | return result; 307 | 308 | 309 | 310 | } 311 | 312 | function subInt(a_p0, b_p1) { 313 | var result = a_p0 - b_p1; 314 | checkOverflowInt(result); 315 | return result; 316 | 317 | 318 | 319 | } 320 | 321 | function cstrToNimstr(c_p0) { 322 | var ln = c_p0.length; 323 | var result = new Array(ln); 324 | var r = 0; 325 | for (var i = 0; i < ln; ++i) { 326 | var ch = c_p0.charCodeAt(i); 327 | 328 | if (ch < 128) { 329 | result[r] = ch; 330 | } 331 | else { 332 | if (ch < 2048) { 333 | result[r] = (ch >> 6) | 192; 334 | } 335 | else { 336 | if (ch < 55296 || ch >= 57344) { 337 | result[r] = (ch >> 12) | 224; 338 | } 339 | else { 340 | ++i; 341 | ch = 65536 + (((ch & 1023) << 10) | (c_p0.charCodeAt(i) & 1023)); 342 | result[r] = (ch >> 18) | 240; 343 | ++r; 344 | result[r] = ((ch >> 12) & 63) | 128; 345 | } 346 | ++r; 347 | result[r] = ((ch >> 6) & 63) | 128; 348 | } 349 | ++r; 350 | result[r] = (ch & 63) | 128; 351 | } 352 | ++r; 353 | } 354 | return result; 355 | 356 | 357 | 358 | } 359 | var ConstSet2 = setConstr([65, 90]); 360 | var ConstSet3 = setConstr(95, 32, 46); 361 | var ConstSet4 = setConstr(95, 32, 46); 362 | 363 | function mulInt(a_p0, b_p1) { 364 | var result = a_p0 * b_p1; 365 | checkOverflowInt(result); 366 | return result; 367 | 368 | 369 | 370 | } 371 | var ConstSet5 = setConstr([97, 122]); 372 | var ConstSet6 = setConstr([65, 90], [97, 122]); 373 | var ConstSet7 = setConstr([97, 122]); 374 | var ConstSet8 = setConstr([65, 90]); 375 | var ConstSet9 = setConstr([65, 90], [97, 122]); 376 | 377 | function nimMax(a_p0, b_p1) { 378 | var Temporary1; 379 | 380 | var result_33557145 = 0; 381 | 382 | BeforeRet: { 383 | if ((b_p1 <= a_p0)) { 384 | Temporary1 = a_p0; 385 | } 386 | else { 387 | Temporary1 = b_p1; 388 | } 389 | 390 | result_33557145 = Temporary1; 391 | break BeforeRet; 392 | }; 393 | 394 | return result_33557145; 395 | 396 | } 397 | 398 | function nimMin(a_p0, b_p1) { 399 | var Temporary1; 400 | 401 | var result_33557141 = 0; 402 | 403 | BeforeRet: { 404 | if ((a_p0 <= b_p1)) { 405 | Temporary1 = a_p0; 406 | } 407 | else { 408 | Temporary1 = b_p1; 409 | } 410 | 411 | result_33557141 = Temporary1; 412 | break BeforeRet; 413 | }; 414 | 415 | return result_33557141; 416 | 417 | } 418 | 419 | function addChar(x_p0, c_p1) { 420 | x_p0.push(c_p1); 421 | 422 | 423 | } 424 | var objectID_1140850865 = [0]; 425 | 426 | function setTheme(theme_p0) { 427 | document.documentElement.setAttribute("data-theme", theme_p0); 428 | window.localStorage.setItem("theme", theme_p0); 429 | 430 | 431 | } 432 | 433 | function add__system_u1943(x_p0, x_p0_Idx, y_p1) { 434 | if (x_p0[x_p0_Idx] === null) { x_p0[x_p0_Idx] = []; } 435 | var off = x_p0[x_p0_Idx].length; 436 | x_p0[x_p0_Idx].length += y_p1.length; 437 | for (var i = 0; i < y_p1.length; ++i) { 438 | x_p0[x_p0_Idx][off+i] = y_p1.charCodeAt(i); 439 | } 440 | 441 | 442 | 443 | } 444 | 445 | function newSeq__system_u2508(len_p0) { 446 | var result_33556944 = []; 447 | 448 | result_33556944 = new Array(len_p0); for (var i = 0 ; i < len_p0 ; ++i) { result_33556944[i] = null; } 449 | return result_33556944; 450 | 451 | } 452 | 453 | function unhandledException(e_p0) { 454 | var buf_33556659 = [[]]; 455 | if (!(((e_p0.message).length == 0))) { 456 | buf_33556659[0].push.apply(buf_33556659[0], [69,114,114,111,114,58,32,117,110,104,97,110,100,108,101,100,32,101,120,99,101,112,116,105,111,110,58,32]);; 457 | buf_33556659[0].push.apply(buf_33556659[0], e_p0.message);; 458 | } 459 | else { 460 | buf_33556659[0].push.apply(buf_33556659[0], [69,114,114,111,114,58,32,117,110,104,97,110,100,108,101,100,32,101,120,99,101,112,116,105,111,110]);; 461 | } 462 | 463 | buf_33556659[0].push.apply(buf_33556659[0], [32,91]);; 464 | add__system_u1943(buf_33556659, 0, e_p0.name); 465 | buf_33556659[0].push.apply(buf_33556659[0], [93,10]);; 466 | var cbuf_33556660 = toJSStr(buf_33556659[0]); 467 | if (typeof(Error) !== "undefined") { 468 | throw new Error(cbuf_33556660); 469 | } 470 | else { 471 | throw cbuf_33556660; 472 | } 473 | 474 | 475 | 476 | } 477 | 478 | function raiseOverflow() { 479 | raiseException({message: [111,118,101,114,45,32,111,114,32,117,110,100,101,114,102,108,111,119], parent: null, m_type: NTI134217743, name: null, trace: [], up: null}, "OverflowDefect"); 480 | 481 | 482 | } 483 | 484 | function checkOverflowInt(a_p0) { 485 | if (a_p0 > 2147483647 || a_p0 < -2147483648) raiseOverflow(); 486 | 487 | 488 | 489 | } 490 | 491 | function raiseRangeError() { 492 | raiseException({message: [118,97,108,117,101,32,111,117,116,32,111,102,32,114,97,110,103,101], parent: null, m_type: NTI134217751, name: null, trace: [], up: null}, "RangeDefect"); 493 | 494 | 495 | } 496 | 497 | function addChars__stdZprivateZdigitsutils_u202(result_p0, result_p0_Idx, x_p1, start_p2, n_p3) { 498 | var Temporary1; 499 | 500 | var old_301990096 = (result_p0[result_p0_Idx]).length; 501 | if (result_p0[result_p0_Idx].length < (Temporary1 = chckRange(addInt(old_301990096, n_p3), 0, 2147483647), Temporary1)) { for (var i = result_p0[result_p0_Idx].length; i < Temporary1; ++i) result_p0[result_p0_Idx].push(0); } 502 | else {result_p0[result_p0_Idx].length = Temporary1; }; 503 | Label2: { 504 | var iHEX60gensym4_301990110 = 0; 505 | var i_536872113 = 0; 506 | Label3: { 507 | Label4: while (true) { 508 | if (!(i_536872113 < n_p3)) break Label4; 509 | iHEX60gensym4_301990110 = i_536872113; 510 | result_p0[result_p0_Idx][chckIndx(addInt(old_301990096, iHEX60gensym4_301990110), 0, (result_p0[result_p0_Idx]).length - 1)] = x_p1.charCodeAt(chckIndx(addInt(start_p2, iHEX60gensym4_301990110), 0, (x_p1).length - 1)); 511 | i_536872113 = addInt(i_536872113, 1); 512 | } 513 | }; 514 | }; 515 | 516 | 517 | } 518 | 519 | function addChars__stdZprivateZdigitsutils_u198(result_p0, result_p0_Idx, x_p1) { 520 | addChars__stdZprivateZdigitsutils_u202(result_p0, result_p0_Idx, x_p1, 0, ((x_p1) == null ? 0 : (x_p1).length)); 521 | 522 | 523 | } 524 | 525 | function addInt__stdZprivateZdigitsutils_u223(result_p0, result_p0_Idx, x_p1) { 526 | addChars__stdZprivateZdigitsutils_u198(result_p0, result_p0_Idx, ((x_p1) + "")); 527 | 528 | 529 | } 530 | 531 | function addInt__stdZprivateZdigitsutils_u241(result_p0, result_p0_Idx, x_p1) { 532 | addInt__stdZprivateZdigitsutils_u223(result_p0, result_p0_Idx, BigInt(x_p1)); 533 | 534 | 535 | } 536 | 537 | function HEX24__systemZdollars_u8(x_p0) { 538 | var result_385875978 = [[]]; 539 | 540 | addInt__stdZprivateZdigitsutils_u241(result_385875978, 0, x_p0); 541 | 542 | return result_385875978[0]; 543 | 544 | } 545 | 546 | function isFatPointer__system_u2866(ti_p0) { 547 | var result_33557300 = false; 548 | 549 | BeforeRet: { 550 | result_33557300 = !((ConstSet1[ti_p0.base.kind] != undefined)); 551 | break BeforeRet; 552 | }; 553 | 554 | return result_33557300; 555 | 556 | } 557 | 558 | function nimCopyAux(dest_p0, src_p1, n_p2) { 559 | switch (n_p2.kind) { 560 | case 0: 561 | break; 562 | case 1: 563 | dest_p0[n_p2.offset] = nimCopy(dest_p0[n_p2.offset], src_p1[n_p2.offset], n_p2.typ); 564 | 565 | break; 566 | case 2: 567 | for (var i = 0; i < n_p2.sons.length; i++) { 568 | nimCopyAux(dest_p0, src_p1, n_p2.sons[i]); 569 | } 570 | 571 | break; 572 | case 3: 573 | dest_p0[n_p2.offset] = nimCopy(dest_p0[n_p2.offset], src_p1[n_p2.offset], n_p2.typ); 574 | for (var i = 0; i < n_p2.sons.length; ++i) { 575 | nimCopyAux(dest_p0, src_p1, n_p2.sons[i][1]); 576 | } 577 | 578 | break; 579 | } 580 | 581 | 582 | } 583 | 584 | function raiseIndexError(i_p0, a_p1, b_p2) { 585 | var Temporary1; 586 | 587 | if ((b_p2 < a_p1)) { 588 | Temporary1 = [105,110,100,101,120,32,111,117,116,32,111,102,32,98,111,117,110,100,115,44,32,116,104,101,32,99,111,110,116,97,105,110,101,114,32,105,115,32,101,109,112,116,121]; 589 | } 590 | else { 591 | Temporary1 = ([105,110,100,101,120,32]).concat(HEX24__systemZdollars_u8(i_p0),[32,110,111,116,32,105,110,32],HEX24__systemZdollars_u8(a_p1),[32,46,46,32],HEX24__systemZdollars_u8(b_p2)); 592 | } 593 | 594 | raiseException({message: nimCopy(null, Temporary1, NTI33554449), parent: null, m_type: NTI134217749, name: null, trace: [], up: null}, "IndexDefect"); 595 | 596 | 597 | } 598 | 599 | function sysFatal__stdZassertions_u45(message_p1) { 600 | raiseException({message: nimCopy(null, message_p1, NTI33554449), m_type: NTI134217745, parent: null, name: null, trace: [], up: null}, "AssertionDefect"); 601 | 602 | 603 | } 604 | 605 | function raiseAssert__stdZassertions_u43(msg_p0) { 606 | sysFatal__stdZassertions_u45(msg_p0); 607 | 608 | 609 | } 610 | 611 | function failedAssertImpl__stdZassertions_u85(msg_p0) { 612 | raiseAssert__stdZassertions_u43(msg_p0); 613 | 614 | 615 | } 616 | 617 | function onDOMLoaded(e_p0) { 618 | var Temporary4; 619 | 620 | function HEX3Aanonymous__dochack_u65(event_p0) { 621 | event_p0.target.parentNode.style.display = "none"; 622 | event_p0.target.parentNode.nextSibling.style.display = "inline"; 623 | 624 | 625 | } 626 | 627 | document.getElementById("theme-select").value = window.localStorage.getItem("theme"); 628 | Label1: { 629 | var pragmaDots_536870976 = null; 630 | var colontmp__536872104 = []; 631 | colontmp__536872104 = document.getElementsByClassName("pragmadots"); 632 | var i_536872106 = 0; 633 | var L_536872107 = (colontmp__536872104).length; 634 | Label2: { 635 | Label3: while (true) { 636 | if (!(i_536872106 < L_536872107)) break Label3; 637 | pragmaDots_536870976 = colontmp__536872104[chckIndx(i_536872106, 0, (colontmp__536872104).length - 1)]; 638 | Temporary4 = HEX3Aanonymous__dochack_u65.bind(null); Temporary4.ClP_0 = HEX3Aanonymous__dochack_u65; Temporary4.ClE_0 = null; 639 | pragmaDots_536870976.onclick = Temporary4; 640 | i_536872106 += 1; 641 | if (!(((colontmp__536872104).length == L_536872107))) { 642 | failedAssertImpl__stdZassertions_u85(makeNimstrLit("iterators.nim(254, 11) `len(a) == L` the length of the seq changed while iterating over it")); 643 | } 644 | 645 | } 646 | }; 647 | }; 648 | 649 | 650 | } 651 | 652 | function isWhitespace__dochack_u408(x_p0) { 653 | var result_536871322 = false; 654 | 655 | result_536871322 = (((x_p0.nodeName == "#text") && !/\S/.test(x_p0.textContent)) || (x_p0.nodeName == "#comment")); 656 | 657 | return result_536871322; 658 | 659 | } 660 | 661 | function toToc__dochack_u411(x_p0, father_p1) { 662 | var Temporary5; 663 | var Temporary6; 664 | var Temporary7; 665 | var Temporary8; 666 | var Temporary15; 667 | 668 | if ((x_p0.nodeName == "UL")) { 669 | var f_536871333 = {heading: null, kids: [], sortId: (father_p1.kids).length, doSort: false}; 670 | var i_536871334 = 0; 671 | Label1: { 672 | Label2: while (true) { 673 | if (!(i_536871334 < x_p0.childNodes.length)) break Label2; 674 | var nxt_536871335 = addInt(i_536871334, 1); 675 | Label3: { 676 | Label4: while (true) { 677 | if (!(nxt_536871335 < x_p0.childNodes.length)) Temporary5 = false; else { Temporary5 = isWhitespace__dochack_u408(x_p0.childNodes[nxt_536871335]); } if (!Temporary5) break Label4; 678 | nxt_536871335 = addInt(nxt_536871335, 1); 679 | } 680 | }; 681 | if (!(nxt_536871335 < x_p0.childNodes.length)) Temporary8 = false; else { Temporary8 = (x_p0.childNodes[i_536871334].nodeName == "LI"); } if (!Temporary8) Temporary7 = false; else { Temporary7 = (x_p0.childNodes[i_536871334].childNodes.length == 1); } if (!Temporary7) Temporary6 = false; else { Temporary6 = (x_p0.childNodes[nxt_536871335].nodeName == "UL"); } if (Temporary6) { 682 | var e_536871348 = {heading: x_p0.childNodes[i_536871334].childNodes[0], kids: [], sortId: (f_536871333.kids).length, doSort: false}; 683 | var it_536871349 = x_p0.childNodes[nxt_536871335]; 684 | Label9: { 685 | var j_536871354 = 0; 686 | var colontmp__536872120 = 0; 687 | colontmp__536872120 = it_536871349.childNodes.length; 688 | var i_536872121 = 0; 689 | Label10: { 690 | Label11: while (true) { 691 | if (!(i_536872121 < colontmp__536872120)) break Label11; 692 | j_536871354 = i_536872121; 693 | toToc__dochack_u411(it_536871349.childNodes[j_536871354], e_536871348); 694 | i_536872121 = addInt(i_536872121, 1); 695 | } 696 | }; 697 | }; 698 | f_536871333.kids.push(e_536871348);; 699 | i_536871334 = addInt(nxt_536871335, 1); 700 | } 701 | else { 702 | toToc__dochack_u411(x_p0.childNodes[i_536871334], f_536871333); 703 | i_536871334 = addInt(i_536871334, 1); 704 | } 705 | 706 | } 707 | }; 708 | father_p1.kids.push(f_536871333);; 709 | } 710 | else { 711 | if (isWhitespace__dochack_u408(x_p0)) { 712 | } 713 | else { 714 | if ((x_p0.nodeName == "LI")) { 715 | var idx_536871372 = []; 716 | Label12: { 717 | var i_536871377 = 0; 718 | var colontmp__536872124 = 0; 719 | colontmp__536872124 = x_p0.childNodes.length; 720 | var i_536872125 = 0; 721 | Label13: { 722 | Label14: while (true) { 723 | if (!(i_536872125 < colontmp__536872124)) break Label14; 724 | i_536871377 = i_536872125; 725 | if (!(isWhitespace__dochack_u408(x_p0.childNodes[i_536871377]))) { 726 | idx_536871372.push(i_536871377);; 727 | } 728 | 729 | i_536872125 = addInt(i_536872125, 1); 730 | } 731 | }; 732 | }; 733 | if (!((idx_536871372).length == 2)) Temporary15 = false; else { Temporary15 = (x_p0.childNodes[idx_536871372[chckIndx(1, 0, (idx_536871372).length - 1)]].nodeName == "UL"); } if (Temporary15) { 734 | var e_536871393 = {heading: x_p0.childNodes[idx_536871372[chckIndx(0, 0, (idx_536871372).length - 1)]], kids: [], sortId: (father_p1.kids).length, doSort: false}; 735 | var it_536871394 = x_p0.childNodes[idx_536871372[chckIndx(1, 0, (idx_536871372).length - 1)]]; 736 | Label16: { 737 | var j_536871399 = 0; 738 | var colontmp__536872128 = 0; 739 | colontmp__536872128 = it_536871394.childNodes.length; 740 | var i_536872129 = 0; 741 | Label17: { 742 | Label18: while (true) { 743 | if (!(i_536872129 < colontmp__536872128)) break Label18; 744 | j_536871399 = i_536872129; 745 | toToc__dochack_u411(it_536871394.childNodes[j_536871399], e_536871393); 746 | i_536872129 = addInt(i_536872129, 1); 747 | } 748 | }; 749 | }; 750 | father_p1.kids.push(e_536871393);; 751 | } 752 | else { 753 | Label19: { 754 | var i_536871408 = 0; 755 | var colontmp__536872132 = 0; 756 | colontmp__536872132 = x_p0.childNodes.length; 757 | var i_536872133 = 0; 758 | Label20: { 759 | Label21: while (true) { 760 | if (!(i_536872133 < colontmp__536872132)) break Label21; 761 | i_536871408 = i_536872133; 762 | toToc__dochack_u411(x_p0.childNodes[i_536871408], father_p1); 763 | i_536872133 = addInt(i_536872133, 1); 764 | } 765 | }; 766 | }; 767 | } 768 | 769 | } 770 | else { 771 | father_p1.kids.push({heading: x_p0, kids: [], sortId: (father_p1.kids).length, doSort: false});; 772 | } 773 | }} 774 | 775 | 776 | } 777 | 778 | function extractItems__dochack_u199(x_p0, heading_p1, items_p2, items_p2_Idx) { 779 | BeforeRet: { 780 | if ((x_p0 == null)) { 781 | break BeforeRet; 782 | } 783 | 784 | if ((!((x_p0.heading == null)) && (x_p0.heading.textContent == heading_p1))) { 785 | Label1: { 786 | var i_536871131 = 0; 787 | var colontmp__536872136 = 0; 788 | colontmp__536872136 = (x_p0.kids).length; 789 | var i_536872137 = 0; 790 | Label2: { 791 | Label3: while (true) { 792 | if (!(i_536872137 < colontmp__536872136)) break Label3; 793 | i_536871131 = i_536872137; 794 | items_p2[items_p2_Idx].push(x_p0.kids[chckIndx(i_536871131, 0, (x_p0.kids).length - 1)].heading);; 795 | i_536872137 = addInt(i_536872137, 1); 796 | } 797 | }; 798 | }; 799 | } 800 | else { 801 | Label4: { 802 | var k_536871157 = null; 803 | var i_536872141 = 0; 804 | var L_536872142 = (x_p0.kids).length; 805 | Label5: { 806 | Label6: while (true) { 807 | if (!(i_536872141 < L_536872142)) break Label6; 808 | k_536871157 = x_p0.kids[chckIndx(i_536872141, 0, (x_p0.kids).length - 1)]; 809 | extractItems__dochack_u199(k_536871157, heading_p1, items_p2, items_p2_Idx); 810 | i_536872141 += 1; 811 | if (!(((x_p0.kids).length == L_536872142))) { 812 | failedAssertImpl__stdZassertions_u85(makeNimstrLit("iterators.nim(254, 11) `len(a) == L` the length of the seq changed while iterating over it")); 813 | } 814 | 815 | } 816 | }; 817 | }; 818 | } 819 | 820 | }; 821 | 822 | 823 | } 824 | 825 | function tree__dochack_u130(tag_p0, kids_p1) { 826 | var result_536871045 = null; 827 | 828 | result_536871045 = document.createElement(tag_p0); 829 | Label1: { 830 | var k_536871059 = null; 831 | var i_536872154 = 0; 832 | Label2: { 833 | Label3: while (true) { 834 | if (!(i_536872154 < (kids_p1).length)) break Label3; 835 | k_536871059 = kids_p1[chckIndx(i_536872154, 0, (kids_p1).length - 1)]; 836 | result_536871045.appendChild(k_536871059); 837 | i_536872154 += 1; 838 | } 839 | }; 840 | }; 841 | 842 | return result_536871045; 843 | 844 | } 845 | 846 | function text__dochack_u155(s_p0) { 847 | var result_536871069 = null; 848 | 849 | result_536871069 = document.createTextNode(s_p0); 850 | 851 | return result_536871069; 852 | 853 | } 854 | 855 | function uncovered__dochack_u600(x_p0) { 856 | var Temporary1; 857 | 858 | var result_536871514 = null; 859 | 860 | BeforeRet: { 861 | if ((((x_p0.kids).length == 0) && !((x_p0.heading == null)))) { 862 | if (!(x_p0.heading.hasOwnProperty('__karaxMarker__'))) { 863 | Temporary1 = x_p0; 864 | } 865 | else { 866 | Temporary1 = null; 867 | } 868 | 869 | result_536871514 = Temporary1; 870 | break BeforeRet; 871 | } 872 | 873 | result_536871514 = {heading: x_p0.heading, kids: [], sortId: x_p0.sortId, doSort: x_p0.doSort}; 874 | Label2: { 875 | var k_536871529 = null; 876 | var i_536872161 = 0; 877 | var L_536872162 = (x_p0.kids).length; 878 | Label3: { 879 | Label4: while (true) { 880 | if (!(i_536872161 < L_536872162)) break Label4; 881 | k_536871529 = x_p0.kids[chckIndx(i_536872161, 0, (x_p0.kids).length - 1)]; 882 | var y_536871530 = uncovered__dochack_u600(k_536871529); 883 | if (!((y_536871530 == null))) { 884 | result_536871514.kids.push(y_536871530);; 885 | } 886 | 887 | i_536872161 += 1; 888 | if (!(((x_p0.kids).length == L_536872162))) { 889 | failedAssertImpl__stdZassertions_u85(makeNimstrLit("iterators.nim(254, 11) `len(a) == L` the length of the seq changed while iterating over it")); 890 | } 891 | 892 | } 893 | }; 894 | }; 895 | if (((result_536871514.kids).length == 0)) { 896 | result_536871514 = null; 897 | } 898 | 899 | }; 900 | 901 | return result_536871514; 902 | 903 | } 904 | 905 | function mergeTocs__dochack_u630(orig_p0, news_p1) { 906 | var result_536871545 = null; 907 | 908 | result_536871545 = uncovered__dochack_u600(orig_p0); 909 | if ((result_536871545 == null)) { 910 | result_536871545 = news_p1; 911 | } 912 | else { 913 | Label1: { 914 | var i_536871557 = 0; 915 | var colontmp__536872157 = 0; 916 | colontmp__536872157 = (news_p1.kids).length; 917 | var i_536872158 = 0; 918 | Label2: { 919 | Label3: while (true) { 920 | if (!(i_536872158 < colontmp__536872157)) break Label3; 921 | i_536871557 = i_536872158; 922 | result_536871545.kids.push(news_p1.kids[chckIndx(i_536871557, 0, (news_p1.kids).length - 1)]);; 923 | i_536872158 = addInt(i_536872158, 1); 924 | } 925 | }; 926 | }; 927 | } 928 | 929 | 930 | return result_536871545; 931 | 932 | } 933 | 934 | function buildToc__dochack_u650(orig_p0, types_p1, procs_p2) { 935 | var result_536871566 = null; 936 | 937 | var newStuff_536871571 = {heading: null, kids: [], doSort: true, sortId: 0}; 938 | Label1: { 939 | var t_536871575 = null; 940 | var i_536872149 = 0; 941 | var L_536872150 = (types_p1).length; 942 | Label2: { 943 | Label3: while (true) { 944 | if (!(i_536872149 < L_536872150)) break Label3; 945 | t_536871575 = types_p1[chckIndx(i_536872149, 0, (types_p1).length - 1)]; 946 | var c_536871580 = {heading: t_536871575.cloneNode(true), kids: [], doSort: true, sortId: 0}; 947 | t_536871575.__karaxMarker__ = true; 948 | Label4: { 949 | var p_536871584 = null; 950 | var i_536872146 = 0; 951 | var L_536872147 = (procs_p2).length; 952 | Label5: { 953 | Label6: while (true) { 954 | if (!(i_536872146 < L_536872147)) break Label6; 955 | p_536871584 = procs_p2[chckIndx(i_536872146, 0, (procs_p2).length - 1)]; 956 | if (!(p_536871584.hasOwnProperty('__karaxMarker__'))) { 957 | var xx_536871585 = p_536871584.parentNode.getElementsByClassName("attachedType"); 958 | if ((((xx_536871585).length == 1) && (xx_536871585[chckIndx(0, 0, (xx_536871585).length - 1)].textContent == t_536871575.textContent))) { 959 | var q_536871590 = tree__dochack_u130("A", [text__dochack_u155(p_536871584.title)]); 960 | q_536871590.setAttribute("href", p_536871584.getAttribute("href")); 961 | c_536871580.kids.push({heading: q_536871590, kids: [], sortId: 0, doSort: false});; 962 | p_536871584.__karaxMarker__ = true; 963 | } 964 | 965 | } 966 | 967 | i_536872146 += 1; 968 | if (!(((procs_p2).length == L_536872147))) { 969 | failedAssertImpl__stdZassertions_u85(makeNimstrLit("iterators.nim(254, 11) `len(a) == L` the length of the seq changed while iterating over it")); 970 | } 971 | 972 | } 973 | }; 974 | }; 975 | newStuff_536871571.kids.push(c_536871580);; 976 | i_536872149 += 1; 977 | if (!(((types_p1).length == L_536872150))) { 978 | failedAssertImpl__stdZassertions_u85(makeNimstrLit("iterators.nim(254, 11) `len(a) == L` the length of the seq changed while iterating over it")); 979 | } 980 | 981 | } 982 | }; 983 | }; 984 | result_536871566 = mergeTocs__dochack_u630(orig_p0, newStuff_536871571); 985 | 986 | return result_536871566; 987 | 988 | } 989 | 990 | function add__dochack_u148(parent_p0, kid_p1) { 991 | if (((parent_p0.nodeName == "TR") && ((kid_p1.nodeName == "TD") || (kid_p1.nodeName == "TH")))) { 992 | var k_536871063 = document.createElement("TD"); 993 | k_536871063.appendChild(kid_p1); 994 | parent_p0.appendChild(k_536871063); 995 | } 996 | else { 997 | parent_p0.appendChild(kid_p1); 998 | } 999 | 1000 | 1001 | 1002 | } 1003 | 1004 | function setClass__dochack_u152(e_p0, value_p1) { 1005 | e_p0.setAttribute("class", value_p1); 1006 | 1007 | 1008 | } 1009 | 1010 | function toHtml__dochack_u278(x_p0, isRoot_p1) { 1011 | var Temporary1; 1012 | 1013 | function HEX3Aanonymous__dochack_u298(a_p0, b_p1) { 1014 | var result_536871213 = 0; 1015 | 1016 | BeforeRet: { 1017 | if ((!((a_p0.heading == null)) && !((b_p1.heading == null)))) { 1018 | var x_536871222 = a_p0.heading.textContent; 1019 | var y_536871223 = b_p1.heading.textContent; 1020 | if ((x_536871222 < y_536871223)) { 1021 | result_536871213 = (-1); 1022 | break BeforeRet; 1023 | } 1024 | 1025 | if ((y_536871223 < x_536871222)) { 1026 | result_536871213 = 1; 1027 | break BeforeRet; 1028 | } 1029 | 1030 | result_536871213 = 0; 1031 | break BeforeRet; 1032 | } 1033 | else { 1034 | result_536871213 = subInt(a_p0.sortId, b_p1.sortId); 1035 | break BeforeRet; 1036 | } 1037 | 1038 | }; 1039 | 1040 | return result_536871213; 1041 | 1042 | } 1043 | 1044 | var result_536871193 = null; 1045 | 1046 | BeforeRet: { 1047 | if ((x_p0 == null)) { 1048 | result_536871193 = null; 1049 | break BeforeRet; 1050 | } 1051 | 1052 | if (((x_p0.kids).length == 0)) { 1053 | if ((x_p0.heading == null)) { 1054 | result_536871193 = null; 1055 | break BeforeRet; 1056 | } 1057 | 1058 | result_536871193 = x_p0.heading.cloneNode(true); 1059 | break BeforeRet; 1060 | } 1061 | 1062 | result_536871193 = tree__dochack_u130("DIV", []); 1063 | if ((!((x_p0.heading == null)) && !(x_p0.heading.hasOwnProperty('__karaxMarker__')))) { 1064 | add__dochack_u148(result_536871193, x_p0.heading.cloneNode(true)); 1065 | } 1066 | 1067 | var ul_536871209 = tree__dochack_u130("UL", []); 1068 | if (isRoot_p1) { 1069 | setClass__dochack_u152(ul_536871209, "simple simple-toc"); 1070 | } 1071 | else { 1072 | setClass__dochack_u152(ul_536871209, "simple"); 1073 | } 1074 | 1075 | if (x_p0.doSort) { 1076 | Temporary1 = HEX3Aanonymous__dochack_u298.bind(null); Temporary1.ClP_0 = HEX3Aanonymous__dochack_u298; Temporary1.ClE_0 = null; 1077 | x_p0.kids.sort(Temporary1); 1078 | } 1079 | 1080 | Label2: { 1081 | var k_536871235 = null; 1082 | var i_536872165 = 0; 1083 | var L_536872166 = (x_p0.kids).length; 1084 | Label3: { 1085 | Label4: while (true) { 1086 | if (!(i_536872165 < L_536872166)) break Label4; 1087 | k_536871235 = x_p0.kids[chckIndx(i_536872165, 0, (x_p0.kids).length - 1)]; 1088 | var y_536871236 = toHtml__dochack_u278(k_536871235, false); 1089 | if (!((y_536871236 == null))) { 1090 | add__dochack_u148(ul_536871209, tree__dochack_u130("LI", [y_536871236])); 1091 | } 1092 | 1093 | i_536872165 += 1; 1094 | if (!(((x_p0.kids).length == L_536872166))) { 1095 | failedAssertImpl__stdZassertions_u85(makeNimstrLit("iterators.nim(254, 11) `len(a) == L` the length of the seq changed while iterating over it")); 1096 | } 1097 | 1098 | } 1099 | }; 1100 | }; 1101 | if (!((ul_536871209.childNodes.length == 0))) { 1102 | add__dochack_u148(result_536871193, ul_536871209); 1103 | } 1104 | 1105 | if ((result_536871193.childNodes.length == 0)) { 1106 | result_536871193 = null; 1107 | } 1108 | 1109 | }; 1110 | 1111 | return result_536871193; 1112 | 1113 | } 1114 | 1115 | function replaceById__dochack_u158(id_p0, newTree_p1) { 1116 | var x_536871073 = document.getElementById(id_p0); 1117 | x_536871073.parentNode.replaceChild(newTree_p1, x_536871073); 1118 | newTree_p1.id = id_p0; 1119 | 1120 | 1121 | } 1122 | 1123 | function togglevis__dochack_u708(d_p0) { 1124 | if ((d_p0.style.display == "none")) { 1125 | d_p0.style.display = "inline"; 1126 | } 1127 | else { 1128 | d_p0.style.display = "none"; 1129 | } 1130 | 1131 | 1132 | 1133 | } 1134 | 1135 | function groupBy(value_p0) { 1136 | var toc_536871624 = document.getElementById("toc-list"); 1137 | if ((alternative_536871619[0] == null)) { 1138 | var tt_536871632 = {heading: null, kids: [], sortId: 0, doSort: false}; 1139 | toToc__dochack_u411(toc_536871624, tt_536871632); 1140 | tt_536871632 = tt_536871632.kids[chckIndx(0, 0, (tt_536871632.kids).length - 1)]; 1141 | var types_536871637 = [[]]; 1142 | var procs_536871642 = [[]]; 1143 | extractItems__dochack_u199(tt_536871632, "Types", types_536871637, 0); 1144 | extractItems__dochack_u199(tt_536871632, "Procs", procs_536871642, 0); 1145 | extractItems__dochack_u199(tt_536871632, "Converters", procs_536871642, 0); 1146 | extractItems__dochack_u199(tt_536871632, "Methods", procs_536871642, 0); 1147 | extractItems__dochack_u199(tt_536871632, "Templates", procs_536871642, 0); 1148 | extractItems__dochack_u199(tt_536871632, "Macros", procs_536871642, 0); 1149 | extractItems__dochack_u199(tt_536871632, "Iterators", procs_536871642, 0); 1150 | var ntoc_536871643 = buildToc__dochack_u650(tt_536871632, types_536871637[0], procs_536871642[0]); 1151 | var x_536871644 = toHtml__dochack_u278(ntoc_536871643, true); 1152 | alternative_536871619[0] = tree__dochack_u130("DIV", [x_536871644]); 1153 | } 1154 | 1155 | if ((value_p0 == "type")) { 1156 | replaceById__dochack_u158("tocRoot", alternative_536871619[0]); 1157 | } 1158 | else { 1159 | replaceById__dochack_u158("tocRoot", tree__dochack_u130("DIV", [])); 1160 | } 1161 | 1162 | togglevis__dochack_u708(document.getElementById("toc-list")); 1163 | 1164 | 1165 | } 1166 | 1167 | function HEX5BHEX5D__pureZstrutils_u1307(s_p0, x_p1) { 1168 | var result_704644384 = []; 1169 | 1170 | var a_704644386 = x_p1.a; 1171 | var L_704644388 = addInt(subInt(subInt((s_p0).length, x_p1.b), a_704644386), 1); 1172 | result_704644384 = nimCopy(null, mnewString(chckRange(L_704644388, 0, 2147483647)), NTI33554449); 1173 | Label1: { 1174 | var i_704644393 = 0; 1175 | var i_536872175 = 0; 1176 | Label2: { 1177 | Label3: while (true) { 1178 | if (!(i_536872175 < L_704644388)) break Label3; 1179 | i_704644393 = i_536872175; 1180 | result_704644384[chckIndx(i_704644393, 0, (result_704644384).length - 1)] = s_p0[chckIndx(addInt(i_704644393, a_704644386), 0, (s_p0).length - 1)]; 1181 | i_536872175 = addInt(i_536872175, 1); 1182 | } 1183 | }; 1184 | }; 1185 | 1186 | return result_704644384; 1187 | 1188 | } 1189 | 1190 | function HEX2EHEX2E__stdZenumutils_u105(a_p0, b_p1) { 1191 | var result_922746992 = ({a: 0, b: 0}); 1192 | 1193 | result_922746992 = nimCopy(result_922746992, {a: a_p0, b: b_p1}, NTI922746965); 1194 | 1195 | return result_922746992; 1196 | 1197 | } 1198 | async function loadIndex__dochack_u928() { 1199 | var result_536871842 = null; 1200 | 1201 | BeforeRet: { 1202 | var indexURL_536871848 = document.getElementById("indexLink").getAttribute("href"); 1203 | var rootURL_536871874 = HEX5BHEX5D__pureZstrutils_u1307(cstrToNimstr(indexURL_536871848), HEX2EHEX2E__stdZenumutils_u105(0, 14)); 1204 | var resp_536871886 = (await (await fetch(indexURL_536871848)).text()); 1205 | var indexElem_536871887 = document.createElement("div"); 1206 | indexElem_536871887.innerHTML = resp_536871886; 1207 | Label1: { 1208 | var href_536871909 = null; 1209 | var colontmp__536872169 = []; 1210 | colontmp__536872169 = indexElem_536871887.getElementsByClassName("reference"); 1211 | var i_536872171 = 0; 1212 | var L_536872172 = (colontmp__536872169).length; 1213 | Label2: { 1214 | Label3: while (true) { 1215 | if (!(i_536872171 < L_536872172)) break Label3; 1216 | href_536871909 = colontmp__536872169[chckIndx(i_536872171, 0, (colontmp__536872169).length - 1)]; 1217 | href_536871909.setAttribute("href", toJSStr((rootURL_536871874).concat(cstrToNimstr(href_536871909.getAttribute("href"))))); 1218 | db_536871661[0].push(href_536871909);; 1219 | contents_536871662[0].push(href_536871909.getAttribute("data-doc-search-tag"));; 1220 | i_536872171 += 1; 1221 | if (!(((colontmp__536872169).length == L_536872172))) { 1222 | failedAssertImpl__stdZassertions_u85(makeNimstrLit("iterators.nim(254, 11) `len(a) == L` the length of the seq changed while iterating over it")); 1223 | } 1224 | 1225 | } 1226 | }; 1227 | }; 1228 | result_536871842 = undefined; 1229 | break BeforeRet; 1230 | }; 1231 | 1232 | return result_536871842; 1233 | 1234 | } 1235 | 1236 | function then__dochack_u1106(future_p0, onSuccess_p1, onReject_p2) { 1237 | var result_536872024 = null; 1238 | 1239 | BeforeRet: { 1240 | var ret_536872034 = null; 1241 | ret_536872034 = future_p0.then(onSuccess_p1, onReject_p2); 1242 | result_536872024 = ret_536872034; 1243 | break BeforeRet; 1244 | }; 1245 | 1246 | return result_536872024; 1247 | 1248 | } 1249 | 1250 | function nsuToLowerAsciiChar(c_p0) { 1251 | var result_704643158 = 0; 1252 | 1253 | if ((ConstSet2[c_p0] != undefined)) { 1254 | result_704643158 = (c_p0 ^ 32); 1255 | } 1256 | else { 1257 | result_704643158 = c_p0; 1258 | } 1259 | 1260 | 1261 | return result_704643158; 1262 | 1263 | } 1264 | 1265 | function fuzzyMatch__fuzzysearch_u16(pattern_p0, str_p1) { 1266 | var Temporary4; 1267 | var Temporary5; 1268 | var Temporary6; 1269 | var Temporary7; 1270 | var Temporary8; 1271 | 1272 | var result_687865877 = {Field0: 0, Field1: false}; 1273 | 1274 | var scoreState_687865878 = (-100); 1275 | var headerMatched_687865879 = false; 1276 | var unmatchedLeadingCharCount_687865880 = 0; 1277 | var consecutiveMatchCount_687865881 = 0; 1278 | var strIndex_687865882 = 0; 1279 | var patIndex_687865883 = 0; 1280 | var score_687865884 = 0; 1281 | Label1: { 1282 | Label2: while (true) { 1283 | if (!((strIndex_687865882 < ((str_p1) == null ? 0 : (str_p1).length)) && (patIndex_687865883 < ((pattern_p0) == null ? 0 : (pattern_p0).length)))) break Label2; 1284 | Label3: { 1285 | var patternChar_687865887 = nsuToLowerAsciiChar(pattern_p0.charCodeAt(chckIndx(patIndex_687865883, 0, (pattern_p0).length - 1))); 1286 | var strChar_687865888 = nsuToLowerAsciiChar(str_p1.charCodeAt(chckIndx(strIndex_687865882, 0, (str_p1).length - 1))); 1287 | if ((ConstSet3[patternChar_687865887] != undefined)) { 1288 | patIndex_687865883 = addInt(patIndex_687865883, 1); 1289 | break Label3; 1290 | } 1291 | 1292 | if ((ConstSet4[strChar_687865888] != undefined)) { 1293 | strIndex_687865882 = addInt(strIndex_687865882, 1); 1294 | break Label3; 1295 | } 1296 | 1297 | if ((!(headerMatched_687865879) && (strChar_687865888 == 58))) { 1298 | headerMatched_687865879 = true; 1299 | scoreState_687865878 = (-100); 1300 | score_687865884 = ((Math.floor((0.5 * score_687865884))) | 0); 1301 | patIndex_687865883 = 0; 1302 | strIndex_687865882 = addInt(strIndex_687865882, 1); 1303 | break Label3; 1304 | } 1305 | 1306 | if ((strChar_687865888 == patternChar_687865887)) { 1307 | switch (scoreState_687865878) { 1308 | case (-100): 1309 | case 20: 1310 | scoreState_687865878 = 10; 1311 | break; 1312 | case 0: 1313 | scoreState_687865878 = 5; 1314 | score_687865884 = addInt(score_687865884, scoreState_687865878); 1315 | break; 1316 | case 10: 1317 | case 5: 1318 | consecutiveMatchCount_687865881 = addInt(consecutiveMatchCount_687865881, 1); 1319 | scoreState_687865878 = 5; 1320 | score_687865884 = addInt(score_687865884, mulInt(5, consecutiveMatchCount_687865881)); 1321 | if ((scoreState_687865878 == 10)) { 1322 | score_687865884 = addInt(score_687865884, 10); 1323 | } 1324 | 1325 | var onBoundary_687865940 = (patIndex_687865883 == ((pattern_p0) == null ? -1 : (pattern_p0).length - 1)); 1326 | if ((!(onBoundary_687865940) && (strIndex_687865882 < ((str_p1) == null ? -1 : (str_p1).length - 1)))) { 1327 | var nextPatternChar_687865941 = nsuToLowerAsciiChar(pattern_p0.charCodeAt(chckIndx(addInt(patIndex_687865883, 1), 0, (pattern_p0).length - 1))); 1328 | var nextStrChar_687865942 = nsuToLowerAsciiChar(str_p1.charCodeAt(chckIndx(addInt(strIndex_687865882, 1), 0, (str_p1).length - 1))); 1329 | if (!!((ConstSet5[nextStrChar_687865942] != undefined))) Temporary4 = false; else { Temporary4 = !((nextStrChar_687865942 == nextPatternChar_687865941)); } onBoundary_687865940 = Temporary4; 1330 | } 1331 | 1332 | if (onBoundary_687865940) { 1333 | scoreState_687865878 = 20; 1334 | score_687865884 = addInt(score_687865884, scoreState_687865878); 1335 | } 1336 | 1337 | break; 1338 | case (-1): 1339 | case (-3): 1340 | if (!((ConstSet6[str_p1.charCodeAt(chckIndx(subInt(strIndex_687865882, 1), 0, (str_p1).length - 1))] != undefined))) Temporary5 = true; else { if (!(ConstSet7[str_p1.charCodeAt(chckIndx(subInt(strIndex_687865882, 1), 0, (str_p1).length - 1))] != undefined)) Temporary6 = false; else { Temporary6 = (ConstSet8[str_p1.charCodeAt(chckIndx(strIndex_687865882, 0, (str_p1).length - 1))] != undefined); } Temporary5 = Temporary6; } var isLeadingChar_687865966 = Temporary5; 1341 | if (isLeadingChar_687865966) { 1342 | scoreState_687865878 = 10; 1343 | } 1344 | else { 1345 | scoreState_687865878 = 0; 1346 | score_687865884 = addInt(score_687865884, scoreState_687865878); 1347 | } 1348 | 1349 | break; 1350 | } 1351 | patIndex_687865883 = addInt(patIndex_687865883, 1); 1352 | } 1353 | else { 1354 | switch (scoreState_687865878) { 1355 | case (-100): 1356 | scoreState_687865878 = (-3); 1357 | score_687865884 = addInt(score_687865884, scoreState_687865878); 1358 | break; 1359 | case 5: 1360 | scoreState_687865878 = (-1); 1361 | score_687865884 = addInt(score_687865884, scoreState_687865878); 1362 | consecutiveMatchCount_687865881 = 0; 1363 | break; 1364 | case (-3): 1365 | if ((unmatchedLeadingCharCount_687865880 < 3)) { 1366 | scoreState_687865878 = (-3); 1367 | score_687865884 = addInt(score_687865884, scoreState_687865878); 1368 | } 1369 | 1370 | unmatchedLeadingCharCount_687865880 = addInt(unmatchedLeadingCharCount_687865880, 1); 1371 | break; 1372 | default: 1373 | scoreState_687865878 = (-1); 1374 | score_687865884 = addInt(score_687865884, scoreState_687865878); 1375 | break; 1376 | } 1377 | } 1378 | 1379 | strIndex_687865882 = addInt(strIndex_687865882, 1); 1380 | }; 1381 | } 1382 | }; 1383 | if (!(patIndex_687865883 == ((pattern_p0) == null ? 0 : (pattern_p0).length))) Temporary7 = false; else { if ((strIndex_687865882 == ((str_p1) == null ? 0 : (str_p1).length))) Temporary8 = true; else { Temporary8 = !((ConstSet9[str_p1.charCodeAt(chckIndx(strIndex_687865882, 0, (str_p1).length - 1))] != undefined)); } Temporary7 = Temporary8; } if (Temporary7) { 1384 | score_687865884 = addInt(score_687865884, 10); 1385 | } 1386 | 1387 | var colontmp__536872188 = nimMax(0, score_687865884); 1388 | var colontmp__536872189 = (0 < score_687865884); 1389 | result_687865877 = nimCopy(result_687865877, {Field0: colontmp__536872188, Field1: colontmp__536872189}, NTI687865870); 1390 | 1391 | return result_687865877; 1392 | 1393 | } 1394 | 1395 | function escapeCString__dochack_u751(x_p0, x_p0_Idx) { 1396 | var s_536871665 = []; 1397 | Label1: { 1398 | var c_536871666 = 0; 1399 | var iHEX60gensym13_536872192 = 0; 1400 | var nHEX60gensym13_536872193 = ((x_p0[x_p0_Idx]) == null ? 0 : (x_p0[x_p0_Idx]).length); 1401 | Label2: { 1402 | Label3: while (true) { 1403 | if (!(iHEX60gensym13_536872192 < nHEX60gensym13_536872193)) break Label3; 1404 | c_536871666 = x_p0[x_p0_Idx].charCodeAt(chckIndx(iHEX60gensym13_536872192, 0, (x_p0[x_p0_Idx]).length - 1)); 1405 | switch (c_536871666) { 1406 | case 60: 1407 | s_536871665.push.apply(s_536871665, [38,108,116,59]);; 1408 | break; 1409 | case 62: 1410 | s_536871665.push.apply(s_536871665, [38,103,116,59]);; 1411 | break; 1412 | default: 1413 | addChar(s_536871665, c_536871666);; 1414 | break; 1415 | } 1416 | iHEX60gensym13_536872192 += 1; 1417 | } 1418 | }; 1419 | }; 1420 | x_p0[x_p0_Idx] = toJSStr(s_536871665); 1421 | 1422 | 1423 | } 1424 | 1425 | function dosearch__dochack_u755(value_p0) { 1426 | var Temporary5; 1427 | 1428 | function HEX3Aanonymous__dochack_u783(a_p0, b_p1) { 1429 | var result_536871708 = 0; 1430 | 1431 | result_536871708 = subInt(b_p1["Field1"], a_p0["Field1"]); 1432 | 1433 | return result_536871708; 1434 | 1435 | } 1436 | 1437 | var result_536871669 = null; 1438 | 1439 | BeforeRet: { 1440 | if (((db_536871661[0]).length == 0)) { 1441 | break BeforeRet; 1442 | } 1443 | 1444 | var ul_536871673 = tree__dochack_u130("UL", []); 1445 | result_536871669 = tree__dochack_u130("DIV", []); 1446 | setClass__dochack_u152(result_536871669, "search_results"); 1447 | var matches_536871678 = []; 1448 | Label1: { 1449 | var i_536871686 = 0; 1450 | var colontmp__536872179 = 0; 1451 | colontmp__536872179 = (db_536871661[0]).length; 1452 | var i_536872180 = 0; 1453 | Label2: { 1454 | Label3: while (true) { 1455 | if (!(i_536872180 < colontmp__536872179)) break Label3; 1456 | i_536871686 = i_536872180; 1457 | Label4: { 1458 | var c_536871687 = contents_536871662[0][chckIndx(i_536871686, 0, (contents_536871662[0]).length - 1)]; 1459 | if (((c_536871687 == "Examples") || (c_536871687 == "PEG construction"))) { 1460 | break Label4; 1461 | } 1462 | 1463 | var tmpTuple_536871688 = fuzzyMatch__fuzzysearch_u16(value_p0, c_536871687); 1464 | var score_536871689 = tmpTuple_536871688["Field0"]; 1465 | var matched_536871690 = tmpTuple_536871688["Field1"]; 1466 | if (matched_536871690) { 1467 | matches_536871678.push({Field0: db_536871661[0][chckIndx(i_536871686, 0, (db_536871661[0]).length - 1)], Field1: score_536871689});; 1468 | } 1469 | 1470 | }; 1471 | i_536872180 = addInt(i_536872180, 1); 1472 | } 1473 | }; 1474 | }; 1475 | Temporary5 = HEX3Aanonymous__dochack_u783.bind(null); Temporary5.ClP_0 = HEX3Aanonymous__dochack_u783; Temporary5.ClE_0 = null; 1476 | matches_536871678.sort(Temporary5); 1477 | Label6: { 1478 | var i_536871725 = 0; 1479 | var colontmp__536872183 = 0; 1480 | colontmp__536872183 = nimMin((matches_536871678).length, 29); 1481 | var i_536872184 = 0; 1482 | Label7: { 1483 | Label8: while (true) { 1484 | if (!(i_536872184 < colontmp__536872183)) break Label8; 1485 | i_536871725 = i_536872184; 1486 | matches_536871678[chckIndx(i_536871725, 0, (matches_536871678).length - 1)]["Field0"].innerHTML = matches_536871678[chckIndx(i_536871725, 0, (matches_536871678).length - 1)]["Field0"].getAttribute("data-doc-search-tag"); 1487 | escapeCString__dochack_u751(matches_536871678[chckIndx(i_536871725, 0, (matches_536871678).length - 1)]["Field0"], "innerHTML"); 1488 | add__dochack_u148(ul_536871673, tree__dochack_u130("LI", [matches_536871678[chckIndx(i_536871725, 0, (matches_536871678).length - 1)]["Field0"]])); 1489 | i_536872184 = addInt(i_536872184, 1); 1490 | } 1491 | }; 1492 | }; 1493 | if ((ul_536871673.childNodes.length == 0)) { 1494 | add__dochack_u148(result_536871669, tree__dochack_u130("B", [text__dochack_u155("no search results")])); 1495 | } 1496 | else { 1497 | add__dochack_u148(result_536871669, tree__dochack_u130("B", [text__dochack_u155("search results")])); 1498 | add__dochack_u148(result_536871669, ul_536871673); 1499 | } 1500 | 1501 | }; 1502 | 1503 | return result_536871669; 1504 | 1505 | } 1506 | 1507 | function wrapper__dochack_u1091() { 1508 | var elem_536872004 = document.getElementById("searchInput"); 1509 | var value_536872005 = elem_536872004.value; 1510 | if (!((((value_536872005) == null ? 0 : (value_536872005).length) == 0))) { 1511 | if ((oldtoc_536871998[0] == null)) { 1512 | oldtoc_536871998[0] = document.getElementById("tocRoot"); 1513 | } 1514 | 1515 | var results_536872009 = dosearch__dochack_u755(value_536872005); 1516 | replaceById__dochack_u158("tocRoot", results_536872009); 1517 | } 1518 | else { 1519 | if (!((oldtoc_536871998[0] == null))) { 1520 | replaceById__dochack_u158("tocRoot", oldtoc_536871998[0]); 1521 | } 1522 | } 1523 | 1524 | 1525 | } 1526 | 1527 | function search() { 1528 | var Temporary1; 1529 | 1530 | if ((loadIndexFut_536872001[0] == null)) { 1531 | loadIndexFut_536872001[0] = loadIndex__dochack_u928(); 1532 | (then__dochack_u1106(loadIndexFut_536872001[0], wrapper__dochack_u1091, null)); 1533 | } 1534 | 1535 | if (!((timer_536871999[0] == null))) { 1536 | clearTimeout(timer_536871999[0]); 1537 | } 1538 | 1539 | Temporary1 = wrapper__dochack_u1091.bind(null); Temporary1.ClP_0 = wrapper__dochack_u1091; Temporary1.ClE_0 = null; 1540 | timer_536871999[0] = setTimeout(Temporary1, 400); 1541 | 1542 | 1543 | } 1544 | 1545 | function copyToClipboard() { 1546 | 1547 | function updatePreTags() { 1548 | 1549 | const allPreTags = document.querySelectorAll("pre:not(.line-nums)") 1550 | 1551 | allPreTags.forEach((e) => { 1552 | 1553 | const div = document.createElement("div") 1554 | div.classList.add("copyToClipBoard") 1555 | 1556 | const preTag = document.createElement("pre") 1557 | preTag.innerHTML = e.innerHTML 1558 | 1559 | const button = document.createElement("button") 1560 | button.value = e.textContent.replace('...', '') 1561 | button.classList.add("copyToClipBoardBtn") 1562 | button.style.cursor = "pointer" 1563 | 1564 | div.appendChild(preTag) 1565 | div.appendChild(button) 1566 | 1567 | e.outerHTML = div.outerHTML 1568 | 1569 | }) 1570 | } 1571 | 1572 | 1573 | function copyTextToClipboard(e) { 1574 | const clipBoardContent = e.target.value 1575 | navigator.clipboard.writeText(clipBoardContent).then(function() { 1576 | e.target.style.setProperty("--clipboard-image", "var(--clipboard-image-selected)") 1577 | }, function(err) { 1578 | console.error("Could not copy text: ", err); 1579 | }); 1580 | } 1581 | 1582 | window.addEventListener("click", (e) => { 1583 | if (e.target.classList.contains("copyToClipBoardBtn")) { 1584 | copyTextToClipboard(e) 1585 | } 1586 | }) 1587 | 1588 | window.addEventListener("mouseover", (e) => { 1589 | if (e.target.nodeName === "PRE") { 1590 | e.target.nextElementSibling.style.setProperty("--clipboard-image", "var(--clipboard-image-normal)") 1591 | } 1592 | }) 1593 | 1594 | window.addEventListener("DOMContentLoaded", updatePreTags) 1595 | 1596 | 1597 | 1598 | 1599 | } 1600 | var Temporary1; 1601 | var Temporary2; 1602 | var t_536870951 = window.localStorage.getItem("theme"); 1603 | if ((t_536870951 == null)) { 1604 | Temporary1 = "auto"; 1605 | } 1606 | else { 1607 | Temporary1 = t_536870951; 1608 | } 1609 | 1610 | setTheme(Temporary1); 1611 | var alternative_536871619 = [null]; 1612 | var db_536871661 = [[]]; 1613 | var contents_536871662 = [[]]; 1614 | var oldtoc_536871998 = [null]; 1615 | var timer_536871999 = [null]; 1616 | var loadIndexFut_536872001 = [null]; 1617 | copyToClipboard(); 1618 | Temporary2 = onDOMLoaded.bind(null); Temporary2.ClP_0 = onDOMLoaded; Temporary2.ClE_0 = null; 1619 | window.addEventListener("DOMContentLoaded", Temporary2, false); 1620 | -------------------------------------------------------------------------------- /docs/nimdoc.out.css: -------------------------------------------------------------------------------- 1 | /* 2 | Stylesheet for use with Docutils/rst2html. 3 | 4 | See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to 5 | customize this style sheet. 6 | 7 | Modified from Chad Skeeters' rst2html-style 8 | https://bitbucket.org/cskeeters/rst2html-style/ 9 | 10 | Modified by Boyd Greenfield and narimiran 11 | */ 12 | 13 | :root { 14 | --primary-background: #fff; 15 | --secondary-background: ghostwhite; 16 | --third-background: #e8e8e8; 17 | --info-background: #50c050; 18 | --warning-background: #c0a000; 19 | --error-background: #e04040; 20 | --border: #dde; 21 | --text: #222; 22 | --anchor: #07b; 23 | --anchor-focus: #607c9f; 24 | --input-focus: #1fa0eb; 25 | --strong: #3c3c3c; 26 | --hint: #9A9A9A; 27 | --nim-sprite-base64: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAN4AAAA9CAYAAADCt9ebAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFFmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDggNzkuMTY0MDM2LCAyMDE5LzA4LzEzLTAxOjA2OjU3ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgMjEuMCAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDE5LTEyLTAzVDAxOjAzOjQ4KzAxOjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAxOS0xMi0wM1QwMjoyODo0MSswMTowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAxOS0xMi0wM1QwMjoyODo0MSswMTowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiIHBob3Rvc2hvcDpJQ0NQcm9maWxlPSJzUkdCIElFQzYxOTY2LTIuMSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDozMzM0ZjAxYS0yMDExLWE1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"); 28 | 29 | --keyword: #5e8f60; 30 | --identifier: #222; 31 | --comment: #484a86; 32 | --operator: #155da4; 33 | --punctuation: black; 34 | --other: black; 35 | --escapeSequence: #c4891b; 36 | --number: #252dbe; 37 | --literal: #a4255b; 38 | --program: #6060c0; 39 | --option: #508000; 40 | --raw-data: #a4255b; 41 | 42 | --clipboard-image-normal: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' style='color: black' fill='none' viewBox='0 0 24 24' stroke='currentColor'%3E %3Cpath stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2' /%3E %3C/svg%3E"); 43 | --clipboard-image-selected: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' style='color: black' viewBox='0 0 20 20' fill='currentColor'%3E %3Cpath d='M8 3a1 1 0 011-1h2a1 1 0 110 2H9a1 1 0 01-1-1z' /%3E %3Cpath d='M6 3a2 2 0 00-2 2v11a2 2 0 002 2h8a2 2 0 002-2V5a2 2 0 00-2-2 3 3 0 01-3 3H9a3 3 0 01-3-3z' /%3E %3C/svg%3E"); 44 | --clipboard-image: var(--clipboard-image-normal) 45 | } 46 | 47 | [data-theme="dark"] { 48 | --primary-background: #171921; 49 | --secondary-background: #1e202a; 50 | --third-background: #2b2e3b; 51 | --info-background: #008000; 52 | --warning-background: #807000; 53 | --error-background: #c03000; 54 | --border: #0e1014; 55 | --text: #fff; 56 | --anchor: #8be9fd; 57 | --anchor-focus: #8be9fd; 58 | --input-focus: #8be9fd; 59 | --strong: #bd93f9; 60 | --hint: #7A7C85; 61 | --nim-sprite-base64: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAARMAAABMCAYAAABOBlMuAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFFmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDggNzkuMTY0MDM2LCAyMDE5LzA4LzEzLTAxOjA2OjU3ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgMjEuMCAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDE5LTEyLTAzVDAxOjE4OjIyKzAxOjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAxOS0xMi0wM1QwMToyMDoxMCswMTowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAxOS0xMi0wM1QwMToyMDoxMCswMTowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiIHBob3Rvc2hvcDpJQ0NQcm9maWxlPSJzUkdCIElFQzYxOTY2LTIuMSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDplZGViMzU3MC1iNmZjLWQy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"); 62 | 63 | --keyword: #ff79c6; 64 | --identifier: #f8f8f2; 65 | --comment: #6272a4; 66 | --operator: #ff79c6; 67 | --punctuation: #f8f8f2; 68 | --other: #f8f8f2; 69 | --escapeSequence: #bd93f9; 70 | --number: #bd93f9; 71 | --literal: #f1fa8c; 72 | --program: #9090c0; 73 | --option: #90b010; 74 | --raw-data: #8be9fd; 75 | 76 | --clipboard-image-normal: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' style='color: lightgray' fill='none' viewBox='0 0 24 24' stroke='currentColor'%3E %3Cpath stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2' /%3E %3C/svg%3E"); 77 | --clipboard-image-selected: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' style='color: lightgray' viewBox='0 0 20 20' fill='currentColor'%3E %3Cpath d='M8 3a1 1 0 011-1h2a1 1 0 110 2H9a1 1 0 01-1-1z' /%3E %3Cpath d='M6 3a2 2 0 00-2 2v11a2 2 0 002 2h8a2 2 0 002-2V5a2 2 0 00-2-2 3 3 0 01-3 3H9a3 3 0 01-3-3z' /%3E %3C/svg%3E"); 78 | --clipboard-image: var(--clipboard-image-normal); 79 | } 80 | 81 | @media (prefers-color-scheme: dark) { 82 | [data-theme="auto"] { 83 | --primary-background: #171921; 84 | --secondary-background: #1e202a; 85 | --third-background: #2b2e3b; 86 | --info-background: #008000; 87 | --warning-background: #807000; 88 | --error-background: #c03000; 89 | --border: #0e1014; 90 | --text: #fff; 91 | --anchor: #8be9fd; 92 | --anchor-focus: #8be9fd; 93 | --input-focus: #8be9fd; 94 | --strong: #bd93f9; 95 | --hint: #7A7C85; 96 | --nim-sprite-base64: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAARMAAABMCAYAAABOBlMuAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFFmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDggNzkuMTY0MDM2LCAyMDE5LzA4LzEzLTAxOjA2OjU3ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgMjEuMCAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDE5LTEyLTAzVDAxOjE4OjIyKzAxOjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAxOS0xMi0wM1QwMToyMDoxMCswMTowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAxOS0xMi0wM1QwMToyMDoxMCswMTowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiIHBob3Rvc2hvcDpJQ0NQcm9maWxlPSJzUkdCIElFQzYxOTY2LTIuMSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDplZGViMzU3MC1iNmZjLWQyNDQtYTExZi0yMjc5YmY4NDNhYTAiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6ZWRlYjM1NzAtYjZmYy1kMjQ0LWExMWYtMjI3OWJmODQzYWEwIiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6ZWRlYjM1NzAtYjZmYy1kMjQ0LWExMWYtMjI3OWJmODQzYWEwIj4gPHhtcE1NOkhpc3Rvcnk+IDxyZGY6U2VxPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0iY3JlYXRlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDplZGViMzU3MC1iNmZjLWQyNDQtYTExZi0yMjc5YmY4NDNhYTAiIHN0RXZ0OndoZW49IjIwMTktMTItMDNUMDE6MTg6MjIrMDE6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCAyMS4wIChXaW5kb3dzKSIvPiA8L3JkZjpTZXE+IDwveG1wTU06SGlzdG9yeT4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4JZNR8AAAfG0lEQVR4nO2deViTZ7r/7yxkJaxJ2MK+GCBAMCwS1kgUFQSKK4XWWqsz1jpjp3b0tDP1V+eqU391fqfT/mpPPd20drTFDS0KFEVWJSGAEgLIZpAICBJACIRs549Rj1WILAkBfD/XlevySp68z/0S3+/7vPdzLyidTgcLkU2bd+z39/f/q1gshsrKSoJELFCa2iaEuU9K6kb+8uXxv54/fzE8L/eswNT2zCfQpjbAGKS8lPFKSEjIXiaTCSEhIeDj4xNnapsQ5j6rktZGp6UlfxIdzQVzCplmanvmG1hTG2BIAtlc26CgoDfT0tL2e3l5AQCAjY0NkMnk/a9s2k6rrKw8UV8n1JjYTIQ5RlAw14KzmL3xze1vfJyUuMJaq9UCFovFm9qu+YbBxcSPFUYkk8l2Q0NDsvo6ocrQx5+I8Ih4bz6f/0l8fHyKlZXV4/dRKBQwmcwwMpn8A4FAoPgHhH9bV1sxa488wZxoaycnJ/a9e/duCa5fkc3WvAiTI4Ib77p+XdqHG9anbfLy8gAAgLGxMdBpF+bjvzExqJj4scKI0dHRnwQHB++orq7+AgDeMuTxJ2Jl4rqU9PT0EwEBAUQCgTDuGAaDAampqYepVKpHUHDk325Ulw0a266YuFW+Gzdu/MDPz29jfn7+XgA4aOw5ESZP6kvpCXv3vnM8NiaSamVl+fj9BepGNDoGFRN7e/slcXFxO1xcXMDJyWnH7j//H/fi4uJdgutXmgw5z5O8smn7X9euXbvf29sbMBjMhONQKBRYWVlBbGzsbjMzM3JoOG+/sKKwy1h2rd/4elpGRsYuLy+vaDweD2w2Oy1h5ZrCvEunEaeeiVnMiabyl/F2/+X9P+8JDPQHHA5napMWBAYTk6DgSNuEhIS9DAYDAP7tq1i6dOkqOp3OWbNu0wens44emeoxA9lcWwKBYEMkEm2JRKIdHo+3QKFQWJ1Op8ZgMER3d/dVq1evTnFycpr0MSkUCsTExGzH4/Gk1LTME/39/TI0Go1FoVCg1WrVY2NjipGRkcGRkRH5dPwrEZHLXMPCwjJSUlIy3dzcfB+97+rqGhYSEpIOAIiYmBguN3zL77dt3uPh4W5qUxYUBhMTb2/vjeHh4cvR6P/dILK0tITIyEg7BweHr363/Z3Ampqaf1Zcu/zMKiVsyVJvMplsRyKR7IhEor2FhYUbhUJhJCYm2pFIJB6JRAIymQx4PB7QaDRoNBowMzMDJycnwOOn7icjEokQGxu7icFgbLp///7jFY1WqwWlUgkjIyOgUCgO7Ni5Rz48PCwfHh7uGRkZeaBQKOSjo6ODCoVCXlNVKn/6uCsT13FXrVr1emho6BYKhfLMnP7+/omrU9LPX8g+UThloxEMxqJFXjxESAyPQcSEExrLWLNmzW57e/txP/fw8ABHR8cdDAaDt3xF2ru9vb03sVgs0cbGxs/FxWVZUlISj0aj+dna2oKtrS1M5PcwJCgUCry8vODRrs84vPfoH6OjoyCXy6Gvr+/R6+CWrX9s7evrk/b19bWr1Wqli4sLZ8OGDe95eXmxUSjUuAd0cHDwjoqK2sYKXFIhvnldYYTTQpgU4/8+jyASCYDGoCd+ZkYYF8OICYezl8PhuOkbQyAQIDo62s/NzS2np6cHbGxsgEajAYFAAAwGA1gsFia6CE0NgUAABwcHsLe3B61WC2q1eo9WqwWNRgNKpRLUajUQiUSgUCh6zwGHwwGTydzo5+eXBQBnZu8MEJ5keHhYPqyYWMtHR0ZBpVIhYj9FUDONgOUvT12+du3avMDAQJjssdRqNWCxCyrEZdLodDoQi8Ulx44de628NL/V1Pa8iERE8l2dHB2CJvpcq9Nqbt1qKURWj1Njxld0ZGTkAW9v70kLCQC8sEIC8O/HKx8fn2gmk8kHgCk7pRFmzrWyAikASE1tx0Jj2uH0EZHL/N7YtuvT4OBgzmz4OBYSeDweIiMjt2S++vtMP1YYEmmJsCCY8mNOIJtr6+zsHBcZGXmIw+G4mZubG8m0hU9HRwcUFxe/KxQKTyDRsQjznSmJCS9+dVRERMTfQ0NDo2xtbfUGiSFMjtHRUaitrc3Jzc09kHvxVLmp7UFAmC6oZQkvrZLL5RJhReHtiQb5scKIXC7371FRUX90dnYGIpE4JR8Jgn40Gg20t7fXFxYWfnr9+vWjz8sdYi+Osh4vzgUBwZSgtu94V+fs7Hx7YGCgra6u7khLS0u2RCwYeTQgKmYFh8fj/f/g4OAldnZ2prR1wdPd3Q1CofBQSUnJkdLi3N8E93FCY6k+Pj48FxcXjlar1ZSWlh65VvYr4kREmDNg79+/D3FxcW5OTk5uXl5evNbW1tL0jK3ZXV1d1ykUintycvInoaGhdkj+gvGxs7MDPp+/m0AgWMQvS/lyeHhYTqPRPJycnIJSU1NZ3t7eW2g0Gly/fv2oWq1Gij0hzClQ/gHhpLS0tEM8Hm/7I8Ho7++HlpYWsLa2Bg8PDxOb+OKhUCigqakJ7t+/D25ubuDu7g4oFAp0Oh08ePAAvv7666TTWUdzTG0nAsKTYMU3ryuSU18+4+bmFrZo0SIOAICVlRUsXrx4zkakLnRIJBI8CgJ8MtdJp9NBZ2enqL29XWRC8xAQxgUNAHD+3L8KGhoaCp78ABES04JCoX4jJAAAAwMDUFtbe96YpRMQEKbL41DU5ubmko6Ojj2PSgggzD36+/vrb9y4cX425zzw93/8EBjon2is44+NjSkePBjqGRwc7G5v7xBV19w8U5B/3qgrr9+/uWtXUuKKD/TZ9MXh/066/OuFmunO8dGBQ98HBbGSp/t9U6LRaDXK0dHBoeFhuVzeL22/0yFqamopufjLqRJ933ssJi0tLSXV1dWHGAzGbuObOzs8ubqa71vZKpUKOjo6blwpOF8zm/Mu5cVkLlkSaswprAHAaVihgK7O7oSGxltvfXLon3nXK4RHT2cdN4pfKDCAlZyUuMJan02nTmczAaBmunPw4qI3cbnh0/36XICq0+lgcPABp7OrK629vUP5z8++LLh2XXD05L++yxrvC4/F5EZ12WBS8saLS5Ys2U2lUufUY45SqQSlUgkqlQrUavXj19jYGGg0GtBoNKDT6UCn05VotVq1TqfToFAojFar1eh0Og0Wi8XhcDgeGo1+/PhgZmYGOBwOsFgsmJmZ/eY1F+nt7YXa2trs2Z73wdCQBgCMHp1IJpHA09MdPD3dLRIS+OtKisvWvbP7vf2lZdePVFwzbHTwyMiI3hidkZFRUKvUYzOZ48HQkBIA5nWqBAqFAktLC7C0tADmIh88Pz4uMSyUk7hn776DV4tKPn/6d/lNxp1MJqsRCASf8vn8XdMpOjRTVCoVjI2NgUqlAq1WCyMjI9DX1wf379+Hvr6+/Q8ePOgdGRmRKxSKx0WLFAqFXKlUKnQ6nUar1arHq47mxwrD4/F4Eg6HI2GxWDwej7cgkUjWFAqFam5uTjU3N6eRyeQPLSwswNraGqysrIBAIDwWFywW+zja11Qi29LSclIikeSZZPJZBovBAI8XA8HBQR9kZZ3lR8cmvFZSlGe00p8IkwONRkNERBj4+i7a4+XpHv307/IbMakWlciXJbx0nMPh7Jqo0JGh0el0MDo6Cl1dXSCVSkEmk7177969W319fe1DQ0M9KpVKoVarlWq1WjndNhUPG3ApAWDcOxLTLwSDwWAOotFoDBaLxRMIBAsrKysne3t7Xzqd7k2n0/c4OzsDlUoFHA4364IyMDAATU1NxdWikhcq6tXKyhJezljPJZKI2eERS5cZeoWCMD2srCwhPX0tVzk2djiCG//GtfLLUoBxShB0dHTU3Lx580sLC4vtJBLJKMZoNBqQSqUglUqPdnR01PT09DT19/fLHjx40DM0NNQ72933GiSVGgB4JFQK+LfoSAGgnL04yppEIh2xtLS0t7GxcaFSqR7Ozs4fMRgMcHR0nJX8pJs3b54Ui8UXjT7RHIRMIkFK8irfwcEHPwQELUmqvYHUGJkLmJubw8YNa/i9vfffY/px3myQiDTPiEl9nVDDX576jaenZ7SnpyfLUJNrNBqQyWRw+/bt4x0dHTdkMlltV1dXw/XygjkdEv4wB0YOAK0AUM70C8HQ6fSzdDrdm0qlejg6OrLc3Ny2MBiMadWjfR4PHjyAmzdvZs/1v5MxoVAokJK8iicWS95k+nH+s0EiQhqpzQGoVFtYk5a87ba0XQAA34xbpagg/5zoT7s/OGNnZ8eaaYkBuVwOnZ2d5VKpVNTS0lLS2NhYWFVZ3Dujg5qQh6uY+ocvCAiKIPn4+Jz19PSMdnV15VCpVL6Dg4NBViw6nQ5EItHRpqamqzM+2DzHzo4O69amftLQeKsAZrDLgmBY/PyYsCIhfs+SiKUFE5Y8EwqFx11cXDihoaFTjjFAoVAwPDwMHR0dourq6jNCofDHhZqUVnvjmgIAcgAgJyg40mLRokX8kJCQjT4+PussLS1n1JPl7t27UFxcfHguB6mNjY2B7G4naNRTWyygUCjAYDGAx+PB0sICSCSi3vFYLBbCwjjA8vddBQtATKb7d3saBwc7IJPJBpsHjUGDGRYLJBIJLK0sAfucmyIGg4FFi3y8AwNZtycUk5KiS02vvf7WWQaDkejg4DApQwAeh3xDaWnpPoFAcPxFqnP6sEvgGf+A8Bx3d/cvIyIiNi1evHjT8wpNj8fAwACUlZW9P9dD5+/ckcFbf9gd2dcnn9LNAovF4inmZHtXNxdOdBR3+/JlS33pdP29wolEInA4weuiYxOy5vvuTkeHDHb+8c8xvb33Z3R9/N+Df+uIjYk02DwkEsna2trS1d/fNyGeF7uTyw1/7g3R3t4O2OxA/TVghULhcQqFQk1JSfmYSNR/5wD4d6EfgUBwvLS09IhUKhW9qAV5H9YjKQwJi6uvrKw8ERoamhkSEpKp7w7yJEqlEiQSyZmysrJv53qjdaVSCZdyTk+3qFMrAJRHRPLPN95qeifj5fU7mYt8JhyMRqMhMJDFdnF25gDAvBYTpXIMWlpay2fq/8m5mDcIABYGnEcGAGI/VlhBZWX1yZdSkz55OX0dV5+7w9bGGvz8mPrFpK62QskJjf2GTqd7x8bGbpnID4BCoUAmk0lLSkqOiESik2UleS/MakQflYKrXQDQxY1a3tTe3i6KiIjY5OXlxX7e9+rr6wsuXbr0t4ffn9OgMWjghMZQRcLp+8GulRVI/QPC37Wxtnal0ajJtjY2E451ZjiBra31vE9lR2PQQKFQaAAwo98Yi8Xq9fpPd56HO6rlvKWJv/PwcK+JilyCmajWMw6HAzs7+rMFpQOCIn6zHywSFvXm5eUdFAqFZ9Rq9bgHa2trq79w4cK+zz49cAARkmcpL81v/a/Dhz49d+7c3qqqqjyVSjXuOJ1OBxKJpDw3N/fA5V+zax6978cKw/sHhM/raMrnUVdboSy4fPWQSFSjd5yFBQWIRNKEd2IEw1J4JUd88WL+R51d3XrHWVDMnxUTa2tr1zXrNiUGsrmPf7DS4tymCxcu7Kuurs55+kKQSqVN586d23vs+8NHDXUCC5Wzp3/Iy8rKeruysvLM2Nhvo7VVKhXU1tYWnj17du/T7UOdnZ2D7OzsfGGB09raVi4S1RzXl0eFw+EAj8chYjKLVFffyOrq1C8mJBLpWTFRKBRyDofzC4vFWvXk+1ev/CLOzs7eKxAIslQqFeh0Oujp6enKzs7em/XTd7OayTqfKb56sT4rK+sPAoHg5KO/o0KhAKFQmHXy5MkdF3/5+TeZmctXpIXZ29v7zqVcKWNRX1epuXu3U/y8pEw0GmndOZt0dnXVDw0P6/W5oNHoZ30mQ0NDPb29vfvj4+Pf3rR5B/7od188XnEUXr4gDgmL+0NfX5/U19d3d3l5+YGfTnyDtLmcIhXXLsu4UcvfR6PRGGtra9eysrIjYrE45+kt4Fheou/69es/unnz5vm7d+/Wmsre2WRkZGTQ1DYg/JYGiUiTm1ugBAC9IfHPiEmDpFITE7fqJI/H27lmzZpDq5LWtz55t6wUXO3ihMYerK+vz2tpaUFaM0yT8tL81ujYle+TSCTrvEunBU9/voTLd92wYcPHVCqV39XVdXCu7+oYCp1O90Kc50Jk3I5+xVcv1jc3N5d4enpSMzIyvkpK3sh78nORsKg3++yPBS/q1q+hKCm61DSekERGJ3ikp6d/ERsbm1xVVXWwtbX1hRFtFAqFPMLMUyZsDyoQCI7LZDKIiIjwzczM/GpV0vro2TTsRSUqZoX3+vXrP1u9enXi0NAQiESirIdRtggIc5oJ40zq6uryGhoa8ry8vBJCQ0O9USjU94mrN7yWc+EnvaXb5gJMvxCMp6cnl0Kh2Le1tZVXXLs8L1LXefGrWRkZGZ/x+XyeUqkEkUh0vqenZ14HZyG8OEwoJjdrygd37NxTEBkZmWBtbQ3BwcEeKBTq+/UbX3/355Pfzlmn66qk9dGbN29+k8PhbCSRSNDZ2Snb9ae/HCkpKTksEhbN2QTD5NSX+Vu3bj0cHBzsjcFg4O7du1BWVvbNwxB9BIQ5j94I2Fu3bhXW19cDl8sFLBYLHA7Hg0wmf/e77e84ffXlPz6fLSMnQ2paZkJ4eHjmtm3b+B4eHvZkMhlQKBTY29s72dvbfxgUFJT8x7ffP1NRUfHjXErnZ/qFYKKjo7dt3rz5g8DAQPtH/XHa2tpqGhsbC55/BASEuYFeMblz505NTU3NgfDw8PcwGAygUCjw9fW1IJPJn/1130Hv0tLSI4WXL4hny9inYS+Osvbz80tgMpn8jIwMPovFch2vpoiDgwM4ODhwfH19OYsWLeJv3/Hu+cbGxquzXZz5aZYlvMRJT0/fFhkZue3JZmfd3d0gEolOIr4ShPmEXjFpkFRqXlrzSnFnZ+d7Tk5OjzNfXVxcICMjY6ezszNnVdL6vU8HWhmbgKAIkrOzMyc1NTXz0YU4maAuOp0OK1as4EVFRfGEQqHg1dfePHzr1q2rs71S8WOF4f38/BLS09M/iIyM5DxdxLq5uVlcVVU1bgVwBIS5il4xAQCQyWRigUBwJikpKe3JVGQcDgdLly7l2tranti0ecf7IpEoy9hbxX6sMDydTvdevXr1ltjY2F3u7u6AxT73FJ7B3Nwc4uLiwthsdphQKCzZkL7l0/r6+oKbNeVG90+EhMXZL1++fFtycvKHrq6uz4igUqmE5ubmEiTHCWG+8dwrUXD9imz9xtd/jIuLS7N5KpsTjUZDUFCQE4PB+F4oFGYmJW888Mv5k4UTHGpGxC9LYaenp78VEhKyxdHRESgUyoyOh0KhwNraGuLi4qIDAgKi6+rqyjekb/mHMSN6N6RvSdu+ffseNpsdZm09ftuW+vp6EIvFSB9hhHnHpG7rUqm0orW1tdXS0tLj6TIEaDQaaDQaxMfH811dXTl/3Xfw+JUrVz411J01cfWG6IiIiC07d+5McHNzs7ewMGyOFw6HAwcHB6BSqVx3d/fwz7/4rkAgEBwXCoUnHpZonDGrU9J5MTEx27du3Zrm4uKC0beaqq6u/ry+vj7XEPMiIMwmkxKTimuXZe/u+fCkp6fnexPdUfF4PPj7+1szGIydLi4unF1/+kvenTt3RG1tbRXTqfma8lIG39/fP/HVV19NZrFYHpMpzjQTzMzMwNPTE+Pp6Zng6emZ4Ofnl5CesfV8bW1tznQe3/wDwvFeXl7Rvr6+Ca+88kpaUFCQh74GXzqdDrq7u6GpqankRQmdR1hYTNrhUFVVlcXj8d6ysrKy0OfstLS0hPj4eC6Xy+U2NzeDRCI5/sa2XeX37t1rGhwc7BoYGJBN1P+FFbiE5OzszGaxWImvvvrqpoCAAKfp+ERmCpPJBCaTmcnhcDJLS0u/TE59+YxUKhXoi/lg+oVgrKysGJaWlna2trYeaWlpXDabvTMgIGDSfp2KiorzbW1tL0zoPMLCYtJX6uVfs2u++PKowMPDgz+ZIslEIhECAgKAxWJlajSazJ6eHmhra4PW1tZvtmz9o6Czs7O+r6+vfWxsbFir1WosLCzsV6xYkcnj8d7z9vaelmPV0Hh5eYGnp+f2mJiY7UVFRZ/HL0v5tru7+5ZGo1FisVg8Docj4fF4CxsbG1c+nx/m7e39sYeHB7i4uIC5ufmU6r4ODQ1BZWXlifkSrYuA8DRTumIrKytPent78728vCb9HRQKBVgsFhwcHIBOpwObzd4yNja2RaVSwdDQEHR1dcHo6CjQaDRwdXWdsWPV0KBQKPDw8AA7O7udERERO2tra2FgYACoVCo4OTkBjUYDMpkMeDz+8WuqaLVaaGxsbL19+/YzSX8ICPOFqYrJidDQ0AwvLy/e80c/CwaDARKJBI86BdJoNHB3dwe1Wj0nViL6IJPJwGQywdnZGZRKJRAIBDBUx8OBgQEoLS39BtkORpjPTJg1PB61N64pmpqarvb39xvUiLkuJE9CJpPBxsbGYEICANDZ2SlHgtQQ5jtTEhMAgLq6ulyJRFJvDGNeREZGRkAikRSUFuci2cEI85opi0l+7hmBWCzOeV6dToTJcfv27cHr168jxbgR5j1TFhMAgObm5hKZDNl0MAQtLS3Xzpw6hkS8Isx7piUmUqlUIBAIJuyjgzA5Ojs7QSKRINGuCAuCaYmJsKKw68qVK59KJJIu5HFneiiVSigqKjouEolOmtoWBARDMC0xAQC4+MvPJadOnXq3ra1N8yL0dDEkOp0OSktLy/Pz8w8+3d4CAWG+Mm0xAQA4fuy/jl+8ePGju3fvGsqeBY9Wq4XKysrWU6dOvX31yi8mKyyFgGBoZiQmAAD/79D+fadPn96PCMrz0el0UFVV1frtt9+mj9fiAgFhPjNjMQEAyMvLO3Ds2LE/tLS0INmuerh27Vr9999//xoiJAgLEYOEntbVVigB4PNNm3cMpqSkfMRms50McdyFgkqlgqKiovJTp069nZ97BhEShAWJQePYj373xdF1GzbLFQrFx6Ghob766ne8KNy7dw+KiopO5ubmfmTK4tsICMbG4EkxWT99d35l4rre/v7+D0NCQvh0Ot3QU8wL1Go1SKVSTX5+/sH8/PyDSP8bhIWOUTLsLuVklQcFR65pbGzcvnLlyvfc3NwsCASCMaaac+h0OhgaGoLq6uqaCxcu/OV01tGcTw7uM7VZCAhGx2jpug/vxAd58atzoqKitq1cuXKnvb29saabE+h0Oqiurpbm5eUdrK6uPlspuDrvY0hmO4YIhUIBGq1/X2CmNqFQKL3/79HomZ/z82xEowyy9zFr80zGDqPn/hdeviBmL47ad+fOnRsRERGbQkNDo62srIw97azT2dkJxcXFx0tKSo7Mdh8hY4LD4TDPH2U4MFjMc6tLmZmZzaj+Aw6H0/t9PB4PGCxmRudNJBL0ngeZTAI0Gj3jv+1szfM88Hic8cUEAKCmqlQOAN/ELU2qkEgkySwWK3HRokVcBoMxG9MbDZ1OB83NzdDU1FRQW1t7XiAQHJ+ovu18pbr6Rg6L5ZtoM0EhcUPT0tJW8tWRb0vQqIkvgKqqmhnVfrl2TfANXo+gjKlUio4OWc1M5sjOzjnQUH8rbqLPu3t6moaGhmfc+3q25tGHUqmECoEIUKbIrVkcEkONiIh4jcvlvu7s7OxLo9GmVe7QVCgUCujq6oKGhoaCioqKo9XV1WeM3YDMVPDik1gpyas+XrVyeaKXl8czjyANjbcgI/MNmkg49Q4ECPOH3NyC4RUr+M8IcHt7B1y9WlKRl3/5kElKnD1sfXEoJCzueEBAQGJYWFgGk8nk2djYAIFAgLm4pTw6Ogqjo6Mgl8vhxo0b50tLS4/U19fnLvS2FIWXfxEDQNLmLW9ueW1TxtchHDaQyWRTm4VgYkZHR6G+vhF+/NfP+y5e+vVjiVgwZpKVydOwF0dZW1lZOTGZTD6bzU4LCAiIptPp8HTDL1MwOjoKLS0tUFdXd1IsFudIpdKKgYGB7tloJTrX4MUnsVJTEj9etzY10dHRAQAAGm81wcsZW5CVyQInL69gNCGBjwcAGBx8ANnncypOnTr3H9nn/reD55wovvrQpyIHAHFUzIocGo3mQaPRfBwdHVlubm7bXF1dgcFgABqNNvruglwuh7t374JMJoOOjo7P79y5I+ru7m7q7e1tXQi7MzOh8PIv4pCw2DdaWtte37Au7aPIyCWAxWABjUbPif9HCMbjURtKiaQBfvr5zH9evlJ0uLQ4r/nJMXNiZTIRrMAlJAcHB18HBweWo6Mjy8rKajeJRAJLS0uwtLQECwsLoFAogMfjAYvFgpmZ2XNXMyqVCoaHh2FoaAiGh4cfvwYGBqCvrw+6u7vfvnfvXlNvb29rT09Pq0QsUM7S6c4rNqS/lrZ5U+YPRBKR9M7u9xwqBUUvtNAudH766XSLE8PR49ixE78/8tVnX403Zk7fUR46NUUAIPIPCMdTKJTdNjY2QKPRgE6nA51OB1tbWyCRSIDD4YBAIAAejwcCgfDYUajVakGlUoFarQadTvfY79HX1wf9/f0gl8tBLpfDvXv3HvXw+dxQPYYXMj+d+P7Mmzv+5OHr6/OJWq1GBHeB09TcUiKuq/coKS3/eqIx/wPkiIXC3w6YjAAAAABJRU5ErkJggg=="); 97 | 98 | --keyword: #ff79c6; 99 | --identifier: #f8f8f2; 100 | --comment: #6272a4; 101 | --operator: #ff79c6; 102 | --punctuation: #f8f8f2; 103 | --other: #f8f8f2; 104 | --escapeSequence: #bd93f9; 105 | --number: #bd93f9; 106 | --literal: #f1fa8c; 107 | --program: #9090c0; 108 | --option: #90b010; 109 | --raw-data: #8be9fd; 110 | 111 | --clipboard-image-normal: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' style='color: lightgray' fill='none' viewBox='0 0 24 24' stroke='currentColor'%3E %3Cpath stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2' /%3E %3C/svg%3E"); 112 | --clipboard-image-selected: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' style='color: lightgray' viewBox='0 0 20 20' fill='currentColor'%3E %3Cpath d='M8 3a1 1 0 011-1h2a1 1 0 110 2H9a1 1 0 01-1-1z' /%3E %3Cpath d='M6 3a2 2 0 00-2 2v11a2 2 0 002 2h8a2 2 0 002-2V5a2 2 0 00-2-2 3 3 0 01-3 3H9a3 3 0 01-3-3z' /%3E %3C/svg%3E"); 113 | --clipboard-image: var(--clipboard-image-normal); 114 | } 115 | } 116 | 117 | .theme-select-wrapper { 118 | display: flex; 119 | align-items: center; 120 | } 121 | 122 | html { 123 | font-size: 100%; 124 | -webkit-text-size-adjust: 100%; 125 | -ms-text-size-adjust: 100%; } 126 | 127 | body { 128 | font-family: "Lato", "Helvetica Neue", "HelveticaNeue", Helvetica, Arial, sans-serif; 129 | font-weight: 400; 130 | font-size: 1.125em; 131 | line-height: 1.5; 132 | color: var(--text); 133 | background-color: var(--primary-background); } 134 | 135 | /* Skeleton grid */ 136 | .container { 137 | position: relative; 138 | width: 100%; 139 | max-width: 1050px; 140 | margin: 0 auto; 141 | padding: 0; 142 | box-sizing: border-box; } 143 | 144 | .column, .columns { 145 | width: 100%; 146 | float: left; 147 | box-sizing: border-box; 148 | margin-left: 1%; } 149 | 150 | @media print { 151 | #global-links, .link-seesrc, .theme-switch-wrapper, #searchInputDiv, .search-groupby { 152 | display:none; 153 | } 154 | .columns { 155 | width:100% !important; 156 | } 157 | } 158 | 159 | .column:first-child, .columns:first-child { 160 | margin-left: 0; } 161 | 162 | .container .row { 163 | display: flex; } 164 | 165 | .three.columns { 166 | width: 25.0%; 167 | height: 100vh; 168 | position: sticky; 169 | top: 0px; 170 | overflow-y: auto; 171 | padding: 2px; 172 | } 173 | 174 | .nine.columns { 175 | width: 75.0%; 176 | padding-left: 1.5em; } 177 | 178 | .twelve.columns { 179 | width: 100%; 180 | margin-left: 0; } 181 | 182 | @media screen and (max-width: 860px) { 183 | .three.columns { 184 | display: none; 185 | } 186 | .nine.columns { 187 | width: 98.0%; 188 | } 189 | body { 190 | font-size: 1em; 191 | line-height: 1.35; 192 | } 193 | } 194 | 195 | cite { 196 | font-style: italic !important; } 197 | 198 | 199 | /* Nim search input */ 200 | div#searchInputDiv { 201 | margin-bottom: 1em; 202 | } 203 | input#searchInput { 204 | width: 80%; 205 | } 206 | 207 | /* 208 | * Some custom formatting for input forms. 209 | * This also fixes input form colors on Firefox with a dark system theme on Linux. 210 | */ 211 | input { 212 | -moz-appearance: none; 213 | background-color: var(--secondary-background); 214 | color: var(--text); 215 | border: 1px solid var(--border); 216 | font-family: "Lato", "Helvetica Neue", "HelveticaNeue", Helvetica, Arial, sans-serif; 217 | font-size: 0.9em; 218 | padding: 6px; 219 | } 220 | 221 | input:focus { 222 | border: 1px solid var(--input-focus); 223 | box-shadow: 0 0 3px var(--input-focus); 224 | } 225 | 226 | select { 227 | -moz-appearance: none; 228 | background-color: var(--secondary-background); 229 | color: var(--text); 230 | border: 1px solid var(--border); 231 | font-family: "Lato", "Helvetica Neue", "HelveticaNeue", Helvetica, Arial, sans-serif; 232 | font-size: 0.9em; 233 | padding: 6px; 234 | } 235 | 236 | select:focus { 237 | border: 1px solid var(--input-focus); 238 | box-shadow: 0 0 3px var(--input-focus); 239 | } 240 | 241 | /* Docgen styles */ 242 | 243 | :target { 244 | border: 2px solid #B5651D; 245 | border-style: dotted; 246 | } 247 | 248 | /* Links */ 249 | a { 250 | color: var(--anchor); 251 | text-decoration: none; 252 | } 253 | 254 | a span.Identifier { 255 | text-decoration: underline; 256 | text-decoration-color: #aab; 257 | } 258 | 259 | a.reference-toplevel { 260 | font-weight: bold; 261 | } 262 | 263 | a.nimdoc { 264 | word-spacing: 0.3em; 265 | } 266 | 267 | a.toc-backref { 268 | text-decoration: none; 269 | color: var(--text); 270 | } 271 | 272 | a.link-seesrc { 273 | color: #607c9f; 274 | font-size: 0.9em; 275 | font-style: italic; 276 | } 277 | 278 | a:hover, a:focus { 279 | color: var(--anchor-focus); 280 | text-decoration: underline; 281 | } 282 | 283 | a:hover span.Identifier { 284 | color: var(--anchor); 285 | } 286 | 287 | 288 | sub, sup { 289 | position: relative; 290 | font-size: 75%; 291 | line-height: 0; 292 | vertical-align: baseline; } 293 | 294 | sup { 295 | top: -0.5em; } 296 | 297 | sub { 298 | bottom: -0.25em; } 299 | 300 | img { 301 | width: auto; 302 | height: auto; 303 | max-width: 100%; 304 | vertical-align: middle; 305 | border: 0; 306 | -ms-interpolation-mode: bicubic; } 307 | 308 | @media print { 309 | * { 310 | color: black !important; 311 | text-shadow: none !important; 312 | background: transparent !important; 313 | box-shadow: none !important; } 314 | 315 | a, a:visited { 316 | text-decoration: underline; } 317 | 318 | a[href]:after { 319 | content: " (" attr(href) ")"; } 320 | 321 | abbr[title]:after { 322 | content: " (" attr(title) ")"; } 323 | 324 | .ir a:after, 325 | a[href^="javascript:"]:after, 326 | a[href^="#"]:after { 327 | content: ""; } 328 | 329 | pre, blockquote { 330 | border: 1px solid #999; 331 | page-break-inside: avoid; } 332 | 333 | thead { 334 | display: table-header-group; } 335 | 336 | tr, img { 337 | page-break-inside: avoid; } 338 | 339 | img { 340 | max-width: 100% !important; } 341 | 342 | @page { 343 | margin: 0.5cm; } 344 | 345 | h1 { 346 | page-break-before: always; } 347 | 348 | h1.title { 349 | page-break-before: avoid; } 350 | 351 | p, h2, h3 { 352 | orphans: 3; 353 | widows: 3; } 354 | 355 | h2, h3 { 356 | page-break-after: avoid; } 357 | } 358 | 359 | 360 | p { 361 | margin-top: 0.5em; 362 | margin-bottom: 0.5em; } 363 | 364 | small { 365 | font-size: 85%; } 366 | 367 | strong { 368 | font-weight: 600; 369 | font-size: 0.95em; 370 | color: var(--strong); } 371 | 372 | em { 373 | font-style: italic; } 374 | 375 | h1 { 376 | font-size: 1.8em; 377 | font-weight: 400; 378 | padding-bottom: .25em; 379 | border-bottom: 6px solid var(--third-background); 380 | margin-top: 2.5em; 381 | margin-bottom: 1em; 382 | line-height: 1.2em; } 383 | 384 | h1.title { 385 | padding-bottom: 1em; 386 | border-bottom: 0px; 387 | font-size: 2.5em; 388 | text-align: center; 389 | font-weight: 900; 390 | margin-top: 0.75em; 391 | margin-bottom: 0em; } 392 | 393 | h2 { 394 | font-size: 1.3em; 395 | margin-top: 2em; } 396 | 397 | h2.subtitle { 398 | margin-top: 0em; 399 | text-align: center; } 400 | 401 | h3 { 402 | font-size: 1.125em; 403 | font-style: italic; 404 | margin-top: 1.5em; } 405 | 406 | h4 { 407 | font-size: 1.125em; 408 | margin-top: 1em; } 409 | 410 | h5 { 411 | font-size: 1.125em; 412 | margin-top: 0.75em; } 413 | 414 | h6 { 415 | font-size: 1.1em; } 416 | 417 | 418 | ul, ol { 419 | padding: 0; 420 | margin-top: 0.5em; 421 | margin-left: 0.75em; } 422 | 423 | ul ul, ul ol, ol ol, ol ul { 424 | margin-bottom: 0; 425 | margin-left: 1.25em; } 426 | 427 | ul.simple > li { 428 | list-style-type: circle; } 429 | 430 | ul.simple-boot li { 431 | list-style-type: none; 432 | margin-left: 0em; 433 | margin-bottom: 0.5em; } 434 | 435 | ol.simple > li, ul.simple > li { 436 | margin-bottom: 0.2em; 437 | margin-left: 0.4em } 438 | 439 | ul.simple.simple-toc > li { 440 | margin-top: 1em; } 441 | 442 | ul.simple-toc { 443 | list-style: none; 444 | font-size: 0.9em; 445 | margin-left: -0.3em; 446 | margin-top: 1em; } 447 | 448 | ul.simple-toc > li { 449 | list-style-type: none; } 450 | 451 | ul.simple-toc-section { 452 | list-style-type: circle; 453 | margin-left: 0.8em; 454 | color: #6c9aae; } 455 | 456 | ul.nested-toc-section { 457 | list-style-type: circle; 458 | margin-left: -0.75em; 459 | color: var(--text); } 460 | 461 | ul.nested-toc-section > li { 462 | margin-left: 1.25em; } 463 | 464 | 465 | ol.arabic { 466 | list-style: decimal; } 467 | 468 | ol.loweralpha { 469 | list-style: lower-alpha; } 470 | 471 | ol.upperalpha { 472 | list-style: upper-alpha; } 473 | 474 | ol.lowerroman { 475 | list-style: lower-roman; } 476 | 477 | ol.upperroman { 478 | list-style: upper-roman; } 479 | 480 | ul.auto-toc { 481 | list-style-type: none; } 482 | 483 | 484 | dl { 485 | margin-bottom: 1.5em; } 486 | 487 | dt { 488 | margin-bottom: -0.5em; 489 | margin-left: 0.0em; } 490 | 491 | dd { 492 | margin-left: 2.0em; 493 | margin-bottom: 3.0em; 494 | margin-top: 0.5em; } 495 | 496 | 497 | hr { 498 | margin: 2em 0; 499 | border: 0; 500 | border-top: 1px solid #aaa; } 501 | 502 | hr.footnote { 503 | width: 25%; 504 | border-top: 0.15em solid #999; 505 | margin-bottom: 0.15em; 506 | margin-top: 0.15em; 507 | } 508 | div.footnote-group { 509 | margin-left: 1em; 510 | } 511 | div.footnote-label { 512 | display: inline-block; 513 | min-width: 1.7em; 514 | } 515 | 516 | div.option-list { 517 | border: 0.1em solid var(--border); 518 | } 519 | div.option-list-item { 520 | padding-left: 12em; 521 | padding-right: 0; 522 | padding-bottom: 0.3em; 523 | padding-top: 0.3em; 524 | } 525 | div.odd { 526 | background-color: var(--secondary-background); 527 | } 528 | div.option-list-label { 529 | margin-left: -11.5em; 530 | margin-right: 0em; 531 | min-width: 11.5em; 532 | display: inline-block; 533 | vertical-align: top; 534 | } 535 | div.option-list-description { 536 | width: calc(100% - 1em); 537 | padding-left: 1em; 538 | padding-right: 0; 539 | display: inline-block; 540 | } 541 | 542 | blockquote { 543 | font-size: 0.9em; 544 | font-style: italic; 545 | padding-left: 0.5em; 546 | margin-left: 0; 547 | border-left: 5px solid #bbc; 548 | } 549 | 550 | blockquote.markdown-quote { 551 | font-size: 0.9rem; /* use rem to avoid recursion */ 552 | font-style: normal; 553 | } 554 | 555 | .pre, span.tok { 556 | font-family: "Source Code Pro", Monaco, Menlo, Consolas, "Courier New", monospace; 557 | font-weight: 500; 558 | font-size: 0.85em; 559 | color: var(--text); 560 | background-color: var(--third-background); 561 | padding-left: 3px; 562 | padding-right: 3px; 563 | border-radius: 4px; 564 | } 565 | 566 | span.tok { 567 | border: 1px solid #808080; 568 | padding-bottom: 0.1em; 569 | margin-right: 0.2em; 570 | } 571 | 572 | .copyToClipBoard { 573 | position: relative; 574 | } 575 | 576 | pre { 577 | font-family: "Source Code Pro", Monaco, Menlo, Consolas, "Courier New", monospace; 578 | color: var(--text); 579 | font-weight: 500; 580 | display: inline-block; 581 | box-sizing: border-box; 582 | min-width: 100%; 583 | padding: 0.5em; 584 | margin-top: 0.5em; 585 | margin-bottom: 0.5em; 586 | font-size: 0.85em; 587 | white-space: pre !important; 588 | overflow-y: hidden; 589 | overflow-x: visible; 590 | background-color: var(--secondary-background); 591 | border: 1px solid var(--border); 592 | -webkit-border-radius: 6px; 593 | -moz-border-radius: 6px; 594 | border-radius: 6px; 595 | } 596 | 597 | .copyToClipBoardBtn { 598 | visibility: hidden; 599 | position: absolute; 600 | width: 24px; 601 | border-radius: 4px; 602 | background-image: var(--clipboard-image); 603 | right: 5px; 604 | top: 13px; 605 | background-color: var(--secondary-background); 606 | padding: 11px; 607 | border: 0; 608 | } 609 | 610 | .copyToClipBoard:hover .copyToClipBoardBtn { 611 | visibility: visible; 612 | } 613 | 614 | .pre-scrollable { 615 | max-height: 340px; 616 | overflow-y: scroll; } 617 | 618 | 619 | /* Nim line-numbered tables */ 620 | .line-nums-table { 621 | width: 100%; 622 | table-layout: fixed; } 623 | 624 | table.line-nums-table { 625 | border-radius: 4px; 626 | border: 1px solid var(--border); 627 | background-color: var(--secondary-background); 628 | border-collapse: separate; 629 | margin-top: 15px; 630 | margin-bottom: 25px; } 631 | 632 | .line-nums-table tbody { 633 | border: none; } 634 | 635 | .line-nums-table td pre { 636 | border: none; 637 | background-color: transparent; } 638 | 639 | .line-nums-table td.blob-line-nums { 640 | width: 28px; } 641 | 642 | .line-nums-table td.blob-line-nums pre { 643 | color: #b0b0b0; 644 | -webkit-filter: opacity(75%); 645 | filter: opacity(75%); 646 | text-align: right; 647 | border-color: transparent; 648 | background-color: transparent; 649 | padding-left: 0px; 650 | margin-left: 0px; 651 | padding-right: 0px; 652 | margin-right: 0px; } 653 | 654 | 655 | table { 656 | max-width: 100%; 657 | background-color: transparent; 658 | margin-top: 0.5em; 659 | margin-bottom: 1.5em; 660 | border-collapse: collapse; 661 | border-color: var(--third-background); 662 | border-spacing: 0; 663 | } 664 | 665 | table:not(.line-nums-table) { 666 | font-size: 0.9em; 667 | } 668 | 669 | table th, table td { 670 | padding: 0px 0.5em 0px; 671 | border-color: var(--third-background); 672 | } 673 | 674 | table th { 675 | background-color: var(--third-background); 676 | border-color: var(--third-background); 677 | font-weight: bold; } 678 | 679 | table th.docinfo-name { 680 | background-color: transparent; 681 | text-align: right; 682 | } 683 | 684 | table:not(.line-nums-table) tr:hover { 685 | background-color: var(--third-background); } 686 | 687 | 688 | /* rst2html default used to remove borders from tables and images */ 689 | .borderless, table.borderless td, table.borderless th { 690 | border: 0; } 691 | 692 | table.borderless td, table.borderless th { 693 | /* Override padding for "table.docutils td" with "! important". 694 | The right padding separates the table cells. */ 695 | padding: 0 0.5em 0 0 !important; } 696 | 697 | .admonition { 698 | padding: 0.3em; 699 | background-color: var(--secondary-background); 700 | border-left: 0.4em solid #7f7f84; 701 | margin-bottom: 0.5em; 702 | -webkit-box-shadow: 0 5px 8px -6px rgba(0,0,0,.2); 703 | -moz-box-shadow: 0 5px 8px -6px rgba(0,0,0,.2); 704 | box-shadow: 0 5px 8px -6px rgba(0,0,0,.2); 705 | } 706 | .admonition-info { 707 | border-color: var(--info-background); 708 | } 709 | .admonition-info-text { 710 | color: var(--info-background); 711 | } 712 | .admonition-warning { 713 | border-color: var(--warning-background); 714 | } 715 | .admonition-warning-text { 716 | color: var(--warning-background); 717 | } 718 | .admonition-error { 719 | border-color: var(--error-background); 720 | } 721 | .admonition-error-text { 722 | color: var(--error-background); 723 | } 724 | 725 | .first { 726 | /* Override more specific margin styles with "! important". */ 727 | margin-top: 0 !important; } 728 | 729 | .last, .with-subtitle { 730 | margin-bottom: 0 !important; } 731 | 732 | .hidden { 733 | display: none; } 734 | 735 | blockquote.epigraph { 736 | margin: 2em 5em; } 737 | 738 | dl.docutils dd { 739 | margin-bottom: 0.5em; } 740 | 741 | object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] { 742 | overflow: hidden; } 743 | 744 | 745 | div.figure { 746 | margin-left: 2em; 747 | margin-right: 2em; } 748 | 749 | div.footer, div.header { 750 | clear: both; 751 | text-align: center; 752 | color: #666; 753 | font-size: smaller; } 754 | 755 | div.footer { 756 | padding-top: 5em; } 757 | 758 | div.line-block { 759 | display: block; 760 | margin-top: 1em; 761 | margin-bottom: 1em; } 762 | 763 | div.line-block div.line-block { 764 | margin-top: 0; 765 | margin-bottom: 0; 766 | margin-left: 1.5em; } 767 | 768 | div.topic { 769 | margin: 2em; } 770 | 771 | div.search_results { 772 | background-color: var(--third-background); 773 | margin: 3vh 5vw; 774 | padding: 1em; 775 | border: 1px solid #4d4d4d; 776 | position: fixed; 777 | top: 10px; 778 | isolation: isolate; 779 | max-width: calc(100vw - 6em); 780 | z-index: 1; 781 | max-height: calc(100vh - 6em); 782 | overflow-y: scroll;} 783 | 784 | div#global-links ul { 785 | margin-left: 0; 786 | list-style-type: none; } 787 | 788 | div#global-links > simple-boot { 789 | margin-left: 3em; } 790 | 791 | hr.docutils { 792 | width: 75%; } 793 | 794 | img.align-left, .figure.align-left, object.align-left { 795 | clear: left; 796 | float: left; 797 | margin-right: 1em; } 798 | 799 | img.align-right, .figure.align-right, object.align-right { 800 | clear: right; 801 | float: right; 802 | margin-left: 1em; } 803 | 804 | img.align-center, .figure.align-center, object.align-center { 805 | display: block; 806 | margin-left: auto; 807 | margin-right: auto; } 808 | 809 | .align-left { 810 | text-align: left; } 811 | 812 | .align-center { 813 | clear: both; 814 | text-align: center; } 815 | 816 | .align-right { 817 | text-align: right; } 818 | 819 | /* reset inner alignment in figures */ 820 | div.align-right { 821 | text-align: inherit; } 822 | 823 | p.attribution { 824 | text-align: right; 825 | margin-left: 50%; } 826 | 827 | p.caption { 828 | font-style: italic; } 829 | 830 | p.credits { 831 | font-style: italic; 832 | font-size: smaller; } 833 | 834 | p.label { 835 | white-space: nowrap; } 836 | 837 | p.rubric { 838 | font-weight: bold; 839 | font-size: larger; 840 | color: maroon; 841 | text-align: center; } 842 | 843 | p.topic-title { 844 | font-weight: bold; } 845 | 846 | pre.address { 847 | margin-bottom: 0; 848 | margin-top: 0; 849 | font: inherit; } 850 | 851 | pre.literal-block, pre.doctest-block, pre.math, pre.code { 852 | margin-left: 2em; 853 | margin-right: 2em; } 854 | 855 | pre.code .ln { 856 | color: grey; } 857 | 858 | /* line numbers */ 859 | pre.code, code { 860 | background-color: #eeeeee; } 861 | 862 | pre.code .comment, code .comment { 863 | color: #5c6576; } 864 | 865 | pre.code .keyword, code .keyword { 866 | color: #3B0D06; 867 | font-weight: bold; } 868 | 869 | pre.code .literal.string, code .literal.string { 870 | color: #0c5404; } 871 | 872 | pre.code .name.builtin, code .name.builtin { 873 | color: #352b84; } 874 | 875 | pre.code .deleted, code .deleted { 876 | background-color: #DEB0A1; } 877 | 878 | pre.code .inserted, code .inserted { 879 | background-color: #A3D289; } 880 | 881 | span.classifier { 882 | font-style: oblique; } 883 | 884 | span.classifier-delimiter { 885 | font-weight: bold; } 886 | 887 | span.problematic { 888 | color: #b30000; } 889 | 890 | span.section-subtitle { 891 | /* font-size relative to parent (h1..h6 element) */ 892 | font-size: 80%; } 893 | 894 | span.DecNumber { 895 | color: var(--number); } 896 | 897 | span.BinNumber { 898 | color: var(--number); } 899 | 900 | span.HexNumber { 901 | color: var(--number); } 902 | 903 | span.OctNumber { 904 | color: var(--number); } 905 | 906 | span.FloatNumber { 907 | color: var(--number); } 908 | 909 | span.Identifier { 910 | color: var(--identifier); } 911 | 912 | span.Keyword { 913 | font-weight: 600; 914 | color: var(--keyword); } 915 | 916 | span.StringLit { 917 | color: var(--literal); } 918 | 919 | span.LongStringLit { 920 | color: var(--literal); } 921 | 922 | span.CharLit { 923 | color: var(--literal); } 924 | 925 | span.EscapeSequence { 926 | color: var(--escapeSequence); } 927 | 928 | span.Operator { 929 | color: var(--operator); } 930 | 931 | span.Punctuation { 932 | color: var(--punctuation); } 933 | 934 | span.Comment, span.LongComment { 935 | font-style: italic; 936 | font-weight: 400; 937 | color: var(--comment); } 938 | 939 | span.RegularExpression { 940 | color: darkviolet; } 941 | 942 | span.TagStart { 943 | color: darkviolet; } 944 | 945 | span.TagEnd { 946 | color: darkviolet; } 947 | 948 | span.Key { 949 | color: #252dbe; } 950 | 951 | span.Value { 952 | color: #252dbe; } 953 | 954 | span.RawData { 955 | color: var(--raw-data); } 956 | 957 | span.Assembler { 958 | color: #252dbe; } 959 | 960 | span.Preprocessor { 961 | color: #252dbe; } 962 | 963 | span.Directive { 964 | color: #252dbe; } 965 | 966 | span.option { 967 | font-weight: bold; 968 | font-family: "Source Code Pro", Monaco, Menlo, Consolas, "Courier New", monospace; 969 | color: var(--option); } 970 | 971 | span.Prompt { 972 | font-weight: bold; 973 | color: red; } 974 | 975 | span.ProgramOutput { 976 | font-weight: bold; 977 | color: #808080; } 978 | 979 | span.program { 980 | font-weight: bold; 981 | color: var(--program); 982 | text-decoration: underline; 983 | text-decoration-color: var(--hint); 984 | text-decoration-thickness: 0.05em; 985 | text-underline-offset: 0.15em; } 986 | 987 | span.Command, span.Rule, span.Hyperlink, 988 | span.Label, span.Reference, span.Other { 989 | color: var(--other); } 990 | 991 | /* Pop type, const, proc, and iterator defs in nim def blocks */ 992 | dt pre > span.Identifier, dt pre > span.Operator { 993 | color: var(--identifier); 994 | font-weight: 700; } 995 | 996 | dt pre > span.Keyword ~ span.Identifier, dt pre > span.Identifier ~ span.Identifier, 997 | dt pre > span.Operator ~ span.Identifier, dt pre > span.Other ~ span.Identifier { 998 | color: var(--identifier); 999 | font-weight: inherit; } 1000 | 1001 | /* Nim sprite for the footer (taken from main page favicon) */ 1002 | .nim-sprite { 1003 | display: inline-block; 1004 | width: 51px; 1005 | height: 14px; 1006 | background-position: 0 0; 1007 | background-size: 51px 14px; 1008 | -webkit-filter: opacity(50%); 1009 | filter: opacity(50%); 1010 | background-repeat: no-repeat; 1011 | background-image: var(--nim-sprite-base64); 1012 | margin-bottom: 5px; } 1013 | 1014 | span.pragmadots { 1015 | /* Position: relative frees us up to make the dots 1016 | look really nice without fucking up the layout and 1017 | causing bulging in the parent container */ 1018 | position: relative; 1019 | /* 1px down looks slightly nicer */ 1020 | top: 1px; 1021 | padding: 2px; 1022 | background-color: var(--third-background); 1023 | border-radius: 4px; 1024 | margin: 0 2px; 1025 | cursor: pointer; 1026 | font-size: 0.8em; } 1027 | 1028 | span.pragmadots:hover { 1029 | background-color: var(--hint); } 1030 | 1031 | span.pragmawrap { 1032 | display: none; } 1033 | 1034 | span.attachedType { 1035 | display: none; 1036 | visibility: hidden; } 1037 | -------------------------------------------------------------------------------- /sqliteral.nim: -------------------------------------------------------------------------------- 1 | const SQLiteralVersion* = "5.0.1" 2 | static: doAssert(compileOption("threads")) 3 | when not defined(nimdoc) and not defined(gcDestructors): {.fatal: "mm:arc or mm:orc required".} 4 | 5 | # (C) Olli Niinivaara, 2020-2025 6 | # MIT Licensed 7 | 8 | ## A high level SQLite API with support for multi-threading, prepared statements, 9 | ## proper typing, zero-copy data paths, debugging, optimizing, backups, and more. 10 | ## 11 | ## Example 12 | ## ======= 13 | ## 14 | ## .. code-block:: Nim 15 | ## 16 | ## 17 | ## import sqliteral 18 | ## 19 | ## const Schema = "CREATE TABLE IF NOT EXISTS Example(name TEXT NOT NULL, jsondata TEXT NOT NULL) STRICT" 20 | ## 21 | ## type 22 | ## SqlStatements = enum 23 | ## Insert = """INSERT INTO Example (name, jsondata) 24 | ## VALUES (json_extract(?, '$.name'), json_extract(?, '$.data'))""" 25 | ## Select = "SELECT json_extract(jsondata, '$.array') FROM Example" 26 | ## 27 | ## ExtraStatements = enum 28 | ## Count = (2, "SELECT count(*) FROM Example") 29 | ## # Statement ordinal values must be unique across all statements 30 | ## 31 | ## let json = toDb("""{"name":"Alice", "data":{"info":"xxx", "array":["a","b","c"]}}""") 32 | ## 33 | ## var db: SQLiteral 34 | ## when not defined(release): db.setLogger(proc(db: SQLiteral, msg: string, code: int) = echo msg) 35 | ## 36 | ## proc select() = 37 | ## {.gcsafe.}: 38 | ## for row in db.rows(Select): stdout.write(row.getCString(0)) 39 | ## 40 | ## proc run() = 41 | ## echo "inserting 10000 rows..." 42 | ## db.transaction: 43 | ## for i in 1 .. 10000: discard db.insert(Insert, json, json) 44 | ## 45 | ## let count = db.getTheInt(Count) 46 | ## echo "10000 more rows inserted." 47 | ## echo "Press to select from the all existing ", count, " rows in 4 parallel threads..." 48 | ## discard stdin.readChar() 49 | ## 50 | ## var thr: array[4, Thread[void]] 51 | ## for i in 0..high(thr): createThread(thr[i], select) 52 | ## joinThreads(thr) 53 | ## stdout.flushFile() 54 | ## echo "\nSelected " & $(4 * count) & " arrays." 55 | ## 56 | ## db.openDatabase("ex.db", Schema) 57 | ## run() 58 | ## db.close() 59 | ## 60 | ## 61 | ## Compiling with sqlite3.c 62 | ## ======================== 63 | ## 64 | ## | First, sqlite3.c amalgamation must be on compiler search path. 65 | ## | You can extract it from a zip available at https://www.sqlite.org/download.html. 66 | ## | Then, `-d:staticSqlite`compiler option must be used. 67 | ## 68 | ## For your convenience, `-d:staticSqlite` triggers some useful SQLite compiler options, 69 | ## consult sqliteral source code or `about()` proc for details. 70 | ## These can be turned off with `-d:disableSqliteoptions` option. 71 | ## 72 | ## Statements in enum lists 73 | ## ======================== 74 | ## 75 | ## SQLiteral prepares statements only once, and their ordinal value in their corresponding enum 76 | ## list is used internally for indexing. Therefore, if you use statements from more than 77 | ## one enum list, the enums in other lists must be explicitly given unique ordinal values. The 78 | ## example above demonstrates this, where value 2 is set for the Count statement (Insert and 79 | ## Select implicitly get the values 0 and 1). 80 | 81 | when defined(staticSqlite): {.passL: "-lpthread".} 82 | else: 83 | when defined(windows): 84 | when defined(nimOldDlls): 85 | const Lib = "sqlite3.dll" 86 | elif defined(cpu64): 87 | const Lib = "sqlite3_64.dll" 88 | else: 89 | const Lib = "sqlite3_32.dll" 90 | elif defined(macosx): 91 | const Lib = "libsqlite3(|.0).dylib" 92 | else: 93 | const Lib = "libsqlite3.so(|.0)" 94 | 95 | when defined(staticSqlite) and not defined(disableSqliteoptions): 96 | {.passC: "-DSQLITE_DQS=0 -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_LIKE_DOESNT_MATCH_BLOBS".} 97 | {.passC: "-DSQLITE_ENABLE_JSON1 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_OMIT_PROGRESS_CALLBACK".} 98 | when defined(danger): 99 | {.passC: "-DSQLITE_USE_ALLOCA -DSQLITE_MAX_EXPR_DEPTH=0".} 100 | 101 | import db_connector/sqlite3 102 | export PStmt, errmsg, reset, step, finalize, SQLITE_ROW 103 | import locks 104 | from os import getFileSize 105 | from strutils import strip, split, contains, replace 106 | 107 | const 108 | MaxStatements* {.intdefine.} = 200 109 | ## Compile time define pragma that limits amount of prepared statements 110 | MaxDatabases* {.intdefine.} = 2 111 | ## Compile time define pragma that limits amount of databases 112 | 113 | 114 | type 115 | SQLError* = ref object of CatchableError 116 | ## https://www.sqlite.org/rescode.html 117 | rescode*: int 118 | 119 | SQLiteral* = object 120 | sqlite*: PSqlite3 121 | dbname*: string 122 | inreadonlymode*: bool 123 | backupsinprogress*: int 124 | index: int 125 | intransaction: bool 126 | walmode: bool 127 | maxsize: int 128 | transactionlock: Lock 129 | loggerproc: proc(sqliteral: SQLiteral, statement: string, errorcode: int) {.gcsafe, raises: [].} 130 | oncommitproc: proc(sqliteral: SQLiteral) {.gcsafe, raises: [].} 131 | maxparamloggedlen: int 132 | Transaction: PStmt 133 | Commit: PStmt 134 | Rollback: PStmt 135 | 136 | DbValueKind = enum 137 | sqliteInteger, 138 | sqliteReal, 139 | sqliteText, 140 | sqliteBlob 141 | 142 | DbValue* = object 143 | ## | Represents a value in a SQLite database. 144 | ## | https://www.sqlite.org/datatype3.html 145 | ## | NULL values are not possible to avoid the billion-dollar mistake. 146 | case kind*: DbValueKind 147 | of sqliteInteger: 148 | intVal*: int64 149 | of sqliteReal: 150 | floatVal*: float64 151 | of sqliteText: 152 | textVal*: tuple[chararray: cstring, len: int32] 153 | of sqliteBlob: 154 | blobVal*: seq[byte] # TODO: openArray[byte] 155 | 156 | var 157 | openlock: Lock 158 | nextdbindex = 0 159 | preparedstatements {.threadvar.} : array[MaxDatabases * MaxStatements, PStmt] 160 | allpreparedstatements: seq[ptr array[MaxDatabases * MaxStatements, PStmt]] 161 | 162 | 163 | initLock(openlock) 164 | 165 | 166 | template checkRc*(db: SQLiteral, resultcode: int) = 167 | ## | Raises SQLError if resultcode notin SQLITE_OK, SQLITE_ROW, SQLITE_DONE 168 | ## | https://www.sqlite.org/rescode.html 169 | if resultcode notin [SQLITE_OK, SQLITE_ROW, SQLITE_DONE]: 170 | let errormsg = 171 | if resultcode == 10000: "Sqliteral error" 172 | else: $errmsg(db.sqlite) 173 | if db.loggerproc != nil: db.loggerproc(db, errormsg, resultcode) 174 | raise SQLError(msg: db.dbname & " " & errormsg, rescode: resultcode) 175 | 176 | 177 | proc toDb*(val: cstring, len = -1): DbValue {.inline.} = 178 | if len == -1: DbValue(kind: sqliteText, textVal: (val, int32(val.len()))) 179 | else: DbValue(kind: sqliteText, textVal: (val, int32(len))) 180 | 181 | proc toDb*(val: cstring, first, last: int): DbValue {.inline.} = 182 | DbValue(kind: sqliteText, textVal: (cast[cstring](unsafeAddr(val[first])), int32(1 + last - first))) 183 | 184 | proc toDb*(val: string, len = -1): DbValue {.inline.} = 185 | if len == -1: DbValue(kind: sqliteText, textVal: (cstring(val), int32(val.len()))) 186 | else: DbValue(kind: sqliteText, textVal: (cstring(val), int32(len))) 187 | 188 | proc toDb*(val: string, first, last: int): DbValue {.inline.} = 189 | DbValue(kind: sqliteText, textVal: (cast[cstring](unsafeAddr(val[first])), int32(1 + last - first))) 190 | 191 | {.warning[PtrToCstringConv]:off.} 192 | proc toDb*(val: openArray[char], len = -1): DbValue {.inline.} = 193 | if len == -1: DbValue(kind: sqliteText, textVal: (cstring(unsafeAddr val[0]), int32(val.len()))) 194 | else: DbValue(kind: sqliteText, textVal: (cstring(unsafeAddr val[0]), int32(len))) 195 | {.warning[PtrToCstringConv]:on.} 196 | 197 | proc toDb*[T: Ordinal](val: T): DbValue {.inline.} = DbValue(kind: sqliteInteger, intVal: val.int64) 198 | 199 | proc toDb*[T: SomeFloat](val: T): DbValue {.inline.} = DbValue(kind: sqliteReal, floatVal: val.float64) 200 | 201 | proc toDb*(val: seq[byte]): DbValue {.inline.} = DbValue(kind: sqliteBlob, blobVal: val) 202 | 203 | proc toDb*[T: DbValue](val: T): DbValue {.inline.} = val 204 | 205 | 206 | proc `$`*[T: DbValue](val: T): string {.inline.} = 207 | case val.kind 208 | of sqliteInteger: $val.intVal 209 | of sqliteReal: $val.floatVal 210 | of sqliteText: ($val.textVal.chararray)[0 .. val.textVal.len - 1] 211 | of sqliteBlob: cast[string](val.blobVal) 212 | 213 | 214 | proc prepareSql*(db: SQLiteral, sql: cstring): PStmt {.inline.} = 215 | ## Prepares a cstring into an executable statement 216 | checkRc(db, prepare_v2(db.sqlite, sql, sql.len.cint, result, nil)) 217 | return result 218 | 219 | 220 | proc getStatement(db: SQLiteral, statement: enum): PStmt = 221 | result = preparedstatements[db.index * MaxStatements + ord(statement)] 222 | if likely(result != nil): return result 223 | let index = ord(statement) 224 | if unlikely(index >= MaxStatements): 225 | let problem = "Index " & $index & " of '" & $statement & "' larger than MaxStatements = " & $MaxStatements 226 | if db.loggerproc != nil: db.loggerproc(db, problem, 10000) 227 | raise SQLError(msg: db.dbname & " " & problem, rescode: 10000) 228 | result = prepareSql(db, ($statement).cstring) 229 | preparedstatements[db.index * MaxStatements + index] = result 230 | if not allpreparedstatements.contains(addr preparedstatements): 231 | allpreparedstatements.add(addr preparedstatements) 232 | if db.loggerproc != nil: 233 | db.loggerproc(db, "Prepared for thread " & $getThreadId() & ": " & $statement, -1) 234 | 235 | 236 | proc bindParams*(sql: PStmt, params: varargs[DbValue]): int {.inline.} = 237 | var idx = 1.int32 238 | for value in params: 239 | result = 240 | case value.kind 241 | of sqliteInteger: bind_int64(sql, idx, value.intVal) 242 | of sqliteReal: bind_double(sql, idx, value.floatVal) 243 | of sqliteText: bind_text(sql, idx, value.textVal.chararray, value.textVal.len, SQLITE_STATIC) 244 | of sqliteBlob: bind_blob(sql, idx.int32, cast[string](value.blobVal).cstring, value.blobVal.len.int32, SQLITE_STATIC) 245 | if result != SQLITE_OK: return 246 | idx.inc 247 | 248 | 249 | template log() = 250 | var resultcode = 0 251 | var logstring = $statement 252 | var replacement = 0 253 | while replacement < params.len: 254 | let position = logstring.find('?') 255 | if (position == -1): 256 | logstring = $params.len & "is too many params for: " & $statement 257 | replacement = params.len 258 | resultcode = 10000 259 | continue 260 | let param = 261 | if db.maxparamloggedlen < 1: $params[replacement] 262 | else: ($params[replacement]).substr(0, db.maxparamloggedlen - 1) 263 | logstring = logstring[0 .. position-1] & param & logstring.substr(position+1) 264 | replacement += 1 265 | if (logstring.find('?') != -1): 266 | logstring &= " (some params missing)" 267 | resultcode = 10000 268 | db.loggerproc(db, logstring, resultcode) 269 | 270 | 271 | proc doLog*(db: SQLiteral, statement: string, params: varargs[DbValue, toDb]) {.inline.} = 272 | if statement == "Pstmt rows" or statement == "exec Pstmt": db.loggerproc(db, statement & " " & $params, 0) 273 | else: log() 274 | 275 | #----------------------------------------------------------------------------------------------------------- 276 | 277 | proc getInt*(prepared: PStmt, col: int32 = 0): int64 {.inline.} = 278 | ## Returns value of INTEGER -type column at given column index 279 | return column_int64(prepared, col) 280 | 281 | 282 | proc getString*(prepared: PStmt, col: int32 = 0): string {.inline.} = 283 | ## Returns value of TEXT -type column at given column index as string 284 | return $column_text(prepared, col) 285 | 286 | 287 | proc getCString*(prepared: PStmt, col: int32 = 0): cstring {.inline.} = 288 | ## | Returns value of TEXT -type column at given column index as cstring. 289 | ## | Zero-copy, but result is not available after cursor movement or statement reset. 290 | return column_text(prepared, col) 291 | 292 | 293 | proc getFloat*(prepared: PStmt, col: int32 = 0): float64 {.inline.} = 294 | ## Returns value of REAL -type column at given column index 295 | return column_double(prepared, col) 296 | 297 | 298 | proc getSeq*(prepared: PStmt, col: int32 = 0): seq[byte] {.inline.} = 299 | ## Returns value of BLOB -type column at given column index 300 | let blob = column_blob(prepared, col) 301 | let bytes = column_bytes(prepared, col) 302 | result = newSeq[byte](bytes) 303 | if bytes != 0: copyMem(addr(result[0]), blob, bytes) 304 | 305 | 306 | proc getAsStrings*(prepared: PStmt): seq[string] = 307 | ## Returns values of all result columns as a sequence of strings. 308 | ## This proc is mainly useful for debugging purposes. 309 | let columncount = column_count(prepared) 310 | for col in 0 ..< columncount: result.add($column_text(prepared, col)) 311 | 312 | 313 | iterator rows*(db: SQLiteral, statement: enum, params: varargs[DbValue, toDb]): PStmt = 314 | ## Iterates over the query results 315 | if db.loggerproc != nil: log() 316 | let s = db.getStatement(statement) 317 | checkRc(db, bindParams(s, params)) 318 | defer: discard sqlite3.reset(s) 319 | while step(s) == SQLITE_ROW: yield s 320 | 321 | 322 | iterator rows*(db: SQLiteral, pstatement: Pstmt, params: varargs[DbValue, toDb]): PStmt = 323 | ## Iterates over the query results 324 | if db.loggerproc != nil: db.doLog("Pstmt rows", params) 325 | checkRc(db, bindParams(pstatement, params)) 326 | defer: discard sqlite3.reset(pstatement) 327 | while step(pstatement) == SQLITE_ROW: yield pstatement 328 | 329 | 330 | proc getTheInt*(db: SQLiteral, statement: enum, params: varargs[DbValue, toDb]): int64 {.inline.} = 331 | ## | Executes query and returns value of INTEGER -type column at column index 0 of first result row. 332 | ## | If query does not return any rows, returns -2147483647 (low(int32) + 1). 333 | ## | Automatically resets the statement. 334 | if db.loggerproc != nil: log() 335 | let s = db.getStatement(statement) 336 | checkRc(db, bindParams(s, params)) 337 | defer: discard sqlite3.reset(s) 338 | if step(s) == SQLITE_ROW: s.getInt(0) else: -2147483647 339 | 340 | 341 | proc getTheInt*(db: SQLiteral, s: string): int64 {.inline.} = 342 | ## | Dynamically prepares, executes and finalizes given query and returns value of INTEGER -type 343 | ## column at column index 0 of first result row. 344 | ## | If query does not return any rows, returns -2147483647 (low(int32) + 1). 345 | ## | For security and performance reasons, this proc should be used with caution. 346 | if db.loggerproc != nil: db.loggerproc(db, s, 0) 347 | let query = db.prepareSql(s) 348 | try: 349 | let rc = step(query) 350 | checkRc(db, rc) 351 | result = if rc == SQLITE_ROW: query.getInt(0) else: -2147483647 352 | finally: 353 | discard finalize(query) 354 | 355 | 356 | proc getTheString*(db: SQLiteral, statement: enum, params: varargs[DbValue, toDb]): string {.inline.} = 357 | ## | Executes query and returns value of TEXT -type column at column index 0 of first result row. 358 | ## | If query does not return any rows, returns empty string. 359 | ## | Automatically resets the statement. 360 | if db.loggerproc != nil: log() 361 | let s = db.getStatement(statement) 362 | checkRc(db, bindParams(s, params)) 363 | defer: discard sqlite3.reset(s) 364 | if step(s) == SQLITE_ROW: return s.getString(0) 365 | 366 | 367 | proc getTheString*(db: SQLiteral, s: string): string {.inline.} = 368 | ## | Dynamically prepares, executes and finalizes given query and returns value of TEXT -type 369 | ## column at column index 0 of first result row. 370 | ## | If query does not return any rows, returns empty string. 371 | ## | For security and performance reasons, this proc should be used with caution. 372 | if db.loggerproc != nil: db.loggerproc(db, s, 0) 373 | let query = db.prepareSql(s) 374 | try: 375 | let rc = step(query) 376 | checkRc(db, rc) 377 | result = if rc == SQLITE_ROW: query.getString(0) else: "" 378 | finally: 379 | discard finalize(query) 380 | 381 | 382 | proc getLastInsertRowid*(db: SQLiteral): int64 {.inline.} = 383 | ## https://www.sqlite.org/c3ref/last_insert_rowid.html 384 | return db.sqlite.last_insert_rowid() 385 | 386 | 387 | proc rowExists*(db: SQLiteral, statement: enum, params: varargs[DbValue, toDb]): bool {.inline.} = 388 | ## Returns true if query returns any rows 389 | if db.loggerproc != nil: log() 390 | let s = db.getStatement(statement) 391 | checkRc(db, bindParams(s, params)) 392 | defer: discard sqlite3.reset(s) 393 | return step(s) == SQLITE_ROW 394 | 395 | 396 | proc rowExists*(db: SQLiteral, sql: string): bool {.inline.} = 397 | ## | Returns true if query returns any rows. 398 | ## | For security reasons, this proc should be used with caution. 399 | if db.loggerproc != nil: db.loggerproc(db, sql, 0) 400 | let preparedstatement = db.prepareSql(sql.cstring) 401 | defer: discard finalize(preparedstatement) 402 | return step(preparedstatement) == SQLITE_ROW 403 | 404 | 405 | template withRow*(db: SQLiteral, sql: string, row, body: untyped) = 406 | ## | Dynamically prepares and finalizes an sql query. 407 | ## | Name for the resulting prepared statement is given with row parameter. 408 | ## | The code block will be executed only if query returns a row. 409 | ## | For security and performance reasons, this proc should be used with caution. 410 | if db.loggerproc != nil: db.loggerproc(db, sql, 0) 411 | let preparedstatement = prepareSql(db, sql.cstring) 412 | try: 413 | if step(preparedstatement) == SQLITE_ROW: 414 | var row {.inject.} = preparedstatement 415 | body 416 | finally: 417 | discard finalize(preparedstatement) 418 | 419 | 420 | template withRowOr*(db: SQLiteral, sql: string, row, body1, body2: untyped) = 421 | ## | Dynamically prepares and finalizes an sql query. 422 | ## | Name for the resulting prepared statement is given with row parameter. 423 | ## | First block will be executed if query returns a row, otherwise the second block. 424 | ## | For security and performance reasons, this proc should be used with caution. 425 | ## **Example:** 426 | ## 427 | ## .. code-block:: Nim 428 | ## 429 | ## db.withRowOr("SELECT (1) FROM sqlite_master", rowname): 430 | ## echo "database has some tables because first column = ", rowname.getInt(0) 431 | ## do: 432 | ## echo "we have a fresh database" 433 | ## 434 | if db.loggerproc != nil: db.loggerproc(db, sql, 0) 435 | let preparedstatement = prepareSql(db, sql.cstring) 436 | try: 437 | if step(preparedstatement) == SQLITE_ROW: 438 | var row {.inject.} = preparedstatement 439 | body1 440 | else: body2 441 | finally: 442 | discard finalize(preparedstatement) 443 | 444 | 445 | template withRow*(db: SQLiteral, statement: enum, params: varargs[DbValue, toDb], row, body: untyped) = 446 | ## | Executes given statement. 447 | ## | Name for the prepared statement is given with row parameter. 448 | ## | The code block will be executed only if query returns a row. 449 | if db.loggerproc != nil: doLog(db, $statement, params) 450 | let s = db.getStatement(statement) 451 | defer: discard reset(s) 452 | checkRc(db, bindParams(s, params)) 453 | if step(s) == SQLITE_ROW: 454 | var row {.inject.} = s 455 | body 456 | 457 | 458 | template withRowOr*(db: SQLiteral, statement: enum, params: varargs[DbValue, toDb], row, body1, body2: untyped) = 459 | ## | Executes given statement. 460 | ## | Name for the prepared statement is given with row parameter. 461 | ## | First block will be executed if query returns a row, otherwise the second block. 462 | if db.loggerproc != nil: doLog(db, $statement, params) 463 | let s = db.getStatement(statement) 464 | checkRc(db, bindParams(s, params)) 465 | try: 466 | if step(s) == SQLITE_ROW: 467 | var row {.inject.} = s 468 | body1 469 | else: body2 470 | finally: 471 | discard sqlite3.reset(s) 472 | 473 | #----------------------------------------------------------------------------------------------------------- 474 | 475 | proc exec*(db: SQLiteral, pstatement: Pstmt, params: varargs[DbValue, toDb]) {.inline.} = 476 | ## Executes given prepared statement 477 | if db.loggerproc != nil: db.doLog("exec Pstmt", params) 478 | defer: discard sqlite3.reset(pstatement) 479 | checkRc(db, bindParams(pstatement, params)) 480 | checkRc(db, step(pstatement)) 481 | 482 | 483 | proc exec*(db: SQLiteral, statement: enum, params: varargs[DbValue, toDb]) {.inline.} = 484 | ## Executes given statement 485 | if db.loggerproc != nil: log() 486 | let s = db.getStatement(statement) 487 | defer: discard sqlite3.reset(s) 488 | checkRc(db, bindParams(s, params)) 489 | checkRc(db, step(s)) 490 | 491 | 492 | proc exes*(db: SQLiteral, sql: string) = 493 | ## | Prepares, executes and finalizes given semicolon-separated sql statements. 494 | ## | For security and performance reasons, this proc should be used with caution. 495 | if db.loggerproc != nil: db.loggerproc(db, sql, -1) 496 | var errormsg: cstring 497 | let rescode = sqlite3.exec(db.sqlite, sql.cstring, nil, nil, errormsg) 498 | if rescode != 0: 499 | var error: string 500 | if errormsg != nil: 501 | error = $errormsg 502 | free(errormsg) 503 | if db.loggerproc != nil: db.loggerproc(db, error, rescode) 504 | raise SQLError(msg: db.dbname & " " & $rescode & " " & error, rescode: rescode) 505 | 506 | 507 | proc insert*(db: SQLiteral, statement: enum, params: varargs[DbValue, toDb]): int64 {.inline.} = 508 | ## | Executes given statement and, if succesful, returns db.getLastinsertRowid(). 509 | ## | If not succesful, returns -2147483647 (low(int32) + 1). 510 | if db.loggerproc != nil: log() 511 | let s = db.getStatement(statement) 512 | defer: discard sqlite3.reset(s) 513 | checkRc(db, bindParams(s, params)) 514 | result = 515 | if step(s) == SQLITE_DONE: db.getLastinsertRowid() 516 | else: -2147483647 517 | 518 | 519 | proc update*(db: SQLiteral, sql: string, column: string, newvalue: DbValue, where: DbValue) = 520 | ## | Dynamically constructs, prepares, executes and finalizes given update query. 521 | ## | Update must target one column and WHERE -clause must contain one value. 522 | ## | For security and performance reasons, this proc should be used with caution. 523 | if column.find(' ') != -1: raise (ref Exception)(msg: "Column must not contain spaces: " & column) 524 | let update = sql.replace("Column", column).cstring 525 | var pstmt: PStmt 526 | if db.loggerproc != nil: db.loggerproc(db, $update & " (" & $newvalue & ", " & $where & ")", 0) 527 | checkRc(db, prepare_v2(db.sqlite, update, update.len.cint, pstmt, nil)) 528 | try: 529 | db.exec(pstmt, newvalue, where) 530 | finally: 531 | discard pstmt.finalize() 532 | 533 | 534 | proc columnExists*(db: SQLiteral, table: string, column: string): bool = 535 | ## Returns true if given column exists in given table 536 | result = false 537 | if table.find(' ') != -1: raise (ref Exception)(msg: "Table must not contain spaces: " & table) 538 | if column.find(' ') != -1: raise (ref Exception)(msg: "Column must not contain spaces: " & column) 539 | let sql = ("SELECT count(*) FROM pragma_table_info('" & table & "') WHERE name = '" & column & "'").cstring 540 | if db.loggerproc != nil: db.loggerproc(db, $sql, 0) 541 | let pstmt = db.prepareSql(sql) 542 | try: 543 | if step(pstmt) == SQLITE_ROW: result = pstmt.getInt(0) == 1 544 | finally: 545 | discard sqlite3.reset(pstmt) 546 | discard pstmt.finalize() 547 | 548 | 549 | template transaction*(db: var SQLiteral, body: untyped) = 550 | ## | Every write to database must happen inside some transaction. 551 | ## | Groups of reads must be wrapped in same transaction if mutual consistency required. 552 | ## | In WAL mode (the default), independent reads must NOT be wrapped in transaction to allow parallel processing. 553 | if not db.inreadonlymode: 554 | acquire(db.transactionlock) 555 | exec(db, db.Transaction) 556 | db.intransaction = true 557 | if db.loggerproc != nil: db.loggerproc(db, "--- BEGIN TRANSACTION", 0) 558 | try: body 559 | except CatchableError as ex: 560 | exec(db, db.Rollback) 561 | if db.loggerproc != nil: db.loggerproc(db, "--- ROLLBACK", 0) 562 | db.intransaction = false 563 | raise ex 564 | finally: 565 | if db.intransaction: 566 | exec(db, db.Commit) 567 | if db.oncommitproc != nil: db.oncommitproc(db) 568 | db.intransaction = false 569 | if db.loggerproc != nil: db.loggerproc(db, "--- COMMIT", 0) 570 | release(db.transactionlock) 571 | 572 | 573 | template transactionsDisabled*(db: var SQLiteral, body: untyped) = 574 | ## Executes `body` in between transactions (ie. does not start transaction, but transactions are blocked during this operation). 575 | acquire(db.transactionlock) 576 | if db.loggerproc != nil: db.loggerproc(db, "--- TRANSACTIONS DISABLED", 0) 577 | try: 578 | body 579 | finally: 580 | if db.loggerproc != nil: db.loggerproc(db, "--- TRANSACTIONS ENABLED", 0) 581 | release(db.transactionlock) 582 | 583 | 584 | proc isIntransaction*(db: SQLiteral): bool {.inline.} = 585 | return db.intransaction 586 | 587 | 588 | proc setLogger*(db: var SQLiteral, logger: proc(sqliteral: SQLiteral, statement: string, code: int) 589 | {.gcsafe, raises: [].}, paramtruncat = 50) = 590 | ## Set callback procedure to gather all executed statements with their parameters. 591 | ## 592 | ## If code == 10000, log concerns internal sqliteral error. 593 | ## 594 | ## If code > 0, log concerns sqlite error with error code in question. 595 | ## 596 | ## If code == 0, log concerns normal operation. 597 | ## 598 | ## If code == -1, log is mainly for debugging purposes. 599 | ## 600 | ## Paramtruncat parameter limits the maximum log length of parameters so that long inputs won't 601 | ## clutter logs. Value < 1 disables truncation. 602 | ## 603 | ## You can use the same logger for multiple sqliterals, the caller is also given as parameter. 604 | db.maxparamloggedlen = paramtruncat 605 | db.loggerproc = logger 606 | 607 | 608 | proc setOnCommitCallback*(db: var SQLiteral, oncommit: proc(sqliteral: SQLiteral) {.gcsafe, raises: [].}) = 609 | ## Set callback procedure that is triggered inside transaction proc, when commit to database has been executed. 610 | db.oncommitproc = oncommit 611 | 612 | # ------------------------------------------------------------------------------------------------------------- 613 | 614 | proc openDatabase*(db: var SQLiteral, dbname: string, schemas: openArray[string], 615 | maxKbSize = 0, wal = true, ignorableschemaerrors: openArray[string] = @["duplicate column name", "no such column"]) = 616 | ## Opens an exclusive connection, boots up the database, executes given schemas and prepares given statements. 617 | ## 618 | ## If dbname is not a path, current working directory will be used. 619 | ## 620 | ## | If wal = true, database is opened in WAL mode with NORMAL synchronous setting. 621 | ## | If wal = false, database is opened in PERSIST mode with FULL synchronous setting. 622 | ## | https://www.sqlite.org/wal.html 623 | ## | https://www.sqlite.org/pragma.html#pragma_synchronous 624 | ## 625 | ## If maxKbSize == 0, database size is limited only by OS or hardware with possibly severe consequences. 626 | ## 627 | ## `ignorableschemaerrors` is a list of error message snippets for sql errors that are to be ignored. 628 | ## If a clause may error, it must be given in a separate schema as its unique clause. 629 | ## If * is given as ignorable error, it means that all errors will be ignored. 630 | ## 631 | ## Note that by default, "duplicate column name" (ADD COLUMN) and "no such column" (DROP COLUMN) -errors will be ignored. 632 | ## Example below. 633 | ## 634 | ## .. code-block:: Nim 635 | ## 636 | ## # nim r -d:Maxdatabases=4 example.nim 637 | ## import sqliteral 638 | ## 639 | ## const 640 | ## Schema1 = "CREATE TABLE IF NOT EXISTS Example(data TEXT NOT NULL) STRICT" 641 | ## Schema2 = "this is crap" 642 | ## Schema3 = "ALTER TABLE Example ADD COLUMN newcolumn TEXT" 643 | ## Schema4 = "ALTER TABLE Example ADD COLUMN newcolumn TEXT" 644 | ## 645 | ## var db1, db2, db3: SQLiteral 646 | ## 647 | ## proc logger(db: SQLiteral, msg: string, code: int) = echo msg 648 | ## db1.setLogger(logger); db2.setLogger(logger); db3.setLogger(logger) 649 | ## 650 | ## # this will succeed because extra ADD COLUMNs are ignored: 651 | ## db1.openDatabase("example1.db", [Schema1, Schema3, Schema4]); db1.close() 652 | ## 653 | ## # this will succeed because suitable ignorableschemaerrors are given: 654 | ## db2.openDatabase("example2.db", [Schema1, Schema2], 655 | ## ignorableschemaerrors = ["""this": syntax error"""]); db2.close() 656 | ## 657 | ## # this will succeed because all schema errors are ignored: 658 | ## db3.openDatabase("example1.db", [Schema1, Schema2, Schema3], 659 | ## ignorableschemaerrors = ["*"]); db3.close() 660 | ## 661 | ## # this will fail because Schema 2 has syntax error: 662 | ## db1.openDatabase("example1.db", [Schema1, Schema2]) 663 | ## 664 | doAssert dbname != "" 665 | withLock(openlock): 666 | if nextdbindex == MaxDatabases: raiseAssert("Cannot open more than " & $MaxDatabases & " databases. Increase the MaxDatabases intdefine.") 667 | db.index = nextdbindex 668 | nextdbindex += 1 669 | initLock(db.transactionlock) 670 | db.dbname = dbname 671 | db.checkRc(open(dbname, db.sqlite)) 672 | 673 | db.exes("PRAGMA encoding = 'UTF-8'") 674 | db.exes("PRAGMA foreign_keys = ON") 675 | db.exes("PRAGMA locking_mode = EXCLUSIVE") 676 | db.walmode = wal 677 | if wal: db.exes("PRAGMA journal_mode = WAL") 678 | else: 679 | db.exes("PRAGMA journal_mode = PERSIST") 680 | db.exes("PRAGMA synchronous = FULL") 681 | if maxKbSize > 0: 682 | db.maxsize = maxKbSize 683 | let pagesize = db.getTheInt("PRAGMA page_size") 684 | db.exes("PRAGMA max_page_count = " & $(maxKbSize * 1024 div pagesize)) 685 | for schema in schemas: 686 | try: db.exes(schema) 687 | except: 688 | var ignorable = false 689 | for ignorableerror in ignorableschemaerrors: 690 | if ignorableerror == "*" or getCurrentExceptionMsg().contains(ignorableerror): (ignorable = true; break) 691 | if not ignorable: raise 692 | db.Transaction = db.prepareSql("BEGIN IMMEDIATE".cstring) 693 | db.Commit = db.prepareSql("COMMIT".cstring) 694 | db.Rollback = db.prepareSql("ROLLBACK".cstring) 695 | if db.loggerproc != nil: db.loggerproc(db, db.dbname & " opened", -1) 696 | 697 | 698 | proc openDatabase*(db: var SQLiteral, dbname: string, schema: string, maxKbSize = 0, wal = true) {.inline.} = 699 | ## Open database with a single schema. 700 | openDatabase(db, dbname, [schema], maxKbSize, wal, @["duplicate column name", "no such column"]) 701 | 702 | 703 | proc prepareStatements*(db: var SQLiteral, statements: typedesc[enum]) {.deprecated: "Preparations happen automatically.".} = discard 704 | proc finalizeStatements*() {.deprecated: "Finalizations happen automatically.".} = discard 705 | 706 | 707 | proc finalizeAllStatements() = 708 | for threadpreparedstatements in allpreparedstatements: 709 | for i in 0 .. threadpreparedstatements[].high: 710 | if threadpreparedstatements[][i] != nil: 711 | discard threadpreparedstatements[][i].finalize() 712 | threadpreparedstatements[][i] = nil 713 | 714 | 715 | proc setReadonly*(db: var SQLiteral, readonly: bool) = 716 | ## When in readonly mode: 717 | ## 718 | ## 1) All transactions will be silently discarded 719 | ## 720 | ## 2) Journal mode is changed to PERSIST in order to be able to change locking mode 721 | ## 722 | ## 3) Locking mode is changed from EXCLUSIVE to NORMAL, allowing other connections access the database 723 | ## 724 | ## Setting readonly fails with exception "cannot change into wal mode from within a transaction" 725 | ## when a statement is being executed, for example a result of a select is being iterated. 726 | ## 727 | ## ``inreadonlymode`` property tells current mode. 728 | if readonly == db.inreadonlymode: return 729 | db.transactionsDisabled: 730 | if readonly: 731 | db.inreadonlymode = readonly 732 | db.exes("PRAGMA journal_mode = PERSIST") 733 | db.exes("PRAGMA locking_mode = NORMAL") 734 | db.exes("SELECT (1) FROM sqlite_master") # dummy access to release file lock 735 | else: 736 | if db.walmode: db.exes("PRAGMA journal_mode = WAL") 737 | db.exes("PRAGMA locking_mode = EXCLUSIVE") # next write will keep the file lock 738 | db.inreadonlymode = readonly 739 | if db.loggerproc != nil: db.loggerproc(db, "--- READONLY MODE: " & $readonly , 0) 740 | 741 | 742 | proc optimize*(db: var SQLiteral, pagesize = -1, walautocheckpoint = -1) = 743 | ## Vacuums and optimizes the database. 744 | ## 745 | ## This proc should be run just before closing, when no other thread accesses the database. 746 | ## 747 | ## | In addition, database read/write performance ratio may be adjusted with parameters: 748 | ## | https://sqlite.org/pragma.html#pragma_page_size 749 | ## | https://www.sqlite.org/pragma.html#pragma_wal_checkpoint 750 | acquire(db.transactionlock) 751 | try: 752 | db.exes("PRAGMA optimize") 753 | if walautocheckpoint > -1: db.exes("PRAGMA wal_autocheckpoint = " & $walautocheckpoint) 754 | if pagesize > -1: 755 | db.exes("PRAGMA journal_mode = PERSIST") 756 | db.exes("PRAGMA page_size = " & $pagesize) 757 | db.exes("VACUUM") 758 | if pagesize > -1 and db.walmode: db.exes("PRAGMA journal_mode = WAL") 759 | except: 760 | if db.loggerproc != nil: db.loggerproc(db, getCurrentExceptionMsg(), 10000) 761 | else: echo "Could not optimize ", db.dbname, ": ", getCurrentExceptionMsg() 762 | finally: 763 | release(db.transactionlock) 764 | 765 | 766 | proc initBackup*(db: var SQLiteral, backupfilename: string): 767 | tuple[backupdb: Psqlite3, backuphandle: PSqlite3_Backup] = 768 | ## Initializes backup processing, returning variables to use with `stepBackup` proc. 769 | ## 770 | ## Note that `close` will fail with SQLITE_BUSY if there's an unfinished backup process going on. 771 | db.checkRc(open(backupfilename, result.backupdb)) 772 | db.transactionsDisabled: 773 | result.backuphandle = backup_init(result.backupdb, "main".cstring, db.sqlite, "main".cstring) 774 | if result.backuphandle == nil: db.checkRc(SQLITE_NULL) 775 | elif db.loggerproc != nil: db.loggerproc(db, "backup to " & backupfilename, 0) 776 | discard db.backupsinprogress.atomicInc 777 | 778 | 779 | proc stepBackup*(db: var SQLiteral, backupdb: Psqlite3, backuphandle: PSqlite3_Backup, pagesperportion = 5.int32): int = 780 | ## Backs up a portion of the database pages (default: 5) to a destination initialized with `initBackup`. 781 | ## 782 | ## Returns percentage of progress; 100% means that backup has been finished. 783 | ## 784 | ## The idea `(check example 2)`_ is to put the thread to sleep 785 | ## between portions so that other operations can proceed concurrently. 786 | ## 787 | ## **Example:** 788 | ## 789 | ## .. code-block:: Nim 790 | ## 791 | ## from os import sleep 792 | ## let (backupdb , backuphandle) = db.initBackup("./backup.db") 793 | ## var progress: int 794 | ## while progress < 100: 795 | ## sleep(250) 796 | ## progress = db.stepBackup(backupdb, backuphandle) 797 | ## 798 | if unlikely(backupdb == nil or backuphandle == nil): db.checkRc(SQLITE_NULL) 799 | var rc = backup_step(backuphandle, pagesperportion) 800 | if rc == SQLITE_DONE: 801 | db.checkRc(backup_finish(backuphandle)) 802 | db.checkRc(backupdb.close()) 803 | discard db.backupsinprogress.atomicDec 804 | if db.loggerproc != nil: db.loggerproc(db, "backup ok", 0) 805 | return 100 806 | if rc notin [SQLITE_OK, SQLITE_BUSY, SQLITE_LOCKED]: 807 | discard db.backupsinprogress.atomicDec 808 | if db.loggerproc != nil: db.loggerproc(db, "backup failed", rc) 809 | discard backup_finish(backuphandle) 810 | discard backupdb.close() 811 | db.checkRc(rc) 812 | return 100 * (backuphandle.backup_pagecount - backuphandle.backup_remaining) div backuphandle.backup_pagecount 813 | 814 | 815 | proc cancelBackup*(db: var SQLiteral, backupdb: Psqlite3, backuphandle: PSqlite3_Backup) = 816 | ## Cancels an ongoing backup process. 817 | if unlikely(backupdb == nil or backuphandle == nil): db.checkRc(SQLITE_NULL) 818 | discard backup_finish(backuphandle) 819 | discard backupdb.close() 820 | discard db.backupsinprogress.atomicDec 821 | if db.loggerproc != nil: db.loggerproc(db, "backup canceled", 0) 822 | 823 | 824 | proc inMemory(db: SQLiteral): bool = 825 | db.dbname == ":memory:" 826 | 827 | 828 | proc about*(db: SQLiteral) = 829 | ## Echoes some info about the database. 830 | echo "" 831 | echo db.dbname & ": " 832 | echo "SQLiteral=", SQLiteralVersion 833 | echo "SQLite=", libversion() 834 | echo "Userversion=", db.getTheString("PRAGMA user_version") 835 | let Get_options = db.prepareSql("PRAGMA compile_options") 836 | for row in db.rows(Get_options): echo row.getString() 837 | discard finalize(Get_options) 838 | echo "Pagesize=", $db.getTheInt("PRAGMA page_size") 839 | echo "WALautocheckpoint=", $db.getTheInt("PRAGMA wal_autocheckpoint") 840 | if not db.inMemory: 841 | let filesize = getFileSize(db.dbname) 842 | echo "Filesize=", filesize 843 | if db.maxsize > 0: 844 | echo "Maxsize=", db.maxsize * 1024 845 | echo "Sizeused=", (filesize div ((db.maxsize.float * 10.24).int)), "%" 846 | echo "" 847 | 848 | 849 | when defined(staticSqlite): 850 | proc db_status(db: PSqlite3, op: int32, cur: ptr int32, highest: ptr int32, reset: int32): int32 {.cdecl, importc: "sqlite3_db_status".} 851 | else: 852 | proc db_status(db: PSqlite3, op: int32, cur: ptr int32, highest: ptr int32, reset: int32): int32 {.cdecl, dynlib: Lib, importc: "sqlite3_db_status".} 853 | 854 | 855 | proc getStatus*(db: SQLiteral, status: int, resethighest = false): (int, int) = 856 | ## Retrieves queried status info. 857 | ## See https://www.sqlite.org/c3ref/c_dbstatus_options.html 858 | ## 859 | ## **Example:** 860 | ## 861 | ## .. code-block:: Nim 862 | ## 863 | ## const SQLITE_DBSTATUS_CACHE_USED = 1 864 | ## echo "current cache usage: ", db.getStatus(SQLITE_DBSTATUS_CACHE_USED)[0] 865 | var c, h: int32 866 | db.checkRc(db_status(db.sqlite, status.int32, addr c, addr h, resethighest.int32)) 867 | return (c.int, h.int) 868 | 869 | 870 | when defined(staticSqlite): 871 | proc callInterrupt(db: PSqlite3) {.cdecl, importc: "sqlite3_interrupt".} 872 | else: 873 | proc callInterrupt(db: PSqlite3) {.cdecl, dynlib: Lib, importc: "sqlite3_interrupt".} 874 | 875 | proc interrupt*(db: var SQLiteral) = 876 | ## Interrupts long running operations by calling https://www.sqlite.org/c3ref/interrupt.html 877 | callInterrupt(db.sqlite) 878 | 879 | 880 | proc close*(db: var SQLiteral) = 881 | ## Closes the database. 882 | if db.Transaction == nil: 883 | if db.loggerproc != nil: db.loggerproc(db, "already closed: " & db.dbname, 10000) 884 | return 885 | if db.backupsinprogress > 0: 886 | raise SQLError(msg: "Cannot close, backups still in progress: " & $db.backupsinprogress, rescode: SQLITE_BUSY) 887 | var rc = 0 888 | acquire(db.transactionlock) 889 | try: 890 | discard db.Transaction.finalize() 891 | discard db.Commit.finalize() 892 | discard db.Rollback.finalize() 893 | finalizeAllStatements() 894 | rc = close(db.sqlite) 895 | if rc == SQLITE_OK: 896 | db.Transaction = nil 897 | if db.loggerproc != nil: db.loggerproc(db, db.dbname & " closed", 0) 898 | else: db.checkRc(rc) 899 | except: 900 | if db.loggerproc != nil: db.loggerproc(db, getCurrentExceptionMsg(), 10000) 901 | raise SQLError(msg: getCurrentExceptionMsg(), rescode: 10000) 902 | finally: 903 | release(db.transactionlock) 904 | if db.Transaction == nil: deinitLock(db.transactionlock) 905 | -------------------------------------------------------------------------------- /sqliteral.nimble: -------------------------------------------------------------------------------- 1 | # Package 2 | 3 | version = "5.0.1" 4 | author = "Olli" 5 | description = "A high level SQLite API for Nim" 6 | license = "MIT" 7 | 8 | # Dependencies 9 | 10 | requires "nim >= 2.0" 11 | requires "db_connector" 12 | --------------------------------------------------------------------------------