FileDocCategorySizeDatePackage
StringComparatorImpl.javaAPI DocphoneME MR2 API (J2ME)13328Wed May 02 18:00:46 BST 2007com.sun.j2me.global

StringComparatorImpl

public class StringComparatorImpl extends Object implements CommonStringComparator
This class realizes string comparison methods of {@link javax.microedition.global.StringComparator}. Specifically, these are:
  • {@link #compare(String, String)}
  • {@link #equals(String, String)}

Fields Summary
private static final int
CAPACITY_INCREMENT
The capacity increment value of the internal buffers.
private int
level
Current collation level.
private int[]
buffer1
Internal buffer used in the compare function for temporary data storage.
private int[]
buffer2
Internal buffer used in the compare function for temporary data storage.
int
buffersLength
Internal buffers length.
private final NormalizationTable
nrmTable
Normalization table
private final StringNormalizer
strNormalizer1
String normalizer 1
private final StringNormalizer
strNormalizer2
String normalizer 2
private final StringCollator
strCollator1
String collator 1
private final StringCollator
strCollator2
String collator 2
Constructors Summary
public StringComparatorImpl(String locale, int level)
Constructs an instance using the specified locale and collation level.

If the specified locale is null or the empty string, this class uses the generic collation algorithm.

param
locale the locale to use, or null to use the generic collation algorithm
param
level the collation level to use
throws
UnsupportedLocaleException if the specified locale is not supported by the StringComparator implementation
throws
IllegalArgumentException if the specified locale is non-null but is not valid according to the MIDP 2.0 specification, or if level is not one of the constants defined in this class
see
javax.microedition.global.StringComparator#LEVEL1
see
javax.microedition.global.StringComparator#LEVEL2
see
javax.microedition.global.StringComparator#LEVEL3
see
javax.microedition.global.StringComparator#IDENTICAL

   
    
                                                                                                                                            
         

        this.level = level;

        CollationElementTable colTable = null;

        nrmTable = NormalizationTableImpl.getInstance();
        colTable = CollationElementTableImpl.getInstance(locale);
        
        strNormalizer1 = new StringNormalizer(nrmTable);
        strCollator1 = new StringCollator(strNormalizer1, colTable);

        strNormalizer2 = new StringNormalizer(nrmTable);
        strCollator2 = new StringCollator(strNormalizer2, colTable);
    
Methods Summary
public intcompare(java.lang.String s1, java.lang.String s2)
Compares the two strings using the rules specific to the associated locale of this instance. Use the equals method to more conveniently test for equality.

param
s1 first string to compare
param
s2 second string to compare
return
negative if s1 belongs before s2, zero if the strings are equal, positive if s1 belongs after s2
throws
NullPointerException if either s1 or s2 is null
see
#equals(String, String)

        synchronized (this) {

            // try to skip as much as possible
            int offset = skipBeginning(s1, s2);
            
            // initialize objects
            strNormalizer1.setSource(s1, offset);
            strNormalizer2.setSource(s2, offset);
            strCollator1.reset();
            strCollator2.reset();
            
            int idx1;
            int idx2;
            
            int result;
            
            int buffered = 0;

            int value1;
            int value2;
            
            idx1 = 0;
            idx2 = 0;
            do {
                if (buffered >= buffersLength) {
                    buffersLength += CAPACITY_INCREMENT;
                    int[] newBuffer1 = 
                            new int[buffersLength];
                    int[] newBuffer2 = 
                            new int[buffersLength];
                    System.arraycopy(buffer1, 0, newBuffer1, 0, buffered);
                    System.arraycopy(buffer2, 0, newBuffer2, 0, buffered);
                    buffer1 = newBuffer1;
                    buffer2 = newBuffer2;                    
                }
                
                buffer1[buffered] = strCollator1.getNextElement();
                buffer2[buffered] = strCollator2.getNextElement();
                
                ++buffered;

                value1 = buffer1[idx1];
                value2 = buffer2[idx2];
                
                if (value1 != -1) {
                    value1 = CollationElementTable.getL1(value1);
                }
                if (value2 != -1) {
                    value2 = CollationElementTable.getL1(value2);
                }
                
                if (value1 != 0) {
                    if (value2 != 0) {
                        result = value1 - value2;
                        if (result != 0) {
                            return result;
                        }
                        ++idx1;
                    }
                    ++idx2;
                } else {
                    if (value2 == 0) {
                        ++idx2;
                    }
                    ++idx1;
                }
            } while ((value1 != -1) || (value2 != -1));
            
            if (level < StringComparator.LEVEL2) {
                return 0;
            }

            idx1 = 0;
            idx2 = 0;
            do {
                value1 = buffer1[idx1];
                value2 = buffer2[idx2];
                
                if (value1 != -1) {
                    value1 = CollationElementTable.getL2(value1);
                }
                if (value2 != -1) {
                    value2 = CollationElementTable.getL2(value2);
                }
                
                if (value1 != 0) {
                    if (value2 != 0) {
                        result = value1 - value2;
                        if (result != 0) {
                            return result;
                        }
                        ++idx1;
                    }
                    ++idx2;
                } else {
                    if (value2 == 0) {
                        ++idx2;
                    }
                    ++idx1;
                }
            } while ((value1 != -1) || (value2 != -1));

            if (level < StringComparator.LEVEL3) {
                return 0;
            }

            idx1 = 0;
            idx2 = 0;
            do {
                value1 = buffer1[idx1];
                value2 = buffer2[idx2];
                
                if (value1 != -1) {
                    value1 = CollationElementTable.getL3(value1);
                }
                if (value2 != -1) {
                    value2 = CollationElementTable.getL3(value2);
                }
                
                if (value1 != 0) {
                    if (value2 != 0) {
                        result = value1 - value2;
                        if (result != 0) {
                            return result;
                        }
                        ++idx1;
                    }
                    ++idx2;
                } else {
                    if (value2 == 0) {
                        ++idx2;
                    }
                    ++idx1;
                }
            } while ((value1 != -1) || (value2 != -1));
            
            if (level == StringComparator.IDENTICAL) {
                strNormalizer1.reset();
                strNormalizer2.reset();
                
                do {
                    value1 = strNormalizer1.getNextElement();
                    value2 = strNormalizer2.getNextElement();
                    
                    if (value1 != -1) {
                        value1 = NormalizationTable.getCodePoint(value1);
                    }
                    if (value2 != -1) {
                        value2 = NormalizationTable.getCodePoint(value2);
                    }

                    result = value1 - value2;
                    if (result != 0) {
                        return result;
                    }
                } while ((value1 != -1) || (value2 != -1));
            }
        }
        
        return 0;
    
public booleanequals(java.lang.String s1, java.lang.String s2)
Tests if the two strings are equal according to the rules specific to the associated locale of this instance.

param
s1 first string to compare
param
s2 second string to compare
return
true if the strings are equal, false if not
throws
NullPointerException if either s1 or s2 is null

        return compare(s1, s2) == 0;
    
private final booleanisUnsafeCharacter(char c)
Test if the given character is unsafe to start the UCA with.

param
c the tested character
return
true if the character is unsafe to start the UCA with

        if ((c & 0xf800) == 0xd800) {
            // low or high surrogate
            return true;
        }
        int value = nrmTable.getCanonicalDecomposition(buffer1, 0, c);
        if (!nrmTable.isSingleCodePoint(value)) {
            return true;
        }
        return nrmTable.isUnsafe(value);
    
private final intskipBeginning(java.lang.String s1, java.lang.String s2)
Returns the starting offset for the UCA comparison. Tries to skip the first characters from both input strings which are equal. This speeds up the comparison.

param
s1 the first string
param
s2 the second string
return
the starting offset

            int offset;
            int length = s1.length();
            if (s2.length() < length) {
                length = s2.length();
            }
            if (length == 0) {
                return 0;
            }
            if (s1.charAt(0) != s2.charAt(0)) {
                return 0;
            }
            for (offset = 1; offset < length; ++offset) {
                if (s1.charAt(offset) != s2.charAt(offset)) {
                    if (!isUnsafeCharacter(s1.charAt(offset)) &&
                            !isUnsafeCharacter(s2.charAt(offset))) {
                        return offset;
                    }

                    for (--offset; offset > 0; --offset) {
                        if (!isUnsafeCharacter(s1.charAt(offset))) {
                            return offset;
                        }
                    }
                    
                    return offset;
                }
            }
            
            if (length < s1.length()) {
                if (!isUnsafeCharacter(s1.charAt(length))) {
                    return length;
                }
                
                for (--length; length > 0; --length) {
                    if (!isUnsafeCharacter(s1.charAt(length))) {
                        return length;
                    }
                }
                                
                return length;
            }
            
            if (length < s2.length()) {
                if (!isUnsafeCharacter(s2.charAt(length))) {
                    return length;
                }

                for (--length; length > 0; --length) {
                    if (!isUnsafeCharacter(s1.charAt(length))) {
                        return length;
                    }
                }
                
                return length;
            }
            
            return length;