| // natCharacter.cc - Native part of Character class. |
| |
| /* Copyright (C) 1998, 1999 Free Software Foundation |
| |
| This file is part of libgcj. |
| |
| This software is copyrighted work licensed under the terms of the |
| Libgcj License. Please consult the file "LIBGCJ_LICENSE" for |
| details. */ |
| |
| #include <config.h> |
| |
| #include <gcj/cni.h> |
| #include <jvm.h> |
| #include <java/lang/Character.h> |
| |
| #include <java-chartables.h> |
| |
| |
| |
| #define asize(x) ((sizeof (x)) / sizeof (x[0])) |
| |
| static jchar |
| to_lower_title (jchar ch) |
| { |
| for (unsigned int i = 0; i < asize (title_to_upper_table); ++i) |
| { |
| // We can assume that the entries in the two tables are |
| // parallel. This is checked in the script. |
| if (title_to_upper_table[i][1] == ch |
| || title_to_upper_table[i][0] == ch) |
| return title_to_lower_table[i][1]; |
| } |
| return ch; |
| } |
| |
| static jchar |
| to_upper_title (jchar ch) |
| { |
| for (unsigned int i = 0; i < asize (title_to_lower_table); ++i) |
| { |
| // We can assume that the entries in the two tables are |
| // parallel. This is checked in the script. |
| if (title_to_lower_table[i][1] == ch |
| || title_to_lower_table[i][0] == ch) |
| return title_to_upper_table[i][1]; |
| } |
| return ch; |
| } |
| |
| jboolean |
| java::lang::Character::isTitleCase (jchar ch) |
| { |
| for (unsigned int i = 0; i < asize (title_to_lower_table); ++i) |
| { |
| if (title_to_lower_table[i][0] == ch) |
| return true; |
| } |
| return false; |
| } |
| |
| jchar |
| java::lang::Character::toTitleCase (jchar ch) |
| { |
| // Both titlecase mapping tables have the same length. This is |
| // checked in the chartables script. |
| for (unsigned int i = 0; i < asize (title_to_lower_table); ++i) |
| { |
| if (title_to_lower_table[i][0] == ch) |
| return ch; |
| if (title_to_lower_table[i][1] == ch) |
| return title_to_lower_table[i][0]; |
| if (title_to_upper_table[i][1] == ch) |
| return title_to_upper_table[i][0]; |
| } |
| return toUpperCase (ch); |
| } |
| |
| #ifdef COMPACT_CHARACTER |
| |
| static int |
| table_search (const jchar table[][2], int table_len, jchar ch) |
| { |
| int low, high, i, old; |
| |
| low = 0; |
| high = table_len; |
| i = high / 2; |
| |
| while (true) |
| { |
| if (ch < table[i][0]) |
| high = i; |
| else if (ch > table[i][1]) |
| low = i; |
| else |
| return i; |
| |
| old = i; |
| i = (high + low) / 2; |
| if (i == old) |
| break; |
| } |
| |
| return -1; |
| } |
| |
| jint |
| java::lang::Character::digit_value (jchar ch) |
| { |
| int index = table_search (digit_table, asize (digit_table), ch); |
| if (index == -1) |
| return -1; |
| |
| jchar base = digit_table[index][0]; |
| // Tamil doesn't have a digit `0'. So we special-case it here. |
| if (base == TAMIL_DIGIT_ONE) |
| return ch - base + 1; |
| return ch - base; |
| } |
| |
| jint |
| java::lang::Character::getNumericValue (jchar ch) |
| { |
| jint d = digit (ch, 36); |
| if (d != -1) |
| return d; |
| |
| for (unsigned int i = 0; i < asize (numeric_table); ++i) |
| { |
| if (numeric_table[i] == ch) |
| return numeric_value[i]; |
| } |
| |
| return -1; |
| } |
| |
| jint |
| java::lang::Character::getType (jchar ch) |
| { |
| int index = table_search (all_table, asize (all_table), ch); |
| if (index != -1) |
| return category_table[index]; |
| return UNASSIGNED; |
| } |
| |
| jboolean |
| java::lang::Character::isLowerCase (jchar ch) |
| { |
| if (ch >= 0x2000 && ch <= 0x2fff) |
| return false; |
| if (table_search (lower_case_table, asize (lower_case_table), ch) != -1) |
| return true; |
| |
| int low, high, i, old; |
| |
| low = 0; |
| high = asize (lower_anomalous_table); |
| i = high / 2; |
| |
| while (true) |
| { |
| if (ch < lower_anomalous_table[i]) |
| high = i; |
| else if (ch > lower_anomalous_table[i]) |
| low = i; |
| else |
| return true; |
| |
| old = i; |
| i = (high + low) / 2; |
| if (i == old) |
| break; |
| } |
| |
| return false; |
| } |
| |
| jboolean |
| java::lang::Character::isSpaceChar (jchar ch) |
| { |
| return table_search (space_table, asize (space_table), ch) != -1; |
| } |
| |
| jboolean |
| java::lang::Character::isUpperCase (jchar ch) |
| { |
| if (ch >= 0x2000 && ch <= 0x2fff) |
| return false; |
| return table_search (upper_case_table, asize (upper_case_table), ch) != -1; |
| } |
| |
| jchar |
| java::lang::Character::toLowerCase (jchar ch) |
| { |
| int index = table_search (upper_case_table, asize (upper_case_table), ch); |
| if (index == -1) |
| return to_lower_title (ch); |
| return (jchar) (ch - upper_case_table[index][0] |
| + upper_case_map_table[index]); |
| } |
| |
| jchar |
| java::lang::Character::toUpperCase (jchar ch) |
| { |
| int index = table_search (lower_case_table, asize (lower_case_table), ch); |
| if (index == -1) |
| return to_upper_title (ch); |
| return (jchar) (ch - lower_case_table[index][0] |
| + lower_case_map_table[index]); |
| } |
| |
| #else /* COMPACT_CHARACTER */ |
| |
| jint |
| java::lang::Character::digit_value (jchar ch) |
| { |
| if (type_table[ch] == DECIMAL_DIGIT_NUMBER) |
| return attribute_table[ch]; |
| return -1; |
| } |
| |
| jint |
| java::lang::Character::getNumericValue (jchar ch) |
| { |
| jint d = digit (ch, 36); |
| if (d != -1) |
| return d; |
| |
| // Some characters require two attributes. We special-case them here. |
| if (ch >= ROMAN_START && ch <= ROMAN_END) |
| return secondary_attribute_table[ch - ROMAN_START]; |
| if (type_table[ch] == LETTER_NUMBER || type_table[ch] == OTHER_NUMBER) |
| return attribute_table[ch]; |
| return -1; |
| } |
| |
| jint |
| java::lang::Character::getType (jchar ch) |
| { |
| return type_table[ch]; |
| } |
| |
| jboolean |
| java::lang::Character::isLowerCase (jchar ch) |
| { |
| if (ch >= 0x2000 && ch <= 0x2fff) |
| return false; |
| return type_table[ch] == LOWERCASE_LETTER; |
| } |
| |
| jboolean |
| java::lang::Character::isSpaceChar (jchar ch) |
| { |
| return (type_table[ch] == SPACE_SEPARATOR |
| || type_table[ch] == LINE_SEPARATOR |
| || type_table[ch] == PARAGRAPH_SEPARATOR); |
| } |
| |
| jboolean |
| java::lang::Character::isUpperCase (jchar ch) |
| { |
| if (ch >= 0x2000 && ch <= 0x2fff) |
| return false; |
| return type_table[ch] == UPPERCASE_LETTER; |
| } |
| |
| jchar |
| java::lang::Character::toLowerCase (jchar ch) |
| { |
| if (type_table[ch] == UPPERCASE_LETTER) |
| return attribute_table[ch]; |
| return to_lower_title (ch); |
| } |
| |
| jchar |
| java::lang::Character::toUpperCase (jchar ch) |
| { |
| if (type_table[ch] == LOWERCASE_LETTER) |
| return attribute_table[ch]; |
| return to_upper_title (ch); |
| } |
| |
| #endif /* COMPACT_CHARACTER */ |