widget/gonk/libui/Tokenizer.cpp

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

michael@0 1 /*
michael@0 2 * Copyright (C) 2010 The Android Open Source Project
michael@0 3 *
michael@0 4 * Licensed under the Apache License, Version 2.0 (the "License");
michael@0 5 * you may not use this file except in compliance with the License.
michael@0 6 * You may obtain a copy of the License at
michael@0 7 *
michael@0 8 * http://www.apache.org/licenses/LICENSE-2.0
michael@0 9 *
michael@0 10 * Unless required by applicable law or agreed to in writing, software
michael@0 11 * distributed under the License is distributed on an "AS IS" BASIS,
michael@0 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
michael@0 13 * See the License for the specific language governing permissions and
michael@0 14 * limitations under the License.
michael@0 15 */
michael@0 16
michael@0 17 #define LOG_TAG "Tokenizer"
michael@0 18 #include "cutils_log.h"
michael@0 19
michael@0 20 #include <stdlib.h>
michael@0 21 #include <unistd.h>
michael@0 22 #include <fcntl.h>
michael@0 23 #include <errno.h>
michael@0 24 #include <sys/types.h>
michael@0 25 #include <sys/stat.h>
michael@0 26 #include "Tokenizer.h"
michael@0 27
michael@0 28 // Enables debug output for the tokenizer.
michael@0 29 #define DEBUG_TOKENIZER 0
michael@0 30
michael@0 31
michael@0 32 namespace android {
michael@0 33
michael@0 34 static inline bool isDelimiter(char ch, const char* delimiters) {
michael@0 35 return strchr(delimiters, ch) != NULL;
michael@0 36 }
michael@0 37
michael@0 38 Tokenizer::Tokenizer(const String8& filename, FileMap* fileMap, char* buffer,
michael@0 39 bool ownBuffer, size_t length) :
michael@0 40 mFilename(filename), mFileMap(fileMap),
michael@0 41 mBuffer(buffer), mOwnBuffer(ownBuffer), mLength(length),
michael@0 42 mCurrent(buffer), mLineNumber(1) {
michael@0 43 }
michael@0 44
michael@0 45 Tokenizer::~Tokenizer() {
michael@0 46 if (mFileMap) {
michael@0 47 mFileMap->release();
michael@0 48 }
michael@0 49 if (mOwnBuffer) {
michael@0 50 delete[] mBuffer;
michael@0 51 }
michael@0 52 }
michael@0 53
michael@0 54 status_t Tokenizer::open(const String8& filename, Tokenizer** outTokenizer) {
michael@0 55 *outTokenizer = NULL;
michael@0 56
michael@0 57 int result = NO_ERROR;
michael@0 58 int fd = ::open(filename.string(), O_RDONLY);
michael@0 59 if (fd < 0) {
michael@0 60 result = -errno;
michael@0 61 ALOGE("Error opening file '%s', %s.", filename.string(), strerror(errno));
michael@0 62 } else {
michael@0 63 struct stat stat;
michael@0 64 if (fstat(fd, &stat)) {
michael@0 65 result = -errno;
michael@0 66 ALOGE("Error getting size of file '%s', %s.", filename.string(), strerror(errno));
michael@0 67 } else {
michael@0 68 size_t length = size_t(stat.st_size);
michael@0 69
michael@0 70 FileMap* fileMap = new FileMap();
michael@0 71 bool ownBuffer = false;
michael@0 72 char* buffer;
michael@0 73 if (fileMap->create(NULL, fd, 0, length, true)) {
michael@0 74 fileMap->advise(FileMap::SEQUENTIAL);
michael@0 75 buffer = static_cast<char*>(fileMap->getDataPtr());
michael@0 76 } else {
michael@0 77 fileMap->release();
michael@0 78 fileMap = NULL;
michael@0 79
michael@0 80 // Fall back to reading into a buffer since we can't mmap files in sysfs.
michael@0 81 // The length we obtained from stat is wrong too (it will always be 4096)
michael@0 82 // so we must trust that read will read the entire file.
michael@0 83 buffer = new char[length];
michael@0 84 ownBuffer = true;
michael@0 85 ssize_t nrd = read(fd, buffer, length);
michael@0 86 if (nrd < 0) {
michael@0 87 result = -errno;
michael@0 88 ALOGE("Error reading file '%s', %s.", filename.string(), strerror(errno));
michael@0 89 delete[] buffer;
michael@0 90 buffer = NULL;
michael@0 91 } else {
michael@0 92 length = size_t(nrd);
michael@0 93 }
michael@0 94 }
michael@0 95
michael@0 96 if (!result) {
michael@0 97 *outTokenizer = new Tokenizer(filename, fileMap, buffer, ownBuffer, length);
michael@0 98 }
michael@0 99 }
michael@0 100 close(fd);
michael@0 101 }
michael@0 102 return result;
michael@0 103 }
michael@0 104
michael@0 105 status_t Tokenizer::fromContents(const String8& filename,
michael@0 106 const char* contents, Tokenizer** outTokenizer) {
michael@0 107 *outTokenizer = new Tokenizer(filename, NULL,
michael@0 108 const_cast<char*>(contents), false, strlen(contents));
michael@0 109 return OK;
michael@0 110 }
michael@0 111
michael@0 112 String8 Tokenizer::getLocation() const {
michael@0 113 String8 result;
michael@0 114 result.appendFormat("%s:%d", mFilename.string(), mLineNumber);
michael@0 115 return result;
michael@0 116 }
michael@0 117
michael@0 118 String8 Tokenizer::peekRemainderOfLine() const {
michael@0 119 const char* end = getEnd();
michael@0 120 const char* eol = mCurrent;
michael@0 121 while (eol != end) {
michael@0 122 char ch = *eol;
michael@0 123 if (ch == '\n') {
michael@0 124 break;
michael@0 125 }
michael@0 126 eol += 1;
michael@0 127 }
michael@0 128 return String8(mCurrent, eol - mCurrent);
michael@0 129 }
michael@0 130
michael@0 131 String8 Tokenizer::nextToken(const char* delimiters) {
michael@0 132 #if DEBUG_TOKENIZER
michael@0 133 ALOGD("nextToken");
michael@0 134 #endif
michael@0 135 const char* end = getEnd();
michael@0 136 const char* tokenStart = mCurrent;
michael@0 137 while (mCurrent != end) {
michael@0 138 char ch = *mCurrent;
michael@0 139 if (ch == '\n' || isDelimiter(ch, delimiters)) {
michael@0 140 break;
michael@0 141 }
michael@0 142 mCurrent += 1;
michael@0 143 }
michael@0 144 return String8(tokenStart, mCurrent - tokenStart);
michael@0 145 }
michael@0 146
michael@0 147 void Tokenizer::nextLine() {
michael@0 148 #if DEBUG_TOKENIZER
michael@0 149 ALOGD("nextLine");
michael@0 150 #endif
michael@0 151 const char* end = getEnd();
michael@0 152 while (mCurrent != end) {
michael@0 153 char ch = *(mCurrent++);
michael@0 154 if (ch == '\n') {
michael@0 155 mLineNumber += 1;
michael@0 156 break;
michael@0 157 }
michael@0 158 }
michael@0 159 }
michael@0 160
michael@0 161 void Tokenizer::skipDelimiters(const char* delimiters) {
michael@0 162 #if DEBUG_TOKENIZER
michael@0 163 ALOGD("skipDelimiters");
michael@0 164 #endif
michael@0 165 const char* end = getEnd();
michael@0 166 while (mCurrent != end) {
michael@0 167 char ch = *mCurrent;
michael@0 168 if (ch == '\n' || !isDelimiter(ch, delimiters)) {
michael@0 169 break;
michael@0 170 }
michael@0 171 mCurrent += 1;
michael@0 172 }
michael@0 173 }
michael@0 174
michael@0 175 } // namespace android

mercurial