Skip to content

Commit c2a4a02

Browse files
committed
feat: add method ReadAsBase64 for binary/PNG files
Allows to read a binary file encoded to Base64. Support for both File and AsyncFile, thread-safe. Update CHANGELOG.
1 parent 6068473 commit c2a4a02

File tree

7 files changed

+39
-0
lines changed

7 files changed

+39
-0
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

77
## [Unreleased]
8+
### Added
9+
- read binary file encoded to Base64 using `ReadAsBase64()`, in both `File` and
10+
`AsyncFile`. This is mainly intended to read PNG files (with a screenshot
11+
feature).
812

913
------------------------
1014

scripts/RedFileSystem/AsyncFile.reds

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ public native class AsyncFile {
1212
public native func GetSize() -> Uint64;
1313
1414
public native func ReadAsText(promise: FilePromise) -> Void;
15+
public native func ReadAsBase64(promise: FilePromise) -> Void;
1516
public native func ReadAsLines(promise: FilePromise) -> Void;
1617
@if(ModuleExists("RedData.Json"))
1718
public native func ReadAsJson(promise: FilePromise) -> Void;

scripts/RedFileSystem/File.reds

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ public native class File {
1212
public native func GetSize() -> Uint64;
1313
1414
public native func ReadAsText() -> String;
15+
public native func ReadAsBase64() -> String;
1516
public native func ReadAsLines() -> array<String>;
1617
@if(ModuleExists("RedData.Json"))
1718
public native func ReadAsJson() -> ref<JsonVariant>;

src/AsyncFile.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
#include <fstream>
66
#include <utility>
77

8+
#include "Base64.h"
9+
810
namespace RedFS {
911
AsyncFile::AsyncFile(SharedMutex p_mutex, std::filesystem::path p_path,
1012
std::filesystem::path p_absolute_path)
@@ -58,6 +60,21 @@ void AsyncFile::read_as_text(const FilePromise& p_promise) {
5860
});
5961
}
6062

63+
void AsyncFile::read_as_base64(const FilePromise& p_promise) {
64+
Red::JobQueue job_queue;
65+
66+
job_queue.Dispatch([*this, p_promise]() -> void {
67+
mutex->lock();
68+
std::ifstream stream(absolute_path, std::ios::binary);
69+
const std::string buffer(std::istreambuf_iterator(stream), {});
70+
71+
mutex->unlock();
72+
const Red::CString data = base64::to_base64(buffer);
73+
74+
p_promise.resolve(data);
75+
});
76+
}
77+
6178
void AsyncFile::read_as_lines(const FilePromise& p_promise) {
6279
Red::JobQueue job_queue;
6380

src/AsyncFile.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ class AsyncFile : public Red::IScriptable {
3131
[[nodiscard]] uint64_t get_size() const;
3232

3333
void read_as_text(const FilePromise& p_promise);
34+
void read_as_base64(const FilePromise& p_promise);
3435
void read_as_lines(const FilePromise& p_promise);
3536
void read_as_json(const FilePromise& p_promise);
3637

@@ -59,6 +60,7 @@ RTTI_DEFINE_CLASS(RedFS::AsyncFile, {
5960
RTTI_METHOD(get_size, "GetSize");
6061

6162
RTTI_METHOD(read_as_text, "ReadAsText");
63+
RTTI_METHOD(read_as_base64, "ReadAsBase64");
6264
RTTI_METHOD(read_as_lines, "ReadAsLines");
6365
RTTI_METHOD(read_as_json, "ReadAsJson");
6466

src/File.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
#include <RedData.hpp>
88
#include <RedLib.hpp>
99

10+
#include "Base64.h"
11+
1012
namespace RedFS {
1113

1214
File::File(SharedMutex p_mutex, std::filesystem::path p_path,
@@ -54,6 +56,16 @@ Red::CString File::read_as_text() {
5456
return data.str();
5557
}
5658

59+
Red::CString File::read_as_base64() {
60+
mutex->lock();
61+
std::ifstream stream(absolute_path, std::ios::binary);
62+
const std::string buffer(std::istreambuf_iterator(stream), {});
63+
64+
mutex->unlock();
65+
Red::CString data = base64::to_base64(buffer);
66+
return data;
67+
}
68+
5769
Red::DynArray<Red::CString> File::read_as_lines() {
5870
mutex->lock();
5971
std::ifstream stream;

src/File.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ class File : public Red::IScriptable {
3333
[[nodiscard]] uint64_t get_size() const;
3434

3535
Red::CString read_as_text();
36+
Red::CString read_as_base64();
3637
Red::DynArray<Red::CString> read_as_lines();
3738
Red::Handle<Red::IScriptable> read_as_json();
3839

@@ -59,6 +60,7 @@ RTTI_DEFINE_CLASS(RedFS::File, {
5960
RTTI_METHOD(get_size, "GetSize");
6061

6162
RTTI_METHOD(read_as_text, "ReadAsText");
63+
RTTI_METHOD(read_as_base64, "ReadAsBase64");
6264
RTTI_METHOD(read_as_lines, "ReadAsLines");
6365
RTTI_METHOD(read_as_json, "ReadAsJson");
6466

0 commit comments

Comments
 (0)