Fossil SCM
Fix various corner cases for the TH1 'string first' and 'string last' sub-commands.
Commit
f61958b183db741bec27ffffcad25acb44856bed
Parent
dd8d3176703278d…
2 files changed
+20
-18
+90
+20
-18
| --- src/th_lang.c | ||
| +++ src/th_lang.c | ||
| @@ -650,30 +650,31 @@ | ||
| 650 | 650 | ** string first NEEDLE HAYSTACK |
| 651 | 651 | */ |
| 652 | 652 | static int string_first_command( |
| 653 | 653 | Th_Interp *interp, void *ctx, int argc, const char **argv, int *argl |
| 654 | 654 | ){ |
| 655 | - const char *zNeedle; | |
| 656 | 655 | int nNeedle; |
| 657 | - const char *zHaystack; | |
| 658 | 656 | int nHaystack; |
| 659 | - int i; | |
| 660 | 657 | int iRes = -1; |
| 661 | 658 | |
| 662 | 659 | if( argc!=4 ){ |
| 663 | 660 | return Th_WrongNumArgs(interp, "string first needle haystack"); |
| 664 | 661 | } |
| 665 | 662 | |
| 666 | - zNeedle = argv[2]; | |
| 667 | 663 | nNeedle = argl[2]; |
| 668 | - zHaystack = argv[3]; | |
| 669 | 664 | nHaystack = argl[3]; |
| 670 | 665 | |
| 671 | - for(i=0; i<(nHaystack-nNeedle); i++){ | |
| 672 | - if( 0==memcmp(zNeedle, &zHaystack[i], nNeedle) ){ | |
| 673 | - iRes = i; | |
| 674 | - break; | |
| 666 | + if( nNeedle && nHaystack && nNeedle<=nHaystack ){ | |
| 667 | + const char *zNeedle = argv[2]; | |
| 668 | + const char *zHaystack = argv[3]; | |
| 669 | + int i; | |
| 670 | + | |
| 671 | + for(i=0; i<=(nHaystack-nNeedle); i++){ | |
| 672 | + if( 0==memcmp(zNeedle, &zHaystack[i], nNeedle) ){ | |
| 673 | + iRes = i; | |
| 674 | + break; | |
| 675 | + } | |
| 675 | 676 | } |
| 676 | 677 | } |
| 677 | 678 | |
| 678 | 679 | return Th_SetResultInt(interp, iRes); |
| 679 | 680 | } |
| @@ -711,30 +712,31 @@ | ||
| 711 | 712 | ** string last NEEDLE HAYSTACK |
| 712 | 713 | */ |
| 713 | 714 | static int string_last_command( |
| 714 | 715 | Th_Interp *interp, void *ctx, int argc, const char **argv, int *argl |
| 715 | 716 | ){ |
| 716 | - const char *zNeedle; | |
| 717 | 717 | int nNeedle; |
| 718 | - const char *zHaystack; | |
| 719 | 718 | int nHaystack; |
| 720 | - int i; | |
| 721 | 719 | int iRes = -1; |
| 722 | 720 | |
| 723 | 721 | if( argc!=4 ){ |
| 724 | 722 | return Th_WrongNumArgs(interp, "string last needle haystack"); |
| 725 | 723 | } |
| 726 | 724 | |
| 727 | - zNeedle = argv[2]; | |
| 728 | 725 | nNeedle = argl[2]; |
| 729 | - zHaystack = argv[3]; | |
| 730 | 726 | nHaystack = argl[3]; |
| 731 | 727 | |
| 732 | - for(i=nHaystack-nNeedle-1; i>=0; i--){ | |
| 733 | - if( 0==memcmp(zNeedle, &zHaystack[i], nNeedle) ){ | |
| 734 | - iRes = i; | |
| 735 | - break; | |
| 728 | + if( nNeedle && nHaystack && nNeedle<=nHaystack ){ | |
| 729 | + const char *zNeedle = argv[2]; | |
| 730 | + const char *zHaystack = argv[3]; | |
| 731 | + int i; | |
| 732 | + | |
| 733 | + for(i=nHaystack-nNeedle; i>=0; i--){ | |
| 734 | + if( 0==memcmp(zNeedle, &zHaystack[i], nNeedle) ){ | |
| 735 | + iRes = i; | |
| 736 | + break; | |
| 737 | + } | |
| 736 | 738 | } |
| 737 | 739 | } |
| 738 | 740 | |
| 739 | 741 | return Th_SetResultInt(interp, iRes); |
| 740 | 742 | } |
| 741 | 743 |
| --- src/th_lang.c | |
| +++ src/th_lang.c | |
| @@ -650,30 +650,31 @@ | |
| 650 | ** string first NEEDLE HAYSTACK |
| 651 | */ |
| 652 | static int string_first_command( |
| 653 | Th_Interp *interp, void *ctx, int argc, const char **argv, int *argl |
| 654 | ){ |
| 655 | const char *zNeedle; |
| 656 | int nNeedle; |
| 657 | const char *zHaystack; |
| 658 | int nHaystack; |
| 659 | int i; |
| 660 | int iRes = -1; |
| 661 | |
| 662 | if( argc!=4 ){ |
| 663 | return Th_WrongNumArgs(interp, "string first needle haystack"); |
| 664 | } |
| 665 | |
| 666 | zNeedle = argv[2]; |
| 667 | nNeedle = argl[2]; |
| 668 | zHaystack = argv[3]; |
| 669 | nHaystack = argl[3]; |
| 670 | |
| 671 | for(i=0; i<(nHaystack-nNeedle); i++){ |
| 672 | if( 0==memcmp(zNeedle, &zHaystack[i], nNeedle) ){ |
| 673 | iRes = i; |
| 674 | break; |
| 675 | } |
| 676 | } |
| 677 | |
| 678 | return Th_SetResultInt(interp, iRes); |
| 679 | } |
| @@ -711,30 +712,31 @@ | |
| 711 | ** string last NEEDLE HAYSTACK |
| 712 | */ |
| 713 | static int string_last_command( |
| 714 | Th_Interp *interp, void *ctx, int argc, const char **argv, int *argl |
| 715 | ){ |
| 716 | const char *zNeedle; |
| 717 | int nNeedle; |
| 718 | const char *zHaystack; |
| 719 | int nHaystack; |
| 720 | int i; |
| 721 | int iRes = -1; |
| 722 | |
| 723 | if( argc!=4 ){ |
| 724 | return Th_WrongNumArgs(interp, "string last needle haystack"); |
| 725 | } |
| 726 | |
| 727 | zNeedle = argv[2]; |
| 728 | nNeedle = argl[2]; |
| 729 | zHaystack = argv[3]; |
| 730 | nHaystack = argl[3]; |
| 731 | |
| 732 | for(i=nHaystack-nNeedle-1; i>=0; i--){ |
| 733 | if( 0==memcmp(zNeedle, &zHaystack[i], nNeedle) ){ |
| 734 | iRes = i; |
| 735 | break; |
| 736 | } |
| 737 | } |
| 738 | |
| 739 | return Th_SetResultInt(interp, iRes); |
| 740 | } |
| 741 |
| --- src/th_lang.c | |
| +++ src/th_lang.c | |
| @@ -650,30 +650,31 @@ | |
| 650 | ** string first NEEDLE HAYSTACK |
| 651 | */ |
| 652 | static int string_first_command( |
| 653 | Th_Interp *interp, void *ctx, int argc, const char **argv, int *argl |
| 654 | ){ |
| 655 | int nNeedle; |
| 656 | int nHaystack; |
| 657 | int iRes = -1; |
| 658 | |
| 659 | if( argc!=4 ){ |
| 660 | return Th_WrongNumArgs(interp, "string first needle haystack"); |
| 661 | } |
| 662 | |
| 663 | nNeedle = argl[2]; |
| 664 | nHaystack = argl[3]; |
| 665 | |
| 666 | if( nNeedle && nHaystack && nNeedle<=nHaystack ){ |
| 667 | const char *zNeedle = argv[2]; |
| 668 | const char *zHaystack = argv[3]; |
| 669 | int i; |
| 670 | |
| 671 | for(i=0; i<=(nHaystack-nNeedle); i++){ |
| 672 | if( 0==memcmp(zNeedle, &zHaystack[i], nNeedle) ){ |
| 673 | iRes = i; |
| 674 | break; |
| 675 | } |
| 676 | } |
| 677 | } |
| 678 | |
| 679 | return Th_SetResultInt(interp, iRes); |
| 680 | } |
| @@ -711,30 +712,31 @@ | |
| 712 | ** string last NEEDLE HAYSTACK |
| 713 | */ |
| 714 | static int string_last_command( |
| 715 | Th_Interp *interp, void *ctx, int argc, const char **argv, int *argl |
| 716 | ){ |
| 717 | int nNeedle; |
| 718 | int nHaystack; |
| 719 | int iRes = -1; |
| 720 | |
| 721 | if( argc!=4 ){ |
| 722 | return Th_WrongNumArgs(interp, "string last needle haystack"); |
| 723 | } |
| 724 | |
| 725 | nNeedle = argl[2]; |
| 726 | nHaystack = argl[3]; |
| 727 | |
| 728 | if( nNeedle && nHaystack && nNeedle<=nHaystack ){ |
| 729 | const char *zNeedle = argv[2]; |
| 730 | const char *zHaystack = argv[3]; |
| 731 | int i; |
| 732 | |
| 733 | for(i=nHaystack-nNeedle; i>=0; i--){ |
| 734 | if( 0==memcmp(zNeedle, &zHaystack[i], nNeedle) ){ |
| 735 | iRes = i; |
| 736 | break; |
| 737 | } |
| 738 | } |
| 739 | } |
| 740 | |
| 741 | return Th_SetResultInt(interp, iRes); |
| 742 | } |
| 743 |
+90
| --- test/th1.test | ||
| +++ test/th1.test | ||
| @@ -207,5 +207,95 @@ | ||
| 207 | 207 | |
| 208 | 208 | ############################################################################### |
| 209 | 209 | |
| 210 | 210 | fossil test-th-eval "set gv(1) 1; upvar 0 gv(1) gv2; unset gv(1); unset gv2" |
| 211 | 211 | test th1-unset-8 {$RESULT eq {TH_ERROR: no such variable: gv2}} |
| 212 | + | |
| 213 | +############################################################################### | |
| 214 | + | |
| 215 | +fossil test-th-eval "string first {} {}" | |
| 216 | +test th1-string-first-1 {$RESULT eq {-1}} | |
| 217 | + | |
| 218 | +############################################################################### | |
| 219 | + | |
| 220 | +fossil test-th-eval "string first {} {a}" | |
| 221 | +test th1-string-first-2 {$RESULT eq {-1}} | |
| 222 | + | |
| 223 | +############################################################################### | |
| 224 | + | |
| 225 | +fossil test-th-eval "string first {a} {}" | |
| 226 | +test th1-string-first-3 {$RESULT eq {-1}} | |
| 227 | + | |
| 228 | +############################################################################### | |
| 229 | + | |
| 230 | +fossil test-th-eval "string first {a} {a}" | |
| 231 | +test th1-string-first-4 {$RESULT eq {0}} | |
| 232 | + | |
| 233 | +############################################################################### | |
| 234 | + | |
| 235 | +fossil test-th-eval "string first {a} {aa}" | |
| 236 | +test th1-string-first-5 {$RESULT eq {0}} | |
| 237 | + | |
| 238 | +############################################################################### | |
| 239 | + | |
| 240 | +fossil test-th-eval "string first {aa} {a}" | |
| 241 | +test th1-string-first-6 {$RESULT eq {-1}} | |
| 242 | + | |
| 243 | +############################################################################### | |
| 244 | + | |
| 245 | +fossil test-th-eval "string first {ab} {abc}" | |
| 246 | +test th1-string-first-7 {$RESULT eq {0}} | |
| 247 | + | |
| 248 | +############################################################################### | |
| 249 | + | |
| 250 | +fossil test-th-eval "string first {bc} {abc}" | |
| 251 | +test th1-string-first-8 {$RESULT eq {1}} | |
| 252 | + | |
| 253 | +############################################################################### | |
| 254 | + | |
| 255 | +fossil test-th-eval "string first {AB} {abc}" | |
| 256 | +test th1-string-first-9 {$RESULT eq {-1}} | |
| 257 | + | |
| 258 | +############################################################################### | |
| 259 | + | |
| 260 | +fossil test-th-eval "string last {} {}" | |
| 261 | +test th1-string-last-1 {$RESULT eq {-1}} | |
| 262 | + | |
| 263 | +############################################################################### | |
| 264 | + | |
| 265 | +fossil test-th-eval "string last {} {a}" | |
| 266 | +test th1-string-last-2 {$RESULT eq {-1}} | |
| 267 | + | |
| 268 | +############################################################################### | |
| 269 | + | |
| 270 | +fossil test-th-eval "string last {a} {}" | |
| 271 | +test th1-string-last-3 {$RESULT eq {-1}} | |
| 272 | + | |
| 273 | +############################################################################### | |
| 274 | + | |
| 275 | +fossil test-th-eval "string last {a} {a}" | |
| 276 | +test th1-string-last-4 {$RESULT eq {0}} | |
| 277 | + | |
| 278 | +############################################################################### | |
| 279 | + | |
| 280 | +fossil test-th-eval "string last {a} {aa}" | |
| 281 | +test th1-string-last-5 {$RESULT eq {1}} | |
| 282 | + | |
| 283 | +############################################################################### | |
| 284 | + | |
| 285 | +fossil test-th-eval "string last {aa} {a}" | |
| 286 | +test th1-string-last-6 {$RESULT eq {-1}} | |
| 287 | + | |
| 288 | +############################################################################### | |
| 289 | + | |
| 290 | +fossil test-th-eval "string last {ab} {abc}" | |
| 291 | +test th1-string-last-7 {$RESULT eq {0}} | |
| 292 | + | |
| 293 | +############################################################################### | |
| 294 | + | |
| 295 | +fossil test-th-eval "string last {bc} {abc}" | |
| 296 | +test th1-string-last-8 {$RESULT eq {1}} | |
| 297 | + | |
| 298 | +############################################################################### | |
| 299 | + | |
| 300 | +fossil test-th-eval "string last {AB} {abc}" | |
| 301 | +test th1-string-last-9 {$RESULT eq {-1}} | |
| 212 | 302 |
| --- test/th1.test | |
| +++ test/th1.test | |
| @@ -207,5 +207,95 @@ | |
| 207 | |
| 208 | ############################################################################### |
| 209 | |
| 210 | fossil test-th-eval "set gv(1) 1; upvar 0 gv(1) gv2; unset gv(1); unset gv2" |
| 211 | test th1-unset-8 {$RESULT eq {TH_ERROR: no such variable: gv2}} |
| 212 |
| --- test/th1.test | |
| +++ test/th1.test | |
| @@ -207,5 +207,95 @@ | |
| 207 | |
| 208 | ############################################################################### |
| 209 | |
| 210 | fossil test-th-eval "set gv(1) 1; upvar 0 gv(1) gv2; unset gv(1); unset gv2" |
| 211 | test th1-unset-8 {$RESULT eq {TH_ERROR: no such variable: gv2}} |
| 212 | |
| 213 | ############################################################################### |
| 214 | |
| 215 | fossil test-th-eval "string first {} {}" |
| 216 | test th1-string-first-1 {$RESULT eq {-1}} |
| 217 | |
| 218 | ############################################################################### |
| 219 | |
| 220 | fossil test-th-eval "string first {} {a}" |
| 221 | test th1-string-first-2 {$RESULT eq {-1}} |
| 222 | |
| 223 | ############################################################################### |
| 224 | |
| 225 | fossil test-th-eval "string first {a} {}" |
| 226 | test th1-string-first-3 {$RESULT eq {-1}} |
| 227 | |
| 228 | ############################################################################### |
| 229 | |
| 230 | fossil test-th-eval "string first {a} {a}" |
| 231 | test th1-string-first-4 {$RESULT eq {0}} |
| 232 | |
| 233 | ############################################################################### |
| 234 | |
| 235 | fossil test-th-eval "string first {a} {aa}" |
| 236 | test th1-string-first-5 {$RESULT eq {0}} |
| 237 | |
| 238 | ############################################################################### |
| 239 | |
| 240 | fossil test-th-eval "string first {aa} {a}" |
| 241 | test th1-string-first-6 {$RESULT eq {-1}} |
| 242 | |
| 243 | ############################################################################### |
| 244 | |
| 245 | fossil test-th-eval "string first {ab} {abc}" |
| 246 | test th1-string-first-7 {$RESULT eq {0}} |
| 247 | |
| 248 | ############################################################################### |
| 249 | |
| 250 | fossil test-th-eval "string first {bc} {abc}" |
| 251 | test th1-string-first-8 {$RESULT eq {1}} |
| 252 | |
| 253 | ############################################################################### |
| 254 | |
| 255 | fossil test-th-eval "string first {AB} {abc}" |
| 256 | test th1-string-first-9 {$RESULT eq {-1}} |
| 257 | |
| 258 | ############################################################################### |
| 259 | |
| 260 | fossil test-th-eval "string last {} {}" |
| 261 | test th1-string-last-1 {$RESULT eq {-1}} |
| 262 | |
| 263 | ############################################################################### |
| 264 | |
| 265 | fossil test-th-eval "string last {} {a}" |
| 266 | test th1-string-last-2 {$RESULT eq {-1}} |
| 267 | |
| 268 | ############################################################################### |
| 269 | |
| 270 | fossil test-th-eval "string last {a} {}" |
| 271 | test th1-string-last-3 {$RESULT eq {-1}} |
| 272 | |
| 273 | ############################################################################### |
| 274 | |
| 275 | fossil test-th-eval "string last {a} {a}" |
| 276 | test th1-string-last-4 {$RESULT eq {0}} |
| 277 | |
| 278 | ############################################################################### |
| 279 | |
| 280 | fossil test-th-eval "string last {a} {aa}" |
| 281 | test th1-string-last-5 {$RESULT eq {1}} |
| 282 | |
| 283 | ############################################################################### |
| 284 | |
| 285 | fossil test-th-eval "string last {aa} {a}" |
| 286 | test th1-string-last-6 {$RESULT eq {-1}} |
| 287 | |
| 288 | ############################################################################### |
| 289 | |
| 290 | fossil test-th-eval "string last {ab} {abc}" |
| 291 | test th1-string-last-7 {$RESULT eq {0}} |
| 292 | |
| 293 | ############################################################################### |
| 294 | |
| 295 | fossil test-th-eval "string last {bc} {abc}" |
| 296 | test th1-string-last-8 {$RESULT eq {1}} |
| 297 | |
| 298 | ############################################################################### |
| 299 | |
| 300 | fossil test-th-eval "string last {AB} {abc}" |
| 301 | test th1-string-last-9 {$RESULT eq {-1}} |
| 302 |