1 /*
2 Copyright (c) 2009 Andrew Caudwell (acaudwell@gmail.com)
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8 1. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14 derived from this software without specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #include "seeklog.h"
29 #include "sdlapp.h"
30
31 long long gSeekLogMaxBufferSize = 104857600;
32
33 //StreamLog
34
StreamLog()35 StreamLog::StreamLog() {
36 this->stream = &std::cin;
37
38 fcntl_fail = false;
39
40 #ifdef _WIN32
41 stdin_handle = GetStdHandle(STD_INPUT_HANDLE);
42 #else
43 int ret = fcntl(STDIN_FILENO, F_GETFL, 0);
44
45 if (fcntl (STDIN_FILENO, F_SETFL, ret | O_NONBLOCK) < 0) {
46 debugLog("fcntl(stdin) failed");
47 fcntl_fail = true;
48 }
49 #endif
50 }
51
~StreamLog()52 StreamLog::~StreamLog() {
53 }
54
getNextLine(std::string & line)55 bool StreamLog::getNextLine(std::string& line) {
56
57 //try and fix the stream
58 if(isFinished()) stream->clear();
59
60 #ifdef _WIN32
61
62 DWORD available_bytes;
63
64 if (!PeekNamedPipe(stdin_handle, 0, 0, 0,
65 &available_bytes, 0)) return false;
66
67 if(available_bytes==0) return false;
68
69 #endif
70
71 std::getline(*stream, line);
72
73 //remove carriage returns
74 if (line.size() > 0 && line[line.size()-1] == '\r') {
75 line.resize(line.size() - 1);
76 }
77
78 if(isFinished()) {
79 return false;
80 }
81
82 return true;
83 }
84
isFinished()85 bool StreamLog::isFinished() {
86
87 if(fcntl_fail || stream->fail() || stream->eof()) {
88 return true;
89 }
90
91 return false;
92 }
93
94 // SeekLog
95
SeekLog(std::string logfile)96 SeekLog::SeekLog(std::string logfile) {
97 this->logfile = logfile;
98
99 this->stream = 0;
100
101 if(!readFully()) {
102 throw SeekLogException(logfile);
103 }
104 }
105
readFully()106 bool SeekLog::readFully() {
107
108 if(stream!=0) delete stream;
109
110 std::ifstream* file = new std::ifstream(logfile.c_str(), std::ios::in | std::ios::binary | std::ios::ate);
111
112 file_size = file->tellg();
113
114 if(!file->is_open()) {
115 delete file;
116 return false;
117 }
118
119 file->seekg (0, std::ios::beg);
120
121 //dont load into memory if larger than
122 if(file_size > gSeekLogMaxBufferSize) {
123 stream = file;
124 return true;
125 }
126
127
128 //buffer entire file into memory
129 char* filebuffer = new char[file_size+1];
130
131 if(!file->read(filebuffer, file_size)) {
132 file->close();
133 delete file;
134 delete [] filebuffer;
135 return false;
136 }
137 filebuffer[file_size] = '\0';
138
139 file->close();
140 delete file;
141
142 stream = new std::istringstream(std::string(filebuffer));
143
144 delete[] filebuffer;
145
146 return true;
147 }
148
~SeekLog()149 SeekLog::~SeekLog() {
150 if(stream!=0) delete stream;
151 }
152
getPercent()153 float SeekLog::getPercent() {
154 return current_percent;
155 }
156
setPointer(std::streampos pointer)157 void SeekLog::setPointer(std::streampos pointer) {
158 stream->seekg(pointer);
159 }
160
getPointer()161 std::streampos SeekLog::getPointer() {
162 return stream->tellg();
163 }
164
seekTo(float percent)165 void SeekLog::seekTo(float percent) {
166
167 if(isFinished()) stream->clear();
168
169 std::streampos mem_offset = (std::streampos) (percent * file_size);
170
171 setPointer(mem_offset);
172
173 //throw away end of line
174 if(mem_offset != (std::streampos)0) {
175 std::string eol;
176 getNextLine(eol);
177 }
178 }
179
getNextLine(std::string & line)180 bool SeekLog::getNextLine(std::string& line) {
181
182 //try and fix the stream
183 if(isFinished()) stream->clear();
184
185 std::getline(*stream, line);
186
187 //remove carriage returns
188 if (line.size() > 0 && line[line.size()-1] == '\r') {
189 line.resize(line.size() - 1);
190 }
191
192 if(stream->fail()) {
193 return false;
194 }
195
196 current_percent = (float) stream->tellg() / file_size;
197 //debugLog("current_percent = %.2f\n", current_percent);
198
199 return true;
200 }
201
202 // temporarily move the file pointer to get a line somewhere else in the file
getNextLineAt(std::string & line,float percent)203 bool SeekLog::getNextLineAt(std::string& line, float percent) {
204 stream->clear();
205
206 std::streampos currpointer = getPointer();
207
208 seekTo(percent);
209
210 bool success = getNextLine(line);
211
212 stream->clear();
213
214 //set the pointer back
215 setPointer(currpointer);
216
217 return success;
218 }
219
isFinished()220 bool SeekLog::isFinished() {
221 bool finished = false;
222
223 if(stream->fail() || stream->eof()) {
224 //debugLog("stream is finished");
225 finished=true;
226 }
227
228 return finished;
229 }
230