Skip to content

Commit 675606a

Browse files
authored
Merge pull request #3 from nibblebits/dev
Implemented new functions to allow for reading and writing of binary files, also fixed a protential issue with arrays not being known as arrays when created natively
2 parents c9442e8 + 6023ff1 commit 675606a

File tree

4 files changed

+105
-4
lines changed

4 files changed

+105
-4
lines changed

include/config.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
2323

2424
// Marble versioning information
2525
#define MARBLE_MAJOR_CODENAME "Clearies"
26-
#define MARBLE_VERSION "0.3.0"
26+
#define MARBLE_VERSION "0.4.0"
2727

2828
#define MAX_KEYWORD_SIZE 15
2929
#define MAX_OPERATORS_SIZE 3

src/stdmods/filemod/include/filemod_file.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,9 @@ class FileModule_File : public Object
6060
static void File_IsFile(Interpreter* interpreter, std::vector<Value> values, Value* return_value, std::shared_ptr<Object> object, Scope* caller_scope);
6161
static void File_Delete(Interpreter* interpreter, std::vector<Value> values, Value* return_value, std::shared_ptr<Object> object, Scope* caller_scope);
6262
static void File_file_get_contents(Interpreter* interpreter, std::vector<Value> values, Value* return_value, std::shared_ptr<Object> object, Scope* caller_scope);
63+
static void File_file_get_binary_contents(Interpreter* interpreter, std::vector<Value> values, Value* return_value, std::shared_ptr<Object> object, Scope* caller_scope);
6364
static void File_file_put_contents(Interpreter* interpreter, std::vector<Value> values, Value* return_value, std::shared_ptr<Object> object, Scope* caller_scope);
65+
static void File_file_put_binary_contents(Interpreter* interpreter, std::vector<Value> values, Value* return_value, std::shared_ptr<Object> object, Scope* caller_scope);
6466
static void File_chmod(Interpreter* interpreter, std::vector<Value> values, Value* return_value, std::shared_ptr<Object> object, Scope* caller_scope);
6567

6668

src/stdmods/filemod/src/filemod_file.cpp

Lines changed: 97 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
2323
#include "exceptionobject.h"
2424
#include "exceptions/systemexception.h"
2525
#include "misc.h"
26+
#include "array.h"
27+
#include "variable.h"
2628
#include <iostream>
2729
#include <sys/types.h>
2830
#include <sys/stat.h>
@@ -165,13 +167,25 @@ Class *FileModule_File::registerClass(ModuleSystem *moduleSystem)
165167
* @class File
166168
*
167169
* Reads the entire file into memory as a string and returns the file contents.
168-
*
170+
* Important to note that this returns only valid ASCII string data. Please use file_get_binary_contents for binary files
169171
* @works_without_class
170172
* function file_get_contents(string filename) : string
171173
*/
172174
c->registerFunction("file_get_contents", {VarType::fromString("string")}, VarType::fromString("string"), FileModule_File::File_file_get_contents);
173175
moduleSystem->getFunctionSystem()->registerFunction("file_get_contents", {VarType::fromString("string")}, VarType::fromString("string"), FileModule_File::File_file_get_contents);
174176

177+
/**
178+
* @class File
179+
*
180+
* Reads the entire file into memory, returns the file contents as a number array that holds 8 bit characters in each index.
181+
* Use this function for reading binary files
182+
* @works_without_class
183+
* function file_get_binary_contents(string filename) : number[]
184+
*/
185+
c->registerFunction("file_get_binary_contents", {VarType::fromString("string")}, VarType::fromString("number[]"), FileModule_File::File_file_get_binary_contents);
186+
moduleSystem->getFunctionSystem()->registerFunction("file_get_binary_contents", {VarType::fromString("string")}, VarType::fromString("number[]"), FileModule_File::File_file_get_binary_contents);
187+
188+
175189
/**
176190
* @class File
177191
*
@@ -181,9 +195,21 @@ Class *FileModule_File::registerClass(ModuleSystem *moduleSystem)
181195
* @works_without_class
182196
* function file_put_contents(string filename, string data) : void
183197
*/
184-
c->registerFunction("file_put_contents", {VarType::fromString("string"), VarType::fromString("string")}, VarType::fromString("string"), FileModule_File::File_file_put_contents);
185-
moduleSystem->getFunctionSystem()->registerFunction("file_put_contents", {VarType::fromString("string"), VarType::fromString("string")}, VarType::fromString("string"), FileModule_File::File_file_put_contents);
198+
c->registerFunction("file_put_contents", {VarType::fromString("string"), VarType::fromString("string")}, VarType::fromString("void"), FileModule_File::File_file_put_contents);
199+
moduleSystem->getFunctionSystem()->registerFunction("file_put_contents", {VarType::fromString("string"), VarType::fromString("string")}, VarType::fromString("void"), FileModule_File::File_file_put_contents);
186200

201+
/**
202+
* @class File
203+
*
204+
* Writes the given number array to the file specified by the filename. Each number in your number array
205+
* will be treated as a single 8 bit character all other bits of the number are ignored. For example if you have a number with the value 0xffff. Only 0xff will be used
206+
* If the file does not exist it creates it, if it does exist it overwrites it
207+
*
208+
* @works_without_class
209+
* function file_put_binary_contents(string filename, number[] data) : void
210+
*/
211+
c->registerFunction("file_put_binary_contents", {VarType::fromString("string"), VarType::fromString("number[]")}, VarType::fromString("void"), FileModule_File::File_file_put_binary_contents);
212+
moduleSystem->getFunctionSystem()->registerFunction("file_put_binary_contents", {VarType::fromString("string"), VarType::fromString("number[]")}, VarType::fromString("void"), FileModule_File::File_file_put_binary_contents);
187213

188214
/**
189215
* @class File
@@ -311,6 +337,45 @@ void FileModule_File::File_file_get_contents(Interpreter *interpreter, std::vect
311337
}
312338
}
313339

340+
void FileModule_File::File_file_get_binary_contents(Interpreter* interpreter, std::vector<Value> values, Value* return_value, std::shared_ptr<Object> object, Scope* caller_scope)
341+
{
342+
std::string absolute_filename_path = getAbsolutePath(values[0].svalue);
343+
// We need to make sure the scope has access to this file
344+
FilePermission::checkPermissionAllows(interpreter, caller_scope, absolute_filename_path, "r");
345+
FILE *fp = fopen(absolute_filename_path.c_str(), "r");
346+
if (!fp)
347+
throw SystemException(std::dynamic_pointer_cast<ExceptionObject>(Object::create(interpreter->getClassSystem()->getClassByName("IOException"))), "Failed to open the file: " + absolute_filename_path, interpreter->getStackTraceLog());
348+
349+
try
350+
{
351+
fseek(fp, 0, SEEK_END);
352+
int size = ftell(fp);
353+
fseek(fp, 0, SEEK_SET);
354+
355+
unsigned char buf[size];
356+
if (!fread(buf, size, 1, fp))
357+
throw SystemException(std::dynamic_pointer_cast<ExceptionObject>(Object::create(interpreter->getClassSystem()->getClassByName("IOException"))), "Failed to read the file: " + absolute_filename_path + " but it opened succesfully", interpreter->getStackTraceLog());
358+
359+
// Ok let's create a number array to store these file contents in
360+
Variable* variables = new Variable[size];
361+
for (int i = 0; i < size; i++)
362+
{
363+
Variable *var = &variables[i];
364+
var->type = VARIABLE_TYPE_NUMBER;
365+
var->value.type = VARIABLE_TYPE_NUMBER;
366+
var->value.holder = var;
367+
var->value.dvalue = buf[i];
368+
}
369+
return_value->set(std::make_shared<Array>(interpreter->getClassSystem()->getClassByName("array"), variables, size));
370+
fclose(fp);
371+
}
372+
catch (...)
373+
{
374+
fclose(fp);
375+
throw;
376+
}
377+
}
378+
314379
void FileModule_File::File_file_put_contents(Interpreter *interpreter, std::vector<Value> values, Value *return_value, std::shared_ptr<Object> object, Scope *caller_scope)
315380
{
316381
std::string absolute_filename_path = getAbsolutePath(values[0].svalue);
@@ -334,6 +399,35 @@ void FileModule_File::File_file_put_contents(Interpreter *interpreter, std::vect
334399
}
335400
}
336401

402+
void FileModule_File::File_file_put_binary_contents(Interpreter* interpreter, std::vector<Value> values, Value* return_value, std::shared_ptr<Object> object, Scope* caller_scope)
403+
{
404+
std::string absolute_filename_path = getAbsolutePath(values[0].svalue);
405+
// We need to make sure the scope has access to this file
406+
FilePermission::checkPermissionAllows(interpreter, caller_scope, absolute_filename_path, "w");
407+
FILE *fp = fopen(absolute_filename_path.c_str(), "w");
408+
if (!fp)
409+
throw SystemException(std::dynamic_pointer_cast<ExceptionObject>(Object::create(interpreter->getClassSystem()->getClassByName("IOException"))), "Failed to open the file: " + absolute_filename_path, interpreter->getStackTraceLog());
410+
411+
try
412+
{
413+
std::shared_ptr<Array> array = std::dynamic_pointer_cast<Array>(values[1].ovalue);
414+
std::unique_ptr<unsigned char[]> data = std::make_unique<unsigned char[]>(array->count);
415+
for (int i = 0; i < array->count; i++)
416+
{
417+
data[i] = (unsigned char) array->variables[i].value.dvalue;
418+
}
419+
if (!fwrite(data.get(), array->count, 1, fp))
420+
throw SystemException(std::dynamic_pointer_cast<ExceptionObject>(Object::create(interpreter->getClassSystem()->getClassByName("IOException"))), "Failed to write the file: " + absolute_filename_path + " but it opened succesfully", interpreter->getStackTraceLog());
421+
422+
fclose(fp);
423+
}
424+
catch (...)
425+
{
426+
fclose(fp);
427+
throw;
428+
}
429+
}
430+
337431
void FileModule_File::File_chmod(Interpreter *interpreter, std::vector<Value> values, Value *return_value, std::shared_ptr<Object> object, Scope *caller_scope)
338432
{
339433
std::string absolute_filename_path = getAbsolutePath(values[0].svalue);

src/system/value.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,11 @@ void Value::set(std::shared_ptr<Object> o)
143143
this->ovalue = o;
144144
// Let's set the array value to this object. The array value will be NULL if casting fails.
145145
this->avalue = std::dynamic_pointer_cast<Array>(o);
146+
if (this->avalue != NULL)
147+
{
148+
// The type is actually an array
149+
this->type = VALUE_TYPE_ARRAY;
150+
}
146151
}
147152

148153
std::string Value::getStringValue(Value *from, Interpreter *interpreter)

0 commit comments

Comments
 (0)