6ddba32f48
Former-commit-id: fa7407621e839f87613476596c6589aeceb9d796
64 lines
1.8 KiB
C++
64 lines
1.8 KiB
C++
#include "range_based_case_converter.hpp"
|
|
|
|
uint32_t RangeBasedCaseConverter::convert(uint32_t code_point) const {
|
|
|
|
const CaseConversionRecord* conversionRecord = findRecord_(code_point);
|
|
|
|
return
|
|
conversionRecord == 0
|
|
? code_point
|
|
: applyRecord_(conversionRecord, code_point);
|
|
}
|
|
|
|
const CaseConversionRecord* RangeBasedCaseConverter::findRecord_(uint32_t code_point) const {
|
|
|
|
for (size_t i = 0; i < tableSize_; ++i) {
|
|
const CaseConversionRecord* currentRecord = &conversionTable_[i];
|
|
|
|
if (code_point < currentRecord->lo_code_point)
|
|
return 0;
|
|
|
|
if (code_point <= currentRecord->hi_code_point)
|
|
return currentRecord;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
uint32_t RangeBasedCaseConverter::applyRecord_(
|
|
const CaseConversionRecord* conversionRecord, uint32_t code_point) const {
|
|
|
|
if (shouldBeSkipped_(conversionRecord, code_point))
|
|
return code_point;
|
|
|
|
return applyDelta_(conversionRecord->delta, code_point);
|
|
}
|
|
|
|
|
|
bool RangeBasedCaseConverter::shouldBeSkipped_(
|
|
const CaseConversionRecord* conversionRecord, uint32_t code_point) const {
|
|
|
|
return
|
|
isSkipRecord_(conversionRecord)
|
|
&& code_point % 2 != conversionRecord->lo_code_point % 2;
|
|
}
|
|
|
|
bool RangeBasedCaseConverter::isSkipRecord_(const CaseConversionRecord* conversionRecord) const {
|
|
return
|
|
conversionRecord->delta == EVEN_ODD_SKIP
|
|
|| conversionRecord->delta == ODD_EVEN_SKIP;
|
|
}
|
|
|
|
uint32_t RangeBasedCaseConverter::applyDelta_(int32_t delta, uint32_t code_point) const {
|
|
switch (delta) {
|
|
case EVEN_ODD:
|
|
case EVEN_ODD_SKIP:
|
|
return code_point % 2 == 0 ? code_point+1 : code_point-1;
|
|
case ODD_EVEN:
|
|
case ODD_EVEN_SKIP:
|
|
return code_point % 2 == 1 ? code_point+1 : code_point-1;
|
|
default:
|
|
return code_point + delta;
|
|
}
|
|
}
|