147e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown/* 247e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown * Copyright (C) 2008 The Android Open Source Project 347e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown * 447e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License"); 547e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown * you may not use this file except in compliance with the License. 647e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown * You may obtain a copy of the License at 747e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown * 847e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown * http://www.apache.org/licenses/LICENSE-2.0 947e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown * 1047e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown * Unless required by applicable law or agreed to in writing, software 1147e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS, 1247e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1347e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown * See the License for the specific language governing permissions and 1447e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown * limitations under the License. 1547e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown */ 1647e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown 1747e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown#define LOG_TAG "PropertyMap" 1847e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown 1947e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown#include <stdlib.h> 2047e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown#include <string.h> 2147e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown 2247e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown#include <utils/PropertyMap.h> 2347e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown#include <utils/Log.h> 2447e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown 2547e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown// Enables debug output for the parser. 2647e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown#define DEBUG_PARSER 0 2747e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown 2847e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown// Enables debug output for parser performance. 2947e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown#define DEBUG_PARSER_PERFORMANCE 0 3047e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown 3147e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown 3247e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brownnamespace android { 3347e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown 3447e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brownstatic const char* WHITESPACE = " \t\r"; 3547e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brownstatic const char* WHITESPACE_OR_PROPERTY_DELIMITER = " \t\r="; 3647e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown 3747e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown 3847e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown// --- PropertyMap --- 3947e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown 4047e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff BrownPropertyMap::PropertyMap() { 4147e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown} 4247e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown 4347e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff BrownPropertyMap::~PropertyMap() { 4447e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown} 4547e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown 4647e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brownvoid PropertyMap::clear() { 4747e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown mProperties.clear(); 4847e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown} 4947e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown 5047e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brownvoid PropertyMap::addProperty(const String8& key, const String8& value) { 5147e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown mProperties.add(key, value); 5247e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown} 5347e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown 5447e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brownbool PropertyMap::hasProperty(const String8& key) const { 5547e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown return mProperties.indexOfKey(key) >= 0; 5647e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown} 5747e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown 5847e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brownbool PropertyMap::tryGetProperty(const String8& key, String8& outValue) const { 5947e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown ssize_t index = mProperties.indexOfKey(key); 6047e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown if (index < 0) { 6147e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown return false; 6247e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown } 6347e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown 6447e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown outValue = mProperties.valueAt(index); 6547e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown return true; 6647e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown} 6747e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown 6847e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brownbool PropertyMap::tryGetProperty(const String8& key, bool& outValue) const { 6947e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown int32_t intValue; 7047e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown if (!tryGetProperty(key, intValue)) { 7147e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown return false; 7247e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown } 7347e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown 7447e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown outValue = intValue; 7547e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown return true; 7647e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown} 7747e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown 7847e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brownbool PropertyMap::tryGetProperty(const String8& key, int32_t& outValue) const { 7947e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown String8 stringValue; 8047e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown if (! tryGetProperty(key, stringValue) || stringValue.length() == 0) { 8147e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown return false; 8247e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown } 8347e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown 8447e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown char* end; 8547e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown int value = strtol(stringValue.string(), & end, 10); 8647e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown if (*end != '\0') { 8747e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown LOGW("Property key '%s' has invalid value '%s'. Expected an integer.", 8847e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown key.string(), stringValue.string()); 8947e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown return false; 9047e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown } 9147e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown outValue = value; 9247e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown return true; 9347e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown} 9447e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown 9547e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brownbool PropertyMap::tryGetProperty(const String8& key, float& outValue) const { 9647e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown String8 stringValue; 9747e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown if (! tryGetProperty(key, stringValue) || stringValue.length() == 0) { 9847e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown return false; 9947e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown } 10047e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown 10147e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown char* end; 10247e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown float value = strtof(stringValue.string(), & end); 10347e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown if (*end != '\0') { 10447e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown LOGW("Property key '%s' has invalid value '%s'. Expected a float.", 10547e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown key.string(), stringValue.string()); 10647e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown return false; 10747e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown } 10847e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown outValue = value; 10947e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown return true; 11047e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown} 11147e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown 11283c09685f2e62bc3cf7e71bc61d903f4b9ccaeb4Jeff Brownvoid PropertyMap::addAll(const PropertyMap* map) { 11383c09685f2e62bc3cf7e71bc61d903f4b9ccaeb4Jeff Brown for (size_t i = 0; i < map->mProperties.size(); i++) { 11483c09685f2e62bc3cf7e71bc61d903f4b9ccaeb4Jeff Brown mProperties.add(map->mProperties.keyAt(i), map->mProperties.valueAt(i)); 11583c09685f2e62bc3cf7e71bc61d903f4b9ccaeb4Jeff Brown } 11683c09685f2e62bc3cf7e71bc61d903f4b9ccaeb4Jeff Brown} 11783c09685f2e62bc3cf7e71bc61d903f4b9ccaeb4Jeff Brown 11847e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brownstatus_t PropertyMap::load(const String8& filename, PropertyMap** outMap) { 11947e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown *outMap = NULL; 12047e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown 12147e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown Tokenizer* tokenizer; 12247e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown status_t status = Tokenizer::open(filename, &tokenizer); 12347e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown if (status) { 12447e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown LOGE("Error %d opening property file %s.", status, filename.string()); 12547e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown } else { 12647e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown PropertyMap* map = new PropertyMap(); 12747e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown if (!map) { 12847e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown LOGE("Error allocating property map."); 12947e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown status = NO_MEMORY; 13047e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown } else { 13147e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown#if DEBUG_PARSER_PERFORMANCE 13247e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown nsecs_t startTime = systemTime(SYSTEM_TIME_MONOTONIC); 13347e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown#endif 13447e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown Parser parser(map, tokenizer); 13547e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown status = parser.parse(); 13647e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown#if DEBUG_PARSER_PERFORMANCE 13747e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown nsecs_t elapsedTime = systemTime(SYSTEM_TIME_MONOTONIC) - startTime; 13847e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown LOGD("Parsed property file '%s' %d lines in %0.3fms.", 13947e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown tokenizer->getFilename().string(), tokenizer->getLineNumber(), 14047e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown elapsedTime / 1000000.0); 14147e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown#endif 14247e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown if (status) { 14347e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown delete map; 14447e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown } else { 14547e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown *outMap = map; 14647e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown } 14747e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown } 14847e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown delete tokenizer; 14947e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown } 15047e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown return status; 15147e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown} 15247e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown 15347e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown 15447e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown// --- PropertyMap::Parser --- 15547e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown 15647e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff BrownPropertyMap::Parser::Parser(PropertyMap* map, Tokenizer* tokenizer) : 15747e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown mMap(map), mTokenizer(tokenizer) { 15847e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown} 15947e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown 16047e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff BrownPropertyMap::Parser::~Parser() { 16147e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown} 16247e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown 16347e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brownstatus_t PropertyMap::Parser::parse() { 16447e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown while (!mTokenizer->isEof()) { 16547e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown#if DEBUG_PARSER 16647e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown LOGD("Parsing %s: '%s'.", mTokenizer->getLocation().string(), 16747e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown mTokenizer->peekRemainderOfLine().string()); 16847e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown#endif 16947e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown 17047e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown mTokenizer->skipDelimiters(WHITESPACE); 17147e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown 17247e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown if (!mTokenizer->isEol() && mTokenizer->peekChar() != '#') { 17347e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown String8 keyToken = mTokenizer->nextToken(WHITESPACE_OR_PROPERTY_DELIMITER); 17447e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown if (keyToken.isEmpty()) { 17547e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown LOGE("%s: Expected non-empty property key.", mTokenizer->getLocation().string()); 17647e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown return BAD_VALUE; 17747e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown } 17847e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown 17947e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown mTokenizer->skipDelimiters(WHITESPACE); 18047e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown 18147e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown if (mTokenizer->nextChar() != '=') { 18247e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown LOGE("%s: Expected '=' between property key and value.", 18347e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown mTokenizer->getLocation().string()); 18447e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown return BAD_VALUE; 18547e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown } 18647e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown 18747e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown mTokenizer->skipDelimiters(WHITESPACE); 18847e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown 18947e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown String8 valueToken = mTokenizer->nextToken(WHITESPACE); 19047e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown if (valueToken.find("\\", 0) >= 0 || valueToken.find("\"", 0) >= 0) { 19147e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown LOGE("%s: Found reserved character '\\' or '\"' in property value.", 19247e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown mTokenizer->getLocation().string()); 19347e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown return BAD_VALUE; 19447e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown } 19547e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown 19647e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown mTokenizer->skipDelimiters(WHITESPACE); 19747e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown if (!mTokenizer->isEol()) { 19847e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown LOGE("%s: Expected end of line, got '%s'.", 19947e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown mTokenizer->getLocation().string(), 20047e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown mTokenizer->peekRemainderOfLine().string()); 20147e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown return BAD_VALUE; 20247e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown } 20347e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown 20447e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown if (mMap->hasProperty(keyToken)) { 20547e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown LOGE("%s: Duplicate property value for key '%s'.", 20647e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown mTokenizer->getLocation().string(), keyToken.string()); 20747e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown return BAD_VALUE; 20847e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown } 20947e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown 21047e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown mMap->addProperty(keyToken, valueToken); 21147e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown } 21247e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown 21347e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown mTokenizer->nextLine(); 21447e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown } 21547e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown return NO_ERROR; 21647e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown} 21747e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown 21847e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown} // namespace android 219