Rework BCollator API
- Strength is now set once, instead of at each comparison, to improve performance and fix potential locking issues - Add a way to enable "numeric" collation (aka "natural order")
This commit is contained in:
@@ -35,9 +35,9 @@
|
|||||||
natural number sorting so that 2 is sorted before 10 unlike byte-based
|
natural number sorting so that 2 is sorted before 10 unlike byte-based
|
||||||
sorting.
|
sorting.
|
||||||
|
|
||||||
\warning This class is not multithread-safe, as Compare() change the
|
\warning This class is not multithread-safe. So if you want to use a
|
||||||
ICUCollator (the strength). So if you want to use a BCollator
|
BCollator from more than one thread you need to protect it with
|
||||||
from more than one thread you need to protect it with a lock.
|
a lock.
|
||||||
|
|
||||||
\since Haiku R1
|
\since Haiku R1
|
||||||
*/
|
*/
|
||||||
@@ -121,12 +121,9 @@
|
|||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\fn void BCollator::SetDefaultStrength(int8 strength)
|
\fn void BCollator::SetStrength(int8 strength)
|
||||||
\brief Set the \a strength of the collator.
|
\brief Set the \a strength of the collator.
|
||||||
|
|
||||||
Note that the \a strength can also be chosen on a case-by-case basis
|
|
||||||
when calling other methods.
|
|
||||||
|
|
||||||
\param strength The collator class provide four level of \a strength.
|
\param strength The collator class provide four level of \a strength.
|
||||||
\li \c B_COLLATE_PRIMARY doesn't differentiate e from é,
|
\li \c B_COLLATE_PRIMARY doesn't differentiate e from é,
|
||||||
\li \c B_COLLATE_SECONDARY takes letter accents into account,
|
\li \c B_COLLATE_SECONDARY takes letter accents into account,
|
||||||
@@ -138,16 +135,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn int8 BCollator::DefaultStrength() const
|
|
||||||
\brief Get the current strength of this catalog.
|
|
||||||
|
|
||||||
\returns The current strength of the catalog.
|
|
||||||
|
|
||||||
\since Haiku R1
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\fn void BCollator::SetIgnorePunctuation(bool ignore)
|
\fn void BCollator::SetIgnorePunctuation(bool ignore)
|
||||||
\brief Enable or disable punctuation handling.
|
\brief Enable or disable punctuation handling.
|
||||||
@@ -172,8 +159,21 @@
|
|||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\fn status_t BCollator::GetSortKey(const char* string, BString* key,
|
\fn void BCollator::SetNumericSorting(bool ignore)
|
||||||
int8 strength) const
|
\brief Enable or disable numeric order sorting.
|
||||||
|
|
||||||
|
Numeric sorting enables the collator to identify strings of digits as
|
||||||
|
numbers, and sort them in ascending number. For example, the string "123"
|
||||||
|
is sorted after "234". Numbers and other characters can be mixed in the
|
||||||
|
same string.
|
||||||
|
|
||||||
|
\since Haiku R1
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\fn status_t BCollator::GetSortKey(const char* string, BString* key)
|
||||||
|
const
|
||||||
\brief Compute the sortkey of a \a string.
|
\brief Compute the sortkey of a \a string.
|
||||||
|
|
||||||
The sortkey is a modified version of the input \a string that you can use
|
The sortkey is a modified version of the input \a string that you can use
|
||||||
@@ -184,7 +184,6 @@
|
|||||||
|
|
||||||
\param string String from which to compute the sortkey.
|
\param string String from which to compute the sortkey.
|
||||||
\param key The resulting sortkey.
|
\param key The resulting sortkey.
|
||||||
\param strength The \a strength to use to compute the sortkey.
|
|
||||||
|
|
||||||
\retval B_OK if everything went well.
|
\retval B_OK if everything went well.
|
||||||
\retval B_ERROR if an error occurred generating the sortkey.
|
\retval B_ERROR if an error occurred generating the sortkey.
|
||||||
@@ -194,17 +193,15 @@
|
|||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\fn int BCollator::Compare(const char* s1, const char* s2,
|
\fn int BCollator::Compare(const char* s1, const char* s2)
|
||||||
int8 strength) const
|
const
|
||||||
\brief Returns the difference betweens the two strings according to the
|
\brief Returns the difference betweens the two strings.
|
||||||
collation defined by the \a strength parameter.
|
|
||||||
|
|
||||||
This method should be used in place of the strcmp() function to perform
|
This method should be used in place of the strcmp() function to perform
|
||||||
locale-aware comparisons.
|
locale-aware comparisons.
|
||||||
|
|
||||||
\param s1 The first string to compare.
|
\param s1 The first string to compare.
|
||||||
\param s2 The second string to compare.
|
\param s2 The second string to compare.
|
||||||
\param strength The \a strength to use for the string comparison.
|
|
||||||
|
|
||||||
\returns An integer value representing how the strings compare to each
|
\returns An integer value representing how the strings compare to each
|
||||||
other.
|
other.
|
||||||
@@ -219,8 +216,8 @@
|
|||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\fn bool BCollator::Equal(const char* s1, const char* s2,
|
\fn bool BCollator::Equal(const char* s1, const char* s2)
|
||||||
int8 strength) const
|
const
|
||||||
\brief Compares two strings for equality.
|
\brief Compares two strings for equality.
|
||||||
|
|
||||||
Note that strings that are not byte-by-byte identical may end up being
|
Note that strings that are not byte-by-byte identical may end up being
|
||||||
@@ -232,7 +229,6 @@
|
|||||||
|
|
||||||
\param s1 The first string to compare.
|
\param s1 The first string to compare.
|
||||||
\param s2 The second string to compare.
|
\param s2 The second string to compare.
|
||||||
\param strength The \a strength to use for the string comparison.
|
|
||||||
|
|
||||||
\returns \c true if the strings are identical, \c false otherwise.
|
\returns \c true if the strings are identical, \c false otherwise.
|
||||||
|
|
||||||
@@ -241,8 +237,8 @@
|
|||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\fn bool BCollator::Greater(const char* s1, const char* s2,
|
\fn bool BCollator::Greater(const char* s1, const char* s2)
|
||||||
int8 strength = B_COLLATE_DEFAULT) const
|
const
|
||||||
\brief Determine if a string is greater than another.
|
\brief Determine if a string is greater than another.
|
||||||
|
|
||||||
\note !Greater(s1, s2) is the same as GreaterOrEqual(s2, s1). This means
|
\note !Greater(s1, s2) is the same as GreaterOrEqual(s2, s1). This means
|
||||||
@@ -250,7 +246,6 @@
|
|||||||
|
|
||||||
\param s1 The first string to compare.
|
\param s1 The first string to compare.
|
||||||
\param s2 The second string to compare.
|
\param s2 The second string to compare.
|
||||||
\param strength The \a strength to use for the string comparison.
|
|
||||||
|
|
||||||
\returns \c true if s1 is greater than, but not equal to, s2.
|
\returns \c true if s1 is greater than, but not equal to, s2.
|
||||||
|
|
||||||
@@ -259,15 +254,14 @@
|
|||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\fn bool BCollator::GreaterOrEqual(const char* s1, const char* s2,
|
\fn bool BCollator::GreaterOrEqual(const char* s1, const char* s2)
|
||||||
int8 strength = B_COLLATE_DEFAULT) const
|
const
|
||||||
\brief Determines if one string is greater than another.
|
\brief Determines if one string is greater than another.
|
||||||
|
|
||||||
\note !GreaterOrEqual(s1, s2) is the same as Greater(s2, s1).
|
\note !GreaterOrEqual(s1, s2) is the same as Greater(s2, s1).
|
||||||
|
|
||||||
\param s1 The first string to compare.
|
\param s1 The first string to compare.
|
||||||
\param s2 The second string to compare.
|
\param s2 The second string to compare.
|
||||||
\param strength The \a strength to use for the string comparison.
|
|
||||||
|
|
||||||
\returns \c true if s1 is greater or equal than s2.
|
\returns \c true if s1 is greater or equal than s2.
|
||||||
|
|
||||||
@@ -280,9 +274,7 @@
|
|||||||
\brief Unarchive the collator
|
\brief Unarchive the collator
|
||||||
|
|
||||||
This method allows you to restore a collator that you previously
|
This method allows you to restore a collator that you previously
|
||||||
archived. It is faster to archive and unarchive a collator than it is
|
archived.
|
||||||
to create a new one up each time you need a BCollator object with the
|
|
||||||
same settings.
|
|
||||||
|
|
||||||
\param archive The message to restore the collator from.
|
\param archive The message to restore the collator from.
|
||||||
|
|
||||||
|
|||||||
@@ -34,9 +34,6 @@ enum collator_strengths {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// N.B.: This class is not multithread-safe, as Compare() and GetKey() change
|
|
||||||
// the ICUCollator (the strength). So if you want to use a BCollator from
|
|
||||||
// more than one thread, you need to protect it with a lock
|
|
||||||
class BCollator : public BArchivable {
|
class BCollator : public BArchivable {
|
||||||
public:
|
public:
|
||||||
BCollator();
|
BCollator();
|
||||||
@@ -51,55 +48,54 @@ public:
|
|||||||
|
|
||||||
BCollator& operator=(const BCollator& source);
|
BCollator& operator=(const BCollator& source);
|
||||||
|
|
||||||
void SetDefaultStrength(int8 strength);
|
status_t SetStrength(int8 strength) const;
|
||||||
int8 DefaultStrength() const;
|
|
||||||
|
|
||||||
void SetIgnorePunctuation(bool ignore);
|
void SetIgnorePunctuation(bool ignore);
|
||||||
bool IgnorePunctuation() const;
|
bool IgnorePunctuation() const;
|
||||||
|
|
||||||
status_t GetSortKey(const char* string, BString* key,
|
status_t SetNumericSorting(bool enable);
|
||||||
int8 strength = B_COLLATE_DEFAULT) const;
|
|
||||||
|
|
||||||
int Compare(const char* s1, const char* s2,
|
status_t GetSortKey(const char* string, BString* key)
|
||||||
int8 strength = B_COLLATE_DEFAULT) const;
|
const;
|
||||||
bool Equal(const char* s1, const char* s2,
|
|
||||||
int8 strength = B_COLLATE_DEFAULT) const;
|
int Compare(const char* s1, const char* s2)
|
||||||
bool Greater(const char* s1, const char* s2,
|
const;
|
||||||
int8 strength = B_COLLATE_DEFAULT) const;
|
bool Equal(const char* s1, const char* s2)
|
||||||
bool GreaterOrEqual(const char* s1, const char* s2,
|
const;
|
||||||
int8 strength = B_COLLATE_DEFAULT) const;
|
bool Greater(const char* s1, const char* s2)
|
||||||
|
const;
|
||||||
|
bool GreaterOrEqual(const char* s1, const char* s2)
|
||||||
|
const;
|
||||||
|
|
||||||
// (un-)archiving API
|
// (un-)archiving API
|
||||||
status_t Archive(BMessage* archive, bool deep) const;
|
status_t Archive(BMessage* archive, bool deep) const;
|
||||||
static BArchivable* Instantiate(BMessage* archive);
|
static BArchivable* Instantiate(BMessage* archive);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
status_t _SetStrength(int8 strength) const;
|
|
||||||
|
|
||||||
mutable U_ICU_NAMESPACE::Collator* fICUCollator;
|
mutable U_ICU_NAMESPACE::Collator* fICUCollator;
|
||||||
int8 fDefaultStrength;
|
|
||||||
bool fIgnorePunctuation;
|
bool fIgnorePunctuation;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
BCollator::Equal(const char *s1, const char *s2, int8 strength) const
|
BCollator::Equal(const char *s1, const char *s2) const
|
||||||
{
|
{
|
||||||
return Compare(s1, s2, strength) == 0;
|
return Compare(s1, s2) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
BCollator::Greater(const char *s1, const char *s2, int8 strength) const
|
BCollator::Greater(const char *s1, const char *s2) const
|
||||||
{
|
{
|
||||||
return Compare(s1, s2, strength) > 0;
|
return Compare(s1, s2) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
BCollator::GreaterOrEqual(const char *s1, const char *s2, int8 strength) const
|
BCollator::GreaterOrEqual(const char *s1, const char *s2) const
|
||||||
{
|
{
|
||||||
return Compare(s1, s2, strength) >= 0;
|
return Compare(s1, s2) >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,6 @@
|
|||||||
|
|
||||||
BCollator::BCollator()
|
BCollator::BCollator()
|
||||||
:
|
:
|
||||||
fDefaultStrength(B_COLLATE_PRIMARY),
|
|
||||||
fIgnorePunctuation(true)
|
fIgnorePunctuation(true)
|
||||||
{
|
{
|
||||||
// TODO: the collator construction will have to change; the default
|
// TODO: the collator construction will have to change; the default
|
||||||
@@ -33,16 +32,17 @@ BCollator::BCollator()
|
|||||||
|
|
||||||
UErrorCode error = U_ZERO_ERROR;
|
UErrorCode error = U_ZERO_ERROR;
|
||||||
fICUCollator = Collator::createInstance(error);
|
fICUCollator = Collator::createInstance(error);
|
||||||
|
SetStrength(B_COLLATE_TERTIARY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BCollator::BCollator(const char* locale, int8 strength, bool ignorePunctuation)
|
BCollator::BCollator(const char* locale, int8 strength, bool ignorePunctuation)
|
||||||
:
|
:
|
||||||
fDefaultStrength(strength),
|
|
||||||
fIgnorePunctuation(ignorePunctuation)
|
fIgnorePunctuation(ignorePunctuation)
|
||||||
{
|
{
|
||||||
UErrorCode error = U_ZERO_ERROR;
|
UErrorCode error = U_ZERO_ERROR;
|
||||||
fICUCollator = Collator::createInstance(locale, error);
|
fICUCollator = Collator::createInstance(locale, error);
|
||||||
|
SetStrength(strength);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -50,15 +50,8 @@ BCollator::BCollator(BMessage* archive)
|
|||||||
:
|
:
|
||||||
BArchivable(archive),
|
BArchivable(archive),
|
||||||
fICUCollator(NULL),
|
fICUCollator(NULL),
|
||||||
fDefaultStrength(B_COLLATE_PRIMARY),
|
|
||||||
fIgnorePunctuation(true)
|
fIgnorePunctuation(true)
|
||||||
{
|
{
|
||||||
int32 data;
|
|
||||||
if (archive->FindInt32("loc:strength", &data) == B_OK)
|
|
||||||
fDefaultStrength = (uint8)data;
|
|
||||||
else
|
|
||||||
fDefaultStrength = B_COLLATE_PRIMARY;
|
|
||||||
|
|
||||||
archive->FindBool("loc:punctuation", &fIgnorePunctuation);
|
archive->FindBool("loc:punctuation", &fIgnorePunctuation);
|
||||||
|
|
||||||
UErrorCode error = U_ZERO_ERROR;
|
UErrorCode error = U_ZERO_ERROR;
|
||||||
@@ -101,7 +94,6 @@ BCollator& BCollator::operator=(const BCollator& source)
|
|||||||
fICUCollator = source.fICUCollator != NULL
|
fICUCollator = source.fICUCollator != NULL
|
||||||
? source.fICUCollator->clone()
|
? source.fICUCollator->clone()
|
||||||
: NULL;
|
: NULL;
|
||||||
fDefaultStrength = source.fDefaultStrength;
|
|
||||||
fIgnorePunctuation = source.fIgnorePunctuation;
|
fIgnorePunctuation = source.fIgnorePunctuation;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,20 +101,6 @@ BCollator& BCollator::operator=(const BCollator& source)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
BCollator::SetDefaultStrength(int8 strength)
|
|
||||||
{
|
|
||||||
fDefaultStrength = strength;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int8
|
|
||||||
BCollator::DefaultStrength() const
|
|
||||||
{
|
|
||||||
return fDefaultStrength;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BCollator::SetIgnorePunctuation(bool ignore)
|
BCollator::SetIgnorePunctuation(bool ignore)
|
||||||
{
|
{
|
||||||
@@ -138,10 +116,19 @@ BCollator::IgnorePunctuation() const
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BCollator::GetSortKey(const char* string, BString* key, int8 strength) const
|
BCollator::SetNumericSorting(bool enable)
|
||||||
{
|
{
|
||||||
_SetStrength(strength);
|
UErrorCode error = U_ZERO_ERROR;
|
||||||
|
fICUCollator->setAttribute(UCOL_NUMERIC_COLLATION,
|
||||||
|
enable ? UCOL_ON : UCOL_OFF, error);
|
||||||
|
|
||||||
|
return error == U_ZERO_ERROR ? B_OK : B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BCollator::GetSortKey(const char* string, BString* key) const
|
||||||
|
{
|
||||||
// TODO : handle fIgnorePunctuation
|
// TODO : handle fIgnorePunctuation
|
||||||
|
|
||||||
int length = strlen(string);
|
int length = strlen(string);
|
||||||
@@ -175,10 +162,8 @@ BCollator::GetSortKey(const char* string, BString* key, int8 strength) const
|
|||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
BCollator::Compare(const char* s1, const char* s2, int8 strength) const
|
BCollator::Compare(const char* s1, const char* s2) const
|
||||||
{
|
{
|
||||||
_SetStrength(strength);
|
|
||||||
|
|
||||||
// TODO : handle fIgnorePunctuation
|
// TODO : handle fIgnorePunctuation
|
||||||
|
|
||||||
UErrorCode error = U_ZERO_ERROR;
|
UErrorCode error = U_ZERO_ERROR;
|
||||||
@@ -193,8 +178,6 @@ BCollator::Archive(BMessage* archive, bool deep) const
|
|||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
if (status == B_OK)
|
|
||||||
status = archive->AddInt32("loc:strength", fDefaultStrength);
|
|
||||||
if (status == B_OK)
|
if (status == B_OK)
|
||||||
status = archive->AddBool("loc:punctuation", fIgnorePunctuation);
|
status = archive->AddBool("loc:punctuation", fIgnorePunctuation);
|
||||||
|
|
||||||
@@ -229,10 +212,10 @@ BCollator::Instantiate(BMessage* archive)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BCollator::_SetStrength(int8 strength) const
|
BCollator::SetStrength(int8 strength) const
|
||||||
{
|
{
|
||||||
if (strength == B_COLLATE_DEFAULT)
|
if (strength == B_COLLATE_DEFAULT)
|
||||||
strength = fDefaultStrength;
|
strength = B_COLLATE_TERTIARY;
|
||||||
|
|
||||||
Collator::ECollationStrength icuStrength;
|
Collator::ECollationStrength icuStrength;
|
||||||
switch (strength) {
|
switch (strength) {
|
||||||
|
|||||||
@@ -50,11 +50,11 @@ CollatorTest::TestSortKeys()
|
|||||||
|
|
||||||
for (int32 strength = B_COLLATE_PRIMARY; strength < 4; strength++) {
|
for (int32 strength = B_COLLATE_PRIMARY; strength < 4; strength++) {
|
||||||
BString a, b;
|
BString a, b;
|
||||||
collator.GetSortKey(tests[i].first, &a, strength);
|
collator.SetStrength(strength);
|
||||||
collator.GetSortKey(tests[i].second, &b, strength);
|
collator.GetSortKey(tests[i].first, &a);
|
||||||
|
collator.GetSortKey(tests[i].second, &b);
|
||||||
|
|
||||||
int difference = collator.Compare(tests[i].first, tests[i].second,
|
int difference = collator.Compare(tests[i].first, tests[i].second);
|
||||||
strength);
|
|
||||||
CPPUNIT_ASSERT_EQUAL(tests[i].sign[strength - 1], difference);
|
CPPUNIT_ASSERT_EQUAL(tests[i].sign[strength - 1], difference);
|
||||||
int keydiff = strcmp(a.String(), b.String());
|
int keydiff = strcmp(a.String(), b.String());
|
||||||
// Check that the keys compare the same as the strings. Either both
|
// Check that the keys compare the same as the strings. Either both
|
||||||
|
|||||||
Reference in New Issue
Block a user