• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

polserver / polserver / 25918451630

15 May 2026 12:43PM UTC coverage: 60.929% (+2.1%) from 58.859%
25918451630

push

github

turleypol
added dynamic property which returns a pointer of the object instead of
a copy like the current imp.
needed to be able to eg store a vector

43 of 61 new or added lines in 2 files covered. (70.49%)

14455 existing lines in 345 files now uncovered.

44695 of 73356 relevant lines covered (60.93%)

449621.59 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.45
/pol-core/bscript/compiler/format/StoredTokenDecoder.cpp
1
#include "StoredTokenDecoder.h"
2

3
#include "StoredToken.h"
4
#include "bscript/compiler/representation/DebugStore.h"
5
#include "bscript/compiler/representation/ModuleDescriptor.h"
6
#include "bscript/compiler/representation/ModuleFunctionDescriptor.h"
7
#include "objmembers.h"
8
#include "objmethods.h"
9
#include <algorithm>
10
#include <iterator>
11

12
namespace Pol::Bscript::Compiler
13
{
14
StoredTokenDecoder::StoredTokenDecoder( const std::vector<ModuleDescriptor>& module_descriptors,
1,985✔
15
                                        const std::vector<std::byte>& data )
1,985✔
16
    : module_descriptors( module_descriptors ), data( data )
1,985✔
17
{
18
}
1,985✔
19

20
void StoredTokenDecoder::decode_to( const StoredToken& tkn, std::string& w )
115,403✔
21
{
22
  switch ( tkn.id )
115,403✔
23
  {
24
  case TOK_LONG:
8,973✔
25
    fmt::format_to( std::back_inserter( w ), "{} (integer) offset={:#x}", integer_at( tkn.offset ),
8,973✔
26
                    tkn.offset );
8,973✔
27
    break;
8,973✔
28
  case TOK_DOUBLE:
393✔
29
    fmt::format_to( std::back_inserter( w ), "{} (float) offset={:#x}", double_at( tkn.offset ),
393✔
30
                    tkn.offset );
393✔
31
    break;
393✔
32
  case TOK_STRING:
20,049✔
33
  {
34
    auto s = string_at( tkn.offset );
20,049✔
35
    fmt::format_to( std::back_inserter( w ), "{} (string) len={} offset={:#x}",
20,049✔
36
                    Clib::getencodedquotedstring( s ), s.length(), tkn.offset );
40,098✔
37
    break;
20,049✔
38
  }
20,049✔
39
  case TOK_REGEXP:
150✔
40
    w += "create-regular-expression (TOK_REGEXP)";
150✔
41
    break;
150✔
42
  case TOK_BOOL:
188✔
43
    fmt::format_to( std::back_inserter( w ), "{} (boolean)", static_cast<bool>( tkn.offset ) );
188✔
44
    break;
188✔
45
  case TOK_ADD:
2,178✔
46
    w += "+";
2,178✔
47
    break;
2,178✔
48
  case TOK_SUBTRACT:
360✔
49
    w += "-";
360✔
50
    break;
360✔
51
  case TOK_MULT:
213✔
52
    w += "*";
213✔
53
    break;
213✔
54
  case TOK_DIV:
57✔
55
    w += "/";
57✔
56
    break;
57✔
57

58
  case TOK_ASSIGN:
2,791✔
59
    w += ":=";
2,791✔
60
    break;
2,791✔
61
  case INS_ASSIGN_CONSUME:
63✔
62
    w += ":= #";
63✔
63
    break;
63✔
64

65
  case TOK_PLUSEQUAL:
69✔
66
    w += "+=";
69✔
67
    break;
69✔
68
  case TOK_MINUSEQUAL:
27✔
69
    w += "-=";
27✔
70
    break;
27✔
71
  case TOK_TIMESEQUAL:
24✔
72
    w += "*=";
24✔
73
    break;
24✔
74
  case TOK_DIVIDEEQUAL:
15✔
75
    w += "/=";
15✔
76
    break;
15✔
77
  case TOK_MODULUSEQUAL:
18✔
78
    w += "%=";
18✔
79
    break;
18✔
80
  case TOK_INSERTINTO:
2,883✔
81
    w += "append-array-element (TOK_INSERTINTO)";
2,883✔
82
    break;
2,883✔
83

84
  case TOK_LESSTHAN:
201✔
85
    w += "<";
201✔
86
    break;
201✔
87
  case TOK_LESSEQ:
66✔
88
    w += "<=";
66✔
89
    break;
66✔
90
  case TOK_GRTHAN:
135✔
91
    w += ">";
135✔
92
    break;
135✔
93
  case TOK_GREQ:
78✔
94
    w += ">=";
78✔
95
    break;
78✔
96

97
  case TOK_IS:
51✔
98
    w += "is";
51✔
99
    break;
51✔
100

101
  case TOK_AND:
32✔
102
    w += "&& (logical and)";
32✔
103
    break;
32✔
104
  case TOK_OR:
93✔
105
    w += "|| (logical or)";
93✔
106
    break;
93✔
107

108
    // equalite/inequality operators */
109
  case TOK_EQUAL:
747✔
110
    w += "==";
747✔
111
    break;
747✔
112
  case TOK_NEQ:
174✔
113
    w += "!=";
174✔
114
    break;
174✔
115

UNCOV
116
  case TOK_UNPLUS:
×
UNCOV
117
    w += "unary +";
×
UNCOV
118
    break;
×
119
  case TOK_UNMINUS:
3✔
120
    w += "unary -";
3✔
121
    break;
3✔
122
  case TOK_LOG_NOT:
96✔
123
    w += "! (logical inversion)";
96✔
124
    break;
96✔
125
  case TOK_BITWISE_NOT:
12✔
126
    w += "~ (bitwise inversion)";
12✔
127
    break;
12✔
128

129
  case TOK_CONSUMER:
15,341✔
130
    w += "# (consume)";
15,341✔
131
    break;
15,341✔
132

133
  case TOK_ARRAY_SUBSCRIPT:
711✔
134
    w += "TOK_ARRAY_SUBSCRIPT";
711✔
135
    break;
711✔
136

137
  case TOK_ADDMEMBER:
96✔
138
    w += ".+ (add-member)";
96✔
139
    break;
96✔
140
  case TOK_DELMEMBER:
9✔
141
    w += ".- (delete-member)";
9✔
142
    break;
9✔
143
  case TOK_CHKMEMBER:
72✔
144
    w += ".? (check-member)";
72✔
145
    break;
72✔
146

UNCOV
147
  case CTRL_STATEMENTBEGIN:
×
148
  {
149
    const Pol::Bscript::DebugToken& debug_token = debug_token_at( tkn.offset );
×
150

151
    fmt::format_to( std::back_inserter( w ), "CTRL_STATEMENTBEGIN sourceFile={} x={} y={}",
×
UNCOV
152
                    debug_token.sourceFile, debug_token.offset,
×
UNCOV
153
                    string_at( debug_token.strOffset ) );
×
UNCOV
154
    break;
×
155
  }
156
  case CTRL_PROGEND:
2,000✔
157
    w += "progend";
2,000✔
158
    break;
2,000✔
159
  case CTRL_MAKELOCAL:
2,073✔
160
    w += "makelocal";
2,073✔
161
    break;
2,073✔
162
  case INS_CHECK_MRO:
213✔
163
    fmt::format_to( std::back_inserter( w ), "check mro (this @ offset {})", tkn.offset );
213✔
164
    break;
213✔
165
  case CTRL_JSR_USERFUNC:
2,073✔
166
    fmt::format_to( std::back_inserter( w ), "jsr userfunc @{}", tkn.offset );
2,073✔
167
    break;
2,073✔
168
  case INS_POP_PARAM:
2,321✔
169
    fmt::format_to( std::back_inserter( w ), "pop param '{}'", string_at( tkn.offset ) );
4,642✔
170
    break;
2,321✔
171
  case CTRL_LEAVE_BLOCK:
876✔
172
    fmt::format_to( std::back_inserter( w ), "leave block (remove {} locals)", tkn.offset );
876✔
173
    break;
876✔
174

175
  case RSV_JMPIFFALSE:
1,083✔
176
    fmt::format_to( std::back_inserter( w ), "if false goto {}", tkn.offset );
1,083✔
177
    break;
1,083✔
178
  case RSV_JMPIFTRUE:
158✔
179
    fmt::format_to( std::back_inserter( w ), "if true goto {}", tkn.offset );
158✔
180
    break;
158✔
181
  case RSV_GOTO:
1,231✔
182
    fmt::format_to( std::back_inserter( w ), "goto {}", tkn.offset );
1,231✔
183
    break;
1,231✔
184
  case RSV_RETURN:
2,603✔
185
    w += "return";
2,603✔
186
    break;
2,603✔
187
  case RSV_EXIT:
18✔
188
    w += "exit";
18✔
189
    break;
18✔
190

191
  case RSV_LOCAL:
1,247✔
192
    fmt::format_to( std::back_inserter( w ), "declare local #{}", tkn.offset );
1,247✔
193
    break;
1,247✔
194
  case RSV_GLOBAL:
1,952✔
195
    fmt::format_to( std::back_inserter( w ), "declare global #{}", tkn.offset );
1,952✔
196
    break;
1,952✔
197

198
  case INS_TAKE_LOCAL:
267✔
199
    fmt::format_to( std::back_inserter( w ), "take local #{}", tkn.offset );
267✔
200
    break;
267✔
201

202
  case INS_TAKE_GLOBAL:
183✔
203
    fmt::format_to( std::back_inserter( w ), "take global #{}", tkn.offset );
183✔
204
    break;
183✔
205

206
  case INS_DECLARE_ARRAY:
69✔
207
    w += "declare array";
69✔
208
    break;
69✔
209

210
  case TOK_FUNC:
10,263✔
211
  {
212
    unsigned module_id = tkn.module;
10,263✔
213
    unsigned function_index = tkn.type;
10,263✔
214
    fmt::format_to( std::back_inserter( w ), "call module function ({}, {}): ", module_id,
10,263✔
215
                    function_index );
216
    if ( module_id >= module_descriptors.size() )
10,263✔
217
    {
UNCOV
218
      fmt::format_to( std::back_inserter( w ), "module index {} exceeds module_descriptors size {}",
×
UNCOV
219
                      module_id, module_descriptors.size() );
×
UNCOV
220
      break;
×
221
    }
222
    auto& module = module_descriptors.at( module_id );
10,263✔
223
    if ( function_index >= module.functions.size() )
10,263✔
224
    {
UNCOV
225
      fmt::format_to( std::back_inserter( w ), "function index {} exceeds module.functions size {}",
×
UNCOV
226
                      function_index, module.functions.size() );
×
UNCOV
227
      break;
×
228
    }
229
    auto& defn = module.functions.at( function_index );
10,263✔
230
    fmt::format_to( std::back_inserter( w ), "{}", defn.name );
10,263✔
231
    break;
10,263✔
232
  }
233
  case TOK_ERROR:
48✔
234
    w += "error";
48✔
235
    break;
48✔
236

237
  case TOK_LOCALVAR:
9,713✔
238
    fmt::format_to( std::back_inserter( w ), "local variable #{}", tkn.offset );
9,713✔
239
    break;
9,713✔
240
  case TOK_GLOBALVAR:
6,487✔
241
    fmt::format_to( std::back_inserter( w ), "global variable #{}", tkn.offset );
6,487✔
242
    break;
6,487✔
243

244
  case INS_INITFOREACH:
282✔
245
    fmt::format_to( std::back_inserter( w ), "initforeach @{}", tkn.offset );
282✔
246
    break;
282✔
247
  case INS_STEPFOREACH:
282✔
248
    fmt::format_to( std::back_inserter( w ), "stepforeach @{}", tkn.offset );
282✔
249
    break;
282✔
250
  case INS_CASEJMP:
90✔
251
  {
252
    w += "casejmp";
90✔
253
    decode_casejmp_table( w, tkn.offset );
90✔
254
    break;
90✔
255
  }
256
  case INS_GET_ARG:
42✔
257
    fmt::format_to( std::back_inserter( w ), "get arg '{}'", string_at( tkn.offset ) );
84✔
258
    break;
42✔
259
  case TOK_ARRAY:
1,317✔
260
    w += "create-array (TOK_ARRAY)";
1,317✔
261
    break;
1,317✔
262

263
  case INS_CALL_METHOD:
282✔
264
    fmt::format_to( std::back_inserter( w ), "call method '{}'", string_at( tkn.offset ) );
564✔
265
    break;
282✔
266

267
  case TOK_DICTIONARY:
150✔
268
    w += "TOK_DICTIONARY";
150✔
269
    break;
150✔
270
  case INS_INITFOR:
42✔
271
    fmt::format_to( std::back_inserter( w ), "initfor @{}", tkn.offset );
42✔
272
    break;
42✔
273
  case INS_NEXTFOR:
42✔
274
    fmt::format_to( std::back_inserter( w ), "nextfor @{}", tkn.offset );
42✔
275
    break;
42✔
276
  case INS_POP_PARAM_BYREF:
1,182✔
277
    fmt::format_to( std::back_inserter( w ), "pop param byref '{}'", string_at( tkn.offset ) );
2,364✔
278
    break;
1,182✔
279
  case TOK_MODULUS:
30✔
280
    w += "modulus";
30✔
281
    break;
30✔
282

283
  case TOK_BSLEFT:
15✔
284
    w += "<<";  // bitshift-left-sift";
15✔
285
    break;
15✔
286
  case TOK_BSRIGHT:
15✔
287
    w += ">>";  // bitshift-right-shift";
15✔
288
    break;
15✔
289
  case TOK_BITAND:
15✔
290
    w += "&";  // bitwise-and";
15✔
291
    break;
15✔
292
  case TOK_BITOR:
15✔
293
    w += "|";  // bitwise-or";
15✔
294
    break;
15✔
295
  case TOK_BITXOR:
15✔
296
    w += "^";  // bitwise-xor";
15✔
297
    break;
15✔
298

299
  case TOK_STRUCT:
300✔
300
    w += "create empty struct";
300✔
301
    break;
300✔
302
  case TOK_CLASSINST:
234✔
303
    fmt::format_to( std::back_inserter( w ), "create class instance (index={})", tkn.offset );
234✔
304
    break;
234✔
305
  case INS_SUBSCRIPT_ASSIGN:
9✔
306
    w += "subscript assign";
9✔
307
    break;
9✔
308
  case INS_SUBSCRIPT_ASSIGN_CONSUME:
420✔
309
    w += "subscript assign and consume";
420✔
310
    break;
420✔
311
  case INS_MULTISUBSCRIPT:
225✔
312
    fmt::format_to( std::back_inserter( w ), "multi subscript get ({} indexes)", tkn.offset );
225✔
313
    break;
225✔
314
  case INS_MULTISUBSCRIPT_ASSIGN:
6✔
315
    fmt::format_to( std::back_inserter( w ), "multi subscript assign ({} indexes)", tkn.offset );
6✔
316
    break;
6✔
317
  case INS_ASSIGN_LOCALVAR:
558✔
318
    fmt::format_to( std::back_inserter( w ), "local #{} :=", tkn.offset );
558✔
319
    break;
558✔
320
  case INS_ASSIGN_GLOBALVAR:
690✔
321
    fmt::format_to( std::back_inserter( w ), "global #{} :=", tkn.offset );
690✔
322
    break;
690✔
323

324
  case INS_GET_MEMBER:
414✔
325
    fmt::format_to( std::back_inserter( w ), "get-member {} (offset {})", string_at( tkn.offset ),
828✔
326
                    tkn.offset );
414✔
327
    break;
414✔
328
  case INS_SET_MEMBER:
3✔
329
    fmt::format_to( std::back_inserter( w ), "set-member {} (offset {})", string_at( tkn.offset ),
6✔
330
                    tkn.offset );
3✔
331
    break;
3✔
332
  case INS_SET_MEMBER_CONSUME:
162✔
333
    fmt::format_to( std::back_inserter( w ), "set-member-consume {} (offset {})",
162✔
334
                    string_at( tkn.offset ), tkn.offset );
324✔
335
    break;
162✔
336

337
  case INS_ADDMEMBER2:
45✔
338
    fmt::format_to( std::back_inserter( w ), "add uninitialized member ({}) to struct",
45✔
339
                    string_at( tkn.offset ) );
90✔
340
    break;
45✔
341
  case INS_ADDMEMBER_ASSIGN:
447✔
342
    fmt::format_to( std::back_inserter( w ), "add member ({}) to struct", string_at( tkn.offset ) );
894✔
343
    break;
447✔
344
  case INS_UNINIT:
96✔
345
    w += "push-uninit";
96✔
346
    break;
96✔
347
  case INS_DICTIONARY_ADDMEMBER:
126✔
348
    w += "add member to dictionary";
126✔
349
    break;
126✔
350

351
  case INS_GET_MEMBER_ID:
174✔
UNCOV
352
    fmt::format_to( std::back_inserter( w ), "get-member-id '{}' ({})",
×
353
                    getObjMember( tkn.offset )->code, tkn.offset );
174✔
354
    break;
174✔
355
  case INS_SET_MEMBER_ID:
3✔
UNCOV
356
    fmt::format_to( std::back_inserter( w ), "set-member-id '{}' ({})",
×
357
                    getObjMember( tkn.offset )->code, tkn.offset );
3✔
358
    break;
3✔
359
  case INS_SET_MEMBER_ID_CONSUME:
90✔
UNCOV
360
    fmt::format_to( std::back_inserter( w ), "set-member-id-consume '{}' ({})",
×
361
                    getObjMember( tkn.offset )->code, tkn.offset );
90✔
362
    break;
90✔
363
  case INS_CALL_METHOD_ID:
2,474✔
UNCOV
364
    fmt::format_to( std::back_inserter( w ), "call-method-id '{}' (#{}, {} arguments)",
×
365
                    getObjMethod( tkn.offset )->code, tkn.offset, tkn.type );
2,474✔
366
    break;
2,474✔
367

368
  case INS_SET_MEMBER_ID_CONSUME_PLUSEQUAL:
15✔
UNCOV
369
    fmt::format_to( std::back_inserter( w ), "set member id '{}' ({}) += #",
×
370
                    getObjMember( tkn.offset )->code, tkn.offset );
15✔
371
    break;
15✔
372
  case INS_SET_MEMBER_ID_CONSUME_MINUSEQUAL:
6✔
UNCOV
373
    fmt::format_to( std::back_inserter( w ), "set member id '{}' ({}) -=#",
×
374
                    getObjMember( tkn.offset )->code, tkn.offset );
6✔
375
    break;
6✔
376
  case INS_SET_MEMBER_ID_CONSUME_TIMESEQUAL:
9✔
UNCOV
377
    fmt::format_to( std::back_inserter( w ), "set member id '{}' ({}) *= #",
×
378
                    getObjMember( tkn.offset )->code, tkn.offset );
9✔
379
    break;
9✔
380
  case INS_SET_MEMBER_ID_CONSUME_DIVIDEEQUAL:
6✔
UNCOV
381
    fmt::format_to( std::back_inserter( w ), "set member id '{}' ({}) /= #",
×
382
                    getObjMember( tkn.offset )->code, tkn.offset );
6✔
383
    break;
6✔
384
  case INS_SET_MEMBER_ID_CONSUME_MODULUSEQUAL:
6✔
UNCOV
385
    fmt::format_to( std::back_inserter( w ), "set member id '{}' ({}) %= #",
×
386
                    getObjMember( tkn.offset )->code, tkn.offset );
6✔
387
    break;
6✔
388

389
  case TOK_SPREAD:
669✔
390
  {
UNCOV
391
    fmt::format_to( std::back_inserter( w ), "{} (TOK_SPREAD)",
×
392
                    tkn.offset ? "spread-into" : "create-spread" );
669✔
393

394
    break;
669✔
395
  }
396

397
  case TOK_FUNCTOR:
633✔
398
  {
UNCOV
399
    fmt::format_to( std::back_inserter( w ),
×
400
                    "create-functor index={} instructions={} (TOK_FUNCTOR)",
401
                    static_cast<int>( tkn.type ), tkn.offset );
633✔
402
    break;
633✔
403
  }
404

405
  case TOK_FUNCREF:
693✔
406
  {
407
    fmt::format_to( std::back_inserter( w ), "create-funcref index={} (TOK_FUNCREF)", tkn.offset );
693✔
408
    break;
693✔
409
  }
410

411
  case TOK_UNPLUSPLUS:
84✔
412
    w += "prefix unary ++";
84✔
413
    break;
84✔
414
  case TOK_UNMINUSMINUS:
48✔
415
    w += "prefix unary --";
48✔
416
    break;
48✔
417
  case TOK_UNPLUSPLUS_POST:
96✔
418
    w += "postfix unary ++";
96✔
419
    break;
96✔
420
  case TOK_UNMINUSMINUS_POST:
48✔
421
    w += "postfix unary --";
48✔
422
    break;
48✔
423
  case INS_SET_MEMBER_ID_UNPLUSPLUS:
9✔
UNCOV
424
    fmt::format_to( std::back_inserter( w ), "set member id '{}' unary ++",
×
425
                    getObjMember( tkn.offset )->code );
9✔
426
    break;
9✔
427
  case INS_SET_MEMBER_ID_UNMINUSMINUS:
12✔
UNCOV
428
    fmt::format_to( std::back_inserter( w ), "set member id '{}' unary --",
×
429
                    getObjMember( tkn.offset )->code );
12✔
430
    break;
12✔
431
  case INS_SET_MEMBER_ID_UNPLUSPLUS_POST:
3✔
UNCOV
432
    fmt::format_to( std::back_inserter( w ), "set member id '{}' unary ++ post",
×
433
                    getObjMember( tkn.offset )->code );
3✔
434
    break;
3✔
435
  case INS_SET_MEMBER_ID_UNMINUSMINUS_POST:
3✔
UNCOV
436
    fmt::format_to( std::back_inserter( w ), "set member id '{}' unary -- post",
×
437
                    getObjMember( tkn.offset )->code );
3✔
438
    break;
3✔
439
  case INS_SKIPIFTRUE_ELSE_CONSUME:
183✔
UNCOV
440
    fmt::format_to( std::back_inserter( w ),
×
441
                    "peek at top of stack; skip {}"
442
                    " instructions if true, otherwise consume it",
443
                    tkn.offset );
183✔
444
    break;
183✔
445
  case TOK_INTERPOLATE_STRING:
1,028✔
446
    fmt::format_to( std::back_inserter( w ), "interpolate string ({} parts)", tkn.offset );
1,028✔
447
    break;
1,028✔
448
  case TOK_FORMAT_EXPRESSION:
6✔
449
    w += "format expression";
6✔
450
    break;
6✔
451

452
  case INS_UNPACK_SEQUENCE:
99✔
453
  {
454
    int rest_index = tkn.offset > 0x7F ? ( ( tkn.offset >> 7 ) & 0x7F ) : -1;
99✔
UNCOV
455
    fmt::format_to( std::back_inserter( w ), "unpack sequence ({} elements, rest index {})",
×
456
                    tkn.offset & 0x7F, rest_index );
99✔
457
    break;
99✔
458
  }
459

460
  case INS_UNPACK_INDICES:
78✔
461
  {
462
    int rest_index = tkn.offset > 0x7F ? ( ( tkn.offset >> 7 ) & 0x7F ) : -1;
78✔
UNCOV
463
    fmt::format_to( std::back_inserter( w ), "unpack indices ({} elements, rest index {})",
×
464
                    tkn.offset & 0x7F, rest_index );
78✔
465
    break;
78✔
466
  }
467

468
  case INS_LOGICAL_JUMP:
63✔
UNCOV
469
    fmt::format_to( std::back_inserter( w ), "logical jump if {} to {}",
×
470
                    tkn.type != TYP_LOGICAL_JUMP_FALSE, tkn.offset );
63✔
471
    break;
63✔
472
  case INS_LOGICAL_CONVERT:
47✔
473
    w += "logical convert";
47✔
474
    break;
47✔
475

476
  default:
21✔
UNCOV
477
    fmt::format_to( std::back_inserter( w ), "id={:#x} type={} offset={} module={}", tkn.id,
×
478
                    tkn.type, tkn.offset, tkn.module );
42✔
479
  }
480
}
115,403✔
481

482
double StoredTokenDecoder::double_at( unsigned offset ) const
393✔
483
{
484
  if ( offset > data.size() - sizeof( double ) )
393✔
485
    throw std::runtime_error( "data overflow reading double at offset " + std::to_string( offset ) +
×
UNCOV
486
                              ".  Data size is " + std::to_string( data.size() ) );
×
487

488
  return *reinterpret_cast<const double*>( &data[offset] );
393✔
489
}
490

491
int StoredTokenDecoder::integer_at( unsigned offset ) const
9,117✔
492
{
493
  if ( offset > data.size() - sizeof( int ) )
9,117✔
494
    throw std::runtime_error( "data overflow reading integer at offset " +
×
495
                              std::to_string( offset ) + ".  Data size is " +
×
UNCOV
496
                              std::to_string( data.size() ) );
×
497

498
  return *reinterpret_cast<const int*>( &data[offset] );
9,117✔
499
}
500

501
uint16_t StoredTokenDecoder::uint16_t_at( unsigned offset ) const
342✔
502
{
503
  if ( offset > data.size() - sizeof( uint16_t ) )
342✔
504
    throw std::runtime_error( "data overflow reading uint16_t at offset " +
×
505
                              std::to_string( offset ) + ".  Data size is " +
×
UNCOV
506
                              std::to_string( data.size() ) );
×
507

508
  return *reinterpret_cast<const uint16_t*>( &data[offset] );
342✔
509
}
510

511
std::string StoredTokenDecoder::string_at( unsigned offset ) const
24,947✔
512
{
513
  if ( offset > data.size() )
24,947✔
UNCOV
514
    throw std::runtime_error( "data overflow reading string starting at offset " +
×
UNCOV
515
                              std::to_string( offset ) + ".  Data size is " +
×
UNCOV
516
                              std::to_string( data.size() ) );
×
517

518
  const char* s_begin = reinterpret_cast<const char*>( data.data() + offset );
24,947✔
519
  const char* data_end = reinterpret_cast<const char*>( data.data() + data.size() );
24,947✔
520

521
  auto s_end = std::find( s_begin, data_end, '\0' );
24,947✔
522
  if ( s_end == data_end )
24,947✔
523
    throw std::runtime_error( "No null terminator for string at offset " +
×
UNCOV
524
                              std::to_string( offset ) );
×
525

526
  return std::string( s_begin, s_end );
24,947✔
527
}
528

UNCOV
529
const Pol::Bscript::DebugToken& StoredTokenDecoder::debug_token_at( unsigned offset ) const
×
530
{
UNCOV
531
  if ( offset > data.size() - sizeof( Pol::Bscript::DebugToken ) )
×
UNCOV
532
    throw std::runtime_error( "data overflow reading DebugToken at offset " +
×
UNCOV
533
                              std::to_string( offset ) + ".  Data size is " +
×
UNCOV
534
                              std::to_string( data.size() ) );
×
535

UNCOV
536
  return *reinterpret_cast<const Pol::Bscript::DebugToken*>( &data[offset] );
×
537
}
538

539
void StoredTokenDecoder::decode_casejmp_table( std::string& w, unsigned offset ) const
90✔
540
{
541
  std::string indent( 24, ' ' );
90✔
542
  for ( ;; )
543
  {
544
    unsigned short jump_address = uint16_t_at( offset );
342✔
545
    offset += 2;
342✔
546
    auto type = static_cast<ESCRIPT_CASE_TYPES>( data.at( offset ) );
342✔
547
    offset++;
342✔
548

549
    if ( type == CASE_TYPE_LONG )
342✔
550
    {
551
      int value = integer_at( offset );
144✔
552
      offset += 4;
144✔
553
      fmt::format_to( std::back_inserter( w ), "\n{}{}: @{}", indent, value, jump_address );
288✔
554
    }
555
    else if ( type == CASE_TYPE_BOOL )
198✔
556
    {
557
      bool value = static_cast<bool>( data.at( offset ) );
18✔
558
      offset += 1;
18✔
559
      fmt::format_to( std::back_inserter( w ), "\n{}{}: @{}", indent, value, jump_address );
36✔
560
    }
561
    else if ( type == CASE_TYPE_UNINIT )
180✔
562
    {
563
      fmt::format_to( std::back_inserter( w ), "\n{}<uninit>: @{}", indent, jump_address );
12✔
564
    }
565
    else if ( type == CASE_TYPE_DEFAULT )
174✔
566
    {
567
      fmt::format_to( std::back_inserter( w ), "\n{}default: @{}", indent, jump_address );
90✔
568
      break;
90✔
569
    }
570
    else if ( type == CASE_TYPE_STRING )
84✔
571
    {
572
      unsigned string_length = static_cast<unsigned>( data.at( offset ) );
84✔
573
      offset += 1;
84✔
574
      if ( offset + string_length > data.size() )
84✔
UNCOV
575
        throw std::runtime_error( "casejmp string at offset " + std::to_string( offset ) + " of " +
×
UNCOV
576
                                  std::to_string( string_length ) +
×
577
                                  " characters exceeds data size of " +
×
UNCOV
578
                                  std::to_string( data.size() ) );
×
579

580
      const char* s_begin = reinterpret_cast<const char*>( data.data() + offset );
84✔
581
      std::string contents( s_begin, s_begin + string_length );
84✔
582
      fmt::format_to( std::back_inserter( w ), "\n{}{}: @{}", indent,
84✔
583
                      Clib::getencodedquotedstring( contents ), jump_address );
168✔
584
      offset += string_length;
84✔
585
    }
84✔
586
    else
587
    {
UNCOV
588
      throw std::runtime_error( "casejmp unhandled type " + std::to_string( type ) );
×
589
    }
590
  }
252✔
591
}
90✔
592

593
}  // namespace Pol::Bscript::Compiler
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc