// automatically generated by props.pl at $ Tue Feb 21 20:59:55 2006 $
inline CharProperty::GeneralCategory CharProperty::getGeneralCategory(CodePoint cp) {
	if(const PropertyRange* p = findInRange(categories_, categories_ + categoryCount_, cp))
		return static_cast<GeneralCategory>(p->property);
	else
		return GC_OTHER_NOT_ASSIGNED;
}
inline CharProperty::CodeBlock CharProperty::getCodeBlock(CodePoint cp) {
	if(const PropertyRange* p = findInRange(blocks_, blocks_ + blockCount_, cp))
		return static_cast<CodeBlock>(p->property);
	else
		return CB_NOT_ASSIGNED;
}
inline CharProperty::Script CharProperty::getScript(CodePoint cp) {
	if(const PropertyRange* p = findInRange(scripts_, scripts_ + scriptCount_, cp))
		return static_cast<Script>(p->property);
	else
		return S_COMMON;
}
template<> inline bool CharProperty::hasBinaryProperty<CharProperty::BP_WHITE_SPACE>(CodePoint cp) {return std::binary_search(tableOfBp__White_Space_,tableOfBp__White_Space_+12,static_cast<char_t>(cp));}
template<> inline bool CharProperty::hasBinaryProperty<CharProperty::BP_BIDI_CONTROL>(CodePoint cp) {return findInRange(tableOfBp__Bidi_Control_,tableOfBp__Bidi_Control_+4,cp)!=0;}
template<> inline bool CharProperty::hasBinaryProperty<CharProperty::BP_JOIN_CONTROL>(CodePoint cp) {return findInRange(tableOfBp__Join_Control_,tableOfBp__Join_Control_+2,cp)!=0;}
template<> inline bool CharProperty::hasBinaryProperty<CharProperty::BP_DASH>(CodePoint cp) {return std::binary_search(tableOfBp__Dash_,tableOfBp__Dash_+16,static_cast<char_t>(cp));}
template<> inline bool CharProperty::hasBinaryProperty<CharProperty::BP_HYPHEN>(CodePoint cp) {return std::binary_search(tableOfBp__Hyphen_,tableOfBp__Hyphen_+10,static_cast<char_t>(cp));}
template<> inline bool CharProperty::hasBinaryProperty<CharProperty::BP_QUOTATION_MARK>(CodePoint cp) {return std::binary_search(tableOfBp__Quotation_Mark_,tableOfBp__Quotation_Mark_+27,static_cast<char_t>(cp));}
template<> inline bool CharProperty::hasBinaryProperty<CharProperty::BP_TERMINAL_PUNCTUATION>(CodePoint cp) {return findInRange(tableOfBp__Terminal_Punctuation_,tableOfBp__Terminal_Punctuation_+80,cp)!=0;}
template<> inline bool CharProperty::hasBinaryProperty<CharProperty::BP_OTHER_MATH>(CodePoint cp) {return findInRange(tableOfBp__Other_Math_,tableOfBp__Other_Math_+206,cp)!=0;}
template<> inline bool CharProperty::hasBinaryProperty<CharProperty::BP_HEX_DIGIT>(CodePoint cp) {return findInRange(tableOfBp__Hex_Digit_,tableOfBp__Hex_Digit_+12,cp)!=0;}
template<> inline bool CharProperty::hasBinaryProperty<CharProperty::BP_ASCII_HEX_DIGIT>(CodePoint cp) {return findInRange(tableOfBp__ASCII_Hex_Digit_,tableOfBp__ASCII_Hex_Digit_+6,cp)!=0;}
template<> inline bool CharProperty::hasBinaryProperty<CharProperty::BP_OTHER_ALPHABETIC>(CodePoint cp) {return findInRange(tableOfBp__Other_Alphabetic_,tableOfBp__Other_Alphabetic_+282,cp)!=0;}
template<> inline bool CharProperty::hasBinaryProperty<CharProperty::BP_IDEOGRAPHIC>(CodePoint cp) {return findInRange(tableOfBp__Ideographic_,tableOfBp__Ideographic_+20,cp)!=0;}
template<> inline bool CharProperty::hasBinaryProperty<CharProperty::BP_DIACRITIC>(CodePoint cp) {return findInRange(tableOfBp__Diacritic_,tableOfBp__Diacritic_+186,cp)!=0;}
template<> inline bool CharProperty::hasBinaryProperty<CharProperty::BP_EXTENDER>(CodePoint cp) {return std::binary_search(tableOfBp__Extender_,tableOfBp__Extender_+12,static_cast<char_t>(cp));}
template<> inline bool CharProperty::hasBinaryProperty<CharProperty::BP_OTHER_LOWERCASE>(CodePoint cp) {return findInRange(tableOfBp__Other_Lowercase_,tableOfBp__Other_Lowercase_+22,cp)!=0;}
template<> inline bool CharProperty::hasBinaryProperty<CharProperty::BP_OTHER_UPPERCASE>(CodePoint cp) {return findInRange(tableOfBp__Other_Uppercase_,tableOfBp__Other_Uppercase_+4,cp)!=0;}
template<> inline bool CharProperty::hasBinaryProperty<CharProperty::BP_NONCHARACTER_CODE_POINT>(CodePoint cp) {return findInRange(tableOfBp__Noncharacter_Code_Point_,tableOfBp__Noncharacter_Code_Point_+34,cp)!=0;}
template<> inline bool CharProperty::hasBinaryProperty<CharProperty::BP_OTHER_GRAPHEME_EXTEND>(CodePoint cp) {return std::binary_search(tableOfBp__Other_Grapheme_Extend_,tableOfBp__Other_Grapheme_Extend_+15,cp);}
template<> inline bool CharProperty::hasBinaryProperty<CharProperty::BP_GRAPHEME_LINK>(CodePoint cp) {return std::binary_search(tableOfBp__Grapheme_Link_,tableOfBp__Grapheme_Link_+16,cp);}
template<> inline bool CharProperty::hasBinaryProperty<CharProperty::BP_IDS_BINARY_OPERATOR>(CodePoint cp) {return findInRange(tableOfBp__IDS_Binary_Operator_,tableOfBp__IDS_Binary_Operator_+4,cp)!=0;}
template<> inline bool CharProperty::hasBinaryProperty<CharProperty::BP_IDS_TRINARY_OPERATOR>(CodePoint cp) {return findInRange(tableOfBp__IDS_Trinary_Operator_,tableOfBp__IDS_Trinary_Operator_+2,cp)!=0;}
template<> inline bool CharProperty::hasBinaryProperty<CharProperty::BP_RADICAL>(CodePoint cp) {return findInRange(tableOfBp__Radical_,tableOfBp__Radical_+6,cp)!=0;}
template<> inline bool CharProperty::hasBinaryProperty<CharProperty::BP_UNIFIED_IDEOGRAPH>(CodePoint cp) {return findInRange(tableOfBp__Unified_Ideograph_,tableOfBp__Unified_Ideograph_+20,cp)!=0;}
template<> inline bool CharProperty::hasBinaryProperty<CharProperty::BP_OTHER_DEFAULT_IGNORABLE_CODE_POINT>(CodePoint cp) {return findInRange(tableOfBp__Other_Default_Ignorable_Code_Point_,tableOfBp__Other_Default_Ignorable_Code_Point_+20,cp)!=0;}
template<> inline bool CharProperty::hasBinaryProperty<CharProperty::BP_DEPRECATED>(CodePoint cp) {return findInRange(tableOfBp__Deprecated_,tableOfBp__Deprecated_+8,cp)!=0;}
template<> inline bool CharProperty::hasBinaryProperty<CharProperty::BP_SOFT_DOTTED>(CodePoint cp) {return findInRange(tableOfBp__Soft_Dotted_,tableOfBp__Soft_Dotted_+58,cp)!=0;}
template<> inline bool CharProperty::hasBinaryProperty<CharProperty::BP_LOGICAL_ORDER_EXCEPTION>(CodePoint cp) {return findInRange(tableOfBp__Logical_Order_Exception_,tableOfBp__Logical_Order_Exception_+4,cp)!=0;}
template<> inline bool CharProperty::hasBinaryProperty<CharProperty::BP_OTHER_ID_START>(CodePoint cp) {return std::binary_search(tableOfBp__Other_ID_Start_,tableOfBp__Other_ID_Start_+3,static_cast<char_t>(cp));}
template<> inline bool CharProperty::hasBinaryProperty<CharProperty::BP_OTHER_ID_CONTINUE>(CodePoint cp) {return findInRange(tableOfBp__Other_ID_Continue_,tableOfBp__Other_ID_Continue_+2,cp)!=0;}
template<> inline bool CharProperty::hasBinaryProperty<CharProperty::BP_STERM>(CodePoint cp) {return std::binary_search(tableOfBp__STerm_,tableOfBp__STerm_+26,static_cast<char_t>(cp));}
template<> inline bool CharProperty::hasBinaryProperty<CharProperty::BP_VARIATION_SELECTOR>(CodePoint cp) {return findInRange(tableOfBp__Variation_Selector_,tableOfBp__Variation_Selector_+6,cp)!=0;}
template<> inline bool CharProperty::hasBinaryProperty<CharProperty::BP_PATTERN_WHITE_SPACE>(CodePoint cp) {return std::binary_search(tableOfBp__Pattern_White_Space_,tableOfBp__Pattern_White_Space_+6,static_cast<char_t>(cp));}
template<> inline bool CharProperty::hasBinaryProperty<CharProperty::BP_PATTERN_SYNTAX>(CodePoint cp) {return findInRange(tableOfBp__Pattern_Syntax_,tableOfBp__Pattern_Syntax_+478,cp)!=0;}
template<> inline bool CharProperty::hasBinaryProperty<CharProperty::BP_ALPHABETIC>(CodePoint cp) {
	const GeneralCategory gc = getGeneralCategory(cp);
	return gc == GC_LETTER_UPPERCASE
		|| gc == GC_LETTER_LOWERCASE
		|| gc == GC_LETTER_TITLECASE
		|| gc == GC_LETTER_OTHER
		|| gc == GC_NUMBER_LETTER
		|| hasBinaryProperty<BP_OTHER_ALPHABETIC>(cp);
}
template<> inline bool CharProperty::hasBinaryProperty<CharProperty::BP_DEFAULT_IGNORABLE_CODE_POINT>(CodePoint cp) {
	const GeneralCategory gc = getGeneralCategory(cp);
	return (gc == GC_OTHER_FORMAT
		|| gc == GC_OTHER_CONTROL
		|| gc == GC_OTHER_SURROGATE
		|| hasBinaryProperty<BP_OTHER_DEFAULT_IGNORABLE_CODE_POINT>(cp)
		|| hasBinaryProperty<BP_NONCHARACTER_CODE_POINT>(cp))
		&& !hasBinaryProperty<BP_WHITE_SPACE>(cp);
}
template<> inline bool CharProperty::hasBinaryProperty<CharProperty::BP_LOWERCASE>(CodePoint cp) {
	return getGeneralCategory(cp) == GC_LETTER_LOWERCASE || hasBinaryProperty<BP_OTHER_LOWERCASE>(cp);
}
template<> inline bool CharProperty::hasBinaryProperty<CharProperty::BP_GRAPHEME_EXTEND>(CodePoint cp) {
	const GeneralCategory gc = getGeneralCategory(cp);
	return gc == GC_MARK_ENCLOSING
		|| gc == GC_MARK_NONSPACING
		|| hasBinaryProperty<BP_OTHER_GRAPHEME_EXTEND>(cp);
}
template<> inline bool CharProperty::hasBinaryProperty<CharProperty::BP_GRAPHEME_BASE>(CodePoint cp) {
	const GeneralCategory gc = getGeneralCategory(cp);
	return gc != GC_OTHER_CONTROL
		&& gc != GC_OTHER_FORMAT
		&& gc != GC_OTHER_SURROGATE
		&& gc != GC_OTHER_PRIVATE_USE
		&& gc != GC_OTHER_NOT_ASSIGNED
		&& gc != GC_SEPARATOR_LINE
		&& gc != GC_SEPARATOR_PARAGRAPH
		&& !hasBinaryProperty<BP_GRAPHEME_EXTEND>(cp);
}
template<> inline bool CharProperty::hasBinaryProperty<CharProperty::BP_MATH>(CodePoint cp) {
	return getGeneralCategory(cp) == GC_SYMBOL_MATH || hasBinaryProperty<BP_OTHER_MATH>(cp);
}
template<> inline bool CharProperty::hasBinaryProperty<CharProperty::BP_UPPERCASE>(CodePoint cp) {
	return getGeneralCategory(cp) == GC_LETTER_UPPERCASE || hasBinaryProperty<BP_OTHER_UPPERCASE>(cp);
}
inline bool CharProperty::isLetter(CodePoint cp) {
	const GeneralCategory gc = getGeneralCategory(cp);
	return gc >= GC_LETTER_UPPERCASE && gc < GC_MARK_NONSPACING;
}
inline bool CharProperty::isMark(CodePoint cp) {
	const GeneralCategory gc = getGeneralCategory(cp);
	return gc >= GC_MARK_NONSPACING && gc < GC_NUMBER_DECIMAL_DIGIT;
}
inline bool CharProperty::isNumber(CodePoint cp) {
	const GeneralCategory gc = getGeneralCategory(cp);
	return gc >= GC_NUMBER_DECIMAL_DIGIT && gc < GC_SYMBOL_MATH;
}
inline bool CharProperty::isSymbol(CodePoint cp) {
	const GeneralCategory gc = getGeneralCategory(cp);
	return gc >= GC_SYMBOL_MATH && gc < GC_PUNCTUATION_CONNECTOR;
}
inline bool CharProperty::isPunctuation(CodePoint cp) {
	const GeneralCategory gc = getGeneralCategory(cp);
	return gc >= GC_PUNCTUATION_CONNECTOR && gc < GC_SEPARATOR_SPACE;
}
inline bool CharProperty::isSeparator(CodePoint cp) {
	const GeneralCategory gc = getGeneralCategory(cp);
	return gc >= GC_SEPARATOR_SPACE && gc < GC_OTHER_CONTROL;
}
inline bool CharProperty::isOther(CodePoint cp) {
	const GeneralCategory gc = getGeneralCategory(cp);
	return gc >= GC_OTHER_CONTROL && gc <= GC_OTHER_NOT_ASSIGNED;
}
inline CodePoint CharacterFolder::foldCase(CodePoint cp) {
	if(cp < 0x10000) {
		const char_t* const p = std::lower_bound(CASED_UCS2, CASED_UCS2 + 865, static_cast<char_t>(cp));
		return (*p == cp) ? FOLDED_UCS2[p - CASED_UCS2] : cp;
	} else {
		const CodePoint* const p = std::lower_bound(CASED_UCS4, CASED_UCS4 + (904 + 1 - 865), cp);
		return (*p == cp) ? FOLDED_UCS4[p - CASED_UCS4] : cp;
	}
}
inline std::size_t CharProperty::toNFD(CodePoint cp, CodePoint& first, CodePoint& second) {
	const CodePoint* const p = std::lower_bound(NFD_SRC, NFD_SRC + 2031 - 1, cp);
	if(*p != cp)
		return (first = cp), 1;
	const CodePoint res = NFD_RES[p - NFD_SRC];
	if(res <= 0x10FFFF)
		return (first = res), 1;
	else if(cp >= 0x10000 && cp < 0x20000)
		return (first = (res >> 16) + 0x10000), (second = (res & 0xFFFF) + 0x10000), 2;
	else
		return (first = (res >> 16)), (second = (res & 0xFFFF)), 2;
}
inline length_t CharProperty::toNFD(CodePoint cp, char_t* dest) {
	CodePoint first, second;
	if(toNFD(cp, first, second) == 1)
		return UTF16Surrogates::encode(first, dest) ? 2 : 1;
	else {
		const length_t c = UTF16Surrogates::encode(first, dest) ? 2 : 1;
		return c + UTF16Surrogates::encode(second, dest + c) ? 2 : 1;
	}
}
