Mantis Bugtracker
  

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 04-18-10 22:05
Reporter johnmci View Status public  
Assigned To andreas
Priority normal Resolution fixed  
Status closed   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  beginsWithWideStringPatch.1.cs [^] (1,375 bytes) 03-22-07 23:51
 WideString-OrderRelation-Test.2.cs [^] (3,205 bytes) 07-28-07 21:26
 WideString-beginsWith-Test.1.cs [^] (1,101 bytes) 07-28-07 21:26
 WideString-compare-Test.2.cs [^] (4,287 bytes) 07-28-07 21:27
 WideString-endsWith-Test.1.cs [^] (949 bytes) 07-28-07 21:27
 WideString-match-Test.2.cs [^] (2,073 bytes) 07-28-07 21:27

- Relationships

SYSTEM WARNING: Creating default object from empty value

SYSTEM WARNING: Creating default object from empty value

related to 0003574closed andreas String>>findFirstInString:inSet:startingAt: does not work if character of interest is last character in String, also WideString 
related to 0006367closed nicolas cellier [BUG] WideString substrings broken 
related to 0006366closed andreas [BUG] WideString findString:startingAt: and other matchTable problems 

- 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 [^]
 

- Issue History
Date Modified Username Field Change
10-31-06 03:47 johnmci New Issue
03-22-07 23:16 nicolas cellier Note Added: 0010462
03-22-07 23:17 nicolas cellier Note Edited: 0010462
03-22-07 23:51 nicolas cellier File Added: beginsWithWideStringPatch.1.cs
03-23-07 06:39 andreas Note Added: 0010464
03-30-07 17:33 nicolas cellier Note Added: 0010483
03-30-07 17:35 nicolas cellier Note Edited: 0010483
07-27-07 20:47 nicolas cellier Note Added: 0010940
07-28-07 21:26 nicolas cellier File Added: WideString-OrderRelation-Test.2.cs
07-28-07 21:26 nicolas cellier File Added: WideString-beginsWith-Test.1.cs
07-28-07 21:27 nicolas cellier File Added: WideString-compare-Test.2.cs
07-28-07 21:27 nicolas cellier File Added: WideString-endsWith-Test.1.cs
07-28-07 21:27 nicolas cellier File Added: WideString-match-Test.2.cs
07-28-07 21:33 nicolas cellier Note Added: 0010943
03-24-08 22:09 nicolas cellier Note Added: 0011954
04-06-08 16:44 nicolas cellier Note Edited: 0011954
12-17-08 04:31 Keith_Hodges Status new => acknowledged
01-10-09 01:53 Keith_Hodges Status acknowledged => pending
01-10-09 02:27 Keith_Hodges Status pending => testing
01-10-09 03:39 Keith_Hodges Status testing => resolved
01-10-09 03:39 Keith_Hodges Fixed in Version  => 3.11
01-10-09 03:39 Keith_Hodges Resolution open => fixed
01-10-09 03:39 Keith_Hodges Assigned To  => Keith_Hodges
01-10-09 03:41 Keith_Hodges Status resolved => testing
10-03-09 19:24 nicolas cellier Relationship added related to 0006366
10-03-09 19:34 Keith_Hodges Status testing => assigned
10-03-09 19:34 Keith_Hodges Assigned To Keith_Hodges => andreas
10-03-09 19:46 nicolas cellier Relationship added related to 0003574
10-03-09 19:46 nicolas cellier Relationship added related to 0006367
10-03-09 19:47 nicolas cellier Note Added: 0013325
10-03-09 19:59 nicolas cellier Status assigned => resolved
10-03-09 19:59 nicolas cellier Fixed in Version 3.11 => trunk
04-18-10 22:05 andreas Status resolved => closed


Mantis 1.0.8[^]
Copyright © 2000 - 2007 Mantis Group
105 total queries executed.
51 unique queries executed.
Powered by Mantis Bugtracker