diff options
author | Kevin Newton <[email protected]> | 2023-09-27 12:22:36 -0400 |
---|---|---|
committer | Kevin Newton <[email protected]> | 2023-09-27 13:57:38 -0400 |
commit | 8ab56869a64fdccc094f4a83c6367fb23b72d38b (patch) | |
tree | 46ef2bd5c51d5b7f923eda6a60edefc7a08200db /prism/util/pm_string.c | |
parent | 7e0971eb5d679bb6219abb0ec238139aa6502c5a (diff) |
Rename YARP filepaths to prism filepaths
Diffstat (limited to 'prism/util/pm_string.c')
-rw-r--r-- | prism/util/pm_string.c | 200 |
1 files changed, 200 insertions, 0 deletions
diff --git a/prism/util/pm_string.c b/prism/util/pm_string.c new file mode 100644 index 0000000000..9ee25155a3 --- /dev/null +++ b/prism/util/pm_string.c @@ -0,0 +1,200 @@ +#include "yarp/util/yp_string.h" + +// The following headers are necessary to read files using demand paging. +#ifdef _WIN32 +#include <windows.h> +#else +#include <fcntl.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <unistd.h> +#endif + +// Initialize a shared string that is based on initial input. +void +yp_string_shared_init(yp_string_t *string, const uint8_t *start, const uint8_t *end) { + assert(start <= end); + + *string = (yp_string_t) { + .type = YP_STRING_SHARED, + .source = start, + .length = (size_t) (end - start) + }; +} + +// Initialize an owned string that is responsible for freeing allocated memory. +void +yp_string_owned_init(yp_string_t *string, uint8_t *source, size_t length) { + *string = (yp_string_t) { + .type = YP_STRING_OWNED, + .source = source, + .length = length + }; +} + +// Initialize a constant string that doesn't own its memory source. +void +yp_string_constant_init(yp_string_t *string, const char *source, size_t length) { + *string = (yp_string_t) { + .type = YP_STRING_CONSTANT, + .source = (const uint8_t *) source, + .length = length + }; +} + +static void +yp_string_mapped_init_internal(yp_string_t *string, uint8_t *source, size_t length) { + *string = (yp_string_t) { + .type = YP_STRING_MAPPED, + .source = source, + .length = length + }; +} + +// Returns the memory size associated with the string. +size_t +yp_string_memsize(const yp_string_t *string) { + size_t size = sizeof(yp_string_t); + if (string->type == YP_STRING_OWNED) { + size += string->length; + } + return size; +} + +// Ensure the string is owned. If it is not, then reinitialize it as owned and +// copy over the previous source. +void +yp_string_ensure_owned(yp_string_t *string) { + if (string->type == YP_STRING_OWNED) return; + + size_t length = yp_string_length(string); + const uint8_t *source = yp_string_source(string); + + uint8_t *memory = malloc(length); + if (!memory) return; + + yp_string_owned_init(string, memory, length); + memcpy((void *) string->source, source, length); +} + +// Returns the length associated with the string. +YP_EXPORTED_FUNCTION size_t +yp_string_length(const yp_string_t *string) { + return string->length; +} + +// Returns the start pointer associated with the string. +YP_EXPORTED_FUNCTION const uint8_t * +yp_string_source(const yp_string_t *string) { + return string->source; +} + +// Free the associated memory of the given string. +YP_EXPORTED_FUNCTION void +yp_string_free(yp_string_t *string) { + void *memory = (void *) string->source; + + if (string->type == YP_STRING_OWNED) { + free(memory); + } else if (string->type == YP_STRING_MAPPED && string->length) { +#if defined(_WIN32) + UnmapViewOfFile(memory); +#else + munmap(memory, string->length); +#endif + } +} + +bool +yp_string_mapped_init(yp_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) { + perror("CreateFile failed"); + return false; + } + + // Get the file size. + DWORD file_size = GetFileSize(file, NULL); + if (file_size == INVALID_FILE_SIZE) { + CloseHandle(file); + perror("GetFileSize failed"); + 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); + uint8_t empty[] = ""; + yp_string_mapped_init_internal(string, empty, 0); + return true; + } + + // Create a mapping of the file. + HANDLE mapping = CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL); + if (mapping == NULL) { + CloseHandle(file); + perror("CreateFileMapping failed"); + return false; + } + + // Map the file into memory. + uint8_t *source = (uint8_t *) MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0); + CloseHandle(mapping); + CloseHandle(file); + + if (source == NULL) { + perror("MapViewOfFile failed"); + return false; + } + + yp_string_mapped_init_internal(string, source, (size_t) file_size); + return true; +#else + // Open the file for reading + int fd = open(filepath, O_RDONLY); + if (fd == -1) { + perror("open"); + return false; + } + + // Stat the file to get the file size + struct stat sb; + if (fstat(fd, &sb) == -1) { + close(fd); + perror("fstat"); + return false; + } + + // mmap the file descriptor to virtually get the contents + size_t size = (size_t) sb.st_size; + uint8_t *source = NULL; + + if (size == 0) { + close(fd); + uint8_t empty[] = ""; + yp_string_mapped_init_internal(string, empty, 0); + return true; + } + + source = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); + if (source == MAP_FAILED) { + perror("Map failed"); + return false; + } + + close(fd); + yp_string_mapped_init_internal(string, source, size); + return true; +#endif +} + +// Returns the size of the yp_string_t struct. This is necessary to allocate the +// correct amount of memory in the FFI backend. +YP_EXPORTED_FUNCTION size_t +yp_string_sizeof(void) { + return sizeof(yp_string_t); +} |