Projection: make invalid by default, add IsValid()
[xcsoar.git] / src / IO / LineSplitter.cpp
blobfba22d27c7c347b482f8e281e885c105e74f4d51
1 /*
2 Copyright_License {
4 XCSoar Glide Computer - http://www.xcsoar.org/
5 Copyright (C) 2000-2013 The XCSoar Project
6 A detailed list of copyright holders can be found in the file "AUTHORS".
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 #include "LineSplitter.hpp"
26 #include <string.h>
28 static std::pair<unsigned, unsigned>
29 extract_line(const char *data, unsigned length)
31 const char *eol = (const char *)memchr(data, '\n', length);
32 if (eol == NULL)
33 return std::pair<unsigned, unsigned>(length, length);
35 length = eol + 1 - data;
37 /* purge trailing carriage return characters */
38 while (eol > data && eol[-1] == '\r')
39 --eol;
41 return std::pair<unsigned, unsigned>(eol - data, length);
44 char *
45 LineSplitter::ReadLine()
47 /* is there enough data left in the buffer to read another line? */
48 if (memchr(remaining.data, '\n', remaining.length) == NULL) {
49 /* no: read more data from the Source */
50 remaining = source.Read();
51 if (remaining.IsEmpty())
52 /* end of file */
53 return NULL;
56 assert(!remaining.IsEmpty());
58 Source<char>::Range range = remaining;
59 std::pair<unsigned, unsigned> bounds =
60 extract_line(range.data, range.length);
61 source.Consume(bounds.second);
62 remaining.data += bounds.second;
63 remaining.length -= bounds.second;
65 if (bounds.first >= range.length) {
66 /* last line, not terminated by a line feed: copy to local buffer,
67 because we want to append the null byte */
68 char *line = last.get(range.length + 1);
69 if (line == NULL)
70 /* allocation has failed */
71 return NULL;
73 memcpy(line, range.data, range.length);
74 line[range.length] = 0;
75 return line;
76 } else {
77 /* there is space left for the null byte */
78 range.data[bounds.first] = 0;
79 return range.data;
83 long
84 LineSplitter::GetSize() const
86 return source.GetSize();
89 long
90 LineSplitter::Tell() const
92 return source.Tell();