16f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/* 26f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Copyright (C) 2015 The Android Open Source Project 36f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * 46f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Licensed under the Apache License, Version 2.0 (the "License"); 56f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * you may not use this file except in compliance with the License. 66f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * You may obtain a copy of the License at 76f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * 86f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * http://www.apache.org/licenses/LICENSE-2.0 96f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * 106f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Unless required by applicable law or agreed to in writing, software 116f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * distributed under the License is distributed on an "AS IS" BASIS, 126f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * See the License for the specific language governing permissions and 146f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * limitations under the License. 156f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */ 166f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 176f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include "Locale.h" 186f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 196f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <ctype.h> 20ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 21cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski#include <algorithm> 226f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <string> 236f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <vector> 246f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 25ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include "util/Util.h" 26ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 27b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinskiusing ::android::ResTable_config; 28b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinskiusing ::android::StringPiece; 296f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 30b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinskinamespace aapt { 316f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 32ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskivoid LocaleValue::set_language(const char* language_chars) { 33cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski size_t i = 0; 34ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski while ((*language_chars) != '\0') { 35ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski language[i++] = ::tolower(*language_chars); 36ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski language_chars++; 37cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 386f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 396f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 40ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskivoid LocaleValue::set_region(const char* region_chars) { 41cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski size_t i = 0; 42ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski while ((*region_chars) != '\0') { 43ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski region[i++] = ::toupper(*region_chars); 44ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski region_chars++; 45cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 466f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 476f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 48ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskivoid LocaleValue::set_script(const char* script_chars) { 49cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski size_t i = 0; 50ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski while ((*script_chars) != '\0') { 51cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (i == 0) { 52ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski script[i++] = ::toupper(*script_chars); 53cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } else { 54ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski script[i++] = ::tolower(*script_chars); 556f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 56ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski script_chars++; 57cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 586f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 596f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 60ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskivoid LocaleValue::set_variant(const char* variant_chars) { 61cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski size_t i = 0; 62ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski while ((*variant_chars) != '\0') { 63ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski variant[i++] = *variant_chars; 64ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski variant_chars++; 65cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 666f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 676f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 68ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic inline bool is_alpha(const std::string& str) { 69cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return std::all_of(std::begin(str), std::end(str), ::isalpha); 706f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 716f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 72ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic inline bool is_number(const std::string& str) { 73cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return std::all_of(std::begin(str), std::end(str), ::isdigit); 746f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 756f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 76b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinskibool LocaleValue::InitFromFilterString(const StringPiece& str) { 77cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // A locale (as specified in the filter) is an underscore separated name such 78cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // as "en_US", "en_Latn_US", or "en_US_POSIX". 79ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::vector<std::string> parts = util::SplitAndLowercase(str, '_'); 80cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 81ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const int num_tags = parts.size(); 82cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski bool valid = false; 83ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (num_tags >= 1) { 84cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski const std::string& lang = parts[0]; 85ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (is_alpha(lang) && (lang.length() == 2 || lang.length() == 3)) { 86ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski set_language(lang.c_str()); 87cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski valid = true; 88cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 89cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 90cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 91ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!valid || num_tags == 1) { 92cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return valid; 93cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 94cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 95cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // At this point, valid == true && numTags > 1. 96cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski const std::string& part2 = parts[1]; 97ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if ((part2.length() == 2 && is_alpha(part2)) || 98ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski (part2.length() == 3 && is_number(part2))) { 99ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski set_region(part2.c_str()); 100ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } else if (part2.length() == 4 && is_alpha(part2)) { 101ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski set_script(part2.c_str()); 102cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } else if (part2.length() >= 4 && part2.length() <= 8) { 103ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski set_variant(part2.c_str()); 104cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } else { 105cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski valid = false; 106cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 107cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 108ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!valid || num_tags == 2) { 109cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return valid; 110cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 111cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 112cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // At this point, valid == true && numTags > 1. 113cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski const std::string& part3 = parts[2]; 114ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (((part3.length() == 2 && is_alpha(part3)) || 115ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski (part3.length() == 3 && is_number(part3))) && 116cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski script[0]) { 117ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski set_region(part3.c_str()); 118cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } else if (part3.length() >= 4 && part3.length() <= 8) { 119ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski set_variant(part3.c_str()); 120cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } else { 121cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski valid = false; 122cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 123cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 124ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!valid || num_tags == 3) { 125cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return valid; 126cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 127cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 128cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski const std::string& part4 = parts[3]; 129cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (part4.length() >= 4 && part4.length() <= 8) { 130ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski set_variant(part4.c_str()); 131cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } else { 132cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski valid = false; 133cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 134cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 135ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!valid || num_tags > 4) { 136cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return false; 137cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 138cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 139cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return true; 1406f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 1416f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 142b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinskibool LocaleValue::InitFromBcp47Tag(const StringPiece& bcp47tag) { 143b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski return InitFromBcp47TagImpl(bcp47tag, '-'); 144b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski} 145b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski 146b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinskibool LocaleValue::InitFromBcp47TagImpl(const StringPiece& bcp47tag, const char separator) { 147b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski std::vector<std::string> subtags = util::SplitAndLowercase(bcp47tag, separator); 148b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski if (subtags.size() == 1) { 149b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski set_language(subtags[0].c_str()); 150b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski } else if (subtags.size() == 2) { 151b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski set_language(subtags[0].c_str()); 152b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski 153b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski // The second tag can either be a region, a variant or a script. 154b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski switch (subtags[1].size()) { 155b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski case 2: 156b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski case 3: 157b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski set_region(subtags[1].c_str()); 158b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski break; 159b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski case 4: 160b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski if ('0' <= subtags[1][0] && subtags[1][0] <= '9') { 161b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski // This is a variant: fall through 162b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski } else { 163b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski set_script(subtags[1].c_str()); 164b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski break; 165b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski } 166b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski case 5: 167b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski case 6: 168b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski case 7: 169b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski case 8: 170b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski set_variant(subtags[1].c_str()); 171b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski break; 172b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski default: 173b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski return false; 174b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski } 175b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski } else if (subtags.size() == 3) { 176b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski // The language is always the first subtag. 177b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski set_language(subtags[0].c_str()); 178b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski 179b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski // The second subtag can either be a script or a region code. 180b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski // If its size is 4, it's a script code, else it's a region code. 181b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski if (subtags[1].size() == 4) { 182b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski set_script(subtags[1].c_str()); 183b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski } else if (subtags[1].size() == 2 || subtags[1].size() == 3) { 184b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski set_region(subtags[1].c_str()); 185b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski } else { 186b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski return false; 187b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski } 188b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski 189b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski // The third tag can either be a region code (if the second tag was 190b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski // a script), else a variant code. 191b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski if (subtags[2].size() >= 4) { 192b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski set_variant(subtags[2].c_str()); 193b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski } else { 194b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski set_region(subtags[2].c_str()); 195b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski } 196b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski } else if (subtags.size() == 4) { 197b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski set_language(subtags[0].c_str()); 198b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski set_script(subtags[1].c_str()); 199b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski set_region(subtags[2].c_str()); 200b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski set_variant(subtags[3].c_str()); 201b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski } else { 202b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski return false; 203b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski } 204b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski return true; 205b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski} 206b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski 207ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskissize_t LocaleValue::InitFromParts(std::vector<std::string>::iterator iter, 208cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::vector<std::string>::iterator end) { 209ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const std::vector<std::string>::iterator start_iter = iter; 210cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 211cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string& part = *iter; 212cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (part[0] == 'b' && part[1] == '+') { 213cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // This is a "modified" BCP 47 language tag. Same semantics as BCP 47 tags, 214b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski // except that the separator is "+" and not "-". Skip the prefix 'b+'. 215b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski if (!InitFromBcp47TagImpl(StringPiece(part).substr(2), '+')) { 216cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return -1; 217cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 218cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ++iter; 219cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } else { 220b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski if ((part.length() == 2 || part.length() == 3) && is_alpha(part) && part != "car") { 221ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski set_language(part.c_str()); 222cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ++iter; 223cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 224cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (iter != end) { 225ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const std::string& region_part = *iter; 226ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (region_part.c_str()[0] == 'r' && region_part.length() == 3) { 227ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski set_region(region_part.c_str() + 1); 228cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ++iter; 2296f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 230cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 2316f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 232cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 233ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return static_cast<ssize_t>(iter - start_iter); 2346f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 2356f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 236ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskivoid LocaleValue::InitFromResTable(const ResTable_config& config) { 237cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski config.unpackLanguage(language); 238cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski config.unpackRegion(region); 239cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (config.localeScript[0] && !config.localeScriptWasComputed) { 240cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski memcpy(script, config.localeScript, sizeof(config.localeScript)); 241cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 242cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 243cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (config.localeVariant[0]) { 244cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski memcpy(variant, config.localeVariant, sizeof(config.localeVariant)); 245cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 2466f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 2476f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 248ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskivoid LocaleValue::WriteTo(ResTable_config* out) const { 249cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski out->packLanguage(language); 250cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski out->packRegion(region); 2516f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 252cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (script[0]) { 253cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski memcpy(out->localeScript, script, sizeof(out->localeScript)); 254cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 2556f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 256cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (variant[0]) { 257cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski memcpy(out->localeVariant, variant, sizeof(out->localeVariant)); 258cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 2596f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 2606f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 261cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski} // namespace aapt 262