mirror of
https://github.com/openharmony/third_party_vulkan-loader.git
synced 2026-07-01 21:54:05 -04:00
89db313139
Signed-off-by: ZhangLiang <zhangliang335@h-partners.com>
259 lines
9.1 KiB
C
259 lines
9.1 KiB
C
/*
|
|
Copyright (c) 2015-2021 The Khronos Group Inc.
|
|
Copyright (c) 2015-2021 Valve Corporation
|
|
Copyright (c) 2015-2021 LunarG, Inc.
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
in the Software without restriction, including without limitation the rights
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
THE SOFTWARE.
|
|
*/
|
|
|
|
#include "loader_json.h"
|
|
|
|
#include <assert.h>
|
|
#include <float.h>
|
|
#include <limits.h>
|
|
#include <math.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "cJSON.h"
|
|
|
|
#include "allocation.h"
|
|
#include "loader.h"
|
|
#include "log.h"
|
|
|
|
#if COMMON_UNIX_PLATFORMS
|
|
#include <fcntl.h>
|
|
#include <sys/stat.h>
|
|
#endif
|
|
|
|
#ifdef _WIN32
|
|
static VkResult loader_read_entire_file(const struct loader_instance *inst, const char *filename, size_t *out_len,
|
|
char **out_buff) {
|
|
HANDLE file_handle = INVALID_HANDLE_VALUE;
|
|
DWORD len = 0, read_len = 0;
|
|
VkResult res = VK_SUCCESS;
|
|
BOOL read_ok = false;
|
|
|
|
int filename_utf16_size = MultiByteToWideChar(CP_UTF8, 0, filename, -1, NULL, 0);
|
|
if (filename_utf16_size > 0) {
|
|
wchar_t *filename_utf16 = (wchar_t *)loader_stack_alloc(filename_utf16_size * sizeof(wchar_t));
|
|
if (MultiByteToWideChar(CP_UTF8, 0, filename, -1, filename_utf16, filename_utf16_size) == filename_utf16_size) {
|
|
file_handle =
|
|
CreateFileW(filename_utf16, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
}
|
|
}
|
|
if (INVALID_HANDLE_VALUE == file_handle) {
|
|
loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Failed to open JSON file %s", filename);
|
|
res = VK_ERROR_INITIALIZATION_FAILED;
|
|
goto out;
|
|
}
|
|
len = GetFileSize(file_handle, NULL);
|
|
if (INVALID_FILE_SIZE == len) {
|
|
loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Failed to read file size of JSON file %s", filename);
|
|
res = VK_ERROR_INITIALIZATION_FAILED;
|
|
goto out;
|
|
}
|
|
*out_buff = (char *)loader_instance_heap_calloc(inst, len + 1, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
|
|
if (NULL == *out_buff) {
|
|
loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Failed to allocate memory to read JSON file %s", filename);
|
|
res = VK_ERROR_OUT_OF_HOST_MEMORY;
|
|
goto out;
|
|
}
|
|
read_ok = ReadFile(file_handle, *out_buff, len, &read_len, NULL);
|
|
if (len != read_len || false == read_ok) {
|
|
loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Failed to read entire JSON file %s", filename);
|
|
res = VK_ERROR_INITIALIZATION_FAILED;
|
|
goto out;
|
|
}
|
|
*out_len = len + 1;
|
|
(*out_buff)[len] = '\0';
|
|
|
|
out:
|
|
if (INVALID_HANDLE_VALUE != file_handle) {
|
|
CloseHandle(file_handle);
|
|
}
|
|
return res;
|
|
}
|
|
#elif COMMON_UNIX_PLATFORMS
|
|
static VkResult loader_read_entire_file(const struct loader_instance *inst, const char *filename, size_t *out_len,
|
|
char **out_buff) {
|
|
FILE *file = NULL;
|
|
struct stat stats = {0};
|
|
VkResult res = VK_SUCCESS;
|
|
|
|
file = fopen(filename, "rb");
|
|
if (NULL == file) {
|
|
loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Failed to open JSON file %s", filename);
|
|
res = VK_ERROR_INITIALIZATION_FAILED;
|
|
goto out;
|
|
}
|
|
if (-1 == fstat(fileno(file), &stats)) {
|
|
loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Failed to read file size of JSON file %s", filename);
|
|
res = VK_ERROR_INITIALIZATION_FAILED;
|
|
goto out;
|
|
}
|
|
*out_buff = (char *)loader_instance_heap_calloc(inst, stats.st_size + 1, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
|
|
if (NULL == *out_buff) {
|
|
loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Failed to allocate memory to read JSON file %s", filename);
|
|
res = VK_ERROR_OUT_OF_HOST_MEMORY;
|
|
goto out;
|
|
}
|
|
if (stats.st_size != (long int)fread(*out_buff, sizeof(char), stats.st_size, file)) {
|
|
loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Failed to read entire JSON file %s", filename);
|
|
res = VK_ERROR_INITIALIZATION_FAILED;
|
|
goto out;
|
|
}
|
|
*out_len = stats.st_size + 1;
|
|
(*out_buff)[stats.st_size] = '\0';
|
|
|
|
out:
|
|
if (NULL != file) {
|
|
fclose(file);
|
|
}
|
|
return res;
|
|
}
|
|
#else
|
|
#warning fopen not available on this platform
|
|
VkResult loader_read_entire_file(const struct loader_instance *inst, const char *filename, size_t *out_len, char **out_buff) {
|
|
return VK_ERROR_INITIALIZATION_FAILED;
|
|
}
|
|
#endif
|
|
|
|
TEST_FUNCTION_EXPORT VkResult loader_get_json(const struct loader_instance *inst, const char *filename, cJSON **json) {
|
|
char *json_buf = NULL;
|
|
VkResult res = VK_SUCCESS;
|
|
|
|
assert(json != NULL);
|
|
|
|
size_t json_len = 0;
|
|
*json = NULL;
|
|
res = loader_read_entire_file(inst, filename, &json_len, &json_buf);
|
|
if (VK_SUCCESS != res) {
|
|
goto out;
|
|
}
|
|
bool out_of_memory = false;
|
|
// Parse text from file
|
|
*json = loader_cJSON_ParseWithLength(inst ? &inst->alloc_callbacks : NULL, json_buf, json_len, &out_of_memory);
|
|
if (out_of_memory) {
|
|
loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Out of Memory error occurred while parsing JSON file %s.",
|
|
filename);
|
|
res = VK_ERROR_OUT_OF_HOST_MEMORY;
|
|
goto out;
|
|
} else if (*json == NULL) {
|
|
loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Invalid JSON file %s.", filename);
|
|
goto out;
|
|
}
|
|
|
|
out:
|
|
loader_instance_heap_free(inst, json_buf);
|
|
if (res != VK_SUCCESS && *json != NULL) {
|
|
loader_cJSON_Delete(*json);
|
|
*json = NULL;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
VkResult loader_parse_json_string_to_existing_str(cJSON *object, const char *key, size_t out_str_len, char *out_string) {
|
|
if (NULL == key) {
|
|
return VK_ERROR_INITIALIZATION_FAILED;
|
|
}
|
|
cJSON *item = loader_cJSON_GetObjectItem(object, key);
|
|
if (NULL == item) {
|
|
return VK_ERROR_INITIALIZATION_FAILED;
|
|
}
|
|
|
|
if (item->type != cJSON_String || item->valuestring == NULL) {
|
|
return VK_ERROR_INITIALIZATION_FAILED;
|
|
}
|
|
bool out_of_memory = false;
|
|
bool success = loader_cJSON_PrintPreallocated(item, out_string, (int)out_str_len, cJSON_False);
|
|
if (out_of_memory) {
|
|
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
|
}
|
|
if (!success) {
|
|
return VK_ERROR_INITIALIZATION_FAILED;
|
|
}
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
VkResult loader_parse_json_string(cJSON *object, const char *key, char **out_string) {
|
|
if (NULL == key) {
|
|
return VK_ERROR_INITIALIZATION_FAILED;
|
|
}
|
|
|
|
cJSON *item = loader_cJSON_GetObjectItem(object, key);
|
|
if (NULL == item || NULL == item->valuestring) {
|
|
return VK_ERROR_INITIALIZATION_FAILED;
|
|
}
|
|
|
|
bool out_of_memory = false;
|
|
char *str = loader_cJSON_Print(item, &out_of_memory);
|
|
if (out_of_memory || NULL == str) {
|
|
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
|
}
|
|
if (NULL != out_string) {
|
|
*out_string = str;
|
|
}
|
|
return VK_SUCCESS;
|
|
}
|
|
VkResult loader_parse_json_array_of_strings(const struct loader_instance *inst, cJSON *object, const char *key,
|
|
struct loader_string_list *string_list) {
|
|
if (NULL == key) {
|
|
return VK_ERROR_INITIALIZATION_FAILED;
|
|
}
|
|
cJSON *item = loader_cJSON_GetObjectItem(object, key);
|
|
if (NULL == item) {
|
|
return VK_ERROR_INITIALIZATION_FAILED;
|
|
}
|
|
|
|
uint32_t count = loader_cJSON_GetArraySize(item);
|
|
if (count == 0) {
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
VkResult res = create_string_list(inst, count, string_list);
|
|
if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
|
|
goto out;
|
|
}
|
|
cJSON *element = NULL;
|
|
cJSON_ArrayForEach(element, item) {
|
|
if (element->type != cJSON_String) {
|
|
return VK_ERROR_INITIALIZATION_FAILED;
|
|
}
|
|
bool out_of_memory = false;
|
|
char *out_data = loader_cJSON_Print(element, &out_of_memory);
|
|
if (out_of_memory) {
|
|
res = VK_ERROR_OUT_OF_HOST_MEMORY;
|
|
goto out;
|
|
}
|
|
res = append_str_to_string_list(inst, string_list, out_data);
|
|
if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
|
|
goto out;
|
|
}
|
|
}
|
|
out:
|
|
if (res == VK_ERROR_OUT_OF_HOST_MEMORY && NULL != string_list->list) {
|
|
free_string_list(inst, string_list);
|
|
}
|
|
|
|
return res;
|
|
}
|