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 | |
40 | static inline bool isDelimiter(char ch, const char* delimiters) { |
41 | return strchr(delimiters, ch) != NULL; |
42 | } |
43 | |
44 | SysTokenizer::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 | |
51 | SysTokenizer::~SysTokenizer() { |
52 | if (mOwnBuffer) { |
53 | delete[] mBuffer; |
54 | } |
55 | } |
56 | |
57 | int 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 | |
99 | int 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 | |
106 | char* 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 | |
112 | char* 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 | |
128 | char* 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 | |
153 | void 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 | |
167 | void 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 |