ClickHouse/dbms/include/DB/Common/Collator.h

64 lines
1.5 KiB
C
Raw Normal View History

2013-05-28 16:56:05 +00:00
#pragma once
#include <unicode/ucol.h>
#include <DB/Core/ErrorCodes.h>
#include <DB/Core/Exception.h>
2013-05-28 16:56:05 +00:00
#include <Yandex/Common.h>
2013-05-28 16:56:05 +00:00
#include <Poco/String.h>
#include <Poco/NumberFormatter.h>
#include <boost/noncopyable.hpp>
class Collator : private boost::noncopyable
2013-05-28 16:56:05 +00:00
{
public:
explicit Collator(const std::string & locale_) : locale(Poco::toLower(locale_))
2013-05-28 16:56:05 +00:00
{
UErrorCode status = U_ZERO_ERROR;
collator = ucol_open(locale.c_str(), &status);
if (status != U_ZERO_ERROR)
{
ucol_close(collator);
throw DB::Exception("Unsupported collation locale: " + locale, DB::ErrorCodes::UNSUPPORTED_COLLATION_LOCALE);
}
}
~Collator()
{
ucol_close(collator);
}
int compare(const char * str1, size_t length1, const char * str2, size_t length2) const
{
UCharIterator iter1, iter2;
uiter_setUTF8(&iter1, str1, length1);
uiter_setUTF8(&iter2, str2, length2);
UErrorCode status = U_ZERO_ERROR;
UCollationResult compare_result = ucol_strcollIter(collator, &iter1, &iter2, &status);
if (status != U_ZERO_ERROR)
throw DB::Exception("ICU collation comparison failed with error code: " + Poco::NumberFormatter::format(status),
DB::ErrorCodes::COLLATION_COMPARISON_FAILED);
/** Значения enum UCollationResult совпадают с нужными нам:
* UCOL_EQUAL = 0
* UCOL_GREATER = 1
* UCOL_LESS = -1
*/
return compare_result;
}
const std::string & getLocale() const
{
return locale;
}
private:
std::string locale;
UCollator * collator;
};