-
Notifications
You must be signed in to change notification settings - Fork 49
/
sscanf2.inc
2423 lines (2264 loc) · 73.7 KB
/
sscanf2.inc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
* sscanf 2.15.1
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the sscanf 2.0 SA:MP plugin.
*
* The Initial Developer of the Original Code is Alex "Y_Less" Cole.
* Portions created by the Initial Developer are Copyright (c) 2022
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Cheaterman
* DEntisT
* Emmet_
* karimcambridge
* kalacsparty
* Kirima
* leHeix
* maddinat0r
* Southclaws
* Y_Less
* ziggi
*
* Special Thanks to:
*
* SA:MP Team past, present, and future.
* maddinat0r, for hosting the repo for a very long time.
* Emmet_, for his efforts in maintaining it for almost a year.
*/
#if defined _INC_SSCANF
#endinput
#endif
#define _INC_SSCANF
#if !defined _samp_included
#error Please include <a_npc> or <a_samp> first.
#endif
/**
* <library
* name="sscanf"
* summary="Extracts structured information from strings."
* license="Copyright (c) 2022 Alex "Y_Less" Cole. Licensed under MPL 1.1"
* >
* <summary pawndoc="true">
* This library uses the enhanced <em>pawndoc.xsl</em> from
* <a href="https://github.com/pawn-lang/pawndoc">pawn-lang/pawndoc</a>.
* This XSL has features such as library and markdown support, and will not
* render this message when used.
* </summary>
* <remarks>
* This is the <em>sscanf</em> plugin, which provides the <c>sscanf</c>
* function to extract basic structured data from strings. This is slightly
* different to regular expressions, but both have their place. A regular
* expression gives you total control over the exact structure of data down
* to the character level; however, extracting structured data like numbers
* using it is tricky. Conversely this gives slightly higher-level
* <em>specifiers</em> which can easily extract data types, at the expense
* of fine-grained control. To convert a string in to two numbers would
* look like:
*
* <code>
* new num1, num2; <br />
* sscanf("45 100", "ii", num1, num2);
* </code>
*
* <c>ii</c> is the specifier string, which here means "integer integer";
* stating that the input string should be two whole numbers in a row (which
* is - <c>"45 100"</c>). <c>num1</c> and <c>num2</c> are the destination
* variables to store the found numbers in (after conversion from strings).
* You can check if the conversion failed by looking for a non-naught return
* value:
*
* <code>
* new num1, num2; <br />
* if (sscanf("hello 100", "ii", num1, num2)) <br />
* { <br /><indent />
* printf("The input was not two numbers."); <br />
* }
* </code>
*
* This will fail because <c>"hello"</c> is not a whole number (or indeed
* any type of number at all). For more information on using the function
* refer to the tutorials or the reference documentation in
* <a href="https://github.com/Y-Less/sscanf/blob/master/README.md">the
* attached readme</a>.
* </remarks>
* </library>
*/
/// <p/>
#if defined __PawnBuild
#if __PawnBuild == 0
#undef __PawnBuild
#define __pawn_build 0
#else
#define __pawn_build __PawnBuild
#endif
#else
#define __pawn_build 0
#endif
#define SSCANF_STATIC__
#if __pawn_build >= 11
// `const static` support.
#undef SSCANF_STATIC__
#define SSCANF_STATIC__ static
#endif
#if __pawn_build == 0
#if !defined SSCANF_NO_NICE_FEATURES
#error sscanf utilises community compiler features. Use `#define SSCANF_NO_NICE_FEATURES` to live without (if you can call that living) or better yet download it here: github.com/pawn-lang/compiler/releases
#endif
#endif
/**
* <library>sscanf</library>
* <remarks>
* Was sscanf built for an NPC mode or a normal mode?
* </remarks>
*/
#if defined GetDistanceFromMeToPoint
// NPC script.
const SSCANF_NPC = 1;
#define SSCANF_NPC (1)
#pragma library sscanf
#else
const SSCANF_NPC = 0;
#define SSCANF_NPC (0)
#endif
/**
* <library>sscanf</library>
* <remarks>
* The sscanf major version number.
* </remarks>
*/
const SSCANF_VERSION_MAJOR = 2;
#define SSCANF_VERSION_MAJOR 2
/**
* <library>sscanf</library>
* <remarks>
* The sscanf minor version number.
* </remarks>
*/
const SSCANF_VERSION_MINOR = 15;
#define SSCANF_VERSION_MINOR 15
/**
* <library>sscanf</library>
* <remarks>
* The sscanf build number.
* </remarks>
*/
const SSCANF_VERSION_BUILD = 1;
#define SSCANF_VERSION_BUILD 1
/**
* <library>sscanf</library>
* <remarks>
* The sscanf version as a string. E.g. <c>"2.8.1"</c>.
* </remarks>
*/
stock const SSCANF_VERSION_STRING[] = #SSCANF_VERSION_MAJOR "." #SSCANF_VERSION_MINOR "." #SSCANF_VERSION_BUILD;
#define SSCANF_VERSION_STRING #SSCANF_VERSION_MAJOR "." #SSCANF_VERSION_MINOR "." #SSCANF_VERSION_BUILD
/**
* <library>sscanf</library>
* <remarks>
* Converts a version string to
* <a href="https://en.wikipedia.org/wiki/Binary-coded_decimal">BCD</a>. For example:
*
* <code>
* BCD(5.6.17);
* </code>
*
* Returns:
*
* <code>
* 0x050617
* </code>
*
* Each section (between dots) is assigned a single byte and the last section is
* always in the lowest byte. This implies a maximum of four sections and two
* digits per section.
*
* </remarks>
*/
forward BCD(number);
#define BCD(%0) (_:MORE_BCD:NO_MORE_BCD:%0.$0)
#define MORE_BCD:NO_MORE_BCD:%0.%1$%2) MORE_BCD:NO_MORE_BCD:%1$(%2) << 8 | DO_BCD(%0))
#define NO_MORE_BCD:$
#define DO_BCD(%0) _:(%0) / 10 << 4 | _:(%0) % 10
/**
* <library>sscanf</library>
* <remarks>
* The sscanf version in BCD as a proper constant. Example:
*
* <code>
* 2.10.3 <br />
* => 02 10 03 <br />
* => 0x021003
* </code>
* </remarks>
*/
const SSCANF_VERSION = BCD(SSCANF_VERSION_MAJOR.SSCANF_VERSION_MINOR.SSCANF_VERSION_BUILD);
#define SSCANF_VERSION (BCD(SSCANF_VERSION_MAJOR.SSCANF_VERSION_MINOR.SSCANF_VERSION_BUILD))
/**
* <library>sscanf</library>
* <remarks>
* The sscanf version in BCD. Example:
*
* <code>
* 2.10.3 <br />
* => 02 10 03 <br />
* => 0x021003
* </code>
* </remarks>
*/
const SSCANF_VERSION_BCD = SSCANF_VERSION;
#define SSCANF_VERSION_BCD SSCANF_VERSION
#define sscanf_%0\32; sscanf_
#define SSCANF:%0(%1) forward sscanf_%0(%1);public sscanf_%0(%1)
#define @kustom()%0(%1) forward sscanf_%0(%1);public sscanf_%0(%1)
// The check for `SSCANF_GetClosestString` ensures that this is the first
// compiler pass and thus the check for `sscanf` only finds earlier definitions
// not our later fake definition made purely for documentation purposes.
#if defined sscanf && !defined SSCANF_GetClosestString
#error sscanf already defined, or used before inclusion.
#endif
/// <p/>
/**
* <library>sscanf</library>
* <remarks>
* There are almost 100 different unique error codes, but many of them can often
* be dealt with in the same way. For example - <em><b>1011</b> - An int was
* wanted, but the input didn't match</em> and <em><b>1012</b> - A number was
* wanted, but the input didn't match</em> can probably usually use the same
* result processing (especially since they can never be returned by the same
* specifier). Hence the errors are grouped together in to a few large groups
* for ease of processing.
* </remarks>
*/
enum sscanf_error:SSCANF_ERRORS__ (+= 65536)
{
UNKNOWN_SSCANF_ERROR = -1,
SSCANF_ERROR_NONE,
SSCANF_ERROR_NATIVE = 65536,
SSCANF_ERROR_SPECIFIER,
SSCANF_ERROR_INVALID,
SSCANF_ERROR_MISSING,
SSCANF_ERROR_EXCESS,
SSCANF_ERROR_COLOUR,
SSCANF_ERROR_OVERFLOW,
SSCANF_ERROR_NOT_FOUND,
SSCANF_ERROR_NO_ALTS
}
static stock sscanf_error:_@SSCANF_ERROR() { return SSCANF_ERRORS__; }
// We use both `enum` and `#define` together so that `#emit` and arrays will
// both work. See the open.mp documentation for more details.
#define UNKNOWN_SSCANF_ERROR (sscanf_error:-1)
#define SSCANF_ERROR_NONE (sscanf_error:0) // 0 << 16
#define SSCANF_ERROR_NATIVE (sscanf_error:65536) // 1 << 16
#define SSCANF_ERROR_SPECIFIER (sscanf_error:131072) // 2 << 16
#define SSCANF_ERROR_INVALID (sscanf_error:196608) // 3 << 16
#define SSCANF_ERROR_MISSING (sscanf_error:262144) // 4 << 16
#define SSCANF_ERROR_EXCESS (sscanf_error:327680) // 5 << 16
#define SSCANF_ERROR_COLOUR (sscanf_error:393216) // 6 << 16
#define SSCANF_ERROR_OVERFLOW (sscanf_error:458752) // 7 << 16
#define SSCANF_ERROR_NOT_FOUND (sscanf_error:524288) // 8 << 16
#define SSCANF_ERROR_NO_ALTS (sscanf_error:589824) // 9 << 16
/**
* <library>sscanf</library>
* <param name="specifier">The index of the problem specifier.</param>
* <param name="error">The code or category of the potential problem.</param>
* <remarks>
* Combine a specifier index and error code together for use as a return value
* from <c>sscanf</c>.
* </remarks>
*/
forward SSCANF_ERROR(specifier, sscanf_error:error);
#define SSCANF_ERROR(%0,%1) (((_:@ss_S:@ss_0:@ss_1:@ss_2:@ss_3:@ss_4:@ss_5:@ss_6:@ss_7:@ss_8:@ss_9:((%1)))<<16)|(((_:(%1))>>>16)<<16)|(%0))
// Allows for all these variations:
//
// SSCANF_ERROR(3, NATIVE)
// SSCANF_ERROR(3, SSCANF_ERROR_EXCESS)
// SSCANF_ERROR(3, 1001)
// SSCANF_ERROR(3, sscanf_error:262144)
//
// However, the tags aren't checked, because there are two allowed, and that's
// hard to do in a macro.
#define @ss_S:@ss_0:@ss_1:@ss_2:@ss_3:@ss_4:@ss_5:@ss_6:@ss_7:@ss_8:@ss_9:((%0\32%1))) @ss_S:@ss_0:@ss_1:@ss_2:@ss_3:@ss_4:@ss_5:@ss_6:@ss_7:@ss_8:@ss_9:((%0%1)))
#define @ss_0:@ss_1:@ss_2:@ss_3:@ss_4:@ss_5:@ss_6:@ss_7:@ss_8:@ss_9:((NONE)))<<16)|(((_:(%9)) ((SSCANF_ERROR_NONE)))<<16)|(((_:(SSCANF_ERROR_NONE))
#define @ss_1:@ss_2:@ss_3:@ss_4:@ss_5:@ss_6:@ss_7:@ss_8:@ss_9:((NATIVE)))<<16)|(((_:(%9)) ((SSCANF_ERROR_NATIVE)))<<16)|(((_:(SSCANF_ERROR_NATIVE))
#define @ss_2:@ss_3:@ss_4:@ss_5:@ss_6:@ss_7:@ss_8:@ss_9:((SPECIFIER)))<<16)|(((_:(%9)) ((SSCANF_ERROR_SPECIFIER)))<<16)|(((_:(SSCANF_ERROR_SPECIFIER))
#define @ss_3:@ss_4:@ss_5:@ss_6:@ss_7:@ss_8:@ss_9:((INVALID)))<<16)|(((_:(%9)) ((SSCANF_ERROR_INVALID)))<<16)|(((_:(SSCANF_ERROR_INVALID))
#define @ss_4:@ss_5:@ss_6:@ss_7:@ss_8:@ss_9:((MISSING)))<<16)|(((_:(%9)) ((SSCANF_ERROR_MISSING)))<<16)|(((_:(SSCANF_ERROR_MISSING))
#define @ss_5:@ss_6:@ss_7:@ss_8:@ss_9:((EXCESS)))<<16)|(((_:(%9)) ((SSCANF_ERROR_EXCESS)))<<16)|(((_:(SSCANF_ERROR_EXCESS))
#define @ss_6:@ss_7:@ss_8:@ss_9:((COLOUR)))<<16)|(((_:(%9)) ((SSCANF_ERROR_COLOUR)))<<16)|(((_:(SSCANF_ERROR_COLOUR))
#define @ss_7:@ss_8:@ss_9:((OVERFLOW)))<<16)|(((_:(%9)) ((SSCANF_ERROR_OVERFLOW)))<<16)|(((_:(SSCANF_ERROR_OVERFLOW))
#define @ss_8:@ss_9:((NOT_FOUND)))<<16)|(((_:(%9)) ((SSCANF_ERROR_NOT_FOUND)))<<16)|(((_:(SSCANF_ERROR_NOT_FOUND))
#define @ss_9:((NO_ALTS)))<<16)|(((_:(%9)) ((SSCANF_ERROR_NO_ALTS)))<<16)|(((_:(SSCANF_ERROR_NO_ALTS))
// Consume spaces.
#define SSCANF_ERROR_%0\32 SSCANF_ERROR_
/**
* <library>sscanf</library>
* <param name="file">The file in which this call is found.</param>
* <param name="line">The line at which this call is found.</param>
* <param name="data">The input string containing the data to parse out.</param>
* <param name="format">The format description of what the input data should contain.</param>
* <remarks>
* The current true implementation of <c>sscanf</c> in the plugin. This is
* wrapped by macros to provide <c>sscanf</c> enhanced with filenames and line
* numbers so that errors have more information. The plugin also contains a
* native function called <c>sscanf</c> which is only for backwards-
* compatibility with older versions of this include.
* </remarks>
*/
/* */ native SSCANF__(const file[], const line, const data[], const format[], {T_WEAPON, Float, _}:...);
/**
* <library>sscanf</library>
* <param name="file">The file in which this call is found.</param>
* <param name="line">The line at which this call is found.</param>
* <param name="data">The input string containing the data to parse out.</param>
* <param name="format">The format description of what the input data should contain.</param>
* <remarks>
* An alternative name for <c>SSCANF__</c>, used by <c>extract</c> so that the
* name can be used as a macro.
* </remarks>
*/
/* */ native UNFORMAT__(const file[], const line, const data[], const format[], {T_WEAPON, Float, _}:...) = SSCANF__;
/**
* <library>sscanf</library>
* <param name="players">The maximum players on the server.</param>
* <param name="invalid">The invalid player ID.</param>
* <param name="len"><c>MAX_PLAYER_NAME</c>.</param>
* <remarks>
* Initialise the plugin with real server information.
* </remarks>
*/
/* */ native SSCANF_Init(players, invalid, len);
/**
* <library>sscanf</library>
* <param name="playerid">The ID of the player.</param>
* <param name="name">The name of the player.</param>
* <param name="npc">Is this player an NPC?</param>
* <remarks>
* Called when a player joins to inform the plugin of the connection.
* </remarks>
*/
/* */ native SSCANF_Join(playerid, const name[], bool:npc);
/**
* <library>sscanf</library>
* <param name="playerid">The ID of the player.</param>
* <remarks>
* Called when a player leaves to inform the plugin of the disconnection.
* </remarks>
*/
/* */ native SSCANF_Leave(playerid);
/**
* <library>sscanf</library>
* <param name="playerid">The ID of the player.</param>
* <remarks>
* Checks if the plugin knows about a given player ID. Used when modes restart
* to re-add players.
* </remarks>
*/
/* */ native bool:SSCANF_IsConnected(playerid);
/**
* <library>sscanf</library>
* <remarks>
* Gets the error code set by the most recent call to any other <b>sscanf</b>
* function. Calling this function does <b>not</b> clear the error, unlike some
* other implementations. To do that call <c>SSCANF_ClearLastError</c>.
* </remarks>
*/
native SSCANF_GetLastError();
/**
* <library>sscanf</library>
* <remarks>
* Gets the index of the specifier that generated the last error. When the
* error was in an alternate this will return the final underlying specifier
* that had an error, while <c>sscanf</c> itself will just return an index of
* <c>1</c> for "no matching alternative". This is the only place where the
* two may be different.
* </remarks>
*/
native SSCANF_GetErrorSpecifier();
/**
* <library>sscanf</library>
* <remarks>
* Resets the error code from any previous <b>sscanf</b> function call. Note
* that calling any other function also resets this value, but with more
* side-effects.
* </remarks>
*/
native SSCANF_ClearLastError();
/**
* <library>sscanf</library>
* <param name="error">The exact error code.</param>
* <remarks>
* There are almost 100 different unique error codes, but many of them can often
* be dealt with in the same way. For example - <em><b>1011</b> - An int was
* wanted, but the input didn't match</em> and <em><b>1012</b> - A number was
* wanted, but the input didn't match</em> can probably usually use the same
* result processing (especially since they can never be returned by the same
* specifier). Hence the errors are grouped together in to a few large groups
* for ease of processing.
* </remarks>
*/
native sscanf_error:SSCANF_GetErrorCategory(error);
/**
* <library>sscanf</library>
* <param name="string1">The first string to compare.</param>
* <param name="string2">The second string to compare.</param>
* <remarks>
* Computes the <a href="https://en.wikipedia.org/wiki/Levenshtein_distance">
* Levenshtein Distance</a> between two strings. This is simlar to
* <c>strcmp</c> in usage, but is slightly more "fuzzy". Distances are used to
* work out which string is the most similar to another one, though they may not
* be identical. Useful in <c>k</c> callback functions to determine if the
* entered string is close to a possible string.
* </remarks>
*/
native SSCANF_Levenshtein(const string1[], const string2[]);
/**
* <library>sscanf</library>
* <param name="string1">The first string to compare.</param>
* <param name="string2">The second string to compare.</param>
* <remarks>
* This works out the similarity between two strings. The Levenshtein distance
* often produces results that seem weird to people, for example by that measure
* <c>NRG</c> is closer to <c>TUG</c> than <c>NRG-500</c>. Instead this
* function compares all pairs of letters between the two strings to work out
* what percentage of each string is in the other string, then multiplies the
* results to get the final similarity. This algorithm produces much more human
* sane results, and can handle things like <c>ls police<c> matching
* <c>Police Car (LSPD)</c>. It ignores all punctuation and case as well.
* </remarks>
*/
native Float:SSCANF_TextSimilarity(const string1[], const string2[]);
/**
* <library>sscanf</library>
* <param name="name">The sscanf option to look up. For example <c>SSCANF_COLOUR_FORMS</c>.</param>
* <remarks>
* The old API used <c>SSCANF_Option</c> to both get and set parse options,
* with an optional parameter for setting. This was problematic if you wanted
* to actually set an option to the default value - there was no way to
* differentiate between getting an option and setting an option to the default
* value. Instead the new API has explicit <c>Get</c> and <c>Set</c> functions.
* </remarks>
*/
native SSCANF_GetOption(const name[]) = SSCANF_Option;
/**
* <library>sscanf</library>
* <param name="name">The sscanf option to look up. For example <c>MATCH_NAME_PARTIAL</c>.</param>
* <remarks>
* The old API used <c>SSCANF_Option</c> to both get and set parse options,
* with an optional parameter for setting. This was problematic if you wanted
* to actually set an option to the default value - there was no way to
* differentiate between getting an option and setting an option to the default
* value. Instead the new API uses true parameter counts to differentiate in
* the legacy <c>SSCANF_Option</c> function, which are resolved through macros
* to <c>Get__</c> and <c>Set__</c> functions.
* </remarks>
*/
/* */ native SSCANF_GetOption__(const name[]) = SSCANF_Option;
/**
* <library>sscanf</library>
* <param name="name">The sscanf option to set. For example <c>CELLMIN_ON_MATCHES</c>.</param>
* <param name="value">The value to set the option to.</param>
* <remarks>
* The old API used <c>SSCANF_Option</c> to both get and set parse options,
* with an optional parameter for setting. This was problematic if you wanted
* to actually set an option to the default value - there was no way to
* differentiate between getting an option and setting an option to the default
* value. Instead the new API has explicit <c>Get</c> and <c>Set</c> functions.
* </remarks>
*/
native SSCANF_SetOption(const name[], {_, Float}:value) = SSCANF_Option;
/**
* <library>sscanf</library>
* <param name="name">The sscanf option to set. For example <c>OLD_DEFAULT_CUSTOM</c>.</param>
* <param name="value">The value to set the option to.</param>
* <remarks>
* The old API used <c>SSCANF_Option</c> to both get and set parse options,
* with an optional parameter for setting. This was problematic if you wanted
* to actually set an option to the default value - there was no way to
* differentiate between getting an option and setting an option to the default
* value. Instead the new API uses true parameter counts to differentiate in
* the legacy <c>SSCANF_Option</c> function, which are resolved through macros
* to <c>Get__</c> and <c>Set__</c> functions.
* </remarks>
*/
/* */ native SSCANF_SetOption__(const name[], {_, Float}:value) = SSCANF_Option;
/**
* <library>sscanf</library>
* <param name="name">The sscanf option to get or set. For example <c>SSCANF_ARGB</c>.</param>
* <param name="value">The optional value to use when setting the option.</param>
* <remarks>
* Backwards-compatibility with <c>SSCANF_Option</c>. Usage:
*
* <code>
* SSCANF_Option(SSCANF_QUIET, 1); <br />
* new quiet = SSCANF_Option(SSCANF_QUIET);
* </code>
*
* This doesn't actually use a default parameter because a user may want to set
* the option to whatever that parameter is. Instead this is a macro that calls
* <c>SSCANF_GetOption__</c> when called with one parameter (just a name), or
* instead calls <c>SSCANF_SetOption__</c> when called with two - a name and a
* value.
* </remarks>
*/
forward SSCANF_Option(const name[], {_, Float}:value = -1);
#define SSCANF_Option SSCANF_GetOption__
#define SSCANF_GetOption__(%0,%1) SSCANF_SetOption__(%0,%1)
#define _ALS_SSCANF_Option
#define _ALS_SSCANF_GetOption__
/**
* <library>sscanf</library>
* <param name="version">Pass-by-reference return value.</param>
* <param name="size">The size of the destination array.</param>
* <remarks>
* Get the SSCANF plugin version as a string (e.g. <c>"2.11.2"</c>). Compare
* this value to the constant <c>SSCANF_VERSION_STRING</c>.
* </remarks>
*/
native SSCANF_VersionString(version[], size = sizeof (version)) = SSCANF_Version;
/**
* <library>sscanf</library>
* <param name="version">Pass-by-reference return value.</param>
* <param name="size">The size of the destination array.</param>
* <remarks>
* Get the SSCANF plugin version as a string (e.g. <c>"2.11.2"</c>). Compare
* this value to the constant <c>SSCANF_VERSION_STRING</c>. This internal
* alternate spelling is used by the <c>SSCANF_Version</c> macro, which will
* return a string when called with parameters, or a BCD value when not.
* </remarks>
*/
/* */ native SSCANF_VersionString__(version[], size = sizeof (version)) = SSCANF_Version;
/**
* <library>sscanf</library>
* <remarks>
* Get the SSCANF plugin version as a BCD-encoded value (e.g. <c>0x021102</c>).
* Compare this value to the constant <c>SSCANF_VERSION_BCD</c>.
* </remarks>
*/
native SSCANF_VersionBCD() = SSCANF_Version;
/**
* <library>sscanf</library>
* <remarks>
* Get the SSCANF plugin version as a BCD-encoded value (e.g. <c>0x021102</c>).
* Compare this value to the constant <c>SSCANF_VERSION_BCD</c>. This internal
* alternate spelling is used by the <c>SSCANF_Version</c> macro, which will
* return a string when called with parameters, or a BCD value when not.
* </remarks>
*/
/* */ native SSCANF_VersionBCD__() = SSCANF_Version;
// The `SSCANF_Version` function is overloaded to take 0 or 2 parameters (or 1 plus a default).
/**
* <library>sscanf</library>
* <param name="version">Pass-by-reference return value.</param>
* <param name="size">The size of the destination array.</param>
* <remarks>
* Get the SSCANF plugin version as a string (e.g. <c>"2.11.2"</c>) <em>or</em>
* a BCD-encoded value (e.g. <c>0x021102</c>). This function returns a string
* (by reference) when called with parameters, or a number (directly) when not.
* </remarks>
*/
static stock SSCANF_Version(version[] = "", size = sizeof (version))
{
return SSCANF_VERSION_BCD;
}
#define SSCANF_Version SSCANF_VersionString__
#define SSCANF_VersionString__() SSCANF_VersionBCD__()
#define _ALS_SSCANF_Version
#define _ALS_SSCANF_VersionString__
/**
* <library>sscanf</library>
* <param name="data">The input string containing the data to parse out.</param>
* <param name="format">The format description of what the input data should contain.</param>
* <remarks>
* The main entry point. See the readme for vast amounts of information on how
* to call this function and all the details on what it does. This is a macro
* that calls <c>SSCANF__</c> and passes the current file and line number as
* well for improved error messages.
* </remarks>
*/
#if __pawn_build > 4
// On old compilers, only issue the warning at the call site.
#pragma warning push
#pragma warning disable 234
#endif
#pragma deprecated - include <sscanf2> first.
forward sscanf(const data[], const format[], {T_WEAPON, Float, _}:...);
#if __pawn_build > 4
#pragma warning pop
#endif
// For pawno native detection.
/*
native sscanf(const data[], const format[], {T_WEAPON, Float, _}:...);
*/
#if __pawn_build > 4
#define sscanf( SSCANF__(__file,__line,
#else
// `-1` because the old compiler doesn't have `__line` so we can't know
// where this function was used. Tell the plugin this. Actually, we *can*
// know, if we look at the CIP and try extract the file/line information
// from any included debug information. `SSCANF_UNK_` tells the plugin that
// this was called via `sscanf` not `unformat`, because they're actually the
// same function once compiled.
#define sscanf( SSCANF__(SSCANF_UNK_,-1,
#endif
/**
* - include <sscanf2> first.
* <library>sscanf</library>
* <param name="data">The input string containing the data to parse out.</param>
* <param name="format">The format description of what the input data should contain.</param>
* <remarks>
* An alternative spelling of <c>sscanf</c>, requested by Kalcor because the
* original doesn't match the C specification for the format descriptor. This
* is a macro that calls <c>UNFORMAT__</c> and passes the current file and line
* number as well for improved error messages.
* </remarks>
*/
#if __pawn_build > 4
// On old compilers, only issue the warning at the call site.
#pragma warning push
#pragma warning disable 234
#endif
#pragma deprecated - include <sscanf2> first.
forward unformat(const data[], const format[], {T_WEAPON, Float, _}:...);
#if __pawn_build > 4
#pragma warning pop
#endif
// For pawno native detection.
/*
native unformat(const data[], const format[], {T_WEAPON, Float, _}:...);
*/
#if __pawn_build > 4
#define unformat( SSCANF__(__file,__line,
#else
// `-1` because the old compiler doesn't have `__line` so we can't know
// where this function was used. Tell the plugin this. Actually, we *can*
// know, if we look at the CIP and try extract the file/line information
// from any included debug information. `SSCANF_FOM_` tells the plugin that
// this was called via `unformat` not `sscanf`, because they're actually the
// same function once compiled.
#define unformat( SSCANF__(SSCANF_FOM_,-1,
#endif
/**
* <library>sscanf</library>
* <remarks>
* The fallback for the filename in <c>sscanf</c> on the old compiler, which
* doesn't have the inbuilt <c>__file</c> macro. This is the "feature" enabled
* by <c>SSCANF_NO_NICE_FEATURES</c>. Appends <c>"unknown file"</c> in the
* plugin when line number <c>< 0</c>.
* </remarks>
*/
stock const SSCANF_UNK_[] = "sscanf";
/**
* <library>sscanf</library>
* <remarks>
* The fallback for the filename in <c>unformat</c> on the old compiler, which
* doesn't have the inbuilt <c>__file</c> macro. This is the "feature" enabled
* by <c>SSCANF_NO_NICE_FEATURES</c>. Appends <c>"unknown file"</c> in the
* plugin when line number <c>< 0</c>.
* </remarks>
*/
stock const SSCANF_FOM_[] = "unformat";
/**
* <library>sscanf</library>
* <remarks>
* The fallback for the filename in <c>extract</c> on the old compiler, which
* doesn't have the inbuilt <c>__file</c> macro. This is the "feature" enabled
* by <c>SSCANF_NO_NICE_FEATURES</c>. Appends <c>"unknown file"</c> in the
* plugin when line number <c>< 0</c>.
* </remarks>
*/
stock const SSCANF_EXT_[] = "extract";
/**
* <library>sscanf</library>
* <remarks>
* The <c>SSCANF_QUIET</c> option as a constant string so you can get compile-
* time spell checking on the name. Don't print any errors to the console.
* <em>Really</em> not recommended unless you <em>know</em> your code is stable
* and in production.
* </remarks>
*/
stock const SSCANF_QUIET[] = "SSCANF_QUIET";
/**
* <library>sscanf</library>
* <remarks>
* The <c>OLD_DEFAULT_NAME</c> option as a constant string so you can get
* compile-time spell checking on the name. The behaviour of <c>U</c>, <c>Q</c>
* and <c>R</c> have been changed to take any number as a default, instead of a
* connected player. Setting <c>OLD_DEFAULT_NAME</c> to <c>1</c> will revert to
* the old version.
* </remarks>
*/
stock const OLD_DEFAULT_NAME[] = "OLD_DEFAULT_NAME";
/**
* <library>sscanf</library>
* <remarks>
* The <c>MATCH_NAME_PARTIAL</c> option as a constant string so you can get
* compile-time spell checking on the name. Currently sscanf will search for
* players by name, and will <em>always</em> search for player whose name
* <em>starts</em> with the specified string. If someone types <c>Y_Less</c>,
* sscanf will not find say <c>[CLAN]Y_Less</c> because there name doesn't start
* with the specified text. This option, when set to <c>1</c>, will search
* <em>anywhere</em> in the player's name for the given string.
* </remarks>
*/
stock const MATCH_NAME_PARTIAL[] = "MATCH_NAME_PARTIAL";
/**
* <library>sscanf</library>
* <remarks>
* The <c>CELLMIN_ON_MATCHES</c> option as a constant string so you can get
* compile-time spell checking on the name. Whatever the value of
* <c>MATCH_NAME_PARTIAL</c>, the first found player will always be returned,
* so if you do a search for <c>_</c> on an RP server, you could get almost
* anyone. To detect this case, if more than one player will match the
* specified string then <em>sscanf</em> will return an ID of <c>cellmin</c>
* instead. This can be combined with <c>U</c> for a lot more power:
*
* <code>
* sscanf(params, "?<CELLMIN_ON_MATCHES=1>U(-1)", id); <br />
* if (id == -1) <br />
* { <br /><indent />
* // No player was entered. <br />
* } <br />
* else if (id == cellmin) <br />
* { <br /><indent />
* // Multiple matches found <br />
* } <br />
* else if (id == INVALID_PLAYER_ID) <br />
* { <br /><indent />
* // Entered player is not connected. <br />
* } <br />
* else <br />
* { <br /><indent />
* // Found just one player. <br />
* }
* </code>
* </remarks>
*/
stock const CELLMIN_ON_MATCHES[] = "CELLMIN_ON_MATCHES";
/**
* <library>sscanf</library>
* <remarks>
* The <c>OLD_DEFAULT_KUSTOM</c> option as a constant string so you can get
* compile-time spell checking on the name. As with <c>U</c>, <c>K</c> used to
* require a valid identifier as the default and would parse it using the
* specified callback, so this would <em>not</em> work:
*
* <code>
* K<vehicle>(Veyron)
* </code>
*
* Because that is not a valid vehicle name in GTA. The new version now just
* takes a number and returns that regardless:
*
* <code>
* K<vehicle>(999)
* </code>
*
* This setting reverts to the old behaviour.
* </remarks>
*/
stock const OLD_DEFAULT_KUSTOM[] = "OLD_DEFAULT_KUSTOM";
/**
* <library>sscanf</library>
* <remarks>
* The <c>OLD_DEFAULT_CUSTOM</c> option as a constant string so you can get
* compile-time spell checking on the name. This is the same as
* <c>OLD_DEFAULT_KUSTOM</c>, but with an alternate spelling.
* </remarks>
*/
stock const OLD_DEFAULT_CUSTOM[] = "OLD_DEFAULT_CUSTOM";
/**
* <library>sscanf</library>
* <remarks>
* The <c>SSCANF_COLOUR_FORMS</c> option as a constant string so you can get
* compile-time spell checking on the name. There are multiple valid colour
* input formats, which you can enable or disable here. The parameter is a
* bit map (flags) for all the following values:
*
* <ul>
* <li><c>1</c> - <c>#RGB</c></li>
* <li><c>2</c> - <c>#RRGGBB</c></li>
* <li><c>4</c> - <c>0xRRGGBB</c></li>
* <li><c>8</c> - <c>RRGGBB</c></li>
* <li><c>16</c> - <c>{RRGGBB}</c></li>
* <li><c>32</c> - <c>0xRRGGBBAA</c></li>
* <li><c>64</c> - <c>RRGGBBAA</c></li>
* </ul>
*
* So to ONLY accept SA:MP `SendClientMessage` colours use:
*
* <code>
* SSCANF_Option(SSCANF_COLOUR_FORMS, 16);
* </code>
*
* To only accept 8-digit values use:
*
* <code>
* SSCANF_Option(SSCANF_COLOUR_FORMS, 96);
* </code>
*
* Default values (those specified between <c>()</c>s for <c>M</c>) ignore this
* setting - they can always use any form.
* </remarks>
*/
stock const SSCANF_COLOUR_FORMS[] = "SSCANF_COLOUR_FORMS";
/**
* <library>sscanf</library>
* <remarks>
* The <c>SSCANF_ALPHA</c> option as a constant string so you can get compile-
* time spell checking on the name. Specify the default alpha value for colours
* (<c>m</c>) which don't manually specify an alpha channel. The alpha values
* are specified as a <em>decimal</em> number, <em>not</em> a <em>hex</em>
* number, so setting an alpha of <c>0x80</c> would be:
*
* <code>
* SSCANF_Option(SSCANF_ALPHA, 128);
* </code>
* </remarks>
*/
stock const SSCANF_ALPHA[] = "SSCANF_ALPHA";
/**
* <library>sscanf</library>
* <remarks>
* The <c>SSCANF_ARGB</c> option as a constant string so you can get compile-
* time spell checking on the name. Specify whether the returned colour is
* <c>ARGB</c> or <c>RGBA</c>:
*
* <code>
* SSCANF_Option(SSCANF_ARGB, 1); // Set 3- and 6-digit colour outputs to `AARRGGBB`. <br />
* SSCANF_Option(SSCANF_ARGB, 0); // Set 3- and 6-digit colour outputs to `RRGGBBAA` (default).
* </code>
* </remarks>
*/
stock const SSCANF_ARGB[] = "SSCANF_ARGB";
/**
* <library>sscanf</library>
* <remarks>
* The <c>MATCH_NAME_FIRST</c> option as a constant string so you can get compile-
* time spell checking on the name. Specify whether <c>u</c> etc keep searching
* for better matching player names after finding one:
*
* <code>
* SSCANF_Option(MATCH_NAME_FIRST, 0); // Enable scanning for the best name match not the first (default). <br />
* SSCANF_Option(MATCH_NAME_FIRST, 1); // Enable scanning for the first name match not the best (old behaviour).
* </code>
* </remarks>
*/
stock const MATCH_NAME_FIRST[] = "MATCH_NAME_FIRST";
/**
* <library>sscanf</library>
* <remarks>
* The <c>MATCH_NAME_SIMILARITY</c> option as a constant string so you can get
* compile-time spell checking on the name. Specify whether <c>u</c> etc should
* use the ngrams-based similarity algorithm when searching for players matching
* a given name. I.e. enable or disable fuzzy name matching. It will return
* the best match found, but depending on the threshold that may still be very
* different to what was typed.
*
* <code>
* SSCANF_Option(MATCH_NAME_SIMILARITY, 0.0); // Will find all names, regardless of input. <br />
* SSCANF_Option(MATCH_NAME_SIMILARITY, 1.0); // Will find exact matches only. <br />
* SSCANF_Option(MATCH_NAME_SIMILARITY, 0.5); // Will find names somewhat similar to the input. <br />
* SSCANF_Option(MATCH_NAME_SIMILARITY, -1.0); // Disable fuzzy name matching.
* </code>
* </remarks>
*/
stock const MATCH_NAME_SIMILARITY[] = "MATCH_NAME_SIMILARITY";
/**
* <library>sscanf</library>
* <remarks>
* The <c>ERROR_CODE_IN_RET</c> option as a constant string so you can get
* compile-time spell checking on the name. The return value from <c>sscanf</c>
* is <c>0</c> for no error, or the index of the specifier that failed. If you
* get a failure you can call <c>SSCANF_GetLastError</c> to get the exact error
* code, or you can set this option to <c>true</c> to have the return value also
* include this error value in the return, ORed with the index.
* </remarks>
*
* <code>
* SSCANF_Option(ERROR_CODE_IN_RET, 1); // Failures return `spec | code << 16`.<br />
* SSCANF_Option(ERROR_CODE_IN_RET, 0); // Failures return only the bad specifier index.
* </code>
*/
stock const ERROR_CODE_IN_RET[] = "ERROR_CODE_IN_RET";
/**
* <library>sscanf</library>
* <remarks>
* The <c>WARNINGS_AS_ERRORS</c> option as a constant string so you can get
* compile-time spell checking on the name. This setting allows <c>sscanf</c>
* to fail when a warning is given, as well as an error.
*
* <code>
* SSCANF_Option(WARNINGS_AS_ERRORS, 1); // Warnings will cause `sscanf` to fail.<br />
* SSCANF_Option(WARNINGS_AS_ERRORS, 0); // Warnings will not fail `sscanf` function calls.
* </code>
* </remarks>
*/
stock const WARNINGS_AS_ERRORS[] = "WARNINGS_AS_ERRORS";
/**
* <library>sscanf</library>
* <remarks>
* The <c>ERROR_CATEGORY_ONLY</c> option as a constant string so you can get
* compile-time spell checking on the name. When <c>ERROR_CODE_IN_RET</c> is
* enabled returns the error category instead of the exact error code.
*
* <code>
* SSCANF_Option(ERROR_CATEGORY_ONLY, 1); // `sscanf` failures will return `sscanf_error:`<br />
* SSCANF_Option(ERROR_CATEGORY_ONLY, 0); // `sscanf` failures will return the exact error.
* </code>
* </remarks>