| Anonymous | Login | Signup for a new account | 02-09-2010 14:31 UTC |
| Main | My View | View Issues | Change Log | Docs |
| Viewing Issue Simple Details [ Jump to Notes ] | [ View Advanced ] [ Issue History ] [ Print ] | ||||||||||||
| ID | Category | Severity | Reproducibility | Date Submitted | Last Update | ||||||||
| 0005331 | [Squeak] Collections | major | always | 10-31-06 03:47 | 10-03-09 19:59 | ||||||||
| Reporter | johnmci | View Status | public | ||||||||||
| Assigned To | andreas | ||||||||||||
| Priority | normal | Resolution | fixed | ||||||||||
| Status | resolved | Product Version | 3.9 | ||||||||||
| Summary | 0005331: 'abc' beginsWith: 'ab' asWideString (returns wrong result) | ||||||||||||
| Description |
Given 'abc' match: 'abc' asWideString true 'abc' asWideString match: 'abc' true 'abc' = 'abc' asWideString true 'abc' asWideString = 'abc' true 'abc' asWideString beginsWith: 'ab' true then likly 'abc' beginsWith: 'ab' asWideString false is wrong |
||||||||||||
| Additional Information |
likely more tests are needed testStringWideString self assert: 'abc' = 'abc'. self assert: 'abc' = 'abc' asWideString. self assert: 'abc' asWideString = 'abc'. self assert: 'abc' asWideString = 'abc' asWideString. self assert: ('abc' = 'ABC') not. self assert: ('abc' = 'ABC' asWideString) not. self assert: ('abc' asWideString = 'ABC') not. self assert: ('abc' asWideString = 'abc' asWideString). self assert: ((ByteArray with: 97 with: 0 with: 0 with: 0) asString ~= 'a000' asWideString). self assert: ('a000' asWideString ~= (ByteArray with: 97 with: 0 with: 0 with: 0) asString). self assert: ('abc' sameAs: 'aBc' asWideString). self assert: ('aBc' asWideString sameAs: 'abc'). self assert: ((ByteArray with: 97 with: 0 with: 0 with: 0) asString sameAs: 'Abcd' asWideString) not. self assert: ('a000' asWideString sameAs: (ByteArray with: 97 with: 0 with: 0 with: 0) asString) not. self assert: ('abc' beginsWith: 'ab'). self assert: ('abc' beginsWith: 'ab' asWideString). self assert: ('abc' asWideString beginsWith: 'ab'). self assert: ('abc' beginsWith: 'aX') not . self assert: ('abc' beginsWith: 'AB') not. self assert: ('abc' beginsWith: 'AB' asWideString) not . self assert: ('ABC' asWideString beginsWith: 'ab') not. self assert: ('abc' endsWith: 'bc'). self assert: ('abc' endsWith: 'bc' asWideString). self assert: ('abc' asWideString endsWith: 'bc'). self assert: ('abc' endsWith: 'bX') not . self assert: ('abc' endsWith: 'BC') not. self assert: ('abc' endsWith: 'BC' asWideString) not . self assert: ('ABC' asWideString endsWith: 'bc') not. self assert: ('ABC' caseInsensitiveLessOrEqual: 'abc'). self assert: ('ABC' caseInsensitiveLessOrEqual: 'abd'). self assert: ('ABD' caseInsensitiveLessOrEqual: 'abc') not. self assert: ('ABC' caseInsensitiveLessOrEqual: 'abc' asWideString). self assert: ('ABC' caseInsensitiveLessOrEqual: 'abd' asWideString). self assert: ('ABD' caseInsensitiveLessOrEqual: 'abc' asWideString) not. self assert: ('ABC' asWideString caseInsensitiveLessOrEqual: 'abc'). self assert: ('ABC' asWideString caseInsensitiveLessOrEqual: 'abd'). self assert: ('ABD' asWideString caseInsensitiveLessOrEqual: 'abc') not. self assert: ('ABC' asWideString caseInsensitiveLessOrEqual: 'abc' asWideString). self assert: ('ABC' asWideString caseInsensitiveLessOrEqual: 'abd' asWideString). self assert: ('ABD' asWideString caseInsensitiveLessOrEqual: 'abc' asWideString) not. self assert: ('abc' caseSensitiveLessOrEqual: 'abc'). self assert: ('abc' caseSensitiveLessOrEqual: 'abd'). self assert: ('abd' caseSensitiveLessOrEqual: 'abc') not. self assert: ('abc' caseSensitiveLessOrEqual: 'abc' asWideString). self assert: ('abc' caseSensitiveLessOrEqual: 'abd' asWideString). self assert: ('abd' caseSensitiveLessOrEqual: 'abc' asWideString) not. self assert: ('abc' asWideString caseSensitiveLessOrEqual: 'abc'). self assert: ('abc' asWideString caseSensitiveLessOrEqual: 'abd'). self assert: ('abd' asWideString caseSensitiveLessOrEqual: 'abc') not. self assert: ('abc' caseSensitiveLessOrEqual: 'ABC') not. self assert: ('abc' charactersExactlyMatching: 'abc') = 3. self assert: ('abd' charactersExactlyMatching: 'abc') = 2. self assert: ('abc' charactersExactlyMatching: 'abc' asWideString) = 3. self assert: ('abd' charactersExactlyMatching: 'abc' asWideString) = 2. self assert: ('abc' asWideString charactersExactlyMatching: 'abc') = 3. self assert: ('abd' asWideString charactersExactlyMatching: 'abc') = 2. self assert: ('abc' asWideString charactersExactlyMatching: 'abc' asWideString) = 3. self assert: ('abd' asWideString charactersExactlyMatching: 'abc' asWideString)= 2. self assert: ('abc' charactersExactlyMatching: 'ABC') = 0. self assert: ('abc' compare: 'abc') = 2. self assert: ('abc' compare: 'abd') = 1. self assert: ('abd' compare: 'abc') = 3. self assert: ('abc' compare: 'abC') = 2. self assert: ('abc' compare: 'abD') = 1. self assert: ('abd' compare: 'abC') = 3. self assert: ('aBc' compare: 'abC') = 2. self assert: ('aBc' compare: 'abD') = 1. self assert: ('aDd' compare: 'abC') = 3. self assert: ('abc' compare: 'abc' asWideString) = 2. self assert: ('abc' compare: 'abd' asWideString) = 1. self assert: ('abd' compare: 'abc' asWideString) = 3. self assert: ('abc' compare: 'abC' asWideString) = 2. self assert: ('abc' compare: 'abD' asWideString) = 1. self assert: ('abd' compare: 'abC' asWideString) = 3. self assert: ('aBc' compare: 'abC' asWideString) = 2. self assert: ('aBc' compare: 'abD' asWideString) = 1. self assert: ('aDd' compare: 'abC' asWideString) = 3. self assert: ('abc' asWideString compare: 'abc') = 2. self assert: ('abc' asWideString compare: 'abd') = 1. self assert: ('abd' asWideString compare: 'abc') = 3. self assert: ('abc' asWideString compare: 'abC') = 2. self assert: ('abc' asWideString compare: 'abD') = 1. self assert: ('abd' asWideString compare: 'abC') = 3. self assert: ('aBc' asWideString compare: 'abC') = 2. self assert: ('aBc' asWideString compare: 'abD') = 1. self assert: ('aDd' asWideString compare: 'abC') = 3. self assert: ('abc' asWideString compare: 'abc' asWideString) = 2. self assert: ('abc' asWideString compare: 'abd' asWideString) = 1. self assert: ('abd' asWideString compare: 'abc' asWideString) = 3. self assert: ('abc' asWideString compare: 'abC' asWideString) = 2. self assert: ('abc' asWideString compare: 'abD' asWideString) = 1. self assert: ('abd' asWideString compare: 'abC' asWideString) = 3. self assert: ('aBc' asWideString compare: 'abC' asWideString) = 2. self assert: ('aBc' asWideString compare: 'abD' asWideString) = 1. self assert: ('aDd' asWideString compare: 'abC' asWideString) = 3. self assert: ('abc' compare: 'abc' caseSensitive: true) = 2. self assert: ('abc' compare: 'abC' caseSensitive: false) = 2. self assert: ('abc' compare: 'abc' asWideString caseSensitive: true) = 2. self assert: ('abc' compare: 'abC' asWideString caseSensitive: false) = 2. self assert: ('abc' asWideString compare: 'abc' caseSensitive: true) = 2. self assert: ('abc' asWideString compare: 'abC' caseSensitive: false) = 2. self assert: ('abc' asWideString compare: 'abc' asWideString caseSensitive: true) = 2. self assert: ('abc' asWideString compare: 'abC' asWideString caseSensitive: false) = 2. self assert: ('*baz' match: 'mobaz' ). self assert: ('*foo#zort' match: 'afoo3zortthenfoo3zort' ). self assert: ('*baz' match: 'mobaz' ). self assert: ('*foo#zort' match: 'afoo3zortthenfoo3zort' ). self assert: ('*baz' match: 'mobaz' asWideString). self assert: ('*foo#zort' match: 'afoo3zortthenfoo3zort' asWideString). self assert: ('*baz' match: 'mobaz' asWideString). self assert: ('*foo#zort' match: 'afoo3zortthenfoo3zort' asWideString). self assert: ('*baz' asWideString match: 'mobaz' ). self assert: ('*foo#zort' asWideString match: 'afoo3zortthenfoo3zort' ). self assert: ('*baz' asWideString match: 'mobaz' ). self assert: ('*foo#zort' asWideString match: 'afoo3zortthenfoo3zort' ). self assert: ('*baz' asWideString match: 'mobaz' asWideString). self assert: ('*foo#zort' asWideString match: 'afoo3zortthenfoo3zort' asWideString). self assert: ('*baz' asWideString match: 'mobaz' asWideString). self assert: ('*foo#zort' asWideString match: 'afoo3zortthenfoo3zort' asWideString). self assert: ('aa' < 'ab'). self assert: ('aa' <= 'ab'). self assert: ('aa' <= 'aa'). self assert: ('ab' > 'aa'). self assert: ('ab' >= 'aa'). self assert: ('aa' >= 'aa'). self assert: ('aa' < 'ab' asWideString). self assert: ('aa' <= 'ab' asWideString). self assert: ('aa' <= 'aa' asWideString). self assert: ('ab' > 'aa' asWideString). self assert: ('ab' >= 'aa' asWideString). self assert: ('aa' >= 'aa' asWideString). self assert: ('aa' asWideString < 'ab'). self assert: ('aa' asWideString <= 'ab'). self assert: ('aa' asWideString <= 'aa'). self assert: ('ab' asWideString > 'aa'). self assert: ('ab' asWideString >= 'aa'). self assert: ('aa' asWideString >= 'aa'). self assert: ('aa' asWideString< 'ab' asWideString). self assert: ('aa' asWideString<= 'ab' asWideString). self assert: ('aa' asWideString<= 'aa' asWideString). self assert: ('ab' asWideString> 'aa' asWideString). self assert: ('ab' asWideString >= 'aa' asWideString). self assert: ('aa' asWideString>= 'aa' asWideString). |
||||||||||||
| Attached Files |
|
||||||||||||
|
|
|||||||||||||
Relationships |
||||||||||||||||
|
||||||||||||||||
Notes |
|
|
(0010462 - 1235 - 1460 - 1460 - 1460 - 1460 - 1460) nicolas cellier 03-22-07 23:16 edited on: 03-22-07 23:17 |
Other noticeable points: ======================= 1) even if WideString receiver case is correct, it is incredibly inefficient. current implementation will search the substring argument not only at beginning but will scan the full receiver string... to finally reject it because it has not been found at index 1... Even in the pure ByteString case, primitive will not be faster than super over a hundred of unmatched characters. 2) findSubstring:in:startingAt:matching: is a utility not using self and should therefore be implemented in class side 3) findSubstring:in:startingAt:matching: should fail the primitive in case the argument is a WideString instead of doing incorrect job Actions to be taken: =================== 1) RESOLVE SLOWNESS user super beginsWith: in the wide case to gain efficiency either restrict use with a test, or implement only in Byte subclasses 2) SOLVE PRIMITIVE BUG cure the findSubstring:in:startingAt:matching: with something like (key class isBytes and: [body class isBytes]) ifFalse: [^self primitiveFail]) A partial Patch: =============== I move beginsWith: in ByteString and ByteSymbol to solve 1) TODO: ==== To solve 2) for Slang and VMMaker gurus... |
|
(0010464 - 698 - 918 - 918 - 918 - 918 - 918) andreas 03-23-07 06:39 |
Nice tests, thank you. I would propose the following fixes: 1) For beginsWith: and endsWith: I would use String>>beginsWith: prefix "..." prefix class == self class ifFalse:[^super beginsWith: prefix]. "..." This avoids extra methods and the comment can be put there to explain what is going on. 2) For the comparisons I would recomment implementing: ByteString>>compare: aString caseSensitive: aBool "Bounce the comparison off to the argument to fix some wide vs. byte string comparisons" | map | map := aBool ifTrue:[CaseSensitiveOrder] ifFalse:[CaseInsensitiveOrder]. ^4 - (aString compare: aString with: self collated: map) With those fixes, the tests pass. |
|
(0010483 - 759 - 945 - 945 - 945 - 945 - 945) nicolas cellier 03-30-07 17:33 edited on: 03-30-07 17:35 |
Hi Andreas Testing (self class==prefix class) is far better than my first attempt, however, I do not entirely agree with your solution, BECAUSE: 1) above tests are icomplete because there is no Wide Character in these WideString 2) WideString beginsWith: WideString can fail with your patch (see below, and note it does not fail with my patch applied) 3) WideString beginsWith: WideString is still incredibly slow when answer is false | w1 w2 | w1 := WideString with: 402 asCharacter with: $a with: 400 asCharacter with: $b. w2 := WideString with: 402 asCharacter. "this one fails with your patch" w1 beginsWith: w2. "this one fails, not yet addressed by our patches - action 2) above" w1 findString: w2 startingAt: 1. Cheers |
|
(0010940 - 280 - 310 - 310 - 310 - 310 - 310) nicolas cellier 07-27-07 20:47 |
Finalmente, (self class==prefix class) is bad because ByteString ~= ByteSymbol (self class isBytes = prefix class isBytes) is possible, but weak, because it relies on having only two possibilities, bytes or not bytes. Would be broken in case of String8 String16 String32... |
|
(0010943 - 422 - 464 - 976 - 976 - 976 - 976) nicolas cellier 07-28-07 21:33 |
All proposed WideString-*-Test.*.cs pass if you apply following patches: http://bugs.squeak.org/view.php?id=5331 [^] beginsWithWideStringPatch.1.cs http://bugs.squeak.org/view.php?id=6367 [^] WideString-substrings-Test.1.cs http://bugs.squeak.org/view.php?id=6366 [^] Collection-WideString-findSubstring-Patch.1.cs http://bugs.squeak.org/view.php?id=3574 [^] Collection-String-IndexOf-Patch.3.cs last one is already in 3.10 7137 |
|
(0011954 - 535 - 643 - 643 - 643 - 643 - 643) nicolas cellier 03-24-08 22:09 edited on: 04-06-08 16:44 |
"fix begin" Installer mantis ensureFix: 3574. Installer mantis ensureFix: 6366. Installer mantis ensureFix: 6367. Installer mantis bug: 5331 fix:'beginsWithWideStringPatch.1.cs'. "fix test" Installer mantis bug: 5331 fix:'WideString-OrderRelation-Test.2.cs'. Installer mantis bug: 5331 fix:'WideString-beginsWith-Test.1.cs'. Installer mantis bug: 5331 fix:'WideString-compare-Test.2.cs'. Installer mantis bug: 5331 fix:'WideString-endsWith-Test.1.cs'. Installer mantis bug: 5331 fix:'WideString-match-Test.2.cs'. "fix end" |
|
(0013325 - 65 - 71 - 231 - 231 - 231 - 231) nicolas cellier 10-03-09 19:47 |
Fixed in http://source.squeak.org/trunk/Collections-nice.152.mcz [^] |
| Mantis 1.0.8[^]
Copyright © 2000 - 2007 Mantis Group
104 total queries executed. 51 unique queries executed. |