1/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
2/* If you are missing that file, acquire a complete release at teeworlds.com. */
3#include "linereader.h"
4
5#include <base/system.h>
6
7void CLineReader::Init(IOHANDLE File)
8{
9 m_BufferMaxSize = sizeof(m_aBuffer) - 1;
10 m_BufferSize = 0;
11 m_BufferPos = 0;
12 m_File = File;
13}
14
15char *CLineReader::Get()
16{
17 unsigned LineStart = m_BufferPos;
18 bool CRLFBreak = false;
19
20 while(true)
21 {
22 if(m_BufferPos >= m_BufferSize)
23 {
24 // fetch more
25
26 // move the remaining part to the front
27 unsigned Left = m_BufferSize - LineStart;
28
29 if(LineStart > m_BufferSize)
30 Left = 0;
31 if(Left)
32 mem_move(dest: m_aBuffer, source: &m_aBuffer[LineStart], size: Left);
33 m_BufferPos = Left;
34
35 // fill the buffer
36 unsigned Read = io_read(io: m_File, buffer: &m_aBuffer[m_BufferPos], size: m_BufferMaxSize - m_BufferPos);
37 m_BufferSize = Left + Read;
38 LineStart = 0;
39
40 if(!Read)
41 {
42 if(Left)
43 {
44 m_aBuffer[Left] = '\0'; // return the last line
45 m_BufferPos = Left;
46 m_BufferSize = Left;
47 if(!str_utf8_check(str: m_aBuffer))
48 {
49 LineStart = m_BufferPos;
50 CRLFBreak = false;
51 continue; // skip lines containing invalid UTF-8
52 }
53 return m_aBuffer;
54 }
55 return nullptr; // we are done!
56 }
57 }
58 else
59 {
60 if(m_aBuffer[m_BufferPos] == '\n' || m_aBuffer[m_BufferPos] == '\r')
61 {
62 // line found
63 if(m_aBuffer[m_BufferPos] == '\r')
64 {
65 if(m_BufferPos + 1 >= m_BufferSize)
66 {
67 // read more to get the connected '\n'
68 CRLFBreak = true;
69 ++m_BufferPos;
70 continue;
71 }
72 else if(m_aBuffer[m_BufferPos + 1] == '\n')
73 m_aBuffer[m_BufferPos++] = '\0';
74 }
75 m_aBuffer[m_BufferPos++] = '\0';
76 if(!str_utf8_check(str: &m_aBuffer[LineStart]))
77 {
78 LineStart = m_BufferPos;
79 CRLFBreak = false;
80 continue; // skip lines containing invalid UTF-8
81 }
82 return &m_aBuffer[LineStart];
83 }
84 else if(CRLFBreak)
85 {
86 if(m_aBuffer[m_BufferPos] == '\n')
87 m_aBuffer[m_BufferPos++] = '\0';
88 if(!str_utf8_check(str: &m_aBuffer[LineStart]))
89 {
90 LineStart = m_BufferPos;
91 CRLFBreak = false;
92 continue; // skip lines containing invalid UTF-8
93 }
94 return &m_aBuffer[LineStart];
95 }
96 else
97 m_BufferPos++;
98 }
99 }
100}
101