1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/widget/gonk/libui/VirtualKeyMap.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,171 @@ 1.4 +/* 1.5 + * Copyright (C) 2010 The Android Open Source Project 1.6 + * 1.7 + * Licensed under the Apache License, Version 2.0 (the "License"); 1.8 + * you may not use this file except in compliance with the License. 1.9 + * You may obtain a copy of the License at 1.10 + * 1.11 + * http://www.apache.org/licenses/LICENSE-2.0 1.12 + * 1.13 + * Unless required by applicable law or agreed to in writing, software 1.14 + * distributed under the License is distributed on an "AS IS" BASIS, 1.15 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1.16 + * See the License for the specific language governing permissions and 1.17 + * limitations under the License. 1.18 + */ 1.19 + 1.20 +#define LOG_TAG "VirtualKeyMap" 1.21 +#include "cutils_log.h" 1.22 + 1.23 +#include <stdlib.h> 1.24 +#include <string.h> 1.25 +#include "VirtualKeyMap.h" 1.26 +#include <utils/Errors.h> 1.27 +#include "Tokenizer.h" 1.28 +#include <utils/Timers.h> 1.29 + 1.30 +// Enables debug output for the parser. 1.31 +#define DEBUG_PARSER 0 1.32 + 1.33 +// Enables debug output for parser performance. 1.34 +#define DEBUG_PARSER_PERFORMANCE 0 1.35 + 1.36 + 1.37 +namespace android { 1.38 + 1.39 +static const char* WHITESPACE = " \t\r"; 1.40 +static const char* WHITESPACE_OR_FIELD_DELIMITER = " \t\r:"; 1.41 + 1.42 + 1.43 +// --- VirtualKeyMap --- 1.44 + 1.45 +VirtualKeyMap::VirtualKeyMap() { 1.46 +} 1.47 + 1.48 +VirtualKeyMap::~VirtualKeyMap() { 1.49 +} 1.50 + 1.51 +status_t VirtualKeyMap::load(const String8& filename, VirtualKeyMap** outMap) { 1.52 + *outMap = NULL; 1.53 + 1.54 + Tokenizer* tokenizer; 1.55 + status_t status = Tokenizer::open(filename, &tokenizer); 1.56 + if (status) { 1.57 + ALOGE("Error %d opening virtual key map file %s.", status, filename.string()); 1.58 + } else { 1.59 + VirtualKeyMap* map = new VirtualKeyMap(); 1.60 + if (!map) { 1.61 + ALOGE("Error allocating virtual key map."); 1.62 + status = NO_MEMORY; 1.63 + } else { 1.64 +#if DEBUG_PARSER_PERFORMANCE 1.65 + nsecs_t startTime = systemTime(SYSTEM_TIME_MONOTONIC); 1.66 +#endif 1.67 + Parser parser(map, tokenizer); 1.68 + status = parser.parse(); 1.69 +#if DEBUG_PARSER_PERFORMANCE 1.70 + nsecs_t elapsedTime = systemTime(SYSTEM_TIME_MONOTONIC) - startTime; 1.71 + ALOGD("Parsed key character map file '%s' %d lines in %0.3fms.", 1.72 + tokenizer->getFilename().string(), tokenizer->getLineNumber(), 1.73 + elapsedTime / 1000000.0); 1.74 +#endif 1.75 + if (status) { 1.76 + delete map; 1.77 + } else { 1.78 + *outMap = map; 1.79 + } 1.80 + } 1.81 + delete tokenizer; 1.82 + } 1.83 + return status; 1.84 +} 1.85 + 1.86 + 1.87 +// --- VirtualKeyMap::Parser --- 1.88 + 1.89 +VirtualKeyMap::Parser::Parser(VirtualKeyMap* map, Tokenizer* tokenizer) : 1.90 + mMap(map), mTokenizer(tokenizer) { 1.91 +} 1.92 + 1.93 +VirtualKeyMap::Parser::~Parser() { 1.94 +} 1.95 + 1.96 +status_t VirtualKeyMap::Parser::parse() { 1.97 + while (!mTokenizer->isEof()) { 1.98 +#if DEBUG_PARSER 1.99 + ALOGD("Parsing %s: '%s'.", mTokenizer->getLocation().string(), 1.100 + mTokenizer->peekRemainderOfLine().string()); 1.101 +#endif 1.102 + 1.103 + mTokenizer->skipDelimiters(WHITESPACE); 1.104 + 1.105 + if (!mTokenizer->isEol() && mTokenizer->peekChar() != '#') { 1.106 + // Multiple keys can appear on one line or they can be broken up across multiple lines. 1.107 + do { 1.108 + String8 token = mTokenizer->nextToken(WHITESPACE_OR_FIELD_DELIMITER); 1.109 + if (token != "0x01") { 1.110 + ALOGE("%s: Unknown virtual key type, expected 0x01.", 1.111 + mTokenizer->getLocation().string()); 1.112 + return BAD_VALUE; 1.113 + } 1.114 + 1.115 + VirtualKeyDefinition defn; 1.116 + bool success = parseNextIntField(&defn.scanCode) 1.117 + && parseNextIntField(&defn.centerX) 1.118 + && parseNextIntField(&defn.centerY) 1.119 + && parseNextIntField(&defn.width) 1.120 + && parseNextIntField(&defn.height); 1.121 + if (!success) { 1.122 + ALOGE("%s: Expected 5 colon-delimited integers in virtual key definition.", 1.123 + mTokenizer->getLocation().string()); 1.124 + return BAD_VALUE; 1.125 + } 1.126 + 1.127 +#if DEBUG_PARSER 1.128 + ALOGD("Parsed virtual key: scanCode=%d, centerX=%d, centerY=%d, " 1.129 + "width=%d, height=%d", 1.130 + defn.scanCode, defn.centerX, defn.centerY, defn.width, defn.height); 1.131 +#endif 1.132 + mMap->mVirtualKeys.push(defn); 1.133 + } while (consumeFieldDelimiterAndSkipWhitespace()); 1.134 + 1.135 + if (!mTokenizer->isEol()) { 1.136 + ALOGE("%s: Expected end of line, got '%s'.", 1.137 + mTokenizer->getLocation().string(), 1.138 + mTokenizer->peekRemainderOfLine().string()); 1.139 + return BAD_VALUE; 1.140 + } 1.141 + } 1.142 + 1.143 + mTokenizer->nextLine(); 1.144 + } 1.145 + 1.146 + return NO_ERROR; 1.147 +} 1.148 + 1.149 +bool VirtualKeyMap::Parser::consumeFieldDelimiterAndSkipWhitespace() { 1.150 + mTokenizer->skipDelimiters(WHITESPACE); 1.151 + if (mTokenizer->peekChar() == ':') { 1.152 + mTokenizer->nextChar(); 1.153 + mTokenizer->skipDelimiters(WHITESPACE); 1.154 + return true; 1.155 + } 1.156 + return false; 1.157 +} 1.158 + 1.159 +bool VirtualKeyMap::Parser::parseNextIntField(int32_t* outValue) { 1.160 + if (!consumeFieldDelimiterAndSkipWhitespace()) { 1.161 + return false; 1.162 + } 1.163 + 1.164 + String8 token = mTokenizer->nextToken(WHITESPACE_OR_FIELD_DELIMITER); 1.165 + char* end; 1.166 + *outValue = strtol(token.string(), &end, 0); 1.167 + if (token.isEmpty() || *end != '\0') { 1.168 + ALOGE("Expected an integer, got '%s'.", token.string()); 1.169 + return false; 1.170 + } 1.171 + return true; 1.172 +} 1.173 + 1.174 +} // namespace android