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

polserver / polserver / 21108840797

18 Jan 2026 08:35AM UTC coverage: 60.508% (+0.02%) from 60.492%
21108840797

push

github

web-flow
ClangTidy readability-else-after-return (#857)

* trigger tidy

* Automated clang-tidy change: readability-else-after-return

* compile test

* rerun

* Automated clang-tidy change: readability-else-after-return

* trigger..

* Automated clang-tidy change: readability-else-after-return

* manually removed a few

* Automated clang-tidy change: readability-else-after-return

* removed duplicate code

* fix remaining warnings

* fixed scope

---------

Co-authored-by: Clang Tidy <clang-tidy@users.noreply.github.com>

837 of 1874 new or added lines in 151 files covered. (44.66%)

46 existing lines in 25 files now uncovered.

44448 of 73458 relevant lines covered (60.51%)

525066.38 hits per line

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

82.01
/pol-core/pol/module/basicmod.cpp
1
/** @file
2
 *
3
 * @par History
4
 * - 2005/11/24 Shinigami: added itoa for Linux because it is not ANSI C/C++
5
 * - 2005/11/29 Shinigami: mf_SplitWords will now accept each type of to-split-value as same as in
6
 * the past
7
 * - 2006/10/07 Shinigami: FreeBSD fix - changed __linux__ to __unix__
8
 * - 2006/12/29 Shinigami: mf_SplitWords will not hang server on queue of delimiter
9
 */
10

11

12
#include "basicmod.h"
13
#include <cstdio>
14
#include <cstdlib>
15
#include <cstring>
16
#include <picojson/picojson.h>
17
#include <string>
18
#include <utf8cpp/utf8.h>
19

20
#include "../../bscript/berror.h"
21
#include "../../bscript/bobject.h"
22
#include "../../bscript/dict.h"
23
#include "../../bscript/executor.h"
24
#include "../../bscript/impstr.h"
25
#include "../../bscript/regexp.h"
26
#include "../../clib/stlutil.h"
27

28
#include <module_defs/basic.h>
29

30

31
namespace Pol::Module
32
{
33
using namespace Bscript;
34

35
static const std::string base64_chars =
36
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
37
    "abcdefghijklmnopqrstuvwxyz"
38
    "0123456789+/";
39

40

41
static inline bool is_base64( unsigned char c )
402✔
42
{
43
  return ( isalnum( c ) || ( c == '+' ) || ( c == '/' ) );
402✔
44
}
45

46
BasicExecutorModule::BasicExecutorModule( Executor& exec )
2,356✔
47
    : Bscript::TmplExecutorModule<BasicExecutorModule, Bscript::ExecutorModule>( exec )
2,356✔
48
{
49
}
2,356✔
50

51
Bscript::BObjectImp* BasicExecutorModule::mf_Len()
138✔
52
{
53
  Bscript::BObjectImp* imp = exec.getParamImp( 0 );
138✔
54
  if ( auto* a = impptrIf<Bscript::ObjArray>( imp ) )
138✔
55
    return new BLong( static_cast<int>( a->ref_arr.size() ) );
92✔
56
  if ( auto* s = impptrIf<Bscript::String>( imp ) )
46✔
57
    return new BLong( static_cast<int>( s->length() ) );
37✔
58
  if ( auto* e = impptrIf<Bscript::BError>( imp ) )
9✔
59
    return new BLong( static_cast<int>( e->mapcount() ) );
3✔
60
  return new BLong( 0 );
6✔
61
}
62

63
Bscript::BObjectImp* BasicExecutorModule::mf_Find()
4,054✔
64
{
65
  exec.makeString( 0 );
4,054✔
66
  String* str = static_cast<String*>( exec.getParamImp( 0 ) );
4,054✔
67
  const char* s = exec.paramAsString( 1 );
4,054✔
68
  int d = static_cast<int>( exec.paramAsLong( 2 ) );
4,054✔
69

70
  int posn = str->find( d ? ( d - 1 ) : 0, s ) + 1;
4,054✔
71

72
  return new BLong( posn );
4,054✔
73
}
74

75
Bscript::BObjectImp* BasicExecutorModule::mf_SubStr()
6✔
76
{
77
  exec.makeString( 0 );
6✔
78
  String* str = static_cast<String*>( exec.getParamImp( 0 ) );
6✔
79
  int start = static_cast<int>( exec.paramAsLong( 1 ) );
6✔
80
  int length = static_cast<int>( exec.paramAsLong( 2 ) );
6✔
81

82
  return str->StrStr( start, length );
6✔
83
}
84

85
Bscript::BObjectImp* BasicExecutorModule::mf_Trim()
6✔
86
{
87
  Bscript::BObjectImp* imp = exec.getParamImp( 0 );
6✔
88
  auto* str = impptrIf<Bscript::String>( imp );
6✔
89
  if ( !str )
6✔
90
    return new BError( "Param 1 must be a string." );
×
91
  int type = static_cast<int>( exec.paramAsLong( 1 ) );
6✔
92
  const char* cset = exec.paramAsString( 2 );
6✔
93
  if ( type > 3 )
6✔
94
    type = 3;
×
95
  if ( type < 1 )
6✔
96
    type = 1;
×
97

98
  return str->ETrim( cset, type );
6✔
99
}
100

101
/*
102
eScript Function Useage
103

104
StrReplace(str, to_replace, replace_with);
105
*/
106
Bscript::BObjectImp* BasicExecutorModule::mf_StrReplace()
9✔
107
{
108
  Bscript::BObjectImp* imp = exec.getParamImp( 0 );
9✔
109
  std::unique_ptr<String> string( new String( imp->getStringRep().c_str() ) );
9✔
110
  String* to_replace = static_cast<String*>( exec.getParamImp( 1, Bscript::BObjectImp::OTString ) );
9✔
111
  if ( !to_replace )
9✔
112
    return new BError( "Invalid parameter type" );
×
113
  String* replace_with =
114
      static_cast<String*>( exec.getParamImp( 2, Bscript::BObjectImp::OTString ) );
9✔
115
  if ( !replace_with )
9✔
116
    return new BError( "Invalid parameter type" );
×
117

118
  if ( string->length() < 1 )
9✔
119
    return new BError( "Cannot use empty string for string haystack." );
×
120
  if ( to_replace->length() < 1 )
9✔
121
    return new BError( "Cannot use empty string for string needle." );
×
122

123
  string->EStrReplace( to_replace, replace_with );
9✔
124

125
  return string.release();
9✔
126
}
9✔
127

128
// SubStrReplace(str, replace_with, start, length:=0);
129
Bscript::BObjectImp* BasicExecutorModule::mf_SubStrReplace()
6✔
130
{
131
  Bscript::BObjectImp* imp = exec.getParamImp( 0 );
6✔
132
  std::unique_ptr<String> string( new String( imp->getStringRep().c_str() ) );
6✔
133
  String* replace_with =
134
      static_cast<String*>( exec.getParamImp( 1, Bscript::BObjectImp::OTString ) );
6✔
135
  if ( !replace_with )
6✔
136
    return new BError( "Invalid parameter type" );
×
137
  int index = static_cast<int>( exec.paramAsLong( 2 ) );
6✔
138
  int len = static_cast<int>( exec.paramAsLong( 3 ) );
6✔
139

140
  if ( index < 0 )
6✔
141
    return new BError( "Index must not be negative" );
×
142
  if ( static_cast<unsigned>( index - 1 ) > string->length() )
6✔
143
    return new BError( "Index out of range" );
×
144

145
  // We set it to 1 because of doing -1 later to stay with eScript handling.
146
  if ( !index )
6✔
147
    index = 1;
×
148

149
  if ( static_cast<unsigned>( len ) > ( string->length() - index ) )
6✔
150
    return new BError( "Length out of range" );
×
151
  if ( len < 0 )
6✔
152
    return new BError( "Length must not be negative" );
×
153

154
  if ( !len )
6✔
155
    len = static_cast<int>( replace_with->length() - index );
×
156

157
  string->ESubStrReplace( replace_with, static_cast<unsigned>( index ),
6✔
158
                          static_cast<unsigned>( len ) );
159

160
  return string.release();
6✔
161
}
6✔
162

163
// OMG I HATED THIS REQUEST. Ugly code, but necessary for all the checks
164
// just in case someone's code is bugged :(
165
Bscript::BObjectImp* BasicExecutorModule::mf_Compare()
9✔
166
{
167
  String str1( exec.paramAsString( 0 ) );
9✔
168
  String str2( exec.paramAsString( 1 ) );
9✔
169
  int pos1_index = static_cast<int>( exec.paramAsLong( 2 ) );
9✔
170
  int pos1_len = static_cast<int>( exec.paramAsLong( 3 ) );
9✔
171
  int pos2_index = static_cast<int>( exec.paramAsLong( 4 ) );
9✔
172
  int pos2_len = static_cast<int>( exec.paramAsLong( 5 ) );
9✔
173

174
  size_t str1length( str1.length() );
9✔
175
  size_t str2length( str2.length() );
9✔
176
  if ( pos1_index != 0 )
9✔
177
  {
178
    if ( pos1_index < 0 )
6✔
179
      return new BError( "Index must not be negative for param 1" );
×
180
    if ( static_cast<unsigned>( pos1_index - 1 ) > str1length )
6✔
181
      return new BError( "Index out of range for param 1" );
×
182
  }
183
  if ( pos2_index != 0 )
9✔
184
  {
185
    if ( pos2_index < 0 )
6✔
186
      return new BError( "Index must not be negative for param 2" );
×
187
    if ( static_cast<unsigned>( pos2_index - 1 ) > str2length )
6✔
188
      return new BError( "Index out of range for param 2" );
×
189
  }
190

191

192
  if ( pos1_len < 0 )
9✔
193
    return new BError( "Length must not be negative for param 1" );
×
194
  if ( static_cast<unsigned>( pos1_len ) > ( str1length - pos1_index ) )
9✔
195
    return new BError( "Length out of range for param 1" );
×
196
  if ( pos2_len < 0 )
9✔
197
    return new BError( "Length must not be negative for param 2" );
×
198
  if ( static_cast<unsigned>( pos2_len ) > ( str2length - pos2_index ) )
9✔
199
    return new BError( "Length out of range for param 2" );
×
200

201

202
  if ( pos1_index == 0 )
9✔
203
  {
204
    if ( !str1.compare( str2 ) )
3✔
205
      return new BLong( 0 );
×
206
    return new BLong( 1 );
3✔
207
  }
208
  if ( pos1_index > 0 && pos2_index == 0 )
6✔
209
  {
210
    if ( !str1.compare( pos1_index - 1, pos1_len, str2 ) )
×
211
      return new BLong( 0 );
×
NEW
212
    return new BLong( 1 );
×
213
  }
214

215
  if ( !str1.compare( pos1_index - 1, pos1_len, str2, pos2_index - 1, pos2_len ) )
6✔
NEW
216
    return new BLong( 0 );
×
217
  return new BLong( 1 );
6✔
218
}
9✔
219

220
Bscript::BObjectImp* BasicExecutorModule::mf_Lower()
18✔
221
{
222
  String* string = new String( exec.paramAsString( 0 ) );
18✔
223
  string->toLower();
18✔
224
  return string;
18✔
225
}
226

227
Bscript::BObjectImp* BasicExecutorModule::mf_Upper()
33✔
228
{
229
  String* string = new String( exec.paramAsString( 0 ) );
33✔
230
  string->toUpper();
33✔
231
  return string;
33✔
232
}
233

234
Bscript::BObjectImp* BasicExecutorModule::mf_CInt()
178✔
235
{
236
  Bscript::BObjectImp* imp = exec.getParamImp( 0 );
178✔
237
  if ( imp->isa( Bscript::BObjectImp::OTLong ) )
178✔
238
    return imp->copy();
4✔
239
  if ( auto* s = impptrIf<String>( imp ) )
174✔
240
    return new BLong( strtoul( s->data(), nullptr, 0 ) );
162✔
241
  if ( auto* d = impptrIf<Double>( imp ) )
12✔
242
    return new BLong( static_cast<int>( d->value() ) );
12✔
243
  return new BLong( 0 );
×
244
}
245

246
Bscript::BObjectImp* BasicExecutorModule::mf_CDbl()
9✔
247
{
248
  Bscript::BObjectImp* imp = exec.getParamImp( 0 );
9✔
249
  if ( auto* l = impptrIf<BLong>( imp ) )
9✔
250
    return new Double( l->value() );
3✔
251
  if ( auto* s = impptrIf<String>( imp ) )
6✔
252
    return new Double( strtod( s->data(), nullptr ) );
6✔
NEW
253
  if ( imp->isa( Bscript::BObjectImp::OTDouble ) )
×
254
    return imp->copy();
×
255
  return new Double( 0 );
×
256
}
257

258
Bscript::BObjectImp* BasicExecutorModule::mf_CStr()
1,067✔
259
{
260
  Bscript::BObjectImp* imp = exec.getParamImp( 0 );
1,067✔
261
  return new String( imp->getStringRep() );
1,067✔
262
}
263

264
Bscript::BObjectImp* BasicExecutorModule::mf_CAsc()
36✔
265
{
266
  Bscript::BObjectImp* imp = exec.getParamImp( 0 );
36✔
267
  if ( auto* str = impptrIf<String>( imp ) )
36✔
268
  {
269
    std::unique_ptr<String> substr( str->StrStr( 1, 1 ) );
33✔
270
    const auto& utf16 = substr->toUTF16();
33✔
271
    if ( utf16.empty() )
33✔
272
      return new BLong( 0 );
3✔
273
    if ( utf16.size() > 1 )
30✔
274
      return new BError( "Cannot be represented by a single number" );
×
275
    return new BLong( utf16[0] );
30✔
276
  }
33✔
277

278
  return new BError( "Invalid parameter type" );
3✔
279
}
280

281
Bscript::BObjectImp* BasicExecutorModule::mf_CAscZ()
15✔
282
{
283
  Bscript::BObjectImp* imp = exec.getParamImp( 0 );
15✔
284
  String tmp( imp->getStringRep() );
15✔
285
  int nullterm = static_cast<int>( exec.paramAsLong( 1 ) );
15✔
286
  std::unique_ptr<Bscript::ObjArray> arr( new Bscript::ObjArray );
15✔
287
  const auto& utf16 = tmp.toUTF16();
15✔
288
  for ( const auto& code : utf16 )
276✔
289
  {
290
    arr->addElement( new BLong( code ) );
261✔
291
  }
292
  if ( nullterm )
15✔
293
    arr->addElement( new BLong( 0 ) );
×
294

295
  return arr.release();
30✔
296
}
15✔
297

298
Bscript::BObjectImp* BasicExecutorModule::mf_CChr()
442✔
299
{
300
  int val;
301
  if ( getParam( 0, val ) )
442✔
302
  {
303
    return new String( String::fromUTF16( static_cast<u16>( val & 0xffff ) ) );
436✔
304
  }
305

306
  return new BError( "Invalid parameter type" );
6✔
307
}
308

309
Bscript::BObjectImp* BasicExecutorModule::mf_CChrZ()
12✔
310
{
311
  std::string res;
12✔
312
  Bscript::ObjArray* arr =
313
      static_cast<Bscript::ObjArray*>( exec.getParamImp( 0, Bscript::BObjectImp::OTArray ) );
12✔
314
  int break_first_null = static_cast<int>( exec.paramAsLong( 1 ) );
12✔
315
  if ( !arr )
12✔
316
    return new BError( "Invalid parameter type" );
6✔
317
  return String::fromUCArray( arr, break_first_null != 0 );
6✔
318
}
12✔
319

320
Bscript::BObjectImp* BasicExecutorModule::mf_Hex()
33✔
321
{
322
  Bscript::BObjectImp* imp = exec.getParamImp( 0 );
33✔
323
  if ( auto* l = impptrIf<BLong>( imp ) )
33✔
324
  {
325
    char s[20];
326
    snprintf( s, Clib::arsize( s ), "0x%X", static_cast<unsigned int>( l->value() ) );
15✔
327
    return new String( s );
15✔
328
  }
329
  if ( auto* d = impptrIf<Double>( imp ) )
18✔
330
  {
331
    char s[20];
332
    snprintf( s, Clib::arsize( s ), "0x%X", static_cast<unsigned int>( d->value() ) );
×
333
    return new String( s );
×
334
  }
335
  if ( auto* simp = impptrIf<String>( imp ) )
18✔
336
  {
337
    char s[20];
338
    snprintf( s, Clib::arsize( s ), "0x%X",
18✔
339
              static_cast<unsigned int>( strtoul( simp->data(), nullptr, 0 ) ) );
18✔
340
    return new String( s );
18✔
341
  }
342
  return new BError( "Hex() expects an Integer, Real, or String" );
×
343
}
344

345
#ifdef __unix__
346
char* itoa( int value, char* result, int base )
×
347
{
348
  // check that the base is valid
349
  if ( base < 2 || base > 16 )
×
350
  {
351
    *result = 0;
×
352
    return result;
×
353
  }
354

355
  char* out = result;
×
356
  int quotient = value;
×
357

358
  do
359
  {
360
    *out = "0123456789abcdef"[std::abs( quotient % base )];
×
361
    ++out;
×
362
    quotient /= base;
×
363
  } while ( quotient );
×
364

365
  // Only apply negative sign for base 10
366
  if ( value < 0 && base == 10 )
×
367
    *out++ = '-';
×
368

369
  std::reverse( result, out );
×
370
  *out = 0;
×
371
  return result;
×
372
}
373
#endif
374

375
Bscript::BObjectImp* BasicExecutorModule::mf_Bin()
×
376
{
377
  Bscript::BObjectImp* imp = exec.getParamImp( 0 );
×
378
  if ( auto* v = impptrIf<BLong>( imp ) )
×
379
  {
380
    int number = v->value();
×
381
#ifdef __APPLE__
382
    std::string bits = std::bitset<2>( number ).to_string();
383
    return new String( bits );
384
#else
385
    char buffer[sizeof( int ) * 8 + 1];
386
    return new String( itoa( number, buffer, 2 ) );
×
387
#endif
388
  }
389
  return new BError( "Bin() expects an Integer" );
×
390
}
391

392
Bscript::BObjectImp* BasicExecutorModule::mf_SplitWords()
80✔
393
{
394
  Bscript::BObjectImp* bimp_split = exec.getParamImp( 0 );
80✔
395
  std::string source = bimp_split->getStringRep();
80✔
396

397
  const String* bimp_delimiter;
398
  if ( !exec.getStringParam( 1, bimp_delimiter ) )
80✔
399
  {
400
    return new BError( "Invalid parameter type." );
×
401
  }
402
  std::string delimiter = bimp_delimiter->getStringRep();
80✔
403

404
  // max_split parameter
405
  int max_split = -1;
80✔
406
  int count = 0;
80✔
407

408
  if ( exec.hasParams( 3 ) )
80✔
409
  {
410
    max_split = static_cast<int>( exec.paramAsLong( 2 ) );
80✔
411
  }
412

413
  std::unique_ptr<Bscript::ObjArray> objarr( new Bscript::ObjArray );
80✔
414

415
  // If delimiter is empty, split to characters
416
  if ( delimiter.empty() )
80✔
417
  {
418
    auto limit = max_split <= -1 ? std::numeric_limits<size_t>::max()
15✔
419
                                 : Clib::clamp_convert<size_t>( max_split + 1 );
9✔
420
    return String::getCharacters( source, limit );
15✔
421
  }
422

423
  // Support for how it previously worked.
424
  // Kept to support spaces and tabs as the same.
425
  if ( delimiter == " " )
65✔
426
  {
427
    ISTRINGSTREAM is( source );
33✔
428
    std::string tmp;
33✔
429
    std::streamoff tellg = -1;
33✔
430
    bool splitted = false;
33✔
431

432
    while ( is >> tmp )
129✔
433
    {
434
      tellg = is.tellg();
99✔
435
      if ( count == max_split && tellg != -1 )
99✔
436
      {  // added max_split parameter
437
        splitted = true;
3✔
438
        break;
3✔
439
      }
440
      objarr->addElement( new String( tmp ) );
96✔
441
      tmp = "";
96✔
442
      count += 1;
96✔
443
    }
444

445
    // Merges the remaining of the string
446
    if ( splitted )
33✔
447
    {
448
      std::string remaining_string;
3✔
449
      remaining_string = source.substr( tellg - tmp.length(), source.length() );
3✔
450
      objarr->addElement( new String( remaining_string ) );
3✔
451
    }
3✔
452

453
    return objarr.release();
33✔
454
  }
33✔
455

456
  // New delimiter support.
457
  std::string new_string = source;
32✔
458
  std::string::size_type found;
459
  do
460
  {
461
    found = new_string.find( delimiter, 0 );
83✔
462
    if ( found == std::string::npos )
83✔
463
      break;
32✔
464
    if ( count == max_split )
60✔
465
    {  // added max_split parameter
466
      break;
9✔
467
    }
468

469
    std::string add_string = new_string.substr( 0, found );
51✔
470

471
    // Shinigami: will not hang server on queue of delimiter
472
    // if ( add_string.empty() )
473
    //  continue;
474

475
    objarr->addElement( new String( add_string ) );
51✔
476
    std::string tmp_string = new_string.substr( found + delimiter.length(), new_string.length() );
51✔
477
    new_string = tmp_string;
51✔
478
    count += 1;
51✔
479
  } while ( found != std::string::npos );
51✔
480

481
  // Catch leftovers here.
482
  if ( !new_string.empty() )
32✔
483
    objarr->addElement( new String( new_string ) );
30✔
484

485
  return objarr.release();
32✔
486
}
80✔
487

488
Bscript::BObjectImp* BasicExecutorModule::mf_Pack()
96✔
489
{
490
  Bscript::BObjectImp* imp = exec.getParamImp( 0 );
96✔
491
  return new String( imp->pack() );
96✔
492
}
493

494
Bscript::BObjectImp* BasicExecutorModule::mf_Unpack()
69✔
495
{
496
  const String* str;
497

498
  if ( exec.getStringParam( 0, str ) )
69✔
499
  {
500
    return Bscript::BObjectImp::unpack( str->data() );
69✔
501
  }
502

NEW
503
  return new BError( "Invalid parameter type" );
×
504
}
505
Bscript::BObjectImp* BasicExecutorModule::mf_TypeOf()
292✔
506
{
507
  Bscript::BObjectImp* imp = exec.getParamImp( 0 );
292✔
508
  return new String( imp->typeOf() );
292✔
509
}
510
Bscript::BObjectImp* BasicExecutorModule::mf_SizeOf()
×
511
{
512
  Bscript::BObjectImp* imp = exec.getParamImp( 0 );
×
513
  return new BLong( static_cast<int>( imp->sizeEstimate() ) );
×
514
}
515
Bscript::BObjectImp* BasicExecutorModule::mf_TypeOfInt()
116✔
516
{
517
  BObjectImp* imp = exec.getParamImp( 0 );
116✔
518
  return new BLong( imp->typeOfInt() );
116✔
519
}
520

521
picojson::value recurseE2J( BObjectImp* value )
1,548✔
522
{
523
  if ( auto* s = impptrIf<String>( value ) )
1,548✔
524
  {
525
    return picojson::value( s->getStringRep() );
884✔
526
  }
527
  if ( auto* l = impptrIf<BLong>( value ) )
1,106✔
528
  {
529
    return picojson::value( static_cast<double>( l->value() ) );
393✔
530
  }
531
  if ( auto* d = impptrIf<Double>( value ) )
713✔
532
  {
533
    return picojson::value( d->value() );
186✔
534
  }
535
  if ( auto* b = impptrIf<BBoolean>( value ) )
527✔
536
  {
537
    return picojson::value( b->value() );
33✔
538
  }
539
  if ( auto* a = impptrIf<ObjArray>( value ) )
494✔
540
  {
541
    picojson::array jsonArr;
37✔
542

543
    for ( const auto& elem : a->ref_arr )
112✔
544
    {
545
      BObject* bo = elem.get();
75✔
546
      if ( bo == nullptr )
75✔
547
        continue;
×
548
      BObjectImp* imp = bo->impptr();
75✔
549
      jsonArr.push_back( recurseE2J( imp ) );
75✔
550
    }
551
    return picojson::value( jsonArr );
37✔
552
  }
37✔
553
  if ( auto* bstruct = impptrIf<BStruct>( value ) )
457✔
554
  {
555
    picojson::object jsonObj;
451✔
556
    for ( const auto& content : bstruct->contents() )
1,633✔
557
    {
558
      BObjectImp* imp = content.second->impptr();
1,182✔
559
      jsonObj.insert( std::pair<std::string, picojson::value>( content.first, recurseE2J( imp ) ) );
1,182✔
560
    }
561
    return picojson::value( jsonObj );
451✔
562
  }
451✔
563
  if ( auto* dict = impptrIf<BDictionary>( value ) )
6✔
564
  {
565
    picojson::object jsonObj;
×
566
    for ( const auto& content : dict->contents() )
×
567
    {
568
      BObjectImp* imp = content.second->impptr();
×
569
      jsonObj.insert( std::pair<std::string, picojson::value>( content.first->getStringRep(),
×
570
                                                               recurseE2J( imp ) ) );
×
571
    }
572
    return picojson::value( jsonObj );
×
573
  }
×
574
  return picojson::value();
6✔
575
}
576
Bscript::BObjectImp* BasicExecutorModule::mf_PackJSON()
291✔
577
{
578
  BObjectImp* imp = exec.getParamImp( 0 );
291✔
579
  auto prettify = exec.getParamImp( 1 )->isTrue();
291✔
580

581
  return new String( recurseE2J( imp ).serialize( prettify ) );
291✔
582
}
583

584
Bscript::BObjectImp* recurseJ2E( const picojson::value& v )
7,152✔
585
{
586
  if ( v.is<std::string>() )
7,152✔
587
  {
588
    return new String( v.get<std::string>() );
1,083✔
589
  }
590
  if ( v.is<double>() )
6,069✔
591
  {
592
    // Possible improvement: separate into BLong and Double
593
    return new Double( v.get<double>() );
3,971✔
594
  }
595
  if ( v.is<bool>() )
2,098✔
596
  {
597
    return new BBoolean( v.get<bool>() );
96✔
598
  }
599
  if ( v.is<picojson::array>() )
2,002✔
600
  {
601
    std::unique_ptr<ObjArray> objarr( new ObjArray );
669✔
602
    const picojson::array& arr = v.get<picojson::array>();
669✔
603
    for ( const auto& elem : arr )
2,988✔
604
    {
605
      objarr->addElement( recurseJ2E( elem ) );
2,319✔
606
    }
607
    return objarr.release();
669✔
608
  }
669✔
609
  if ( v.is<picojson::object>() )
1,333✔
610
  {
611
    std::unique_ptr<BStruct> objstruct( new BStruct );
1,041✔
612
    for ( const auto& content : v.get<picojson::object>() )
5,102✔
613
    {
614
      objstruct->addMember( content.first.c_str(), recurseJ2E( content.second ) );
4,061✔
615
    }
616
    return objstruct.release();
1,041✔
617
  }
1,041✔
618
  return UninitObject::create();
292✔
619
}
620

621
Bscript::BObjectImp* BasicExecutorModule::mf_UnpackJSON()
772✔
622
{
623
  const String* str;
624

625
  if ( exec.getStringParam( 0, str ) )
772✔
626
  {
627
    picojson::value v;
772✔
628
    std::string err = picojson::parse( v, str->data() );
772✔
629
    if ( !err.empty() )
772✔
630
    {
631
      return new BError( err );
×
632
    }
633
    return recurseJ2E( v );
772✔
634
  }
772✔
635

NEW
636
  return new BError( "Invalid parameter type" );
×
637
}
638

639
Bscript::BObjectImp* BasicExecutorModule::mf_Boolean()
27✔
640
{
641
  Bscript::BObjectImp* imp = exec.getParamImp( 0 );
27✔
642
  if ( auto* l = impptrIf<BLong>( imp ) )
27✔
643
    return new BBoolean( l->value() != 0 );
27✔
NEW
644
  if ( auto* b = impptrIf<BBoolean>( imp ) )
×
645
    return new BBoolean( *b );
×
646
  return new BError( "Boolean() expects an Integer or Boolean" );
×
647
}
648

649
/*
650
Base64 encode/decode snippit by Rene Nyffenegger rene.nyffenegger@adp-gmbh.ch
651
Copyright (C) 2004-2008 Rene Nyffenegger
652
*/
653
Bscript::BObjectImp* BasicExecutorModule::mf_EncodeBase64()
12✔
654
{
655
  std::string encoded_string = exec.paramAsString( 0 );
12✔
656

657
  if ( encoded_string.empty() )
12✔
658
    return new BError( "Invalid parameter type" );
×
659

660
  unsigned int in_len = static_cast<unsigned int>( encoded_string.length() );
12✔
661

662
  unsigned char const* bytes_to_encode =
663
      reinterpret_cast<const unsigned char*>( encoded_string.c_str() );
12✔
664
  std::string ret;
12✔
665
  int i = 0;
12✔
666
  int j = 0;
12✔
667
  unsigned char char_array_3[3];
668
  unsigned char char_array_4[4];
669

670
  while ( in_len-- )
492✔
671
  {
672
    char_array_3[i++] = *( bytes_to_encode++ );
480✔
673
    if ( i == 3 )
480✔
674
    {
675
      char_array_4[0] = ( char_array_3[0] & 0xfc ) >> 2;
159✔
676
      char_array_4[1] = ( ( char_array_3[0] & 0x03 ) << 4 ) + ( ( char_array_3[1] & 0xf0 ) >> 4 );
159✔
677
      char_array_4[2] = ( ( char_array_3[1] & 0x0f ) << 2 ) + ( ( char_array_3[2] & 0xc0 ) >> 6 );
159✔
678
      char_array_4[3] = char_array_3[2] & 0x3f;
159✔
679

680
      for ( i = 0; ( i < 4 ); i++ )
795✔
681
        ret += base64_chars[char_array_4[i]];
636✔
682
      i = 0;
159✔
683
    }
684
  }
685

686
  if ( i )
12✔
687
  {
688
    for ( j = i; j < 3; j++ )
9✔
689
      char_array_3[j] = '\0';
6✔
690

691
    char_array_4[0] = ( char_array_3[0] & 0xfc ) >> 2;
3✔
692
    char_array_4[1] = ( ( char_array_3[0] & 0x03 ) << 4 ) + ( ( char_array_3[1] & 0xf0 ) >> 4 );
3✔
693
    char_array_4[2] = ( ( char_array_3[1] & 0x0f ) << 2 ) + ( ( char_array_3[2] & 0xc0 ) >> 6 );
3✔
694
    char_array_4[3] = char_array_3[2] & 0x3f;
3✔
695

696
    for ( j = 0; ( j < i + 1 ); j++ )
9✔
697
      ret += base64_chars[char_array_4[j]];
6✔
698

699
    while ( ( i++ < 3 ) )
9✔
700
      ret += '=';
6✔
701
  }
702

703
  return new String( ret );
12✔
704
}
12✔
705

706
Bscript::BObjectImp* BasicExecutorModule::mf_DecodeBase64()
12✔
707
{
708
  std::string encoded_string = exec.paramAsString( 0 );
12✔
709

710
  if ( encoded_string.empty() )
12✔
711
    return new BError( "Invalid parameter type" );
×
712

713
  int in_len = static_cast<int>( encoded_string.size() );
12✔
714
  int i = 0;
12✔
715
  int j = 0;
12✔
716
  int in_ = 0;
12✔
717
  unsigned char char_array_4[4], char_array_3[3];
718
  std::string ret;
12✔
719

720
  while ( in_len-- && ( encoded_string[in_] != '=' ) && is_base64( encoded_string[in_] ) )
414✔
721
  {
722
    char_array_4[i++] = encoded_string[in_];
402✔
723
    in_++;
402✔
724
    if ( i == 4 )
402✔
725
    {
726
      for ( i = 0; i < 4; i++ )
495✔
727
        char_array_4[i] = static_cast<u8>( base64_chars.find( char_array_4[i] ) );
396✔
728

729
      char_array_3[0] = ( char_array_4[0] << 2 ) + ( ( char_array_4[1] & 0x30 ) >> 4 );
99✔
730
      char_array_3[1] = ( ( char_array_4[1] & 0xf ) << 4 ) + ( ( char_array_4[2] & 0x3c ) >> 2 );
99✔
731
      char_array_3[2] = ( ( char_array_4[2] & 0x3 ) << 6 ) + char_array_4[3];
99✔
732

733
      for ( i = 0; ( i < 3 ); i++ )
396✔
734
        ret += char_array_3[i];
297✔
735
      i = 0;
99✔
736
    }
737
  }
738

739
  if ( i )
12✔
740
  {
741
    for ( j = i; j < 4; j++ )
9✔
742
      char_array_4[j] = 0;
6✔
743

744
    for ( j = 0; j < 4; j++ )
15✔
745
      char_array_4[j] = static_cast<u8>( base64_chars.find( char_array_4[j] ) );
12✔
746

747
    char_array_3[0] = ( char_array_4[0] << 2 ) + ( ( char_array_4[1] & 0x30 ) >> 4 );
3✔
748
    char_array_3[1] = ( ( char_array_4[1] & 0xf ) << 4 ) + ( ( char_array_4[2] & 0x3c ) >> 2 );
3✔
749
    char_array_3[2] = ( ( char_array_4[2] & 0x3 ) << 6 ) + char_array_4[3];
3✔
750

751
    for ( j = 0; ( j < i - 1 ); j++ )
6✔
752
      ret += char_array_3[j];
3✔
753
  }
754

755
  return new String( ret );
12✔
756
}
12✔
757

758
Bscript::BObjectImp* BasicExecutorModule::mf_RegExp()
99✔
759
{
760
  const String* expr;
761
  const String* flags;
762
  if ( !getStringParam( 0, expr ) || !getStringParam( 1, flags ) )
99✔
763
    return new BError( "Invalid parameter type" );
3✔
764

765
  return BRegExp::create( expr->getStringRep(), flags->getStringRep() );
96✔
766
}
767

768
}  // namespace Pol::Module
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