[ruby/prism] Parse files from Ruby API using fread, not mmap

https://github.com/ruby/prism/commit/62d4376a53
This commit is contained in:
Kevin Newton 2024-03-01 14:45:36 -05:00 committed by git
parent 6ea01d204e
commit b88973165a
3 changed files with 115 additions and 2 deletions

View File

@ -254,7 +254,7 @@ file_options(int argc, VALUE *argv, pm_string_t *input, pm_options_t *options) {
const char * string_source = (const char *) pm_string_source(&options->filepath);
if (!pm_string_mapped_init(input, string_source)) {
if (!pm_string_file_init(input, string_source)) {
pm_options_free(options);
#ifdef _WIN32

View File

@ -58,7 +58,7 @@ pm_string_constant_init(pm_string_t *string, const char *source, size_t length)
* `MapViewOfFile`, on POSIX systems that have access to `mmap` we'll use
* `mmap`, and on other POSIX systems we'll use `read`.
*/
bool
PRISM_EXPORTED_FUNCTION bool
pm_string_mapped_init(pm_string_t *string, const char *filepath) {
#ifdef _WIN32
// Open the file for reading.
@ -143,6 +143,108 @@ pm_string_mapped_init(pm_string_t *string, const char *filepath) {
#endif
}
/**
* Read the file indicated by the filepath parameter into source and load its
* contents and size into the given `pm_string_t`. The given `pm_string_t`
* should be freed using `pm_string_free` when it is no longer used.
*/
PRISM_EXPORTED_FUNCTION bool
pm_string_file_init(pm_string_t *string, const char *filepath) {
#ifdef _WIN32
// Open the file for reading.
HANDLE file = CreateFile(filepath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (file == INVALID_HANDLE_VALUE) {
return false;
}
// Get the file size.
DWORD file_size = GetFileSize(file, NULL);
if (file_size == INVALID_FILE_SIZE) {
CloseHandle(file);
return false;
}
// If the file is empty, then we don't need to do anything else, we'll set
// the source to a constant empty string and return.
if (file_size == 0) {
CloseHandle(file);
const uint8_t source[] = "";
*string = (pm_string_t) { .type = PM_STRING_CONSTANT, .source = source, .length = 0 };
return true;
}
// Create a buffer to read the file into.
uint8_t *source = malloc(file_size);
if (source == NULL) {
CloseHandle(file);
return false;
}
// Read the contents of the file
DWORD bytes_read;
if (!ReadFile(file, source, file_size, &bytes_read, NULL)) {
CloseHandle(file);
return false;
}
// Check the number of bytes read
if (bytes_read != file_size) {
free(source);
CloseHandle(file);
return false;
}
CloseHandle(file);
*string = (pm_string_t) { .type = PM_STRING_OWNED, .source = source, .length = (size_t) file_size };
return true;
#elif defined(_POSIX_MAPPED_FILES)
FILE *file = fopen(filepath, "rb");
if (file == NULL) {
return false;
}
fseek(file, 0, SEEK_END);
long file_size = ftell(file);
if (file_size == -1) {
fclose(file);
return false;
}
if (file_size == 0) {
fclose(file);
const uint8_t source[] = "";
*string = (pm_string_t) { .type = PM_STRING_CONSTANT, .source = source, .length = 0 };
return true;
}
size_t length = (size_t) file_size;
uint8_t *source = malloc(length);
if (source == NULL) {
fclose(file);
return false;
}
fseek(file, 0, SEEK_SET);
size_t bytes_read = fread(source, length, 1, file);
fclose(file);
if (bytes_read != 1) {
free(source);
return false;
}
*string = (pm_string_t) { .type = PM_STRING_OWNED, .source = source, .length = length };
return true;
#else
(void) string;
(void) filepath;
perror("pm_string_file_init is not implemented for this platform");
return false;
#endif
}
/**
* Returns the memory size associated with the string.
*/

View File

@ -109,6 +109,17 @@ void pm_string_constant_init(pm_string_t *string, const char *source, size_t len
*/
PRISM_EXPORTED_FUNCTION bool pm_string_mapped_init(pm_string_t *string, const char *filepath);
/**
* Read the file indicated by the filepath parameter into source and load its
* contents and size into the given `pm_string_t`. The given `pm_string_t`
* should be freed using `pm_string_free` when it is no longer used.
*
* @param string The string to initialize.
* @param filepath The filepath to read.
* @return Whether or not the file was successfully read.
*/
PRISM_EXPORTED_FUNCTION bool pm_string_file_init(pm_string_t *string, const char *filepath);
/**
* Returns the memory size associated with the string.
*