@@ -1864,13 +1864,20 @@ CpcVm.prototype = {
1864
1864
} ,
1865
1865
1866
1866
instr : function ( p1 , p2 , p3 ) { // optional startpos as first parameter
1867
- this . vmAssertString ( p2 , "INSTR" ) ;
1868
- if ( typeof p1 === "string" ) { // p1=string, p2=search string
1869
- return p1 . indexOf ( p2 ) + 1 ;
1867
+ var startPos = typeof p1 === "number" ? this . vmInRangeRound ( p1 , 1 , 255 , "INSTR" ) - 1 : 0 , // p1=startpos
1868
+ str = typeof p1 === "number" ? p2 : p1 ,
1869
+ search = typeof p1 === "number" ? p3 : p2 ;
1870
+
1871
+ this . vmAssertString ( str , "INSTR" ) ;
1872
+ this . vmAssertString ( search , "INSTR" ) ;
1873
+
1874
+ if ( startPos >= str . length ) {
1875
+ return 0 ; // not found
1876
+ }
1877
+ if ( ! search . length ) {
1878
+ return startPos + 1 ;
1870
1879
}
1871
- p1 = this . vmInRangeRound ( p1 , 1 , 255 , "INSTR" ) ; // p1=startpos
1872
- this . vmAssertString ( p3 , "INSTR" ) ;
1873
- return p2 . indexOf ( p3 , p1 - 1 ) + 1 ; // p2=string, p3=search string
1880
+ return str . indexOf ( search , startPos ) + 1 ;
1874
1881
} ,
1875
1882
1876
1883
"int" : function ( n ) {
@@ -3104,11 +3111,19 @@ CpcVm.prototype = {
3104
3111
} ,
3105
3112
3106
3113
round : function ( n , iDecimals ) {
3114
+ var iMaxDecimals = 20 - Math . floor ( Math . log10 ( n ) ) ; // limit for JS
3115
+
3107
3116
this . vmAssertNumber ( n , "ROUND" ) ;
3108
3117
iDecimals = this . vmInRangeRound ( iDecimals || 0 , - 39 , 39 , "ROUND" ) ;
3109
3118
3119
+ if ( iDecimals >= 0 && iDecimals > iMaxDecimals ) {
3120
+ iDecimals = iMaxDecimals ;
3121
+ }
3122
+
3110
3123
// To avoid rounding errors: https://www.jacklmoore.com/notes/rounding-in-javascript
3111
- return Number ( Math . round ( Number ( n + "e" + iDecimals ) ) + "e" + ( ( iDecimals >= 0 ) ? "-" + iDecimals : "+" + - iDecimals ) ) ;
3124
+ // Use Math.abs(n) and Math.sign(n) To round negative numbers to larger negative numbers
3125
+ return Math . sign ( n ) * Number ( Math . round ( Number ( Math . abs ( n ) + "e" + iDecimals ) ) + "e" + ( ( iDecimals >= 0 ) ? "-" + iDecimals : "+" + - iDecimals ) ) ;
3126
+ //return Number(Math.round(Number(n + "e" + iDecimals)) + "e" + ((iDecimals >= 0) ? "-" + iDecimals : "+" + -iDecimals));
3112
3127
} ,
3113
3128
3114
3129
vmRunCallback : function ( sInput , oMeta ) {
@@ -3470,22 +3485,44 @@ CpcVm.prototype = {
3470
3485
} ,
3471
3486
3472
3487
using : function ( sFormat ) { // varargs
3473
- var reFormat = / ( ! | & | \\ * \\ | (?: \* \* | \$ \$ | \* \* \$ ) ? \+ ? (?: # | , ) + \. ? # * (?: \^ \^ \^ \^ ) ? [ + - ] ? ) / g,
3488
+ var reFormat = / ( _ | ! | & | \\ * \\ | (?: \* \* | \$ \$ | \* \* \$ ) ? \+ ? (?: # | , ) + \. ? # * (?: \^ \^ \^ \^ ) ? [ + - ] ? ) / g,
3474
3489
s = "" ,
3475
3490
aFormat = [ ] ,
3476
- iIndex , oMatch , sFrmt , iFormat , i , arg ;
3491
+ iIndex , aMatch , sFrmt , iFormat , i , arg , nonFormChars , nonFormCharsEnd ;
3477
3492
3478
3493
this . vmAssertString ( sFormat , "USING" ) ;
3479
3494
3480
3495
// We simulate sFormat.split(reFormat) here since it does not work with IE8
3481
3496
iIndex = 0 ;
3482
- while ( ( oMatch = reFormat . exec ( sFormat ) ) !== null ) {
3483
- aFormat . push ( sFormat . substring ( iIndex , oMatch . index ) ) ; // non-format characters at the beginning
3484
- aFormat . push ( oMatch [ 0 ] ) ;
3485
- iIndex = oMatch . index + oMatch [ 0 ] . length ;
3497
+ while ( ( aMatch = reFormat . exec ( sFormat ) ) !== null ) {
3498
+ nonFormChars = sFormat . substring ( iIndex , aMatch . index ) ; // non-format characters at the beginning
3499
+
3500
+ if ( aMatch [ 0 ] === "_" ) { // underscore "_" is escape character
3501
+ nonFormChars += sFormat . charAt ( aMatch . index + 1 ) || "_" ; // add escaped character
3502
+ }
3503
+
3504
+ if ( aFormat . length % 2 ) { // odd?
3505
+ aFormat [ aFormat . length - 1 ] += nonFormChars ;
3506
+ } else {
3507
+ aFormat . push ( nonFormChars ) ;
3508
+ }
3509
+
3510
+ if ( aMatch [ 0 ] === "_" ) { // underscore "_" is escape character
3511
+ reFormat . lastIndex += 1 ;
3512
+ iIndex = reFormat . lastIndex ;
3513
+ } else {
3514
+ aFormat . push ( aMatch [ 0 ] ) ;
3515
+ iIndex = aMatch . index + aMatch [ 0 ] . length ;
3516
+ }
3486
3517
}
3487
3518
if ( iIndex < sFormat . length ) { // non-format characters at the end
3488
- aFormat . push ( sFormat . substr ( iIndex ) ) ;
3519
+ nonFormCharsEnd = sFormat . substring ( iIndex ) ;
3520
+
3521
+ if ( aFormat . length % 2 ) { // odd?
3522
+ aFormat [ aFormat . length - 1 ] += nonFormCharsEnd ;
3523
+ } else {
3524
+ aFormat . push ( nonFormCharsEnd ) ;
3525
+ }
3489
3526
}
3490
3527
3491
3528
if ( aFormat . length < 2 ) {
0 commit comments