| /* |
| * Copyright (C) 2008 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #ifndef GSMALPHABET_H_ |
| #define GSMALPHABET_H_ |
| #include <cstdint> |
| #include <string> |
| #include <map> |
| #include <memory> |
| #include <vector> |
| |
| class GsmAlphabet { |
| public: |
| GsmAlphabet(); |
| virtual ~GsmAlphabet(); |
| /** |
| * This escapes extended characters, and when present indicates that the |
| * following character should be looked up in the "extended" table. |
| * |
| * gsmToChar(GSM_EXTENDED_ESCAPE) returns 0xffff |
| */ |
| static constexpr uint8_t GSM_EXTENDED_ESCAPE = 0x1B; |
| |
| /** |
| * User data header requires one octet for length. Count as one septet, because |
| * all combinations of header elements below will have at least one free bit |
| * when padding to the nearest septet boundary. |
| */ |
| static constexpr int UDH_SEPTET_COST_LENGTH = 1; |
| |
| /** |
| * Using a non-default language locking shift table OR single shift table |
| * requires a user data header of 3 octets, or 4 septets, plus UDH length. |
| */ |
| static constexpr int UDH_SEPTET_COST_ONE_SHIFT_TABLE = 4; |
| |
| /** |
| * Using a non-default language locking shift table AND single shift table |
| * requires a user data header of 6 octets, or 7 septets, plus UDH length. |
| */ |
| static constexpr int UDH_SEPTET_COST_TWO_SHIFT_TABLES = 7; |
| |
| /** |
| * Multi-part messages require a user data header of 5 octets, or 6 septets, |
| * plus UDH length. |
| */ |
| static constexpr int UDH_SEPTET_COST_CONCATENATED_MESSAGE = 6; |
| |
| /** |
| * For a specific text string, this object describes protocol |
| * properties of encoding it for transmission as message user |
| * data. |
| */ |
| class TextEncodingDetails { |
| public: |
| /** |
| *The number of SMS's required to encode the text. |
| */ |
| int msgCount; |
| |
| /** |
| * The number of code units consumed so far, where code units |
| * are basically characters in the encoding -- for example, |
| * septets for the standard ASCII and GSM encodings, and 16 |
| * bits for Unicode. |
| */ |
| int codeUnitCount; |
| |
| /** |
| * How many code units are still available without spilling |
| * into an additional message. |
| */ |
| int codeUnitsRemaining; |
| |
| /** |
| * The encoding code unit size (specified using |
| * android.telephony.SmsMessage ENCODING_*). |
| */ |
| int codeUnitSize; |
| |
| /** |
| * The GSM national language table to use, or 0 for the default 7-bit alphabet. |
| */ |
| int languageTable; |
| |
| /** |
| * The GSM national language shift table to use, or 0 for the default 7-bit extension table. |
| */ |
| int languageShiftTable; |
| |
| std::string toString() { |
| return "TextEncodingDetails { msgCount=" + std::to_string(msgCount) |
| + ", codeUnitCount=" + std::to_string(codeUnitCount) |
| + ", codeUnitsRemaining=" + std::to_string(codeUnitsRemaining) |
| + ", codeUnitSize=" + std::to_string(codeUnitSize) |
| + ", languageTable=" + std::to_string(languageTable) |
| + ", languageShiftTable=" + std::to_string(languageShiftTable) + " }"; |
| } |
| }; |
| |
| static std::string gsm7BitPackedToString(std::vector<uint8_t> pdu, int offset, |
| int lengthSeptets, int numPaddingBits, int languageTable, int shiftTable); |
| static std::vector<uint8_t> stringToGsm7BitPacked(std::string data, int startingSeptetOffset, |
| bool throwException, int languageTable, int languageShiftTable); |
| private: |
| /** Reverse mapping from Unicode characters to indexes into language tables. */ |
| static const std::vector<std::shared_ptr<std::map<char, int>>> sCharsToGsmTables; |
| static std::vector<std::shared_ptr<std::map<char, int>>> initCharsToGsmTables(); |
| /** Reverse mapping from Unicode characters to indexes into language shift tables. */ |
| static const std::vector<std::shared_ptr<std::map<char, int>>> sCharsToShiftTables; |
| static std::vector<std::shared_ptr<std::map<char, int>>> initCharsToShiftTables(); |
| /** OEM configured list of enabled national language single shift tables for encoding. */ |
| static std::vector<int> sEnabledSingleShiftTables; |
| |
| /** OEM configured list of enabled national language locking shift tables for encoding. */ |
| static std::vector<int> sEnabledLockingShiftTables; |
| |
| /** Highest language code to include in array of single shift counters. */ |
| static int sHighestEnabledSingleShiftCode; |
| |
| /** Flag to bypass check for country-specific overlays (for test cases only). */ |
| static bool sDisableCountryEncodingCheck; |
| |
| /** |
| * Septet counter for a specific locking shift table and all of |
| * the single shift tables that it can be paired with. |
| */ |
| class LanguagePairCount { |
| public: |
| int languageCode; |
| std::vector<int> septetCounts; |
| std::vector<int> unencodableCounts; |
| LanguagePairCount(int code) { |
| languageCode = code; |
| int maxSingleShiftCode = sHighestEnabledSingleShiftCode; |
| septetCounts.assign((maxSingleShiftCode + 1), 0); |
| unencodableCounts.assign(maxSingleShiftCode + 1, 0); |
| // set counters for disabled single shift tables to -1 |
| // (GSM default extension table index 0 is always enabled) |
| for (int i = 1, tableOffset = 0; i <= maxSingleShiftCode; i++) { |
| if (sEnabledSingleShiftTables[tableOffset] == i) { |
| tableOffset++; |
| } else { |
| septetCounts[i] = -1; // disabled |
| } |
| } |
| // exclude Turkish locking + Turkish single shift table and |
| // Portuguese locking + Spanish single shift table (these |
| // combinations will never be optimal for any input). |
| if (code == 1 && maxSingleShiftCode >= 1) { |
| septetCounts[1] = -1; // Turkish + Turkish |
| } else if (code == 3 && maxSingleShiftCode >= 2) { |
| septetCounts[2] = -1; // Portuguese + Spanish |
| } |
| } |
| }; |
| static std::vector<std::string> sLanguageTables; |
| static std::vector<std::string> sLanguageShiftTables; |
| static void packSmsChar(std::vector<uint8_t> packedChars, int bitOffset, int value); |
| static int countGsmSeptetsUsingTables(std::string s, bool use7bitOnly,int languageTable, int languageShiftTable); |
| }; |
| |
| #endif /* GSMALPHABET_H_ */ |