Skip to content

Commit a909b63

Browse files
committed
Implemented SourceFile.readline/readlines()
1 parent 5c23a92 commit a909b63

File tree

3 files changed

+86
-12
lines changed

3 files changed

+86
-12
lines changed

src/core/modules/filesystem/filesystem.cpp

Lines changed: 77 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
// Includes.
2929
//---------------------------------------------------------------------------------
3030
// Source.Python
31+
#include "modules/memory/memory_alloc.h"
3132
#include "utilities/wrap_macros.h"
3233
#include "filesystem.h"
3334

@@ -37,6 +38,9 @@
3738
//---------------------------------------------------------------------------------
3839
extern IFileSystem* filesystem;
3940

41+
// Chunk size for InternalReadline()
42+
#define CHUNK_SIZE 128
43+
4044

4145
//---------------------------------------------------------------------------------
4246
// Functions
@@ -96,41 +100,99 @@ PyObject* SourceFile::Read(int size)
96100
size = filesystem->Size(m_handle);
97101
}
98102

99-
void* pOutput = new char[size+1];
103+
char* pOutput = new char[size+1];
100104
int bytesRead = filesystem->Read(pOutput, size, m_handle);
101105
return ConsumeBuffer(pOutput, bytesRead);
102106
}
103107

104-
object SourceFile::Readline(int size)
108+
PyObject* SourceFile::Readline(int size)
105109
{
106110
CheckClosed();
107111
CheckReadable();
108-
// TODO
109-
BOOST_RAISE_EXCEPTION(PyExc_NotImplementedError, "Not implemented yet.")
110-
return object();
112+
113+
int bytesRead = 0;
114+
return InternalReadline(IsBinaryMode(), size, bytesRead);
115+
}
116+
117+
PyObject* SourceFile::InternalReadline(bool binaryMode, int size, int& outBytesRead)
118+
{
119+
int bytesPut = 0;
120+
char* buffer = (char*) UTIL_Alloc(CHUNK_SIZE);
121+
122+
while (size < 0 || bytesPut < size) {
123+
char temp[1];
124+
125+
// EOF?
126+
if (filesystem->Read(temp, 1, m_handle) != 1) {
127+
break;
128+
}
129+
130+
// Ignore \r in text mode
131+
if (!binaryMode && temp[0] == '\r') {
132+
continue;
133+
}
134+
135+
if (temp[0] == '\0') {
136+
buffer[bytesPut] = '\n';
137+
}
138+
else {
139+
buffer[bytesPut] = temp[0];
140+
}
141+
++bytesPut;
142+
++outBytesRead;
143+
144+
if (temp[0] == '\n') {
145+
break;
146+
}
147+
148+
if (bytesPut >= CHUNK_SIZE) {
149+
buffer = (char*) UTIL_Realloc(buffer, bytesPut + CHUNK_SIZE);
150+
if (buffer == NULL)
151+
BOOST_RAISE_EXCEPTION(PyExc_MemoryError, "Failed to reallocate the buffer.")
152+
}
153+
}
154+
155+
PyObject* result = NULL;
156+
if (IsBinaryMode()) {
157+
result = PyBytes_FromStringAndSize(buffer, bytesPut);
158+
}
159+
else {
160+
result = PyUnicode_FromStringAndSize(buffer, bytesPut);
161+
}
162+
163+
return result;
111164
}
112165

113166
list SourceFile::Readlines(int hint)
114167
{
115168
CheckClosed();
116169
CheckReadable();
117170

171+
bool binaryMode = IsBinaryMode();
172+
118173
list result;
119174

120-
// TODO
175+
int bytesRead = 0;
176+
while (true) {
177+
PyObject* line = InternalReadline(binaryMode, -1, bytesRead);
178+
result.append(handle<>(borrowed(line)));
179+
if (EndOfFile() || (hint > 0 && bytesRead > hint)) {
180+
break;
181+
}
182+
}
121183

122184
return result;
123185
}
124186

125187
// internal
126-
PyObject* SourceFile::ConsumeBuffer(void* buffer, int bytesRead)
127-
{
188+
PyObject* SourceFile::ConsumeBuffer(char* buffer, int bytesRead)
189+
{
128190
PyObject* result = NULL;
129191
if (IsBinaryMode()) {
130-
result = PyBytes_FromStringAndSize((char*) buffer, bytesRead);
192+
result = PyBytes_FromStringAndSize(buffer, bytesRead);
131193
}
132194
else {
133-
result = PyUnicode_FromStringAndSize((char*) buffer, bytesRead);
195+
result = PyUnicode_FromStringAndSize(buffer, bytesRead);
134196
}
135197

136198
delete buffer;
@@ -278,6 +340,11 @@ bool SourceFile::Closed()
278340
return m_handle == NULL;
279341
}
280342

343+
bool SourceFile::EndOfFile()
344+
{
345+
return filesystem->EndOfFile(m_handle);
346+
}
347+
281348

282349
//---------------------------------------------------------------------------------
283350
// SourceFile - internal

src/core/modules/filesystem/filesystem.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ class SourceFile
5757
bool Closed();
5858
bool Readable();
5959
bool Writeable();
60-
object Readline(int size=-1);
60+
PyObject* Readline(int size=-1);
6161
// TODO
6262
//__iter__
6363
// __next__
@@ -73,16 +73,18 @@ class SourceFile
7373
// TODO
7474
// void Delete();
7575
// void Rename();
76+
bool EndOfFile();
7677

7778
static SourceFile* Open(const char* pFileName, const char* pMode, const char* pathID=0);
7879

7980
private:
80-
PyObject* ConsumeBuffer(void* buffer, int bytesRead);
81+
PyObject* ConsumeBuffer(char* buffer, int bytesRead);
8182
void CheckClosed();
8283
void WriteData(PyObject* data);
8384
bool IsBinaryMode();
8485
void CheckReadable();
8586
void CheckWriteable();
87+
PyObject* InternalReadline(bool binaryMode, int size, int& outBytesRead);
8688

8789
private:
8890
FileHandle_t m_handle;

src/core/modules/filesystem/filesystem_wrap.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,11 @@ void export_source_file(scope _filesystem)
168168
"handle",
169169
make_function(&SourceFile::GetHandle, return_by_value_policy())
170170
);
171+
172+
_SourceFile.add_property(
173+
"eof",
174+
&SourceFile::EndOfFile
175+
);
171176

172177
_SourceFile.def(
173178
"open",

0 commit comments

Comments
 (0)