• 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

17.83
/pol-core/pol/network/packethooks.cpp
1
/** @file
2
 *
3
 * @par History
4
 * - 2006/05/23 Shinigami: added missing Check to ExportedPacketHookHandler() for
5
 *                         missing default_handler in Packets with SubCommands
6
 * - 2007/08/19 Shinigami: fixed Memory Leak in PacketHook functions
7
 * - 2009/08/03 MuadDib:   Renaming of MSG_HANDLER_6017 and related, to MSG_HANDLER_V2 for better
8
 * description
9
 *                         Renamed secondary handler class to *_V2 for naming convention
10
 * - 2009/08/25 Shinigami: STLport-5.2.1 fix: params in call of Log2()
11
 * - 2009/09/03 MuadDib:   Relocation of account related cpp/h
12
 *
13
 * @note Version member: Positive Integer. This is used to translate the "version" of the packet
14
 * structure
15
 * to the correct internal core Message Handler (Default 1, which translates to use handler[]). Each
16
 * new Handler added to the core needs a new Version number here. As of 8/3/09 there is only 2.
17
 */
18

19

20
#include "packethooks.h"
21

22
#include <ctype.h>
23
#include <stdlib.h>
24
#include <string.h>
25

26
#include "../../clib/cfgelem.h"
27
#include "../../clib/clib.h"
28
#include "../../clib/clib_endian.h"
29
#include "../../clib/logfacility.h"
30
#include "../../clib/rawtypes.h"
31
#include "../../clib/refptr.h"
32
#include "../../clib/stlutil.h"
33
#include "../../clib/strutil.h"
34
#include "../../plib/pkg.h"
35
#include "../globals/network.h"
36
#include "../mobile/charactr.h"
37
#include "../packetscrobj.h"
38
#include "../syshook.h"
39
#include "client.h"
40

41

42
namespace Pol::Network
43
{
44
u32 GetSubCmd( const unsigned char* message, PacketHookData* phd )
×
45
{
46
  if ( phd->sub_command_length == 1 )
×
47
    return *( reinterpret_cast<const u8*>( &message[phd->sub_command_offset] ) );
×
NEW
48
  if ( phd->sub_command_length == 2 )
×
49
    return cfBEu16( *( reinterpret_cast<const u16*>( &message[phd->sub_command_offset] ) ) );
×
50
  // else if(phd->sub_command_length == 4)
51
  //    return cfBEu32(*(reinterpret_cast<const u32*>(&message[phd->sub_command_offset])));
NEW
52
  return cfBEu32( *( reinterpret_cast<const u32*>( &message[phd->sub_command_offset] ) ) );
×
53
}
54

55
// Variable length is defined in MSGLEN_2BYTELEN_DATA
56
static bool is_fixed_length( const PacketHookData* phd )
×
57
{
58
  return phd->length > 0;
×
59
}
60

61
// Gets the packet hook for a specific packet version
62
PacketHookData* get_packethook( u8 msgid, PacketVersion version = PacketVersion::Default )
39,256✔
63
{
64
  if ( version == PacketVersion::V2 )
39,256✔
65
    return Core::networkManager.packet_hook_data_v2.at( msgid ).get();
19,628✔
66

67
  return Core::networkManager.packet_hook_data.at( msgid ).get();
19,628✔
68
}
69

70
// Gets the packet hook according to the client version
71
PacketHookData* get_packethook( u8 msgid, const Client* client )
19,628✔
72
{
73
  PacketHookData* phd = get_packethook( msgid, PacketVersion::V2 );
19,628✔
74
  if ( phd->version == PacketVersion::V2 &&
19,628✔
75
       CompareVersionDetail( client->getversiondetail(), phd->client_ver ) )
×
76
    return phd;
×
77

78
  return get_packethook( msgid, PacketVersion::Default );
19,628✔
79
}
80

81
// MSG_HANDLER function used for each hooked packet type.
82
void ExportedPacketHookHandler( Client* client, void* data )
×
83
{
84
  // find the script handler data
85
  unsigned char* message = static_cast<unsigned char*>( data );
×
86

87
  u8 msgid = message[0];
×
88
  PacketHookData* phd = get_packethook( msgid, client );
×
89

90
  if ( phd->function == nullptr && phd->SubCommands.empty() )
×
91
  {
92
    if ( phd->default_handler == nullptr )
×
93
      POLLOGLN( "Expected packet hook function for msg {:#x} but was null!", (int)*message );
×
94
    else  // only SendFunction is definied but default_handler is definied
95
      phd->default_handler( client, data );
×
96
    return;
×
97
  }
98

99
  if ( !phd->SubCommands.empty() )
×
100
  {
101
    u32 subcmd = GetSubCmd( message, phd );
×
102
    std::map<u32, PacketHookData*>::iterator itr;
×
103
    itr = phd->SubCommands.find( subcmd );
×
104
    if ( itr != phd->SubCommands.end() )
×
105
    {
106
      if ( itr->second->function != nullptr )
×
107
        phd = itr->second;
×
108
    }
109
  }
110
  if ( phd->function ==
×
111
       nullptr )  // this will happen if the main packet entry does not define a receive function,
112
  // but has subcommands, and we've received an unhooked subcmd.
113
  {
114
    if ( phd->default_handler != nullptr )
×
115
      phd->default_handler( client, data );
×
116
    return;
×
117
  }
118

119
  // Sends a client reference if still connecting
120
  Bscript::BObjectImp* calling_ref;
121
  if ( client->chr )
×
122
    calling_ref = client->chr->make_ref();
×
123
  else
124
    calling_ref = client->make_ref();
×
125

126
  // This packet has fixed length
127
  if ( is_fixed_length( phd ) )
×
128
  {
129
    ref_ptr<Core::BPacket> pkt(
130
        new Core::BPacket( message, static_cast<unsigned short>( phd->length ), false ) );
×
131
    // if function returns 0, we need to call the default handler
132

133

134
    if ( phd->function->call( calling_ref, pkt.get() ) == 0 )
×
135
    {
136
      if ( phd->default_handler != nullptr )
×
137
        phd->default_handler( client, static_cast<void*>( &pkt->buffer[0] ) );
×
138
    }
139
  }
×
140
  else  // packet is variable length
141
  {
142
    // discover packet length, and create new packet
143
    unsigned short len = cfBEu16( *( reinterpret_cast<unsigned short*>( &message[1] ) ) );
×
144
    ref_ptr<Core::BPacket> pkt( new Core::BPacket( message, len, true ) );
×
145
    // if function returns 0, we need to call the default handler
146

147
    if ( phd->function->call( calling_ref, pkt.get() ) == 0 )
×
148
    {
149
      if ( phd->default_handler != nullptr )
×
150
      {
151
        // the buffer size may have changed in the script, make sure the packet gets the right size
152
        // u16* sizeptr = (u16*)(&pkt->buffer[1]);
153
        //*sizeptr = ctBEu16(pkt->buffer.size());
154
        phd->default_handler( client, static_cast<void*>( &pkt->buffer[0] ) );
×
155
      }
156
    }
157
  }
×
158
}
159

160

161
void CallOutgoingPacketExportedFunction( Client* client, const void*& data, int& inlength,
×
162
                                         ref_ptr<Core::BPacket>& outpacket, PacketHookData* phd,
163
                                         bool& handled )
164
{
165
  const unsigned char* message = static_cast<const unsigned char*>( data );
×
166

167
  // Sends a client reference if still connecting
168
  Bscript::BObjectImp* calling_ref;
169
  if ( client->chr )
×
170
    calling_ref = client->chr->make_ref();
×
171
  else
172
    calling_ref = client->make_ref();
×
173

174
  // This packet has fixed length
175
  if ( is_fixed_length( phd ) )
×
176
  {
177
    outpacket.set(
×
178
        new Core::BPacket( message, static_cast<unsigned short>( phd->length ), false ) );
×
179
    // if function returns 0, we need to call the default handler
180

181
    if ( phd->outgoing_function->call( calling_ref, outpacket.get() ) == 0 )
×
182
    {
183
      data = static_cast<void*>( &outpacket->buffer[0] );
×
184
      // a fixed-length packet
185
      inlength = phd->length;
×
186
      handled = false;
×
187
    }
188
    else
189
      handled = true;
×
190
  }
191
  else  // packet is variable length
192
  {
193
    // discover packet length, and create new packet
194
    unsigned short len = cfBEu16( *( reinterpret_cast<const unsigned short*>( &message[1] ) ) );
×
195
    outpacket.set( new Core::BPacket( message, len, true ) );
×
196
    // if function returns 0, we need to call the default handler
197

198
    if ( phd->outgoing_function->call( calling_ref, outpacket.get() ) == 0 )
×
199
    {
200
      // the buffer size may have changed in the script, make sure the packet gets the right size
201

202
      u16* sizeptr = reinterpret_cast<u16*>(
203
          &outpacket->buffer[1] );  // var-length packets always have length at 2nd and 3rd byte
×
204
      //*sizeptr = ctBEu16(outpacket->buffer.size());
205

206
      data = static_cast<void*>( &outpacket->buffer[0] );
×
207
      // pass the new size back to client::transmit
208
      inlength = cfBEu16( *sizeptr );
×
209

210
      // This shouldn't trigger unless something is wrong with BPacket.
211
      passert_r( static_cast<u32>( inlength ) <= outpacket->buffer.size(),
×
212
                 "Specified packet length is greater than packet buffer!" );
213

214
      handled = false;
×
215
    }
216
    else
217
      handled = true;
×
218
  }
219
}
×
220

221
bool GetAndCheckPacketHooked( Client* client, const void*& data, PacketHookData*& phd )
19,628✔
222
{
223
  // find the script handler data
224
  bool subcmd_handler_exists = false;
19,628✔
225
  const unsigned char* message = static_cast<const unsigned char*>( data );
19,628✔
226

227
  u8 msgid = message[0];
19,628✔
228
  phd = get_packethook( msgid, client );
19,628✔
229

230
  if ( !phd->SubCommands.empty() )
19,628✔
231
  {
232
    u32 subcmd = GetSubCmd( message, phd );
×
233
    auto itr = phd->SubCommands.find( subcmd );
×
234
    if ( itr != phd->SubCommands.end() )
×
235
    {
236
      if ( itr->second->outgoing_function != nullptr )
×
237
      {
238
        phd = itr->second;
×
239
        subcmd_handler_exists = true;
×
240
      }
241
    }
242
  }
243
  if ( phd->outgoing_function == nullptr && !subcmd_handler_exists )
19,628✔
244
  {
245
    return false;
19,628✔
246
  }
247
  return true;
×
248
}
249

250
static PacketVersion load_packethook_version( Clib::ConfigElem& elem )
×
251
{
252
  unsigned short pktversion;
253

254
  if ( !elem.remove_prop( "Version", &pktversion ) )
×
255
    pktversion = 1;
×
256

257
  switch ( pktversion )
×
258
  {
259
  case 1:
×
260
    return PacketVersion::V1;
×
261
  case 2:
×
262
    return PacketVersion::V2;
×
263
  default:
×
264
    elem.throw_error( "Only versions 1 and 2 are currently implemented." );
×
265
  }
266
}
267

268
static int load_packethook_length( Clib::ConfigElem& elem )
×
269
{
270
  std::string lengthstr;
×
271
  int length = 0;
×
272

273
  if ( !elem.remove_prop( "Length", &lengthstr ) )
×
274
    elem.throw_error( "Length property missing." );
×
275

276
  if ( lengthstr == "variable" )
×
277
    length = MSGLEN_2BYTELEN_DATA;  // sets length to indicate variable length
×
278
  else
279
  {
280
    unsigned short temp;
281
    char* endptr = nullptr;
×
282
    temp = (unsigned short)strtoul( lengthstr.c_str(), &endptr, 0 );
×
283
    if ( temp == 0 || ( ( endptr != nullptr ) && ( *endptr != '\0' ) && !isspace( *endptr ) ) )
×
284
    {
285
      elem.throw_error( "Length must be a positive integer or 'variable'" );
×
286
    }
287
    else
288
      length = temp;
×
289
  }
290

291
  return length;
×
292
}
×
293

294
static void packethook_warn_if_previously_defined( u8 msgid, PacketVersion pktversion )
×
295
{
296
  PacketHookData* hook_data = get_packethook( msgid, pktversion );
×
297

298
  auto existing_in_func = hook_data->function;
×
299
  auto existing_out_func = hook_data->outgoing_function;
×
300

301
  if ( existing_in_func != nullptr )
×
302
    POLLOGLN( "Packet hook receive function multiply defined for packet {:#x}!", (int)msgid );
×
303
  if ( existing_out_func != nullptr )
×
304
    POLLOGLN( "Packet hook send function multiply defined for packet {:#x}!", (int)msgid );
×
305
}
×
306

307
void load_packet_entries( const Plib::Package* pkg, Clib::ConfigElem& elem )
×
308
{
309
  if ( stricmp( elem.type(), "Packet" ) != 0 )
×
310
    return;
×
311

312
  int length = 0;
×
313

314
  PacketVersion pktversion;
315
  std::string client_string;
×
316
  VersionDetailStruct client_struct;
317

318
  Core::ExportedFunction* exfunc = (Core::ExportedFunction*)nullptr;
×
319
  Core::ExportedFunction* exoutfunc = (Core::ExportedFunction*)nullptr;
×
320
  if ( elem.has_prop( "ReceiveFunction" ) )
×
321
    exfunc =
322
        Core::FindExportedFunction( elem, pkg, elem.remove_string( "ReceiveFunction" ), 2, true );
×
323
  if ( elem.has_prop( "SendFunction" ) )
×
324
    exoutfunc =
325
        Core::FindExportedFunction( elem, pkg, elem.remove_string( "SendFunction" ), 2, true );
×
326

327
  char* endptr = nullptr;
×
328
  unsigned int idlong = strtoul( elem.rest(), &endptr, 0 );
×
329
  if ( ( endptr != nullptr ) && ( *endptr != '\0' ) && !isspace( *endptr ) )
×
330
  {
331
    elem.throw_error( "Packet ID not defined or poorly formed" );
×
332
  }
333
  if ( idlong > 0xFF )
×
334
    elem.throw_error( "Packet ID must be between 0x0 and 0xFF" );
×
335

336
  // Reads the packet version ("Version") and throws an error if not 1 or 2
337
  pktversion = load_packethook_version( elem );
×
338

339
  client_string = elem.remove_string( "Client", "1.25.25.0" );
×
340
  SetVersionDetailStruct( client_string, client_struct );
×
341

342
  unsigned char id = static_cast<unsigned char>( idlong );
×
343

344
  unsigned short subcmdoff;
345
  if ( !elem.remove_prop( "SubCommandOffset", &subcmdoff ) )
×
346
    subcmdoff = 0;
×
347
  unsigned short subcmdlen;
348
  if ( !elem.remove_prop( "SubCommandLength", &subcmdlen ) )
×
349
    subcmdlen = 0;
×
350

351
  // Loads the length ("Length"), which is either 'variable' or a positive integer
352
  // if 'variable', length will be MSGLEN_2BYTELEN_DATA
353
  length = load_packethook_length( elem );
×
354

355
  // Checks if packethook has been previously defined and prints a warning
356
  packethook_warn_if_previously_defined( id, pktversion );
×
357

358
  PacketHookData* pkt_data = get_packethook( id, pktversion );
×
359
  pkt_data->function = exfunc;
×
360
  pkt_data->outgoing_function = exoutfunc;
×
361
  pkt_data->length = length;
×
362
  pkt_data->sub_command_offset = subcmdoff;
×
363
  pkt_data->sub_command_length = subcmdlen;
×
364
  pkt_data->version = pktversion;
×
365
  pkt_data->client_ver = client_struct;
×
366
  pkt_data->default_handler = PacketRegistry::get_callback( id, pktversion );
×
367

368
  PacketRegistry::set_handler( id, length, ExportedPacketHookHandler, pktversion );
×
369
}
×
370

371
static void packethook_assert_valid_parent( u8 id, const PacketHookData* parent,
×
372
                                            const Clib::ConfigElem& elem )
373
{
374
  // validate that the parent packet has a definition and a SubCommandOffset
375
  if ( !parent->sub_command_offset )
×
376
    elem.throw_error( std::string( "Parent packet " + Clib::hexint( id ) +
×
377
                                   " does not define SubCommandOffset!" ) );
378
  if ( !parent->sub_command_length )
×
379
    elem.throw_error( std::string( "Parent packet " + Clib::hexint( id ) +
×
380
                                   " does not define SubCommandLength" ) );
381
}
×
382

383
void load_subpacket_entries( const Plib::Package* pkg, Clib::ConfigElem& elem )
×
384
{
385
  if ( stricmp( elem.type(), "SubPacket" ) != 0 )
×
386
    return;
×
387
  Core::ExportedFunction* exfunc = (Core::ExportedFunction*)nullptr;
×
388
  Core::ExportedFunction* exoutfunc = (Core::ExportedFunction*)nullptr;
×
389

390
  PacketVersion pktversion;
391
  std::string client_string;
×
392
  VersionDetailStruct client_struct;
393

394
  if ( elem.has_prop( "ReceiveFunction" ) )
×
395
    exfunc =
396
        Core::FindExportedFunction( elem, pkg, elem.remove_string( "ReceiveFunction" ), 2, true );
×
397
  if ( elem.has_prop( "SendFunction" ) )
×
398
    exoutfunc =
399
        Core::FindExportedFunction( elem, pkg, elem.remove_string( "SendFunction" ), 2, true );
×
400

401
  char* endptr = nullptr;
×
402
  unsigned int idlong = strtoul( elem.rest(), &endptr, 0 );
×
403
  if ( ( endptr != nullptr ) && ( *endptr != '\0' ) && !isspace( *endptr ) )
×
404
  {
405
    elem.throw_error( "Packet ID not defined or poorly formed" );
×
406
  }
407
  if ( idlong > 0xFF )
×
408
    elem.throw_error( "Packet ID must be between 0x0 and 0xFF" );
×
409

410
  unsigned char id = static_cast<unsigned char>( idlong );
×
411

412
  unsigned short subid = elem.remove_ushort( "SubCommandID" );
×
413

414
  // Reads the packet version ("Version") and throws an error if not 1 or 2
415
  pktversion = load_packethook_version( elem );
×
416

417
  client_string = elem.remove_string( "Client", "1.25.25.0" );
×
418
  SetVersionDetailStruct( client_string, client_struct );
×
419

420
  PacketHookData* parent = get_packethook( id, pktversion );
×
421
  packethook_assert_valid_parent( id, parent, elem );
×
422

423
  if ( parent->SubCommands.find( subid ) != parent->SubCommands.end() )
×
424
    elem.throw_error( std::string( "SubCommand " + Clib::hexint( subid ) + " for packet " +
×
425
                                   Clib::hexint( id ) + " multiply defined!" ) );
×
426

427
  PacketHookData* SubData = new PacketHookData();
×
428
  SubData->function = exfunc;
×
429
  SubData->outgoing_function = exoutfunc;
×
430
  SubData->length = parent->length;
×
431
  SubData->default_handler = parent->default_handler;
×
432
  SubData->version = pktversion;
×
433
  SubData->client_ver = client_struct;
×
434

435
  parent->SubCommands.insert( std::make_pair( subid, SubData ) );
×
436
}
×
437

438
// loads "uopacket.cfg" entries from packages
439
void load_packet_hooks()
3✔
440
{
441
  Plib::load_packaged_cfgs( "uopacket.cfg", "packet subpacket", load_packet_entries );
3✔
442
  Plib::load_packaged_cfgs( "uopacket.cfg", "packet subpacket", load_subpacket_entries );
3✔
443
}
3✔
444

445
PacketHookData::PacketHookData()
1,536✔
446
    : length( 0 ),
1,536✔
447
      function( nullptr ),
1,536✔
448
      outgoing_function( nullptr ),
1,536✔
449
      default_handler( nullptr ),
1,536✔
450
      sub_command_offset( 0 ),
1,536✔
451
      sub_command_length( 0 ),
1,536✔
452
      version( PacketVersion::Default )
1,536✔
453
{
454
  memset( &client_ver, 0, sizeof( client_ver ) );
1,536✔
455
};
1,536✔
456

457
PacketHookData::~PacketHookData()
1,536✔
458
{
459
  std::map<u32, PacketHookData*>::iterator itr = SubCommands.begin(), end = SubCommands.end();
1,536✔
460
  for ( ; itr != end; ++itr )
1,536✔
461
  {
462
    delete itr->second;
×
463
  }
464
  if ( function != nullptr )
1,536✔
465
    delete function;
×
466
  if ( outgoing_function != nullptr )
1,536✔
467
    delete outgoing_function;
×
468
}
1,536✔
469

470
void PacketHookData::initializeGameData( std::vector<std::unique_ptr<PacketHookData>>* data )
6✔
471
{
472
  data->clear();
6✔
473
  data->reserve( 256 );
6✔
474
  for ( int i = 0; i < 256; ++i )
1,542✔
475
  {
476
    data->emplace_back( new PacketHookData() );
1,536✔
477
  }
478
}
6✔
479

480
size_t PacketHookData::estimateSize() const
512✔
481
{
482
  size_t size = sizeof( PacketHookData ) + 2 * sizeof( Core::ExportedFunction );
512✔
483
  size += Clib::memsize( SubCommands );
512✔
484
  for ( const auto& subs : SubCommands )
512✔
485
  {
486
    if ( subs.second != nullptr )
×
487
      size += subs.second->estimateSize();
×
488
  }
489
  return size;
512✔
490
}
491

492

493
void clean_packethooks()
3✔
494
{
495
  Core::networkManager.packet_hook_data.clear();
3✔
496
  Core::networkManager.packet_hook_data_v2.clear();
3✔
497
}
3✔
498

499
void SetVersionDetailStruct( const std::string& ver, VersionDetailStruct& detail )
×
500
{
501
  try
502
  {
503
    size_t dot1 = ver.find_first_of( '.', 0 );
×
504
    size_t dot2 = ver.find_first_of( '.', dot1 + 1 );
×
505
    size_t dot3 = ver.find_first_of( '.', dot2 + 1 );
×
506
    if ( dot3 == std::string::npos )  // since 5.0.7 patch is digit
×
507
    {
508
      dot3 = dot2 + 1;
×
509
      while ( ( dot3 < ver.length() ) && ( isdigit( ver[dot3] ) ) )
×
510
      {
511
        dot3++;
×
512
      }
513
    }
514

515
    detail.major = atoi( ver.substr( 0, dot1 ).c_str() );
×
516
    detail.minor = atoi( ver.substr( dot1 + 1, dot2 - dot1 - 1 ).c_str() );
×
517
    detail.rev = atoi( ver.substr( dot2 + 1, dot3 - dot2 - 1 ).c_str() );
×
518
    detail.patch = 0;
×
519
    if ( dot3 < ver.length() )
×
520
    {
521
      if ( ( detail.major <= 5 ) && ( detail.minor <= 0 ) && ( detail.rev <= 6 ) )
×
522
      {
523
        if ( ver[dot3] != ' ' )
×
524
          detail.patch = ( ver[dot3] - 'a' ) + 1;  // char to int
×
525
      }
526
      else
527
        detail.patch = atoi( ver.substr( dot3 + 1, ver.length() - dot3 - 1 ).c_str() );
×
528
    }
529
  }
530
  catch ( ... )
×
531
  {
532
    detail.major = 0;
×
533
    detail.minor = 0;
×
534
    detail.rev = 0;
×
535
    detail.patch = 0;
×
536
    POLLOG_ERRORLN( "Malformed client version string in Packethook: {}", ver );
×
537
  }
×
538
}
×
539

540
bool CompareVersionDetail( VersionDetailStruct ver1, VersionDetailStruct ver2 )
×
541
{
542
  if ( ver1.major > ver2.major )
×
543
    return true;
×
NEW
544
  if ( ver1.major < ver2.major )
×
545
    return false;
×
NEW
546
  if ( ver1.minor > ver2.minor )
×
547
    return true;
×
NEW
548
  if ( ver1.minor < ver2.minor )
×
549
    return false;
×
NEW
550
  if ( ver1.rev > ver2.rev )
×
551
    return true;
×
NEW
552
  if ( ver1.rev < ver2.rev )
×
553
    return false;
×
NEW
554
  if ( ver1.patch > ver2.patch )
×
555
    return true;
×
NEW
556
  if ( ver1.patch < ver2.patch )
×
557
    return false;
×
NEW
558
  return true;
×
559
}
560
}  // namespace Pol::Network
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