1/*
2 * Copyright (C) 2010 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 */
16
17#ifndef _UTILS_TOKENIZER_H
18#define _UTILS_TOKENIZER_H
19
20#include <assert.h>
21#include <utils/Errors.h>
22#include <utils/FileMap.h>
23#include <utils/String8.h>
24
25namespace android {
26
27/**
28 * A simple tokenizer for loading and parsing ASCII text files line by line.
29 */
30class Tokenizer {
31    Tokenizer(const String8& filename, FileMap* fileMap, char* buffer,
32            bool ownBuffer, size_t length);
33
34public:
35    ~Tokenizer();
36
37    /**
38     * Opens a file and maps it into memory.
39     *
40     * Returns NO_ERROR and a tokenizer for the file, if successful.
41     * Otherwise returns an error and sets outTokenizer to NULL.
42     */
43    static status_t open(const String8& filename, Tokenizer** outTokenizer);
44
45    /**
46     * Prepares to tokenize the contents of a string.
47     *
48     * Returns NO_ERROR and a tokenizer for the string, if successful.
49     * Otherwise returns an error and sets outTokenizer to NULL.
50     */
51    static status_t fromContents(const String8& filename,
52            const char* contents, Tokenizer** outTokenizer);
53
54    /**
55     * Returns true if at the end of the file.
56     */
57    inline bool isEof() const { return mCurrent == getEnd(); }
58
59    /**
60     * Returns true if at the end of the line or end of the file.
61     */
62    inline bool isEol() const { return isEof() || *mCurrent == '\n'; }
63
64    /**
65     * Gets the name of the file.
66     */
67    inline String8 getFilename() const { return mFilename; }
68
69    /**
70     * Gets a 1-based line number index for the current position.
71     */
72    inline int32_t getLineNumber() const { return mLineNumber; }
73
74    /**
75     * Formats a location string consisting of the filename and current line number.
76     * Returns a string like "MyFile.txt:33".
77     */
78    String8 getLocation() const;
79
80    /**
81     * Gets the character at the current position.
82     * Returns null at end of file.
83     */
84    inline char peekChar() const { return isEof() ? '\0' : *mCurrent; }
85
86    /**
87     * Gets the remainder of the current line as a string, excluding the newline character.
88     */
89    String8 peekRemainderOfLine() const;
90
91    /**
92     * Gets the character at the current position and advances past it.
93     * Returns null at end of file.
94     */
95    inline char nextChar() { return isEof() ? '\0' : *(mCurrent++); }
96
97    /**
98     * Gets the next token on this line stopping at the specified delimiters
99     * or the end of the line whichever comes first and advances past it.
100     * Also stops at embedded nulls.
101     * Returns the token or an empty string if the current character is a delimiter
102     * or is at the end of the line.
103     */
104    String8 nextToken(const char* delimiters);
105
106    /**
107     * Advances to the next line.
108     * Does nothing if already at the end of the file.
109     */
110    void nextLine();
111
112    /**
113     * Skips over the specified delimiters in the line.
114     * Also skips embedded nulls.
115     */
116    void skipDelimiters(const char* delimiters);
117
118private:
119    Tokenizer(const Tokenizer& other); // not copyable
120
121    String8 mFilename;
122    FileMap* mFileMap;
123    char* mBuffer;
124    bool mOwnBuffer;
125    size_t mLength;
126
127    const char* mCurrent;
128    int32_t mLineNumber;
129
130    inline const char* getEnd() const { return mBuffer + mLength; }
131
132};
133
134} // namespace android
135
136#endif // _UTILS_TOKENIZER_H
137