-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
(stdlib) Add
File.read_all_text()
method
...and use this method from the C# code for reading the Perlang program being executed from disk. Doing it like this makes little "theoretical sense" since it's much more cumbersome than just using the built-in C# methods for this, *but* it means that we start using the new C++/Perlang-based stdlib somewhere. In that sense, it's a small step towards the effort of becoming self-hosted. https://gitlab.perlang.org/perlang/perlang/-/merge_requests/527
- Loading branch information
Showing
11 changed files
with
153 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
#nullable enable | ||
#pragma warning disable SA1300 | ||
#pragma warning disable SA1601 | ||
using System; | ||
using System.Runtime.InteropServices; | ||
|
||
namespace Perlang.ConsoleApp; | ||
|
||
internal static partial class NativeFile | ||
{ | ||
[LibraryImport("perlang_cli", EntryPoint = "File_read_all_text", StringMarshalling = StringMarshalling.Utf8)] | ||
private static partial IntPtr _File_read_all_text(string path); | ||
|
||
[LibraryImport("perlang_cli", EntryPoint = "File_read_all_text_free")] | ||
private static partial void _File_read_all_text_free(IntPtr file_contents); | ||
|
||
public static string read_all_text(string path) | ||
{ | ||
IntPtr file_contents = IntPtr.Zero; | ||
|
||
try { | ||
file_contents = _File_read_all_text(path); | ||
return Marshal.PtrToStringUTF8(file_contents)!; | ||
} | ||
finally { | ||
if (file_contents != IntPtr.Zero) { | ||
_File_read_all_text_free(file_contents); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
// Wrappers on top of the Perlang standard library, to make it usable from C# | ||
// | ||
// These wrappers must take care of a few things: | ||
// | ||
// - Make C++ methods accessible from C# (by wrapping them in extern "C" functions) | ||
// - Handle conversion from Perlang/C++ shared_ptr types to types that can be consumed from the C# side | ||
|
||
#include <cstring> | ||
#include <stdexcept> | ||
|
||
#include "perlang_stdlib.h" | ||
|
||
using namespace perlang; | ||
|
||
extern "C" { | ||
const char* File_read_all_text(const char* path) { | ||
std::unique_ptr<const String> file_contents = perlang::io::File::read_all_text(*UTF8String::from_copied_string(path)); | ||
const char* result = strdup(file_contents->bytes()); | ||
return result; | ||
} | ||
|
||
void File_read_all_text_free(const char* s) { | ||
free((void*) s); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
#include <cstdio> | ||
#include <stdexcept> | ||
|
||
#include "io/file.h" | ||
#include "utf8_string.h" | ||
|
||
namespace perlang::io | ||
{ | ||
[[nodiscard]] | ||
std::unique_ptr<const String> File::read_all_text(const String& path) | ||
{ | ||
FILE *file = fopen(path.bytes(), "r"); | ||
|
||
if (file == nullptr) { | ||
return nullptr; | ||
} | ||
|
||
// Determine the size of the file | ||
fseek(file, 0, SEEK_END); | ||
long length = ftell(file); | ||
|
||
if (length == -1) { | ||
fclose(file); | ||
return nullptr; | ||
} | ||
|
||
// Go back to the beginning and read the file into a buffer | ||
fseek(file, 0, SEEK_SET); | ||
|
||
std::unique_ptr<char[]> buffer = std::make_unique<char[]>(length + 1); | ||
|
||
if (buffer == nullptr) { | ||
fclose(file); | ||
throw std::runtime_error("Failed to allocate memory when attempting to read file " + std::string(path.bytes())); | ||
} | ||
|
||
size_t read = fread(buffer.get(), 1, length, file); | ||
fclose(file); | ||
|
||
// Ensure that we read the entire file; if not, return an error to the caller | ||
if (read != (size_t)length) { | ||
throw std::runtime_error("Expected to read " + std::to_string(length) + " bytes, but only read " + std::to_string(read) + " bytes"); | ||
} | ||
|
||
// Create a Perlang string based on the newly read data. Releasing the buffer afterwards is crucial to avoid | ||
// double-free()ing the memory. | ||
buffer[length] = '\0'; | ||
std::unique_ptr<const String> ptr = UTF8String::from_owned_string(buffer.release(), length); | ||
|
||
return ptr; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
#pragma once | ||
|
||
#include <memory> | ||
|
||
#include "perlang_string.h" | ||
|
||
namespace perlang::io | ||
{ | ||
class File | ||
{ | ||
public: | ||
// Reads a file from the given path and returns its contents as a string. The file is presumed to be encoded in | ||
// UTF-8. | ||
static std::unique_ptr<const String> read_all_text(const String &path); | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters