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