|
27 | 27 |
|
28 | 28 | #include "src/main/cpp/util/path_platform.h" |
29 | 29 | #include "src/tools/singlejar/diag.h" |
| 30 | +#include "src/tools/singlejar/mapped_file.h" |
30 | 31 |
|
31 | 32 | /* |
32 | 33 | * Tokenize command line containing indirect command line arguments. |
@@ -59,39 +60,26 @@ class ArgTokenStream { |
59 | 60 | // Internal class to handle indirect command files. |
60 | 61 | class FileTokenStream { |
61 | 62 | public: |
62 | | - FileTokenStream(const char *filename) { |
63 | | -#ifdef _WIN32 |
64 | | - std::wstring wpath; |
65 | | - std::string error; |
66 | | - if (!blaze_util::AsAbsoluteWindowsPath(filename, &wpath, &error)) { |
67 | | - diag_err(1, "%s:%d: AsAbsoluteWindowsPath failed: %s", __FILE__, |
68 | | - __LINE__, error.c_str()); |
69 | | - } |
70 | | - fp_ = _wfopen(wpath.c_str(), L"r"); |
71 | | -#else |
72 | | - fp_ = fopen(filename, "r"); |
73 | | -#endif |
74 | | - |
75 | | - if (!fp_) { |
76 | | - diag_err(1, "%s", filename); |
| 63 | + FileTokenStream(const char* filename) |
| 64 | + : next_ptr_(nullptr), end_ptr_(nullptr) { |
| 65 | + if (!mapped_file_.Open(filename)) { |
| 66 | + diag_err(1, "Cannot open param file: %s", filename); |
77 | 67 | } |
78 | 68 | filename_ = filename; |
| 69 | + next_ptr_ = static_cast<const unsigned char*>(mapped_file_.start()); |
| 70 | + end_ptr_ = static_cast<const unsigned char*>(mapped_file_.end()); |
79 | 71 | next_char(); |
80 | 72 | } |
81 | 73 |
|
82 | | - ~FileTokenStream() { close(); } |
| 74 | + ~FileTokenStream() = default; |
83 | 75 |
|
84 | 76 | // Assign next token to TOKEN, return true on success, false on EOF. |
85 | 77 | bool next_token(std::string *token) { |
86 | | - if (!fp_) { |
87 | | - return false; |
88 | | - } |
89 | 78 | *token = ""; |
90 | 79 | while (current_char_ != EOF && isspace(current_char_)) { |
91 | 80 | next_char(); |
92 | 81 | } |
93 | 82 | if (current_char_ == EOF) { |
94 | | - close(); |
95 | 83 | return false; |
96 | 84 | } |
97 | 85 | for (;;) { |
@@ -123,14 +111,6 @@ class ArgTokenStream { |
123 | 111 | } |
124 | 112 |
|
125 | 113 | private: |
126 | | - void close() { |
127 | | - if (fp_) { |
128 | | - fclose(fp_); |
129 | | - fp_ = nullptr; |
130 | | - } |
131 | | - filename_.clear(); |
132 | | - } |
133 | | - |
134 | 114 | // Append the quoted string to the TOKEN. The quote character (which can be |
135 | 115 | // single or double quote) is in the current character. Everything up to the |
136 | 116 | // matching quote character is appended. |
@@ -164,34 +144,41 @@ class ArgTokenStream { |
164 | 144 | // Get the next character from the input stream. Skip backslash followed |
165 | 145 | // by the newline. |
166 | 146 | void next_char() { |
167 | | - if (feof(fp_)) { |
168 | | - current_char_ = EOF; |
169 | | - return; |
170 | | - } |
171 | | - current_char_ = getc(fp_); |
172 | | - // Eat "\\\n" sequence. |
173 | | - while (current_char_ == '\\') { |
174 | | - int c = getc(fp_); |
175 | | - if (c == '\n') { |
176 | | - current_char_ = getc(fp_); |
177 | | - } else { |
178 | | - if (c != EOF) { |
179 | | - ungetc(c, fp_); |
180 | | - } |
181 | | - break; |
182 | | - } |
| 147 | + do { |
| 148 | + current_char_ = raw_next(); |
| 149 | + } while (eat_line_continuation()); |
| 150 | + } |
| 151 | + |
| 152 | + bool eat_line_continuation() { |
| 153 | + if (current_char_ == '\\' && peek_raw_next() == '\n') { |
| 154 | + next_ptr_++; |
| 155 | + return true; |
| 156 | + } else if (current_char_ == '\\' && peek_raw_next() == '\r' && |
| 157 | + peek_raw_next(1) == '\n') { |
| 158 | + next_ptr_ += 2; |
| 159 | + return true; |
183 | 160 | } |
| 161 | + return false; |
| 162 | + } |
| 163 | + |
| 164 | + int raw_next() { return next_ptr_ < end_ptr_ ? *next_ptr_++ : EOF; } |
| 165 | + |
| 166 | + int peek_raw_next(size_t offset = 0) { |
| 167 | + return (next_ptr_ + offset) < end_ptr_ ? *(next_ptr_ + offset) : EOF; |
184 | 168 | } |
185 | 169 |
|
186 | | - FILE *fp_; |
| 170 | + MappedFile mapped_file_; |
187 | 171 | std::string filename_; |
| 172 | + const unsigned char* next_ptr_; |
| 173 | + const unsigned char* end_ptr_; |
188 | 174 | int current_char_; |
189 | 175 | }; |
190 | 176 |
|
191 | 177 | public: |
192 | 178 | // Constructor. Automatically reads the first token. |
193 | 179 | ArgTokenStream(int argc, const char *const *argv) |
194 | 180 | : argv_(argv), argv_end_(argv + argc) { |
| 181 | + token_.reserve(1024); |
195 | 182 | next(); |
196 | 183 | } |
197 | 184 |
|
|
0 commit comments