2013-05-28 16:56:05 +00:00
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
#include <unicode/ucol.h>
|
|
|
|
|
|
2015-10-05 01:35:28 +00:00
|
|
|
|
#include <DB/Common/Exception.h>
|
2013-06-21 20:34:19 +00:00
|
|
|
|
#include <DB/IO/WriteHelpers.h>
|
2013-05-29 12:38:20 +00:00
|
|
|
|
|
2015-09-29 19:19:54 +00:00
|
|
|
|
#include <common/Common.h>
|
2013-05-29 12:38:20 +00:00
|
|
|
|
|
2013-05-28 16:56:05 +00:00
|
|
|
|
#include <Poco/String.h>
|
|
|
|
|
|
2013-05-29 12:38:20 +00:00
|
|
|
|
#include <boost/noncopyable.hpp>
|
|
|
|
|
|
2016-01-11 21:46:36 +00:00
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
|
{
|
|
|
|
|
namespace ErrorCodes
|
|
|
|
|
{
|
|
|
|
|
extern const int UNSUPPORTED_COLLATION_LOCALE;
|
|
|
|
|
extern const int COLLATION_COMPARISON_FAILED;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-05-29 12:38:20 +00:00
|
|
|
|
class Collator : private boost::noncopyable
|
2013-05-28 16:56:05 +00:00
|
|
|
|
{
|
|
|
|
|
public:
|
2013-05-29 12:38:20 +00:00
|
|
|
|
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)
|
2013-06-21 20:34:19 +00:00
|
|
|
|
throw DB::Exception("ICU collation comparison failed with error code: " + DB::toString(status),
|
2013-05-28 16:56:05 +00:00
|
|
|
|
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;
|
2016-01-11 21:46:36 +00:00
|
|
|
|
};
|