create_callback_file:
   59|     54|void create_callback_file(const char *filename) {}

create_config_file:
   24|  3.13k|int create_config_file(const char* config_path, const char* config_filename, const uint8_t* data, size_t size) {
   25|  3.13k|  char filename[512];
   26|  3.13k|  char path[256];
   27|  3.13k|  char command[256];
   28|       |
   29|  3.13k|  sprintf(path, "%s/%s", getenv("HOME"), config_path);
   30|  3.13k|  sprintf(command, "mkdir -p %s", path);
   31|       |
   32|  3.13k|  system(command);
   33|       |
   34|  3.13k|  sprintf(filename, "%s/%s", path, config_filename);
   35|       |
   36|  3.13k|  FILE *fp = fopen(filename, "wb");
   37|  3.13k|  if (!fp) {
  ------------------
  |  Branch (37:7): [True: 0, False: 3.13k]
  ------------------
   38|      0|    return 1;
   39|      0|  }
   40|  3.13k|  fwrite(data, size, 1, fp);
   41|  3.13k|  fclose(fp);
   42|       |
   43|  3.13k|  return 0;
   44|  3.13k|}
remove_config_file:
   49|  3.13k|void remove_config_file(const char* config_path, const char* config_filename) {
   50|  3.13k|  char filename[512];
   51|  3.13k|  sprintf(filename, "%s/%s/%s", getenv("HOME"), config_path, config_filename);
   52|  3.13k|  unlink(filename);
   53|  3.13k|}
LLVMFuzzerTestOneInput:
   58|  3.13k|int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
   59|  3.13k|  setenv("HOME", "/tmp", 1);
   60|       |
   61|       |  // Create loader configuration file
   62|  3.13k|  int result = create_config_file(".local/share/vulkan/loader_settings.d", "vk_loader_settings.json", data, size);
   63|  3.13k|  if (result) {
  ------------------
  |  Branch (63:7): [True: 0, False: 3.13k]
  ------------------
   64|      0|    return 0;
   65|      0|  }
   66|       |
   67|  3.13k|  update_global_loader_settings();
   68|  3.13k|  update_global_loader_settings();
   69|  3.13k|  get_current_settings_and_lock(NULL);
   70|  3.13k|  release_current_settings_lock(NULL);
   71|  3.13k|  struct loader_layer_list settings_layers = {0};
   72|       |
   73|  3.13k|  bool should_search_for_other_layers = true;
   74|  3.13k|  get_settings_layers(NULL, &settings_layers, &should_search_for_other_layers);
   75|       |  // Free allocated memory
   76|  3.13k|  loader_delete_layer_list_and_properties(NULL, &settings_layers);
   77|  3.13k|  should_skip_logging_global_messages(0);
   78|  3.13k|  update_global_loader_settings();
   79|  3.13k|  teardown_global_loader_settings();
   80|       |
   81|       |  // Clean up config file
   82|  3.13k|  remove_config_file(".local/share/vulkan/loader_settings.d", "vk_loader_settings.json");
   83|       |
   84|  3.13k|  return 0;
   85|  3.13k|}

loader_calloc:
   51|  6.24M|void *loader_calloc(const VkAllocationCallbacks *pAllocator, size_t size, VkSystemAllocationScope allocation_scope) {
   52|  6.24M|    void *pMemory = NULL;
   53|       |#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
   54|       |    {
   55|       |#else
   56|  6.24M|    if (pAllocator && pAllocator->pfnAllocation) {
  ------------------
  |  Branch (56:9): [True: 0, False: 6.24M]
  |  Branch (56:23): [True: 0, False: 0]
  ------------------
   57|       |        // These are internal structures, so it's best to align everything to
   58|       |        // the largest unit size which is the size of a uint64_t.
   59|      0|        pMemory = pAllocator->pfnAllocation(pAllocator->pUserData, size, sizeof(uint64_t), allocation_scope);
   60|      0|        if (pMemory) {
  ------------------
  |  Branch (60:13): [True: 0, False: 0]
  ------------------
   61|      0|            memset(pMemory, 0, size);
   62|      0|        }
   63|  6.24M|    } else {
   64|  6.24M|#endif
   65|  6.24M|        pMemory = calloc(1, size);
   66|  6.24M|    }
   67|       |
   68|  6.24M|    return pMemory;
   69|  6.24M|}
loader_free:
   71|  7.81M|void loader_free(const VkAllocationCallbacks *pAllocator, void *pMemory) {
   72|  7.81M|    if (pMemory != NULL) {
  ------------------
  |  Branch (72:9): [True: 6.24M, False: 1.57M]
  ------------------
   73|       |#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
   74|       |        {
   75|       |#else
   76|  6.24M|        if (pAllocator && pAllocator->pfnFree) {
  ------------------
  |  Branch (76:13): [True: 0, False: 6.24M]
  |  Branch (76:27): [True: 0, False: 0]
  ------------------
   77|      0|            pAllocator->pfnFree(pAllocator->pUserData, pMemory);
   78|  6.24M|        } else {
   79|  6.24M|#endif
   80|  6.24M|            free(pMemory);
   81|  6.24M|        }
   82|  6.24M|    }
   83|  7.81M|}
loader_realloc:
   86|  1.27M|                     VkSystemAllocationScope allocation_scope) {
   87|  1.27M|    void *pNewMem = NULL;
   88|  1.27M|    if (pMemory == NULL || orig_size == 0) {
  ------------------
  |  Branch (88:9): [True: 0, False: 1.27M]
  |  Branch (88:28): [True: 0, False: 1.27M]
  ------------------
   89|      0|        pNewMem = loader_alloc(pAllocator, size, allocation_scope);
   90|  1.27M|    } else if (size == 0) {
  ------------------
  |  Branch (90:16): [True: 0, False: 1.27M]
  ------------------
   91|      0|        loader_free(pAllocator, pMemory);
   92|       |#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
   93|       |#else
   94|  1.27M|    } else if (pAllocator && pAllocator->pfnReallocation) {
  ------------------
  |  Branch (94:16): [True: 0, False: 1.27M]
  |  Branch (94:30): [True: 0, False: 0]
  ------------------
   95|       |        // These are internal structures, so it's best to align everything to
   96|       |        // the largest unit size which is the size of a uint64_t.
   97|      0|        pNewMem = pAllocator->pfnReallocation(pAllocator->pUserData, pMemory, size, sizeof(uint64_t), allocation_scope);
   98|      0|#endif
   99|  1.27M|    } else {
  100|  1.27M|        pNewMem = realloc(pMemory, size);
  101|       |        // Clear out the newly allocated memory. On failure realloc returns NULL and leaves the original block valid, so
  102|       |        // only write through pNewMem once we know it points at the resized allocation.
  103|  1.27M|        if (NULL != pNewMem && size > orig_size) {
  ------------------
  |  Branch (103:13): [True: 1.27M, False: 0]
  |  Branch (103:32): [True: 3.11k, False: 1.26M]
  ------------------
  104|  3.11k|            memset((uint8_t *)pNewMem + orig_size, 0, size - orig_size);
  105|  3.11k|        }
  106|  1.27M|    }
  107|  1.27M|    return pNewMem;
  108|  1.27M|}
loader_instance_heap_calloc:
  114|   154k|void *loader_instance_heap_calloc(const struct loader_instance *inst, size_t size, VkSystemAllocationScope allocation_scope) {
  115|   154k|    return loader_calloc(inst ? &inst->alloc_callbacks : NULL, size, allocation_scope);
  ------------------
  |  Branch (115:26): [True: 0, False: 154k]
  ------------------
  116|   154k|}
loader_instance_heap_free:
  118|  2.99M|void loader_instance_heap_free(const struct loader_instance *inst, void *pMemory) {
  119|  2.99M|    loader_free(inst ? &inst->alloc_callbacks : NULL, pMemory);
  ------------------
  |  Branch (119:17): [True: 0, False: 2.99M]
  ------------------
  120|  2.99M|}
loader_instance_heap_realloc:
  122|    189|                                   VkSystemAllocationScope allocation_scope) {
  123|    189|    return loader_realloc(inst ? &inst->alloc_callbacks : NULL, pMemory, orig_size, size, allocation_scope);
  ------------------
  |  Branch (123:27): [True: 0, False: 189]
  ------------------
  124|    189|}

loader_cJSON_GetStringValue:
   98|  4.11k|CJSON_PUBLIC(char *) loader_cJSON_GetStringValue(const cJSON *const item) {
   99|  4.11k|    if (!loader_cJSON_IsString(item)) {
  ------------------
  |  Branch (99:9): [True: 1.75k, False: 2.36k]
  ------------------
  100|  1.75k|        return NULL;
  101|  1.75k|    }
  102|       |
  103|  2.36k|    return item->valuestring;
  104|  4.11k|}
loader_cJSON_Delete:
  151|   400k|TEST_FUNCTION_EXPORT CJSON_PUBLIC(void) loader_cJSON_Delete(cJSON *item) {
  152|   400k|    cJSON *next = NULL;
  153|  2.92M|    while (item != NULL) {
  ------------------
  |  Branch (153:12): [True: 2.52M, False: 400k]
  ------------------
  154|  2.52M|        next = item->next;
  155|  2.52M|        if (!(item->type & cJSON_IsReference) && (item->child != NULL)) {
  ------------------
  |  |  106|  2.52M|#define cJSON_IsReference 256
  ------------------
  |  Branch (155:13): [True: 2.52M, False: 0]
  |  Branch (155:50): [True: 247k, False: 2.28M]
  ------------------
  156|   247k|            loader_cJSON_Delete(item->child);
  157|   247k|        }
  158|  2.52M|        if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) {
  ------------------
  |  |  106|  2.52M|#define cJSON_IsReference 256
  ------------------
  |  Branch (158:13): [True: 2.52M, False: 0]
  |  Branch (158:50): [True: 1.57M, False: 951k]
  ------------------
  159|  1.57M|            loader_free(item->pAllocator, item->valuestring);
  160|  1.57M|            item->valuestring = NULL;
  161|  1.57M|        }
  162|  2.52M|        if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) {
  ------------------
  |  |  107|  2.52M|#define cJSON_StringIsConst 512
  ------------------
  |  Branch (162:13): [True: 2.52M, False: 0]
  |  Branch (162:52): [True: 718k, False: 1.81M]
  ------------------
  163|   718k|            loader_free(item->pAllocator, item->string);
  164|       |            item->string = NULL;
  165|   718k|        }
  166|  2.52M|        loader_free(item->pAllocator, item);
  167|  2.52M|        item = next;
  168|  2.52M|    }
  169|   400k|}
loader_cJSON_ParseWithLengthOpts:
  824|  8.00k|                                 const char **return_parse_end, cJSON_bool require_null_terminated, bool *out_of_memory) {
  825|  8.00k|    parse_buffer buffer = {0, 0, 0, 0, 0};
  826|  8.00k|    cJSON *item = NULL;
  827|       |
  828|       |    /* reset error position */
  829|       |    // global_error.json = NULL;
  830|       |    // global_error.position = 0;
  831|       |
  832|  8.00k|    if (value == NULL || 0 == buffer_length) {
  ------------------
  |  Branch (832:9): [True: 0, False: 8.00k]
  |  Branch (832:26): [True: 0, False: 8.00k]
  ------------------
  833|      0|        goto fail;
  834|      0|    }
  835|       |
  836|  8.00k|    buffer.content = (const unsigned char *)value;
  837|  8.00k|    buffer.length = buffer_length;
  838|  8.00k|    buffer.offset = 0;
  839|  8.00k|    buffer.pAllocator = pAllocator;
  840|       |
  841|  8.00k|    item = cJSON_New_Item(pAllocator);
  842|  8.00k|    if (item == NULL) /* memory fail */
  ------------------
  |  Branch (842:9): [True: 0, False: 8.00k]
  ------------------
  843|      0|    {
  844|      0|        *out_of_memory = true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
  845|      0|        goto fail;
  846|      0|    }
  847|       |
  848|  8.00k|    if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer)), out_of_memory)) {
  ------------------
  |  Branch (848:9): [True: 2.85k, False: 5.14k]
  ------------------
  849|       |        /* parse failure. ep is set. */
  850|  2.85k|        goto fail;
  851|  2.85k|    }
  852|       |
  853|       |    /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
  854|  5.14k|    if (require_null_terminated) {
  ------------------
  |  Branch (854:9): [True: 0, False: 5.14k]
  ------------------
  855|      0|        buffer_skip_whitespace(&buffer);
  856|      0|        if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0') {
  ------------------
  |  |  195|      0|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (856:13): [True: 0, False: 0]
  |  Branch (856:49): [True: 0, False: 0]
  ------------------
  857|      0|            goto fail;
  858|      0|        }
  859|      0|    }
  860|  5.14k|    if (return_parse_end) {
  ------------------
  |  Branch (860:9): [True: 0, False: 5.14k]
  ------------------
  861|      0|        *return_parse_end = (const char *)buffer_at_offset(&buffer);
  ------------------
  |  |  195|      0|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  862|      0|    }
  863|       |
  864|  5.14k|    return item;
  865|       |
  866|  2.85k|fail:
  867|  2.85k|    if (item != NULL) {
  ------------------
  |  Branch (867:9): [True: 2.85k, False: 0]
  ------------------
  868|  2.85k|        loader_cJSON_Delete(item);
  869|  2.85k|    }
  870|       |
  871|  2.85k|    if (value != NULL) {
  ------------------
  |  Branch (871:9): [True: 2.85k, False: 0]
  ------------------
  872|  2.85k|        error local_error;
  873|  2.85k|        local_error.json = (const unsigned char *)value;
  874|  2.85k|        local_error.position = 0;
  875|       |
  876|  2.85k|        if (buffer.offset < buffer.length) {
  ------------------
  |  Branch (876:13): [True: 2.58k, False: 263]
  ------------------
  877|  2.58k|            local_error.position = buffer.offset;
  878|  2.58k|        } else if (buffer.length > 0) {
  ------------------
  |  Branch (878:20): [True: 263, False: 0]
  ------------------
  879|    263|            local_error.position = buffer.length - 1;
  880|    263|        }
  881|       |
  882|  2.85k|        if (return_parse_end != NULL) {
  ------------------
  |  Branch (882:13): [True: 0, False: 2.85k]
  ------------------
  883|      0|            *return_parse_end = (const char *)local_error.json + local_error.position;
  884|      0|        }
  885|       |
  886|       |        // global_error = local_error;
  887|  2.85k|    }
  888|       |
  889|       |    return NULL;
  890|  5.14k|}
loader_cJSON_ParseWithLength:
  899|  8.00k|                             bool *out_of_memory) {
  900|  8.00k|    return loader_cJSON_ParseWithLengthOpts(pAllocator, value, buffer_length, 0, 0, out_of_memory);
  901|  8.00k|}
loader_cJSON_Print:
  953|  1.26M|TEST_FUNCTION_EXPORT CJSON_PUBLIC(char *) loader_cJSON_Print(const cJSON *item, bool *out_of_memory) {
  954|  1.26M|    return (char *)print(item, true, out_of_memory);
  ------------------
  |  |   67|  1.26M|#define true ((cJSON_bool)1)
  ------------------
  955|  1.26M|}
loader_cJSON_GetArraySize:
 1457|  7.56k|CJSON_PUBLIC(int) loader_cJSON_GetArraySize(const cJSON *array) {
 1458|  7.56k|    cJSON *child = NULL;
 1459|  7.56k|    size_t size = 0;
 1460|       |
 1461|  7.56k|    if (array == NULL) {
  ------------------
  |  Branch (1461:9): [True: 0, False: 7.56k]
  ------------------
 1462|      0|        return 0;
 1463|      0|    }
 1464|       |
 1465|  7.56k|    child = array->child;
 1466|       |
 1467|   963k|    while (child != NULL) {
  ------------------
  |  Branch (1467:12): [True: 955k, False: 7.56k]
  ------------------
 1468|   955k|        size++;
 1469|   955k|        child = child->next;
 1470|   955k|    }
 1471|       |
 1472|       |    /* FIXME: Can overflow here. Cannot be fixed without breaking the API */
 1473|       |
 1474|  7.56k|    return (int)size;
 1475|  7.56k|}
loader_cJSON_GetObjectItem:
 1527|   718k|CJSON_PUBLIC(cJSON *) loader_cJSON_GetObjectItem(const cJSON *const object, const char *const string) {
 1528|   718k|    return get_object_item(object, string, false);
  ------------------
  |  |   72|   718k|#define false ((cJSON_bool)0)
  ------------------
 1529|   718k|}
loader_cJSON_IsString:
 1670|  4.11k|CJSON_PUBLIC(cJSON_bool) loader_cJSON_IsString(const cJSON *const item) {
 1671|  4.11k|    if (item == NULL) {
  ------------------
  |  Branch (1671:9): [True: 0, False: 4.11k]
  ------------------
 1672|      0|        return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1673|      0|    }
 1674|       |
 1675|  4.11k|    return (item->type & 0xFF) == cJSON_String;
  ------------------
  |  |  101|  4.11k|#define cJSON_String (1 << 4)
  ------------------
 1676|  4.11k|}
cJSON.c:cJSON_New_Item:
  142|  2.52M|static cJSON *cJSON_New_Item(const VkAllocationCallbacks *pAllocator) {
  143|  2.52M|    cJSON *node = (cJSON *)loader_calloc(pAllocator, sizeof(cJSON), VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
  144|  2.52M|    if (NULL != node) {
  ------------------
  |  Branch (144:9): [True: 2.52M, False: 0]
  ------------------
  145|  2.52M|        node->pAllocator = pAllocator;
  146|  2.52M|    }
  147|  2.52M|    return node;
  148|  2.52M|}
cJSON.c:buffer_skip_whitespace:
  772|  6.75M|static parse_buffer *buffer_skip_whitespace(parse_buffer *const buffer) {
  773|  6.75M|    if ((buffer == NULL) || (buffer->content == NULL)) {
  ------------------
  |  Branch (773:9): [True: 0, False: 6.75M]
  |  Branch (773:29): [True: 0, False: 6.75M]
  ------------------
  774|      0|        return NULL;
  775|      0|    }
  776|       |
  777|  6.75M|    if (cannot_access_at_index(buffer, 0)) {
  ------------------
  |  |  193|  6.75M|#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
  |  |  ------------------
  |  |  |  |  192|  6.75M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (192:45): [True: 6.75M, False: 0]
  |  |  |  |  |  Branch (192:65): [True: 6.75M, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  778|      0|        return buffer;
  779|      0|    }
  780|       |
  781|  9.87M|    while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) {
  ------------------
  |  |  192|  19.7M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 9.87M, False: 0]
  |  |  |  Branch (192:65): [True: 9.87M, False: 2.11k]
  |  |  ------------------
  ------------------
                  while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) {
  ------------------
  |  |  195|  9.87M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (781:46): [True: 3.12M, False: 6.75M]
  ------------------
  782|  3.12M|        buffer->offset++;
  783|  3.12M|    }
  784|       |
  785|  6.75M|    if (buffer->offset == buffer->length) {
  ------------------
  |  Branch (785:9): [True: 2.11k, False: 6.75M]
  ------------------
  786|  2.11k|        buffer->offset--;
  787|  2.11k|    }
  788|       |
  789|  6.75M|    return buffer;
  790|  6.75M|}
cJSON.c:skip_utf8_bom:
  793|  8.00k|static parse_buffer *skip_utf8_bom(parse_buffer *const buffer) {
  794|  8.00k|    if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0)) {
  ------------------
  |  Branch (794:9): [True: 0, False: 8.00k]
  |  Branch (794:29): [True: 0, False: 8.00k]
  |  Branch (794:58): [True: 0, False: 8.00k]
  ------------------
  795|      0|        return NULL;
  796|      0|    }
  797|       |
  798|  8.00k|    if (can_access_at_index(buffer, 4) && (strncmp((const char *)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0)) {
  ------------------
  |  |  192|  16.0k|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 8.00k, False: 0]
  |  |  |  Branch (192:65): [True: 7.06k, False: 935]
  |  |  ------------------
  ------------------
                  if (can_access_at_index(buffer, 4) && (strncmp((const char *)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0)) {
  ------------------
  |  |  195|  7.06k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (798:43): [True: 137, False: 6.92k]
  ------------------
  799|    137|        buffer->offset += 3;
  800|    137|    }
  801|       |
  802|  8.00k|    return buffer;
  803|  8.00k|}
cJSON.c:print:
  905|  1.26M|static unsigned char *print(const cJSON *const item, cJSON_bool format, bool *out_of_memory) {
  906|  1.26M|    static const size_t default_buffer_size = 256;
  907|  1.26M|    printbuffer buffer[1];
  908|  1.26M|    unsigned char *printed = NULL;
  909|       |
  910|  1.26M|    memset(buffer, 0, sizeof(buffer));
  911|       |
  912|       |    /* create buffer */
  913|  1.26M|    buffer->buffer = (unsigned char *)loader_calloc(item->pAllocator, default_buffer_size, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  914|  1.26M|    buffer->length = default_buffer_size;
  915|  1.26M|    buffer->format = format;
  916|  1.26M|    buffer->pAllocator = item->pAllocator;
  917|  1.26M|    if (buffer->buffer == NULL) {
  ------------------
  |  Branch (917:9): [True: 0, False: 1.26M]
  ------------------
  918|      0|        *out_of_memory = true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
  919|      0|        goto fail;
  920|      0|    }
  921|       |
  922|       |    /* print the value */
  923|  1.26M|    if (!print_value(item, buffer, out_of_memory)) {
  ------------------
  |  Branch (923:9): [True: 0, False: 1.26M]
  ------------------
  924|      0|        goto fail;
  925|      0|    }
  926|  1.26M|    update_offset(buffer);
  927|       |
  928|  1.26M|    printed = (unsigned char *)loader_realloc(item->pAllocator, buffer->buffer, buffer->length, buffer->offset + 1,
  929|  1.26M|                                              VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  930|  1.26M|    if (printed == NULL) {
  ------------------
  |  Branch (930:9): [True: 0, False: 1.26M]
  ------------------
  931|      0|        *out_of_memory = true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
  932|      0|        goto fail;
  933|      0|    }
  934|  1.26M|    buffer->buffer = NULL;
  935|       |
  936|  1.26M|    return printed;
  937|       |
  938|      0|fail:
  939|      0|    if (buffer->buffer != NULL) {
  ------------------
  |  Branch (939:9): [True: 0, False: 0]
  ------------------
  940|      0|        loader_free(item->pAllocator, buffer->buffer);
  941|      0|        buffer->buffer = NULL;
  942|      0|    }
  943|       |
  944|      0|    if (printed != NULL) {
  ------------------
  |  Branch (944:9): [True: 0, False: 0]
  ------------------
  945|      0|        loader_free(item->pAllocator, printed);
  946|      0|        printed = NULL;
  947|      0|    }
  948|       |
  949|       |    return NULL;
  950|  1.26M|}
cJSON.c:update_offset:
  331|  1.26M|static void update_offset(printbuffer *const buffer) {
  332|  1.26M|    const unsigned char *buffer_pointer = NULL;
  333|  1.26M|    if ((buffer == NULL) || (buffer->buffer == NULL)) {
  ------------------
  |  Branch (333:9): [True: 0, False: 1.26M]
  |  Branch (333:29): [True: 0, False: 1.26M]
  ------------------
  334|      0|        return;
  335|      0|    }
  336|  1.26M|    buffer_pointer = buffer->buffer + buffer->offset;
  337|       |
  338|  1.26M|    buffer->offset += strlen((const char *)buffer_pointer);
  339|  1.26M|}
cJSON.c:parse_value:
 1008|  2.52M|static cJSON_bool parse_value(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory) {
 1009|  2.52M|    if ((input_buffer == NULL) || (input_buffer->content == NULL)) {
  ------------------
  |  Branch (1009:9): [True: 0, False: 2.52M]
  |  Branch (1009:35): [True: 0, False: 2.52M]
  ------------------
 1010|      0|        return false; /* no input */
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1011|      0|    }
 1012|       |
 1013|       |    /* parse the different types of values */
 1014|       |    /* null */
 1015|  2.52M|    if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "null", 4) == 0)) {
  ------------------
  |  |  190|  5.05M|#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (190:33): [True: 2.52M, False: 0]
  |  |  |  Branch (190:53): [True: 2.52M, False: 2.18k]
  |  |  ------------------
  ------------------
                  if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "null", 4) == 0)) {
  ------------------
  |  |  195|  2.52M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1015:38): [True: 1.38k, False: 2.52M]
  ------------------
 1016|  1.38k|        item->type = cJSON_NULL;
  ------------------
  |  |   99|  1.38k|#define cJSON_NULL (1 << 2)
  ------------------
 1017|  1.38k|        input_buffer->offset += 4;
 1018|  1.38k|        return true;
  ------------------
  |  |   67|  1.38k|#define true ((cJSON_bool)1)
  ------------------
 1019|  1.38k|    }
 1020|       |    /* false */
 1021|  2.52M|    if (can_read(input_buffer, 5) && (strncmp((const char *)buffer_at_offset(input_buffer), "false", 5) == 0)) {
  ------------------
  |  |  190|  5.05M|#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (190:33): [True: 2.52M, False: 0]
  |  |  |  Branch (190:53): [True: 2.52M, False: 2.77k]
  |  |  ------------------
  ------------------
                  if (can_read(input_buffer, 5) && (strncmp((const char *)buffer_at_offset(input_buffer), "false", 5) == 0)) {
  ------------------
  |  |  195|  2.52M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1021:38): [True: 1.10k, False: 2.52M]
  ------------------
 1022|  1.10k|        item->type = cJSON_False;
  ------------------
  |  |   97|  1.10k|#define cJSON_False (1 << 0)
  ------------------
 1023|  1.10k|        input_buffer->offset += 5;
 1024|  1.10k|        return true;
  ------------------
  |  |   67|  1.10k|#define true ((cJSON_bool)1)
  ------------------
 1025|  1.10k|    }
 1026|       |    /* true */
 1027|  2.52M|    if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "true", 4) == 0)) {
  ------------------
  |  |  190|  5.05M|#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (190:33): [True: 2.52M, False: 0]
  |  |  |  Branch (190:53): [True: 2.52M, False: 2.18k]
  |  |  ------------------
  ------------------
                  if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "true", 4) == 0)) {
  ------------------
  |  |  195|  2.52M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1027:38): [True: 3.56k, False: 2.52M]
  ------------------
 1028|  3.56k|        item->type = cJSON_True;
  ------------------
  |  |   98|  3.56k|#define cJSON_True (1 << 1)
  ------------------
 1029|  3.56k|        item->valueint = 1;
 1030|  3.56k|        input_buffer->offset += 4;
 1031|  3.56k|        return true;
  ------------------
  |  |   67|  3.56k|#define true ((cJSON_bool)1)
  ------------------
 1032|  3.56k|    }
 1033|       |    /* string */
 1034|  2.52M|    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) {
  ------------------
  |  |  192|  5.04M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 2.52M, False: 0]
  |  |  |  Branch (192:65): [True: 2.52M, False: 0]
  |  |  ------------------
  ------------------
                  if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) {
  ------------------
  |  |  195|  2.52M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1034:49): [True: 1.57M, False: 944k]
  ------------------
 1035|  1.57M|        return parse_string(item, input_buffer, out_of_memory);
 1036|  1.57M|    }
 1037|       |    /* number */
 1038|   944k|    if (can_access_at_index(input_buffer, 0) &&
  ------------------
  |  |  192|  1.88M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 944k, False: 0]
  |  |  |  Branch (192:65): [True: 944k, False: 0]
  |  |  ------------------
  ------------------
 1039|   944k|        ((buffer_at_offset(input_buffer)[0] == '-') ||
  ------------------
  |  |  195|   944k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1039:10): [True: 69.8k, False: 874k]
  ------------------
 1040|   874k|         ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9')))) {
  ------------------
  |  |  195|   874k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
                       ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9')))) {
  ------------------
  |  |  195|   873k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1040:11): [True: 873k, False: 1.04k]
  |  Branch (1040:57): [True: 465k, False: 408k]
  ------------------
 1041|   535k|        return parse_number(item, input_buffer);
 1042|   535k|    }
 1043|       |    /* array */
 1044|   409k|    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '[')) {
  ------------------
  |  |  192|   818k|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 409k, False: 0]
  |  |  |  Branch (192:65): [True: 409k, False: 0]
  |  |  ------------------
  ------------------
                  if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '[')) {
  ------------------
  |  |  195|   409k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1044:49): [True: 158k, False: 250k]
  ------------------
 1045|   158k|        return parse_array(item, input_buffer, out_of_memory);
 1046|   158k|    }
 1047|       |    /* object */
 1048|   250k|    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) {
  ------------------
  |  |  192|   501k|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 250k, False: 0]
  |  |  |  Branch (192:65): [True: 250k, False: 0]
  |  |  ------------------
  ------------------
                  if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) {
  ------------------
  |  |  195|   250k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1048:49): [True: 249k, False: 1.24k]
  ------------------
 1049|   249k|        return parse_object(item, input_buffer, out_of_memory);
 1050|   249k|    }
 1051|       |
 1052|  1.24k|    return false;
  ------------------
  |  |   72|  1.24k|#define false ((cJSON_bool)0)
  ------------------
 1053|   250k|}
cJSON.c:parse_string:
  533|  2.29M|static cJSON_bool parse_string(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory) {
  534|  2.29M|    const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1;
  ------------------
  |  |  195|  2.29M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  535|  2.29M|    const unsigned char *input_end = buffer_at_offset(input_buffer) + 1;
  ------------------
  |  |  195|  2.29M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  536|  2.29M|    unsigned char *output_pointer = NULL;
  537|  2.29M|    unsigned char *output = NULL;
  538|       |
  539|       |    /* not a string */
  540|  2.29M|    if (buffer_at_offset(input_buffer)[0] != '\"') {
  ------------------
  |  |  195|  2.29M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (540:9): [True: 294, False: 2.29M]
  ------------------
  541|    294|        goto fail;
  542|    294|    }
  543|       |
  544|  2.29M|    {
  545|       |        /* calculate approximate size of the output (overestimate) */
  546|  2.29M|        size_t allocation_length = 0;
  547|  2.29M|        size_t skipped_bytes = 0;
  548|  64.3M|        while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"')) {
  ------------------
  |  Branch (548:16): [True: 64.3M, False: 219]
  |  Branch (548:88): [True: 62.0M, False: 2.29M]
  ------------------
  549|       |            /* is escape sequence */
  550|  62.0M|            if (input_end[0] == '\\') {
  ------------------
  |  Branch (550:17): [True: 1.01M, False: 60.9M]
  ------------------
  551|  1.01M|                if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length) {
  ------------------
  |  Branch (551:21): [True: 0, False: 1.01M]
  ------------------
  552|       |                    /* prevent buffer overflow when last input character is a backslash */
  553|      0|                    goto fail;
  554|      0|                }
  555|  1.01M|                skipped_bytes++;
  556|  1.01M|                input_end++;
  557|  1.01M|            }
  558|  62.0M|            input_end++;
  559|  62.0M|        }
  560|  2.29M|        if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"')) {
  ------------------
  |  Branch (560:13): [True: 219, False: 2.29M]
  |  Branch (560:86): [True: 0, False: 2.29M]
  ------------------
  561|    219|            goto fail; /* string ended unexpectedly */
  562|    219|        }
  563|       |
  564|       |        /* This is at most how much we need for the output */
  565|  2.29M|        allocation_length = (size_t)(input_end - buffer_at_offset(input_buffer)) - skipped_bytes;
  ------------------
  |  |  195|  2.29M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  566|  2.29M|        output = (unsigned char *)loader_calloc(input_buffer->pAllocator, allocation_length + sizeof(""),
  567|  2.29M|                                                VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
  568|  2.29M|        if (output == NULL) {
  ------------------
  |  Branch (568:13): [True: 0, False: 2.29M]
  ------------------
  569|      0|            *out_of_memory = true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
  570|      0|            goto fail; /* allocation failure */
  571|      0|        }
  572|  2.29M|    }
  573|       |
  574|  2.29M|    output_pointer = output;
  575|       |    /* loop through the string literal */
  576|  47.1M|    while (input_pointer < input_end) {
  ------------------
  |  Branch (576:12): [True: 44.8M, False: 2.29M]
  ------------------
  577|  44.8M|        if (*input_pointer != '\\') {
  ------------------
  |  Branch (577:13): [True: 44.1M, False: 700k]
  ------------------
  578|  44.1M|            *output_pointer++ = *input_pointer++;
  579|  44.1M|        }
  580|       |        /* escape sequence */
  581|   700k|        else {
  582|   700k|            unsigned char sequence_length = 2;
  583|   700k|            if ((input_end - input_pointer) < 1) {
  ------------------
  |  Branch (583:17): [True: 0, False: 700k]
  ------------------
  584|      0|                goto fail;
  585|      0|            }
  586|       |
  587|   700k|            switch (input_pointer[1]) {
  588|  1.05k|                case 'b':
  ------------------
  |  Branch (588:17): [True: 1.05k, False: 699k]
  ------------------
  589|  1.05k|                    *output_pointer++ = '\b';
  590|  1.05k|                    break;
  591|  9.44k|                case 'f':
  ------------------
  |  Branch (591:17): [True: 9.44k, False: 690k]
  ------------------
  592|  9.44k|                    *output_pointer++ = '\f';
  593|  9.44k|                    break;
  594|  1.14k|                case 'n':
  ------------------
  |  Branch (594:17): [True: 1.14k, False: 699k]
  ------------------
  595|  1.14k|                    *output_pointer++ = '\n';
  596|  1.14k|                    break;
  597|  1.60k|                case 'r':
  ------------------
  |  Branch (597:17): [True: 1.60k, False: 698k]
  ------------------
  598|  1.60k|                    *output_pointer++ = '\r';
  599|  1.60k|                    break;
  600|  2.09k|                case 't':
  ------------------
  |  Branch (600:17): [True: 2.09k, False: 698k]
  ------------------
  601|  2.09k|                    *output_pointer++ = '\t';
  602|  2.09k|                    break;
  603|  2.60k|                case '\"':
  ------------------
  |  Branch (603:17): [True: 2.60k, False: 697k]
  ------------------
  604|  18.5k|                case '\\':
  ------------------
  |  Branch (604:17): [True: 15.9k, False: 684k]
  ------------------
  605|  19.6k|                case '/':
  ------------------
  |  Branch (605:17): [True: 1.06k, False: 699k]
  ------------------
  606|  19.6k|                    *output_pointer++ = input_pointer[1];
  607|  19.6k|                    break;
  608|       |
  609|       |                /* UTF-16 literal */
  610|   665k|                case 'u':
  ------------------
  |  Branch (610:17): [True: 665k, False: 35.0k]
  ------------------
  611|   665k|                    sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer);
  612|   665k|                    if (sequence_length == 0) {
  ------------------
  |  Branch (612:25): [True: 300, False: 664k]
  ------------------
  613|       |                        /* failed to convert UTF16-literal to UTF-8 */
  614|    300|                        goto fail;
  615|    300|                    }
  616|   664k|                    break;
  617|       |
  618|   664k|                default:
  ------------------
  |  Branch (618:17): [True: 62, False: 700k]
  ------------------
  619|     62|                    goto fail;
  620|   700k|            }
  621|   699k|            input_pointer += sequence_length;
  622|   699k|        }
  623|  44.8M|    }
  624|       |
  625|       |    /* zero terminate the output */
  626|  2.29M|    *output_pointer = '\0';
  627|       |
  628|  2.29M|    item->type = cJSON_String;
  ------------------
  |  |  101|  2.29M|#define cJSON_String (1 << 4)
  ------------------
  629|  2.29M|    item->valuestring = (char *)output;
  630|       |
  631|  2.29M|    input_buffer->offset = (size_t)(input_end - input_buffer->content);
  632|  2.29M|    input_buffer->offset++;
  633|       |
  634|  2.29M|    return true;
  ------------------
  |  |   67|  2.29M|#define true ((cJSON_bool)1)
  ------------------
  635|       |
  636|    875|fail:
  637|    875|    if (output != NULL) {
  ------------------
  |  Branch (637:9): [True: 362, False: 513]
  ------------------
  638|    362|        loader_free(input_buffer->pAllocator, output);
  639|    362|        output = NULL;
  640|    362|    }
  641|       |
  642|    875|    if (input_pointer != NULL) {
  ------------------
  |  Branch (642:9): [True: 875, False: 0]
  ------------------
  643|    875|        input_buffer->offset = (size_t)(input_pointer - input_buffer->content);
  644|    875|    }
  645|       |
  646|    875|    return false;
  ------------------
  |  |   72|    875|#define false ((cJSON_bool)0)
  ------------------
  647|  2.29M|}
cJSON.c:utf16_literal_to_utf8:
  435|   665k|                                           unsigned char **output_pointer) {
  436|   665k|    long unsigned int codepoint = 0;
  437|   665k|    unsigned int first_code = 0;
  438|   665k|    const unsigned char *first_sequence = input_pointer;
  439|   665k|    unsigned char utf8_length = 0;
  440|   665k|    unsigned char utf8_position = 0;
  441|   665k|    unsigned char sequence_length = 0;
  442|   665k|    unsigned char first_byte_mark = 0;
  443|       |
  444|   665k|    if ((input_end - first_sequence) < 6) {
  ------------------
  |  Branch (444:9): [True: 40, False: 665k]
  ------------------
  445|       |        /* input ends unexpectedly */
  446|     40|        goto fail;
  447|     40|    }
  448|       |
  449|       |    /* get the first utf16 sequence */
  450|   665k|    first_code = parse_hex4(first_sequence + 2);
  451|       |
  452|       |    /* check that the code is valid */
  453|   665k|    if (((first_code >= 0xDC00) && (first_code <= 0xDFFF))) {
  ------------------
  |  Branch (453:10): [True: 493k, False: 172k]
  |  Branch (453:36): [True: 59, False: 493k]
  ------------------
  454|     59|        goto fail;
  455|     59|    }
  456|       |
  457|       |    /* UTF16 surrogate pair */
  458|   665k|    if ((first_code >= 0xD800) && (first_code <= 0xDBFF)) {
  ------------------
  |  Branch (458:9): [True: 497k, False: 167k]
  |  Branch (458:35): [True: 4.49k, False: 493k]
  ------------------
  459|  4.49k|        const unsigned char *second_sequence = first_sequence + 6;
  460|  4.49k|        unsigned int second_code = 0;
  461|  4.49k|        sequence_length = 12; /* \uXXXX\uXXXX */
  462|       |
  463|  4.49k|        if ((input_end - second_sequence) < 6) {
  ------------------
  |  Branch (463:13): [True: 39, False: 4.45k]
  ------------------
  464|       |            /* input ends unexpectedly */
  465|     39|            goto fail;
  466|     39|        }
  467|       |
  468|  4.45k|        if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u')) {
  ------------------
  |  Branch (468:13): [True: 43, False: 4.41k]
  |  Branch (468:45): [True: 26, False: 4.38k]
  ------------------
  469|       |            /* missing second half of the surrogate pair */
  470|     69|            goto fail;
  471|     69|        }
  472|       |
  473|       |        /* get the second utf16 sequence */
  474|  4.38k|        second_code = parse_hex4(second_sequence + 2);
  475|       |        /* check that the code is valid */
  476|  4.38k|        if ((second_code < 0xDC00) || (second_code > 0xDFFF)) {
  ------------------
  |  Branch (476:13): [True: 77, False: 4.31k]
  |  Branch (476:39): [True: 16, False: 4.29k]
  ------------------
  477|       |            /* invalid second half of the surrogate pair */
  478|     93|            goto fail;
  479|     93|        }
  480|       |
  481|       |        /* calculate the unicode codepoint from the surrogate pair */
  482|  4.29k|        codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF));
  483|   660k|    } else {
  484|   660k|        sequence_length = 6; /* \uXXXX */
  485|   660k|        codepoint = first_code;
  486|   660k|    }
  487|       |
  488|       |    /* encode as UTF-8
  489|       |     * takes at maximum 4 bytes to encode:
  490|       |     * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
  491|   664k|    if (codepoint < 0x80) {
  ------------------
  |  Branch (491:9): [True: 146k, False: 518k]
  ------------------
  492|       |        /* normal ascii, encoding 0xxxxxxx */
  493|   146k|        utf8_length = 1;
  494|   518k|    } else if (codepoint < 0x800) {
  ------------------
  |  Branch (494:16): [True: 9.73k, False: 508k]
  ------------------
  495|       |        /* two bytes, encoding 110xxxxx 10xxxxxx */
  496|  9.73k|        utf8_length = 2;
  497|  9.73k|        first_byte_mark = 0xC0; /* 11000000 */
  498|   508k|    } else if (codepoint < 0x10000) {
  ------------------
  |  Branch (498:16): [True: 504k, False: 4.29k]
  ------------------
  499|       |        /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */
  500|   504k|        utf8_length = 3;
  501|   504k|        first_byte_mark = 0xE0; /* 11100000 */
  502|   504k|    } else if (codepoint <= 0x10FFFF) {
  ------------------
  |  Branch (502:16): [True: 4.29k, False: 0]
  ------------------
  503|       |        /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */
  504|  4.29k|        utf8_length = 4;
  505|  4.29k|        first_byte_mark = 0xF0; /* 11110000 */
  506|  4.29k|    } else {
  507|       |        /* invalid unicode codepoint */
  508|      0|        goto fail;
  509|      0|    }
  510|       |
  511|       |    /* encode as utf8 */
  512|  1.69M|    for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--) {
  ------------------
  |  Branch (512:60): [True: 1.03M, False: 664k]
  ------------------
  513|       |        /* 10xxxxxx */
  514|  1.03M|        (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF);
  515|  1.03M|        codepoint >>= 6;
  516|  1.03M|    }
  517|       |    /* encode first byte */
  518|   664k|    if (utf8_length > 1) {
  ------------------
  |  Branch (518:9): [True: 518k, False: 146k]
  ------------------
  519|   518k|        (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF);
  520|   518k|    } else {
  521|   146k|        (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F);
  522|   146k|    }
  523|       |
  524|   664k|    *output_pointer += utf8_length;
  525|       |
  526|   664k|    return sequence_length;
  527|       |
  528|    300|fail:
  529|    300|    return 0;
  530|   664k|}
cJSON.c:parse_hex4:
  406|   669k|static unsigned parse_hex4(const unsigned char *const input) {
  407|   669k|    unsigned int h = 0;
  408|   669k|    size_t i = 0;
  409|       |
  410|  2.96M|    for (i = 0; i < 4; i++) {
  ------------------
  |  Branch (410:17): [True: 2.43M, False: 523k]
  ------------------
  411|       |        /* parse digit */
  412|  2.43M|        if ((input[i] >= '0') && (input[i] <= '9')) {
  ------------------
  |  Branch (412:13): [True: 2.40M, False: 34.9k]
  |  Branch (412:34): [True: 1.58M, False: 814k]
  ------------------
  413|  1.58M|            h += (unsigned int)input[i] - '0';
  414|  1.58M|        } else if ((input[i] >= 'A') && (input[i] <= 'F')) {
  ------------------
  |  Branch (414:20): [True: 781k, False: 68.0k]
  |  Branch (414:41): [True: 86.8k, False: 694k]
  ------------------
  415|  86.8k|            h += (unsigned int)10 + input[i] - 'A';
  416|   762k|        } else if ((input[i] >= 'a') && (input[i] <= 'f')) {
  ------------------
  |  Branch (416:20): [True: 650k, False: 111k]
  |  Branch (416:41): [True: 616k, False: 33.9k]
  ------------------
  417|   616k|            h += (unsigned int)10 + input[i] - 'a';
  418|   616k|        } else /* invalid */
  419|   145k|        {
  420|   145k|            return 0;
  421|   145k|        }
  422|       |
  423|  2.29M|        if (i < 3) {
  ------------------
  |  Branch (423:13): [True: 1.76M, False: 523k]
  ------------------
  424|       |            /* shift left to make place for the next nibble */
  425|  1.76M|            h = h << 4;
  426|  1.76M|        }
  427|  2.29M|    }
  428|       |
  429|   523k|    return h;
  430|   669k|}
cJSON.c:parse_number:
  198|   535k|static cJSON_bool parse_number(cJSON *const item, parse_buffer *const input_buffer) {
  199|   535k|    double number = 0;
  200|   535k|    unsigned char *after_end = NULL;
  201|   535k|    unsigned char number_c_string[64];
  202|   535k|    unsigned char decimal_point = get_decimal_point();
  203|   535k|    size_t i = 0;
  204|       |
  205|   535k|    if ((input_buffer == NULL) || (input_buffer->content == NULL)) {
  ------------------
  |  Branch (205:9): [True: 0, False: 535k]
  |  Branch (205:35): [True: 0, False: 535k]
  ------------------
  206|      0|        return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
  207|      0|    }
  208|       |
  209|       |    /* copy the number into a temporary buffer and replace '.' with the decimal point
  210|       |     * of the current locale (for strtod)
  211|       |     * This also takes care of '\0' not necessarily being available for marking the end of the input */
  212|  4.18M|    for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++) {
  ------------------
  |  |  192|  4.18M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 4.18M, False: 0]
  |  |  |  Branch (192:65): [True: 4.18M, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (212:17): [True: 4.18M, False: 1.21k]
  ------------------
  213|  4.18M|        switch (buffer_at_offset(input_buffer)[i]) {
  ------------------
  |  |  195|  4.18M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  214|   493k|            case '0':
  ------------------
  |  Branch (214:13): [True: 493k, False: 3.69M]
  ------------------
  215|   853k|            case '1':
  ------------------
  |  Branch (215:13): [True: 360k, False: 3.82M]
  ------------------
  216|  1.07M|            case '2':
  ------------------
  |  Branch (216:13): [True: 221k, False: 3.96M]
  ------------------
  217|  1.39M|            case '3':
  ------------------
  |  Branch (217:13): [True: 323k, False: 3.86M]
  ------------------
  218|  1.72M|            case '4':
  ------------------
  |  Branch (218:13): [True: 321k, False: 3.86M]
  ------------------
  219|  1.91M|            case '5':
  ------------------
  |  Branch (219:13): [True: 193k, False: 3.99M]
  ------------------
  220|  2.31M|            case '6':
  ------------------
  |  Branch (220:13): [True: 396k, False: 3.78M]
  ------------------
  221|  3.08M|            case '7':
  ------------------
  |  Branch (221:13): [True: 777k, False: 3.40M]
  ------------------
  222|  3.26M|            case '8':
  ------------------
  |  Branch (222:13): [True: 178k, False: 4.00M]
  ------------------
  223|  3.50M|            case '9':
  ------------------
  |  Branch (223:13): [True: 243k, False: 3.94M]
  ------------------
  224|  3.51M|            case '+':
  ------------------
  |  Branch (224:13): [True: 6.40k, False: 4.18M]
  ------------------
  225|  3.59M|            case '-':
  ------------------
  |  Branch (225:13): [True: 74.7k, False: 4.11M]
  ------------------
  226|  3.60M|            case 'e':
  ------------------
  |  Branch (226:13): [True: 11.6k, False: 4.17M]
  ------------------
  227|  3.61M|            case 'E':
  ------------------
  |  Branch (227:13): [True: 10.4k, False: 4.17M]
  ------------------
  228|  3.61M|                number_c_string[i] = buffer_at_offset(input_buffer)[i];
  ------------------
  |  |  195|  3.61M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  229|  3.61M|                break;
  230|       |
  231|  39.3k|            case '.':
  ------------------
  |  Branch (231:13): [True: 39.3k, False: 4.14M]
  ------------------
  232|  39.3k|                number_c_string[i] = decimal_point;
  233|  39.3k|                break;
  234|       |
  235|   534k|            default:
  ------------------
  |  Branch (235:13): [True: 534k, False: 3.65M]
  ------------------
  236|   534k|                goto loop_end;
  237|  4.18M|        }
  238|  4.18M|    }
  239|   535k|loop_end:
  240|   535k|    number_c_string[i] = '\0';
  241|       |
  242|   535k|    number = strtod((const char *)number_c_string, (char **)&after_end);
  243|   535k|    if (number_c_string == after_end) {
  ------------------
  |  Branch (243:9): [True: 58, False: 535k]
  ------------------
  244|     58|        return false; /* parse_error */
  ------------------
  |  |   72|     58|#define false ((cJSON_bool)0)
  ------------------
  245|     58|    }
  246|       |
  247|   535k|    item->valuedouble = number;
  248|       |
  249|       |    /* use saturation in case of overflow */
  250|   535k|    if (number >= INT_MAX) {
  ------------------
  |  Branch (250:9): [True: 35.4k, False: 500k]
  ------------------
  251|  35.4k|        item->valueint = INT_MAX;
  252|   500k|    } else if (number <= (double)INT_MIN) {
  ------------------
  |  Branch (252:16): [True: 61.9k, False: 438k]
  ------------------
  253|  61.9k|        item->valueint = INT_MIN;
  254|   438k|    } else {
  255|   438k|        item->valueint = (int)number;
  256|   438k|    }
  257|       |
  258|   535k|    item->type = cJSON_Number;
  ------------------
  |  |  100|   535k|#define cJSON_Number (1 << 3)
  ------------------
  259|       |
  260|   535k|    input_buffer->offset += (size_t)(after_end - number_c_string);
  261|   535k|    return true;
  ------------------
  |  |   67|   535k|#define true ((cJSON_bool)1)
  ------------------
  262|   535k|}
cJSON.c:get_decimal_point:
  172|   535k|static unsigned char get_decimal_point(void) {
  173|       |#ifdef ENABLE_LOCALES
  174|       |    struct lconv *lconv = localeconv();
  175|       |    return (unsigned char)lconv->decimal_point[0];
  176|       |#else
  177|   535k|    return '.';
  178|   535k|#endif
  179|   535k|}
cJSON.c:parse_array:
 1121|   158k|static cJSON_bool parse_array(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory) {
 1122|   158k|    cJSON *head = NULL; /* head of the linked list */
 1123|   158k|    cJSON *current_item = NULL;
 1124|       |
 1125|   158k|    if (input_buffer->depth >= CJSON_NESTING_LIMIT) {
  ------------------
  |  |  138|   158k|#define CJSON_NESTING_LIMIT 1000
  ------------------
  |  Branch (1125:9): [True: 7, False: 158k]
  ------------------
 1126|      7|        return false; /* to deeply nested */
  ------------------
  |  |   72|      7|#define false ((cJSON_bool)0)
  ------------------
 1127|      7|    }
 1128|   158k|    input_buffer->depth++;
 1129|       |
 1130|   158k|    if (buffer_at_offset(input_buffer)[0] != '[') {
  ------------------
  |  |  195|   158k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1130:9): [True: 0, False: 158k]
  ------------------
 1131|       |        /* not an array */
 1132|      0|        goto fail;
 1133|      0|    }
 1134|       |
 1135|   158k|    input_buffer->offset++;
 1136|   158k|    buffer_skip_whitespace(input_buffer);
 1137|   158k|    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']')) {
  ------------------
  |  |  192|   316k|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 158k, False: 0]
  |  |  |  Branch (192:65): [True: 158k, False: 0]
  |  |  ------------------
  ------------------
                  if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']')) {
  ------------------
  |  |  195|   158k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1137:49): [True: 12.8k, False: 145k]
  ------------------
 1138|       |        /* empty array */
 1139|  12.8k|        goto success;
 1140|  12.8k|    }
 1141|       |
 1142|       |    /* check if we skipped to the end of the buffer */
 1143|   145k|    if (cannot_access_at_index(input_buffer, 0)) {
  ------------------
  |  |  193|   145k|#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
  |  |  ------------------
  |  |  |  |  192|   145k|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (192:45): [True: 145k, False: 0]
  |  |  |  |  |  Branch (192:65): [True: 145k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1144|      0|        input_buffer->offset--;
 1145|      0|        goto fail;
 1146|      0|    }
 1147|       |
 1148|       |    /* step back to character in front of the first element */
 1149|   145k|    input_buffer->offset--;
 1150|       |    /* loop through the comma separated array elements */
 1151|  1.80M|    do {
 1152|       |        /* allocate next item */
 1153|  1.80M|        cJSON *new_item = cJSON_New_Item(input_buffer->pAllocator);
 1154|  1.80M|        if (new_item == NULL) {
  ------------------
  |  Branch (1154:13): [True: 0, False: 1.80M]
  ------------------
 1155|      0|            *out_of_memory = true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
 1156|      0|            goto fail; /* allocation failure */
 1157|      0|        }
 1158|       |
 1159|       |        /* attach next item to list */
 1160|  1.80M|        if (head == NULL) {
  ------------------
  |  Branch (1160:13): [True: 145k, False: 1.65M]
  ------------------
 1161|       |            /* start the linked list */
 1162|   145k|            current_item = head = new_item;
 1163|  1.65M|        } else {
 1164|       |            /* add to the end and advance */
 1165|  1.65M|            current_item->next = new_item;
 1166|  1.65M|            new_item->prev = current_item;
 1167|  1.65M|            current_item = new_item;
 1168|  1.65M|        }
 1169|       |
 1170|       |        /* parse next value */
 1171|  1.80M|        input_buffer->offset++;
 1172|  1.80M|        buffer_skip_whitespace(input_buffer);
 1173|  1.80M|        if (!parse_value(current_item, input_buffer, out_of_memory)) {
  ------------------
  |  Branch (1173:13): [True: 130k, False: 1.67M]
  ------------------
 1174|   130k|            goto fail; /* failed to parse value */
 1175|   130k|        }
 1176|  1.67M|        buffer_skip_whitespace(input_buffer);
 1177|  1.67M|    } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
  ------------------
  |  |  192|  3.34M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 1.67M, False: 0]
  |  |  |  Branch (192:65): [True: 1.67M, False: 0]
  |  |  ------------------
  ------------------
                  } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
  ------------------
  |  |  195|  1.67M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1177:54): [True: 1.65M, False: 15.3k]
  ------------------
 1178|       |
 1179|  15.3k|    if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') {
  ------------------
  |  |  193|  30.6k|#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
  |  |  ------------------
  |  |  |  |  192|  15.3k|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (192:45): [True: 15.3k, False: 0]
  |  |  |  |  |  Branch (192:65): [True: 15.3k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
                  if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') {
  ------------------
  |  |  195|  15.3k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1179:52): [True: 538, False: 14.7k]
  ------------------
 1180|    538|        goto fail; /* expected end of array */
 1181|    538|    }
 1182|       |
 1183|  27.6k|success:
 1184|  27.6k|    input_buffer->depth--;
 1185|       |
 1186|  27.6k|    if (head != NULL) {
  ------------------
  |  Branch (1186:9): [True: 14.7k, False: 12.8k]
  ------------------
 1187|  14.7k|        head->prev = current_item;
 1188|  14.7k|    }
 1189|       |
 1190|  27.6k|    item->type = cJSON_Array;
  ------------------
  |  |  102|  27.6k|#define cJSON_Array (1 << 5)
  ------------------
 1191|  27.6k|    item->child = head;
 1192|       |
 1193|  27.6k|    input_buffer->offset++;
 1194|       |
 1195|  27.6k|    return true;
  ------------------
  |  |   67|  27.6k|#define true ((cJSON_bool)1)
  ------------------
 1196|       |
 1197|   130k|fail:
 1198|   130k|    if (head != NULL) {
  ------------------
  |  Branch (1198:9): [True: 130k, False: 0]
  ------------------
 1199|   130k|        loader_cJSON_Delete(head);
 1200|   130k|    }
 1201|       |
 1202|   130k|    return false;
  ------------------
  |  |   72|   130k|#define false ((cJSON_bool)0)
  ------------------
 1203|  15.3k|}
cJSON.c:parse_object:
 1259|   249k|static cJSON_bool parse_object(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory) {
 1260|   249k|    cJSON *head = NULL; /* linked list head */
 1261|   249k|    cJSON *current_item = NULL;
 1262|       |
 1263|   249k|    if (input_buffer->depth >= CJSON_NESTING_LIMIT) {
  ------------------
  |  |  138|   249k|#define CJSON_NESTING_LIMIT 1000
  ------------------
  |  Branch (1263:9): [True: 13, False: 249k]
  ------------------
 1264|     13|        return false; /* to deeply nested */
  ------------------
  |  |   72|     13|#define false ((cJSON_bool)0)
  ------------------
 1265|     13|    }
 1266|   249k|    input_buffer->depth++;
 1267|       |
 1268|   249k|    if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) {
  ------------------
  |  |  193|   499k|#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
  |  |  ------------------
  |  |  |  |  192|   249k|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (192:45): [True: 249k, False: 0]
  |  |  |  |  |  Branch (192:65): [True: 249k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
                  if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) {
  ------------------
  |  |  195|   249k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1268:52): [True: 0, False: 249k]
  ------------------
 1269|      0|        goto fail; /* not an object */
 1270|      0|    }
 1271|       |
 1272|   249k|    input_buffer->offset++;
 1273|   249k|    buffer_skip_whitespace(input_buffer);
 1274|   249k|    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) {
  ------------------
  |  |  192|   499k|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 249k, False: 0]
  |  |  |  Branch (192:65): [True: 249k, False: 0]
  |  |  ------------------
  ------------------
                  if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) {
  ------------------
  |  |  195|   249k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1274:49): [True: 2.89k, False: 246k]
  ------------------
 1275|  2.89k|        goto success; /* empty object */
 1276|  2.89k|    }
 1277|       |
 1278|       |    /* check if we skipped to the end of the buffer */
 1279|   246k|    if (cannot_access_at_index(input_buffer, 0)) {
  ------------------
  |  |  193|   246k|#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
  |  |  ------------------
  |  |  |  |  192|   246k|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (192:45): [True: 246k, False: 0]
  |  |  |  |  |  Branch (192:65): [True: 246k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1280|      0|        input_buffer->offset--;
 1281|      0|        goto fail;
 1282|      0|    }
 1283|       |
 1284|       |    /* step back to character in front of the first element */
 1285|   246k|    input_buffer->offset--;
 1286|       |    /* loop through the comma separated array elements */
 1287|   718k|    do {
 1288|       |        /* allocate next item */
 1289|   718k|        cJSON *new_item = cJSON_New_Item(input_buffer->pAllocator);
 1290|   718k|        if (new_item == NULL) {
  ------------------
  |  Branch (1290:13): [True: 0, False: 718k]
  ------------------
 1291|      0|            *out_of_memory = true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
 1292|      0|            goto fail; /* allocation failure */
 1293|      0|        }
 1294|       |
 1295|       |        /* attach next item to list */
 1296|   718k|        if (head == NULL) {
  ------------------
  |  Branch (1296:13): [True: 246k, False: 472k]
  ------------------
 1297|       |            /* start the linked list */
 1298|   246k|            current_item = head = new_item;
 1299|   472k|        } else {
 1300|       |            /* add to the end and advance */
 1301|   472k|            current_item->next = new_item;
 1302|   472k|            new_item->prev = current_item;
 1303|   472k|            current_item = new_item;
 1304|   472k|        }
 1305|       |
 1306|   718k|        if (cannot_access_at_index(input_buffer, 1)) {
  ------------------
  |  |  193|   718k|#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
  |  |  ------------------
  |  |  |  |  192|   718k|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (192:45): [True: 718k, False: 0]
  |  |  |  |  |  Branch (192:65): [True: 718k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1307|      0|            goto fail; /* nothing comes after the comma */
 1308|      0|        }
 1309|       |
 1310|       |        /* parse the name of the child */
 1311|   718k|        input_buffer->offset++;
 1312|   718k|        buffer_skip_whitespace(input_buffer);
 1313|   718k|        if (!parse_string(current_item, input_buffer, out_of_memory)) {
  ------------------
  |  Branch (1313:13): [True: 369, False: 718k]
  ------------------
 1314|    369|            goto fail; /* failed to parse name */
 1315|    369|        }
 1316|   718k|        buffer_skip_whitespace(input_buffer);
 1317|       |
 1318|       |        /* swap valuestring and string, because we parsed the name */
 1319|   718k|        current_item->string = current_item->valuestring;
 1320|   718k|        current_item->valuestring = NULL;
 1321|       |
 1322|   718k|        if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) {
  ------------------
  |  |  193|  1.43M|#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
  |  |  ------------------
  |  |  |  |  192|   718k|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (192:45): [True: 718k, False: 0]
  |  |  |  |  |  Branch (192:65): [True: 718k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
                      if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) {
  ------------------
  |  |  195|   718k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1322:56): [True: 70, False: 718k]
  ------------------
 1323|     70|            goto fail; /* invalid object */
 1324|     70|        }
 1325|       |
 1326|       |        /* parse the value */
 1327|   718k|        input_buffer->offset++;
 1328|   718k|        buffer_skip_whitespace(input_buffer);
 1329|   718k|        if (!parse_value(current_item, input_buffer, out_of_memory)) {
  ------------------
  |  Branch (1329:13): [True: 13.1k, False: 705k]
  ------------------
 1330|  13.1k|            goto fail; /* failed to parse value */
 1331|  13.1k|        }
 1332|   705k|        buffer_skip_whitespace(input_buffer);
 1333|   705k|    } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
  ------------------
  |  |  192|  1.41M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 705k, False: 0]
  |  |  |  Branch (192:65): [True: 705k, False: 0]
  |  |  ------------------
  ------------------
                  } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
  ------------------
  |  |  195|   705k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1333:54): [True: 472k, False: 233k]
  ------------------
 1334|       |
 1335|   233k|    if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) {
  ------------------
  |  |  193|   466k|#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
  |  |  ------------------
  |  |  |  |  192|   233k|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (192:45): [True: 233k, False: 0]
  |  |  |  |  |  Branch (192:65): [True: 233k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
                  if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) {
  ------------------
  |  |  195|   233k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1335:52): [True: 42, False: 233k]
  ------------------
 1336|     42|        goto fail; /* expected end of object */
 1337|     42|    }
 1338|       |
 1339|   235k|success:
 1340|   235k|    input_buffer->depth--;
 1341|       |
 1342|   235k|    if (head != NULL) {
  ------------------
  |  Branch (1342:9): [True: 233k, False: 2.89k]
  ------------------
 1343|   233k|        head->prev = current_item;
 1344|   233k|    }
 1345|       |
 1346|   235k|    item->type = cJSON_Object;
  ------------------
  |  |  103|   235k|#define cJSON_Object (1 << 6)
  ------------------
 1347|   235k|    item->child = head;
 1348|       |
 1349|   235k|    input_buffer->offset++;
 1350|   235k|    return true;
  ------------------
  |  |   67|   235k|#define true ((cJSON_bool)1)
  ------------------
 1351|       |
 1352|  13.5k|fail:
 1353|  13.5k|    if (head != NULL) {
  ------------------
  |  Branch (1353:9): [True: 13.5k, False: 0]
  ------------------
 1354|  13.5k|        loader_cJSON_Delete(head);
 1355|  13.5k|    }
 1356|       |
 1357|  13.5k|    return false;
  ------------------
  |  |   72|  13.5k|#define false ((cJSON_bool)0)
  ------------------
 1358|   233k|}
cJSON.c:print_value:
 1056|  1.26M|static cJSON_bool print_value(const cJSON *const item, printbuffer *const output_buffer, bool *out_of_memory) {
 1057|  1.26M|    unsigned char *output = NULL;
 1058|       |
 1059|  1.26M|    if ((item == NULL) || (output_buffer == NULL)) {
  ------------------
  |  Branch (1059:9): [True: 0, False: 1.26M]
  |  Branch (1059:27): [True: 0, False: 1.26M]
  ------------------
 1060|      0|        return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1061|      0|    }
 1062|       |
 1063|  1.26M|    switch ((item->type) & 0xFF) {
 1064|      0|        case cJSON_NULL:
  ------------------
  |  |   99|      0|#define cJSON_NULL (1 << 2)
  ------------------
  |  Branch (1064:9): [True: 0, False: 1.26M]
  ------------------
 1065|      0|            output = ensure(output_buffer, 5, out_of_memory);
 1066|      0|            if (output == NULL) {
  ------------------
  |  Branch (1066:17): [True: 0, False: 0]
  ------------------
 1067|      0|                return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1068|      0|            }
 1069|      0|            strcpy((char *)output, "null");
 1070|      0|            return true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
 1071|       |
 1072|      0|        case cJSON_False:
  ------------------
  |  |   97|      0|#define cJSON_False (1 << 0)
  ------------------
  |  Branch (1072:9): [True: 0, False: 1.26M]
  ------------------
 1073|      0|            output = ensure(output_buffer, 6, out_of_memory);
 1074|      0|            if (output == NULL) {
  ------------------
  |  Branch (1074:17): [True: 0, False: 0]
  ------------------
 1075|      0|                return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1076|      0|            }
 1077|      0|            strcpy((char *)output, "false");
 1078|      0|            return true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
 1079|       |
 1080|      0|        case cJSON_True:
  ------------------
  |  |   98|      0|#define cJSON_True (1 << 1)
  ------------------
  |  Branch (1080:9): [True: 0, False: 1.26M]
  ------------------
 1081|      0|            output = ensure(output_buffer, 5, out_of_memory);
 1082|      0|            if (output == NULL) {
  ------------------
  |  Branch (1082:17): [True: 0, False: 0]
  ------------------
 1083|      0|                return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1084|      0|            }
 1085|      0|            strcpy((char *)output, "true");
 1086|      0|            return true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
 1087|       |
 1088|      0|        case cJSON_Number:
  ------------------
  |  |  100|      0|#define cJSON_Number (1 << 3)
  ------------------
  |  Branch (1088:9): [True: 0, False: 1.26M]
  ------------------
 1089|      0|            return print_number(item, output_buffer, out_of_memory);
 1090|       |
 1091|      0|        case cJSON_Raw: {
  ------------------
  |  |  104|      0|#define cJSON_Raw (1 << 7) /* raw json */
  ------------------
  |  Branch (1091:9): [True: 0, False: 1.26M]
  ------------------
 1092|      0|            size_t raw_length = 0;
 1093|      0|            if (item->valuestring == NULL) {
  ------------------
  |  Branch (1093:17): [True: 0, False: 0]
  ------------------
 1094|      0|                return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1095|      0|            }
 1096|       |
 1097|      0|            raw_length = strlen(item->valuestring) + sizeof("");
 1098|      0|            output = ensure(output_buffer, raw_length, out_of_memory);
 1099|      0|            if (output == NULL) {
  ------------------
  |  Branch (1099:17): [True: 0, False: 0]
  ------------------
 1100|      0|                return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1101|      0|            }
 1102|      0|            memcpy(output, item->valuestring, raw_length);
 1103|      0|            return true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
 1104|      0|        }
 1105|       |
 1106|  1.26M|        case cJSON_String:
  ------------------
  |  |  101|  1.26M|#define cJSON_String (1 << 4)
  ------------------
  |  Branch (1106:9): [True: 1.26M, False: 0]
  ------------------
 1107|  1.26M|            return print_string(item, output_buffer, out_of_memory);
 1108|       |
 1109|      0|        case cJSON_Array:
  ------------------
  |  |  102|      0|#define cJSON_Array (1 << 5)
  ------------------
  |  Branch (1109:9): [True: 0, False: 1.26M]
  ------------------
 1110|      0|            return print_array(item, output_buffer, out_of_memory);
 1111|       |
 1112|      0|        case cJSON_Object:
  ------------------
  |  |  103|      0|#define cJSON_Object (1 << 6)
  ------------------
  |  Branch (1112:9): [True: 0, False: 1.26M]
  ------------------
 1113|      0|            return print_object(item, output_buffer, out_of_memory);
 1114|       |
 1115|      0|        default:
  ------------------
  |  Branch (1115:9): [True: 0, False: 1.26M]
  ------------------
 1116|      0|            return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1117|  1.26M|    }
 1118|  1.26M|}
cJSON.c:ensure:
  275|  1.26M|static unsigned char *ensure(printbuffer *const p, size_t needed, bool *out_of_memory) {
  276|  1.26M|    unsigned char *newbuffer = NULL;
  277|  1.26M|    size_t newsize = 0;
  278|       |
  279|  1.26M|    if ((p == NULL) || (p->buffer == NULL)) {
  ------------------
  |  Branch (279:9): [True: 0, False: 1.26M]
  |  Branch (279:24): [True: 0, False: 1.26M]
  ------------------
  280|      0|        return NULL;
  281|      0|    }
  282|       |
  283|  1.26M|    if ((p->length > 0) && (p->offset >= p->length)) {
  ------------------
  |  Branch (283:9): [True: 1.26M, False: 0]
  |  Branch (283:28): [True: 0, False: 1.26M]
  ------------------
  284|       |        /* make sure that offset is valid */
  285|      0|        return NULL;
  286|      0|    }
  287|       |
  288|  1.26M|    if (needed > INT_MAX) {
  ------------------
  |  Branch (288:9): [True: 0, False: 1.26M]
  ------------------
  289|       |        /* sizes bigger than INT_MAX are currently not supported */
  290|      0|        return NULL;
  291|      0|    }
  292|       |
  293|  1.26M|    needed += p->offset + 1;
  294|  1.26M|    if (needed <= p->length) {
  ------------------
  |  Branch (294:9): [True: 1.26M, False: 2.92k]
  ------------------
  295|  1.26M|        return p->buffer + p->offset;
  296|  1.26M|    }
  297|       |
  298|  2.92k|    if (p->noalloc) {
  ------------------
  |  Branch (298:9): [True: 0, False: 2.92k]
  ------------------
  299|      0|        return NULL;
  300|      0|    }
  301|       |
  302|       |    /* calculate new buffer size */
  303|  2.92k|    if (needed > (INT_MAX / 2)) {
  ------------------
  |  Branch (303:9): [True: 0, False: 2.92k]
  ------------------
  304|       |        /* overflow of int, use INT_MAX if possible */
  305|      0|        if (needed <= INT_MAX) {
  ------------------
  |  Branch (305:13): [True: 0, False: 0]
  ------------------
  306|      0|            newsize = INT_MAX;
  307|      0|        } else {
  308|      0|            return NULL;
  309|      0|        }
  310|  2.92k|    } else {
  311|  2.92k|        newsize = needed * 2;
  312|  2.92k|    }
  313|       |
  314|  2.92k|    newbuffer = (unsigned char *)loader_realloc(p->pAllocator, p->buffer, p->length, newsize, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  315|  2.92k|    if (newbuffer == NULL) {
  ------------------
  |  Branch (315:9): [True: 0, False: 2.92k]
  ------------------
  316|      0|        *out_of_memory = true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
  317|      0|        loader_free(p->pAllocator, p->buffer);
  318|      0|        p->length = 0;
  319|      0|        p->buffer = NULL;
  320|       |
  321|      0|        return NULL;
  322|      0|    }
  323|       |
  324|  2.92k|    p->length = newsize;
  325|  2.92k|    p->buffer = newbuffer;
  326|       |
  327|  2.92k|    return newbuffer + p->offset;
  328|  2.92k|}
cJSON.c:print_string:
  759|  1.26M|static cJSON_bool print_string(const cJSON *const item, printbuffer *const p, bool *out_of_memory) {
  760|  1.26M|    return print_string_ptr((unsigned char *)item->valuestring, p, out_of_memory);
  761|  1.26M|}
cJSON.c:print_string_ptr:
  650|  1.26M|static cJSON_bool print_string_ptr(const unsigned char *const input, printbuffer *const output_buffer, bool *out_of_memory) {
  651|  1.26M|    const unsigned char *input_pointer = NULL;
  652|  1.26M|    unsigned char *output = NULL;
  653|  1.26M|    unsigned char *output_pointer = NULL;
  654|  1.26M|    size_t output_length = 0;
  655|       |    /* numbers of additional characters needed for escaping */
  656|  1.26M|    size_t escape_characters = 0;
  657|       |
  658|  1.26M|    if (output_buffer == NULL) {
  ------------------
  |  Branch (658:9): [True: 0, False: 1.26M]
  ------------------
  659|      0|        return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
  660|      0|    }
  661|       |
  662|       |    /* empty string */
  663|  1.26M|    if (input == NULL) {
  ------------------
  |  Branch (663:9): [True: 0, False: 1.26M]
  ------------------
  664|      0|        output = ensure(output_buffer, sizeof(""), out_of_memory);
  665|      0|        if (output == NULL) {
  ------------------
  |  Branch (665:13): [True: 0, False: 0]
  ------------------
  666|      0|            return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
  667|      0|        }
  668|       |
  669|      0|        return true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
  670|      0|    }
  671|       |
  672|       |    /* set "flag" to 1 if something needs to be escaped */
  673|  11.6M|    for (input_pointer = input; *input_pointer; input_pointer++) {
  ------------------
  |  Branch (673:33): [True: 10.3M, False: 1.26M]
  ------------------
  674|  10.3M|        switch (*input_pointer) {
  675|  1.17k|            case '\"':
  ------------------
  |  Branch (675:13): [True: 1.17k, False: 10.3M]
  ------------------
  676|  9.06k|            case '\\':
  ------------------
  |  Branch (676:13): [True: 7.88k, False: 10.3M]
  ------------------
  677|  22.8k|            case '\b':
  ------------------
  |  Branch (677:13): [True: 13.7k, False: 10.3M]
  ------------------
  678|  59.7k|            case '\f':
  ------------------
  |  Branch (678:13): [True: 36.9k, False: 10.3M]
  ------------------
  679|  99.4k|            case '\n':
  ------------------
  |  Branch (679:13): [True: 39.7k, False: 10.3M]
  ------------------
  680|   102k|            case '\r':
  ------------------
  |  Branch (680:13): [True: 3.42k, False: 10.3M]
  ------------------
  681|   109k|            case '\t':
  ------------------
  |  Branch (681:13): [True: 6.56k, False: 10.3M]
  ------------------
  682|       |                /* one character escape sequence */
  683|   109k|                escape_characters++;
  684|   109k|                break;
  685|  10.2M|            default:
  ------------------
  |  Branch (685:13): [True: 10.2M, False: 109k]
  ------------------
  686|  10.2M|                if (*input_pointer < 32) {
  ------------------
  |  Branch (686:21): [True: 8.39M, False: 1.89M]
  ------------------
  687|       |                    /* UTF-16 escape sequence uXXXX */
  688|  8.39M|                    escape_characters += 5;
  689|  8.39M|                }
  690|  10.2M|                break;
  691|  10.3M|        }
  692|  10.3M|    }
  693|  1.26M|    output_length = (size_t)(input_pointer - input) + escape_characters;
  694|       |
  695|  1.26M|    output = ensure(output_buffer, output_length + sizeof(""), out_of_memory);
  696|  1.26M|    if (output == NULL) {
  ------------------
  |  Branch (696:9): [True: 0, False: 1.26M]
  ------------------
  697|      0|        return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
  698|      0|    }
  699|       |
  700|       |    /* no characters have to be escaped */
  701|  1.26M|    if (escape_characters == 0) {
  ------------------
  |  Branch (701:9): [True: 1.23M, False: 32.1k]
  ------------------
  702|  1.23M|        memcpy(output, input, output_length);
  703|  1.23M|        output[output_length] = '\0';
  704|       |
  705|  1.23M|        return true;
  ------------------
  |  |   67|  1.23M|#define true ((cJSON_bool)1)
  ------------------
  706|  1.23M|    }
  707|       |
  708|  32.1k|    output_pointer = output;
  709|       |    /* copy the string */
  710|  9.19M|    for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++) {
  ------------------
  |  Branch (710:33): [True: 9.16M, False: 32.1k]
  ------------------
  711|  9.16M|        if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\')) {
  ------------------
  |  Branch (711:13): [True: 674k, False: 8.49M]
  |  Branch (711:38): [True: 673k, False: 1.17k]
  |  Branch (711:66): [True: 665k, False: 7.88k]
  ------------------
  712|       |            /* normal character, copy */
  713|   665k|            *output_pointer = *input_pointer;
  714|  8.49M|        } else {
  715|       |            // Loader specific modification - don't add a backslash because that will 'double up' any existing back slashes.
  716|       |            // This change was added right after vulkan's public release, so while it may not be a problem, there are plenty
  717|       |            // of API calls made which might not work if the paths have "\\"" in them
  718|       |            /* character needs to be escaped */
  719|       |            //*output_pointer++ = '\\';
  720|  8.49M|            switch (*input_pointer) {
  721|  7.88k|                case '\\':
  ------------------
  |  Branch (721:17): [True: 7.88k, False: 8.49M]
  ------------------
  722|  7.88k|                    *output_pointer = '\\';
  723|  7.88k|                    break;
  724|  1.17k|                case '\"':
  ------------------
  |  Branch (724:17): [True: 1.17k, False: 8.49M]
  ------------------
  725|  1.17k|                    *output_pointer = '\"';
  726|  1.17k|                    break;
  727|  13.7k|                case '\b':
  ------------------
  |  Branch (727:17): [True: 13.7k, False: 8.48M]
  ------------------
  728|  13.7k|                    *output_pointer = '\b';
  729|  13.7k|                    break;
  730|  36.9k|                case '\f':
  ------------------
  |  Branch (730:17): [True: 36.9k, False: 8.46M]
  ------------------
  731|  36.9k|                    *output_pointer = '\f';
  732|  36.9k|                    break;
  733|  39.7k|                case '\n':
  ------------------
  |  Branch (733:17): [True: 39.7k, False: 8.46M]
  ------------------
  734|  39.7k|                    *output_pointer = '\n';
  735|  39.7k|                    break;
  736|  3.42k|                case '\r':
  ------------------
  |  Branch (736:17): [True: 3.42k, False: 8.49M]
  ------------------
  737|  3.42k|                    *output_pointer = '\r';
  738|  3.42k|                    break;
  739|  6.56k|                case '\t':
  ------------------
  |  Branch (739:17): [True: 6.56k, False: 8.49M]
  ------------------
  740|  6.56k|                    *output_pointer = '\t';
  741|  6.56k|                    break;
  742|  8.39M|                default:
  ------------------
  |  Branch (742:17): [True: 8.39M, False: 109k]
  ------------------
  743|       |                    /* escape and print as unicode codepoint */
  744|  8.39M|                    snprintf((char *)output_pointer, output_length - (size_t)(output_pointer - output), "u%04x", *input_pointer);
  745|  8.39M|                    output_pointer += 4;
  746|  8.39M|                    break;
  747|  8.49M|            }
  748|  8.49M|        }
  749|  9.16M|    }
  750|       |    // The loader-specific escaping above emits one byte where the standard form emits two, so the written
  751|       |    // length is shorter than output_length. Terminate at the actual end, otherwise the bytes between it and
  752|       |    // output_length (uninitialised when the caller buffer is not zeroed) get read back as part of the string.
  753|  32.1k|    *output_pointer = '\0';
  754|       |
  755|  32.1k|    return true;
  ------------------
  |  |   67|  32.1k|#define true ((cJSON_bool)1)
  ------------------
  756|  32.1k|}
cJSON.c:get_object_item:
 1501|   718k|static cJSON *get_object_item(const cJSON *const object, const char *const name, const cJSON_bool case_sensitive) {
 1502|   718k|    cJSON *current_element = NULL;
 1503|       |
 1504|   718k|    if ((object == NULL) || (name == NULL)) {
  ------------------
  |  Branch (1504:9): [True: 0, False: 718k]
  |  Branch (1504:29): [True: 0, False: 718k]
  ------------------
 1505|      0|        return NULL;
 1506|      0|    }
 1507|       |
 1508|   718k|    current_element = object->child;
 1509|   718k|    if (case_sensitive) {
  ------------------
  |  Branch (1509:9): [True: 0, False: 718k]
  ------------------
 1510|      0|        while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0)) {
  ------------------
  |  Branch (1510:16): [True: 0, False: 0]
  |  Branch (1510:45): [True: 0, False: 0]
  |  Branch (1510:82): [True: 0, False: 0]
  ------------------
 1511|      0|            current_element = current_element->next;
 1512|      0|        }
 1513|   718k|    } else {
 1514|  1.80M|        while ((current_element != NULL) &&
  ------------------
  |  Branch (1514:16): [True: 1.60M, False: 198k]
  ------------------
 1515|  1.60M|               (case_insensitive_strcmp((const unsigned char *)name, (const unsigned char *)(current_element->string)) != 0)) {
  ------------------
  |  Branch (1515:16): [True: 1.08M, False: 519k]
  ------------------
 1516|  1.08M|            current_element = current_element->next;
 1517|  1.08M|        }
 1518|   718k|    }
 1519|       |
 1520|   718k|    if ((current_element == NULL) || (current_element->string == NULL)) {
  ------------------
  |  Branch (1520:9): [True: 198k, False: 519k]
  |  Branch (1520:38): [True: 0, False: 519k]
  ------------------
 1521|   198k|        return NULL;
 1522|   198k|    }
 1523|       |
 1524|   519k|    return current_element;
 1525|   718k|}
cJSON.c:case_insensitive_strcmp:
  120|  1.60M|static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2) {
  121|  1.60M|    if ((string1 == NULL) || (string2 == NULL)) {
  ------------------
  |  Branch (121:9): [True: 0, False: 1.60M]
  |  Branch (121:30): [True: 456, False: 1.60M]
  ------------------
  122|    456|        return 1;
  123|    456|    }
  124|       |
  125|  1.60M|    if (string1 == string2) {
  ------------------
  |  Branch (125:9): [True: 0, False: 1.60M]
  ------------------
  126|      0|        return 0;
  127|      0|    }
  128|       |
  129|  4.41M|    for (; tolower(*string1) == tolower(*string2); (void)string1++, string2++) {
  ------------------
  |  Branch (129:12): [True: 0, False: 0]
  |  Branch (129:12): [True: 0, False: 0]
  |  Branch (129:12): [Folded, False: 4.41M]
  |  Branch (129:12): [True: 3.32M, False: 1.08M]
  |  Branch (129:33): [True: 0, False: 0]
  |  Branch (129:33): [True: 0, False: 0]
  |  Branch (129:33): [Folded, False: 4.41M]
  ------------------
  130|  3.32M|        if (*string1 == '\0') {
  ------------------
  |  Branch (130:13): [True: 519k, False: 2.80M]
  ------------------
  131|   519k|            return 0;
  132|   519k|        }
  133|  3.32M|    }
  134|       |
  135|  1.08M|    return tolower(*string1) - tolower(*string2);
  ------------------
  |  Branch (135:12): [True: 0, False: 0]
  |  Branch (135:12): [True: 0, False: 0]
  |  Branch (135:12): [Folded, False: 1.08M]
  |  Branch (135:32): [True: 0, False: 0]
  |  Branch (135:32): [True: 0, False: 0]
  |  Branch (135:32): [Folded, False: 1.08M]
  ------------------
  136|  1.60M|}

loader_make_full_version:
  121|      2|loader_api_version loader_make_full_version(uint32_t version) {
  122|      2|    loader_api_version out_version;
  123|      2|    out_version.major = VK_API_VERSION_MAJOR(version);
  124|      2|    out_version.minor = VK_API_VERSION_MINOR(version);
  125|       |    out_version.patch = VK_API_VERSION_PATCH(version);
  126|      2|    return out_version;
  127|      2|}
is_json:
  193|  5.83k|bool is_json(const char *path, size_t len) {
  194|  5.83k|    if (len < 5) {
  ------------------
  |  Branch (194:9): [True: 4.02k, False: 1.80k]
  ------------------
  195|  4.02k|        return false;
  196|  4.02k|    }
  197|  1.80k|    return !strncmp(path + len - 5, ".json", 5);
  198|  5.83k|}
loader_free_layer_properties:
  248|   115k|void loader_free_layer_properties(const struct loader_instance *inst, struct loader_layer_properties *layer_properties) {
  249|   115k|    loader_instance_heap_free(inst, layer_properties->manifest_file_name);
  250|   115k|    loader_instance_heap_free(inst, layer_properties->lib_name);
  251|   115k|    loader_instance_heap_free(inst, layer_properties->functions.str_gipa);
  252|   115k|    loader_instance_heap_free(inst, layer_properties->functions.str_gdpa);
  253|   115k|    loader_instance_heap_free(inst, layer_properties->functions.str_negotiate_interface);
  254|   115k|    loader_destroy_generic_list(inst, (struct loader_generic_list *)&layer_properties->instance_extension_list);
  255|   115k|    if (layer_properties->device_extension_list.capacity > 0 && NULL != layer_properties->device_extension_list.list) {
  ------------------
  |  Branch (255:9): [True: 0, False: 115k]
  |  Branch (255:65): [True: 0, False: 0]
  ------------------
  256|      0|        for (uint32_t i = 0; i < layer_properties->device_extension_list.count; i++) {
  ------------------
  |  Branch (256:30): [True: 0, False: 0]
  ------------------
  257|      0|            free_string_list(inst, &layer_properties->device_extension_list.list[i].entrypoints);
  258|      0|        }
  259|      0|    }
  260|   115k|    loader_destroy_generic_list(inst, (struct loader_generic_list *)&layer_properties->device_extension_list);
  261|   115k|    loader_instance_heap_free(inst, layer_properties->disable_env_var.name);
  262|   115k|    loader_instance_heap_free(inst, layer_properties->disable_env_var.value);
  263|   115k|    loader_instance_heap_free(inst, layer_properties->enable_env_var.name);
  264|   115k|    loader_instance_heap_free(inst, layer_properties->enable_env_var.value);
  265|   115k|    free_string_list(inst, &layer_properties->component_layer_names);
  266|   115k|    loader_instance_heap_free(inst, layer_properties->pre_instance_functions.enumerate_instance_extension_properties);
  267|   115k|    loader_instance_heap_free(inst, layer_properties->pre_instance_functions.enumerate_instance_layer_properties);
  268|   115k|    loader_instance_heap_free(inst, layer_properties->pre_instance_functions.enumerate_instance_version);
  269|   115k|    free_string_list(inst, &layer_properties->override_paths);
  270|   115k|    free_string_list(inst, &layer_properties->blacklist_layer_names);
  271|   115k|    free_string_list(inst, &layer_properties->app_key_paths);
  272|       |
  273|       |    // Make sure to clear out the removed layer, in case new layers are added in the previous location
  274|   115k|    memset(layer_properties, 0, sizeof(struct loader_layer_properties));
  275|   115k|}
loader_copy_to_new_str:
  297|   114k|VkResult loader_copy_to_new_str(const struct loader_instance *inst, const char *source_str, char **dest_str) {
  298|   114k|    assert(source_str && dest_str);
  299|   114k|    size_t str_len = strlen(source_str) + 1;
  300|   114k|    *dest_str = loader_instance_heap_calloc(inst, str_len, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  301|   114k|    if (NULL == *dest_str) return VK_ERROR_OUT_OF_HOST_MEMORY;
  ------------------
  |  Branch (301:9): [True: 0, False: 114k]
  ------------------
  302|   114k|    loader_strncpy(*dest_str, str_len, source_str, str_len);
  303|   114k|    (*dest_str)[str_len - 1] = 0;
  304|   114k|    return VK_SUCCESS;
  305|   114k|}
create_string_list:
  307|  5.17k|VkResult create_string_list(const struct loader_instance *inst, uint32_t allocated_count, struct loader_string_list *string_list) {
  308|  5.17k|    assert(string_list);
  309|  5.17k|    string_list->list = loader_instance_heap_calloc(inst, sizeof(char *) * allocated_count, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  310|  5.17k|    if (NULL == string_list->list) {
  ------------------
  |  Branch (310:9): [True: 0, False: 5.17k]
  ------------------
  311|      0|        return VK_ERROR_OUT_OF_HOST_MEMORY;
  312|      0|    }
  313|  5.17k|    string_list->allocated_count = allocated_count;
  314|  5.17k|    string_list->count = 0;
  315|  5.17k|    return VK_SUCCESS;
  316|  5.17k|}
increase_str_capacity_by_at_least_one:
  318|   764k|VkResult increase_str_capacity_by_at_least_one(const struct loader_instance *inst, struct loader_string_list *string_list) {
  319|   764k|    assert(string_list);
  320|   764k|    if (string_list->allocated_count == 0) {
  ------------------
  |  Branch (320:9): [True: 0, False: 764k]
  ------------------
  321|      0|        string_list->allocated_count = 32;
  322|      0|        string_list->list =
  323|      0|            loader_instance_heap_calloc(inst, sizeof(char *) * string_list->allocated_count, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  324|      0|        if (NULL == string_list->list) {
  ------------------
  |  Branch (324:13): [True: 0, False: 0]
  ------------------
  325|      0|            return VK_ERROR_OUT_OF_HOST_MEMORY;
  326|      0|        }
  327|   764k|    } else if (string_list->count + 1 > string_list->allocated_count) {
  ------------------
  |  Branch (327:16): [True: 0, False: 764k]
  ------------------
  328|      0|        uint32_t new_allocated_count = string_list->allocated_count * 2;
  329|      0|        void *new_ptr = loader_instance_heap_realloc(inst, string_list->list, sizeof(char *) * string_list->allocated_count,
  330|      0|                                                     sizeof(char *) * new_allocated_count, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  331|      0|        if (NULL == new_ptr) {
  ------------------
  |  Branch (331:13): [True: 0, False: 0]
  ------------------
  332|      0|            return VK_ERROR_OUT_OF_HOST_MEMORY;
  333|      0|        }
  334|      0|        string_list->list = new_ptr;
  335|      0|        string_list->allocated_count *= 2;
  336|      0|    }
  337|   764k|    return VK_SUCCESS;
  338|   764k|}
append_str_to_string_list:
  340|   764k|VkResult append_str_to_string_list(const struct loader_instance *inst, struct loader_string_list *string_list, char *str) {
  341|   764k|    assert(string_list && str);
  342|   764k|    VkResult res = increase_str_capacity_by_at_least_one(inst, string_list);
  343|   764k|    if (res == VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (343:9): [True: 0, False: 764k]
  ------------------
  344|      0|        loader_instance_heap_free(inst, str);  // Must clean up in case of failure
  345|      0|        return res;
  346|      0|    }
  347|   764k|    string_list->list[string_list->count++] = str;
  348|   764k|    return VK_SUCCESS;
  349|   764k|}
free_string_list:
  407|   478k|void free_string_list(const struct loader_instance *inst, struct loader_string_list *string_list) {
  408|   478k|    assert(string_list);
  409|   478k|    if (string_list->list) {
  ------------------
  |  Branch (409:9): [True: 5.17k, False: 473k]
  ------------------
  410|   769k|        for (uint32_t i = 0; i < string_list->count; i++) {
  ------------------
  |  Branch (410:30): [True: 764k, False: 5.17k]
  ------------------
  411|   764k|            loader_instance_heap_free(inst, string_list->list[i]);
  412|       |            string_list->list[i] = NULL;
  413|   764k|        }
  414|  5.17k|        loader_instance_heap_free(inst, string_list->list);
  415|  5.17k|    }
  416|   478k|    memset(string_list, 0, sizeof(struct loader_string_list));
  417|   478k|}
loader_append_layer_property:
  757|   115k|                                      struct loader_layer_properties *layer_property) {
  758|   115k|    VkResult res = VK_SUCCESS;
  759|   115k|    if (layer_list->capacity == 0) {
  ------------------
  |  Branch (759:9): [True: 173, False: 115k]
  ------------------
  760|    173|        res = loader_init_generic_list(inst, (struct loader_generic_list *)layer_list, sizeof(struct loader_layer_properties));
  761|    173|        if (VK_SUCCESS != res) {
  ------------------
  |  Branch (761:13): [True: 0, False: 173]
  ------------------
  762|      0|            goto out;
  763|      0|        }
  764|    173|    }
  765|       |
  766|       |    // Ensure enough room to add an entry
  767|   115k|    if ((layer_list->count + 1) * sizeof(struct loader_layer_properties) > layer_list->capacity) {
  ------------------
  |  Branch (767:9): [True: 189, False: 115k]
  ------------------
  768|    189|        void *new_ptr = loader_instance_heap_realloc(inst, layer_list->list, layer_list->capacity, layer_list->capacity * 2,
  769|    189|                                                     VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  770|    189|        if (NULL == new_ptr) {
  ------------------
  |  Branch (770:13): [True: 0, False: 189]
  ------------------
  771|      0|            loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_append_layer_property: realloc failed for layer list");
  772|      0|            res = VK_ERROR_OUT_OF_HOST_MEMORY;
  773|      0|            goto out;
  774|      0|        }
  775|    189|        layer_list->list = new_ptr;
  776|    189|        layer_list->capacity *= 2;
  777|    189|    }
  778|   115k|    memcpy(&layer_list->list[layer_list->count], layer_property, sizeof(struct loader_layer_properties));
  779|   115k|    layer_list->count++;
  780|   115k|    memset(layer_property, 0, sizeof(struct loader_layer_properties));
  781|   115k|out:
  782|   115k|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (782:9): [True: 0, False: 115k]
  ------------------
  783|      0|        loader_free_layer_properties(inst, layer_property);
  784|      0|    }
  785|   115k|    return res;
  786|   115k|}
loader_delete_layer_list_and_properties:
  829|  3.13k|                                                                  struct loader_layer_list *layer_list) {
  830|  3.13k|    uint32_t i;
  831|  3.13k|    if (!layer_list) return;
  ------------------
  |  Branch (831:9): [True: 0, False: 3.13k]
  ------------------
  832|       |
  833|   118k|    for (i = 0; i < layer_list->count; i++) {
  ------------------
  |  Branch (833:17): [True: 115k, False: 3.13k]
  ------------------
  834|   115k|        if (layer_list->list[i].lib_handle) {
  ------------------
  |  Branch (834:13): [True: 0, False: 115k]
  ------------------
  835|      0|            loader_platform_close_library(layer_list->list[i].lib_handle);
  836|      0|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT | VULKAN_LOADER_LAYER_BIT, 0, "Unloading layer library %s",
  837|      0|                       layer_list->list[i].lib_name);
  838|      0|            layer_list->list[i].lib_handle = NULL;
  839|      0|        }
  840|   115k|        loader_free_layer_properties(inst, &(layer_list->list[i]));
  841|   115k|    }
  842|  3.13k|    layer_list->count = 0;
  843|       |
  844|  3.13k|    if (layer_list->capacity > 0) {
  ------------------
  |  Branch (844:9): [True: 173, False: 2.96k]
  ------------------
  845|    173|        layer_list->capacity = 0;
  846|    173|        loader_instance_heap_free(inst, layer_list->list);
  847|    173|    }
  848|  3.13k|    memset(layer_list, 0, sizeof(struct loader_layer_list));
  849|  3.13k|}
loader_init_generic_list:
 1054|    173|VkResult loader_init_generic_list(const struct loader_instance *inst, struct loader_generic_list *list_info, size_t element_size) {
 1055|    173|    size_t capacity = 32 * element_size;
 1056|    173|    list_info->count = 0;
 1057|    173|    list_info->capacity = 0;
 1058|    173|    list_info->list = loader_instance_heap_calloc(inst, capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
 1059|    173|    if (list_info->list == NULL) {
  ------------------
  |  Branch (1059:9): [True: 0, False: 173]
  ------------------
 1060|      0|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_init_generic_list: Failed to allocate space for generic list");
 1061|      0|        return VK_ERROR_OUT_OF_HOST_MEMORY;
 1062|      0|    }
 1063|    173|    list_info->capacity = capacity;
 1064|    173|    return VK_SUCCESS;
 1065|    173|}
loader_destroy_generic_list:
 1083|   231k|void loader_destroy_generic_list(const struct loader_instance *inst, struct loader_generic_list *list) {
 1084|   231k|    loader_instance_heap_free(inst, list->list);
 1085|   231k|    memset(list, 0, sizeof(struct loader_generic_list));
 1086|   231k|}
loader_initialize:
 2340|      2|void loader_initialize(void) {
 2341|      2|    loader_platform_thread_create_mutex(&loader_lock);
 2342|      2|    loader_platform_thread_create_mutex(&loader_preload_icd_lock);
 2343|      2|    init_global_loader_settings();
 2344|      2|#endif
 2345|       |
 2346|       |    // initialize logging
 2347|      2|    loader_init_global_debug_level();
 2348|       |#if defined(_WIN32)
 2349|       |    windows_initialization();
 2350|       |#endif
 2351|       |
 2352|      2|    loader_api_version version = loader_make_full_version(VK_HEADER_VERSION_COMPLETE);
 2353|      2|    loader_log(NULL, VULKAN_LOADER_INFO_BIT, 0, "Vulkan Loader Version %d.%d.%d", version.major, version.minor, version.patch);
 2354|       |
 2355|       |#if defined(GIT_BRANCH_NAME) && defined(GIT_TAG_INFO)
 2356|       |    loader_log(NULL, VULKAN_LOADER_INFO_BIT, 0, "[Vulkan Loader Git - Tag: " GIT_BRANCH_NAME ", Branch/Commit: " GIT_TAG_INFO "]");
 2357|       |#endif
 2358|       |
 2359|      2|    char *loader_disable_dynamic_library_unloading_env_var = loader_getenv("VK_LOADER_DISABLE_DYNAMIC_LIBRARY_UNLOADING", NULL);
 2360|      2|    if (loader_disable_dynamic_library_unloading_env_var &&
  ------------------
  |  Branch (2360:9): [True: 0, False: 2]
  ------------------
 2361|      0|        0 == strncmp(loader_disable_dynamic_library_unloading_env_var, "1", 2)) {
  ------------------
  |  Branch (2361:9): [True: 0, False: 0]
  ------------------
 2362|      0|        loader_disable_dynamic_library_unloading = true;
 2363|      0|        loader_log(NULL, VULKAN_LOADER_WARN_BIT, 0, "Vulkan Loader: library unloading is disabled");
 2364|      2|    } else {
 2365|      2|        loader_disable_dynamic_library_unloading = false;
 2366|      2|    }
 2367|      2|    loader_free_getenv(loader_disable_dynamic_library_unloading_env_var, NULL);
 2368|       |#if defined(LOADER_USE_UNSAFE_FILE_SEARCH)
 2369|       |    loader_log(NULL, VULKAN_LOADER_WARN_BIT, 0, "Vulkan Loader: unsafe searching is enabled");
 2370|       |#endif
 2371|       |#if defined(_WIN32)
 2372|       |    return TRUE;
 2373|       |#endif
 2374|      2|}
loader_init_library:
 2411|      2|__attribute__((constructor)) void loader_init_library(void) { loader_initialize(); }

loader_getenv:
   43|      4|char *loader_getenv(const char *name, const struct loader_instance *inst) {
   44|      4|    if (NULL == name) return NULL;
  ------------------
  |  Branch (44:9): [True: 0, False: 4]
  ------------------
   45|       |    // No allocation of memory necessary for Linux, but we should at least touch
   46|       |    // the inst pointer to get rid of compiler warnings.
   47|      4|    (void)inst;
   48|      4|    return getenv(name);
   49|      4|}
loader_secure_getenv:
   51|  47.0k|char *loader_secure_getenv(const char *name, const struct loader_instance *inst) {
   52|       |#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__)
   53|       |    // Apple does not appear to have a secure getenv implementation.
   54|       |    // The main difference between secure getenv and getenv is that secure getenv
   55|       |    // returns NULL if the process is being run with elevated privileges by a normal user.
   56|       |    // The idea is to prevent the reading of malicious environment variables by a process
   57|       |    // that can do damage.
   58|       |    // This algorithm is derived from glibc code that sets an internal
   59|       |    // variable (__libc_enable_secure) if the process is running under setuid or setgid.
   60|       |    return is_high_integrity() ? NULL : loader_getenv(name, inst);
   61|       |#elif defined(__Fuchsia__)
   62|       |    return loader_getenv(name, inst);
   63|       |#else
   64|       |    // Linux
   65|  47.0k|    char *out;
   66|  47.0k|#if defined(HAVE_SECURE_GETENV) && !defined(LOADER_USE_UNSAFE_FILE_SEARCH)
   67|  47.0k|    (void)inst;
   68|  47.0k|    out = secure_getenv(name);
   69|       |#elif defined(HAVE___SECURE_GETENV) && !defined(LOADER_USE_UNSAFE_FILE_SEARCH)
   70|       |    (void)inst;
   71|       |    out = __secure_getenv(name);
   72|       |#else
   73|       |    out = loader_getenv(name, inst);
   74|       |#if !defined(LOADER_USE_UNSAFE_FILE_SEARCH)
   75|       |    loader_log(inst, VULKAN_LOADER_INFO_BIT, 0, "Loader is using non-secure environment variable lookup for %s", name);
   76|       |#endif
   77|       |#endif
   78|  47.0k|    return out;
   79|  47.0k|#endif
   80|  47.0k|}
loader_free_getenv:
   82|      4|void loader_free_getenv(char *val, const struct loader_instance *inst) {
   83|       |    // No freeing of memory necessary for Linux, but we should at least touch
   84|       |    // the val and inst pointers to get rid of compiler warnings.
   85|      4|    (void)val;
   86|      4|    (void)inst;
   87|      4|}

loader_get_json:
  160|  8.10k|TEST_FUNCTION_EXPORT VkResult loader_get_json(const struct loader_instance *inst, const char *filename, cJSON **json) {
  161|  8.10k|    char *json_buf = NULL;
  162|  8.10k|    VkResult res = VK_SUCCESS;
  163|       |
  164|  8.10k|    assert(json != NULL);
  165|       |
  166|  8.10k|    size_t json_len = 0;
  167|  8.10k|    *json = NULL;
  168|  8.10k|    res = loader_read_entire_file(inst, filename, &json_len, &json_buf);
  169|  8.10k|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (169:9): [True: 101, False: 8.00k]
  ------------------
  170|    101|        goto out;
  171|    101|    }
  172|  8.10k|    bool out_of_memory = false;
  173|       |    // Parse text from file
  174|  8.00k|    *json = loader_cJSON_ParseWithLength(inst ? &inst->alloc_callbacks : NULL, json_buf, json_len, &out_of_memory);
  ------------------
  |  Branch (174:42): [True: 0, False: 8.00k]
  ------------------
  175|  8.00k|    if (out_of_memory) {
  ------------------
  |  Branch (175:9): [True: 0, False: 8.00k]
  ------------------
  176|      0|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Out of Memory error occurred while parsing JSON file %s.",
  177|      0|                   filename);
  178|      0|        res = VK_ERROR_OUT_OF_HOST_MEMORY;
  179|      0|        goto out;
  180|  8.00k|    } else if (*json == NULL) {
  ------------------
  |  Branch (180:16): [True: 2.85k, False: 5.14k]
  ------------------
  181|  2.85k|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Invalid JSON file %s.", filename);
  182|  2.85k|        goto out;
  183|  2.85k|    }
  184|       |
  185|  8.10k|out:
  186|  8.10k|    loader_instance_heap_free(inst, json_buf);
  187|  8.10k|    if (res != VK_SUCCESS && *json != NULL) {
  ------------------
  |  Branch (187:9): [True: 101, False: 8.00k]
  |  Branch (187:30): [True: 0, False: 101]
  ------------------
  188|      0|        loader_cJSON_Delete(*json);
  189|      0|        *json = NULL;
  190|      0|    }
  191|       |
  192|  8.10k|    return res;
  193|  8.00k|}
loader_parse_json_string:
  218|   503k|VkResult loader_parse_json_string(cJSON *object, const char *key, char **out_string) {
  219|   503k|    if (NULL == key) {
  ------------------
  |  Branch (219:9): [True: 0, False: 503k]
  ------------------
  220|      0|        return VK_ERROR_INITIALIZATION_FAILED;
  221|      0|    }
  222|       |
  223|   503k|    cJSON *item = loader_cJSON_GetObjectItem(object, key);
  224|   503k|    if (NULL == item || NULL == item->valuestring) {
  ------------------
  |  Branch (224:9): [True: 784, False: 502k]
  |  Branch (224:25): [True: 6, False: 502k]
  ------------------
  225|    790|        return VK_ERROR_INITIALIZATION_FAILED;
  226|    790|    }
  227|       |
  228|   503k|    bool out_of_memory = false;
  229|   502k|    char *str = loader_cJSON_Print(item, &out_of_memory);
  230|   502k|    if (out_of_memory || NULL == str) {
  ------------------
  |  Branch (230:9): [True: 0, False: 502k]
  |  Branch (230:26): [True: 0, False: 502k]
  ------------------
  231|      0|        return VK_ERROR_OUT_OF_HOST_MEMORY;
  232|      0|    }
  233|   502k|    if (NULL != out_string) {
  ------------------
  |  Branch (233:9): [True: 502k, False: 0]
  ------------------
  234|   502k|        *out_string = str;
  235|   502k|    }
  236|   502k|    return VK_SUCCESS;
  237|   502k|}
loader_parse_json_array_of_strings:
  239|  15.9k|                                            struct loader_string_list *string_list) {
  240|  15.9k|    if (NULL == key) {
  ------------------
  |  Branch (240:9): [True: 0, False: 15.9k]
  ------------------
  241|      0|        return VK_ERROR_INITIALIZATION_FAILED;
  242|      0|    }
  243|  15.9k|    cJSON *item = loader_cJSON_GetObjectItem(object, key);
  244|  15.9k|    if (NULL == item) {
  ------------------
  |  Branch (244:9): [True: 10.1k, False: 5.83k]
  ------------------
  245|  10.1k|        return VK_ERROR_INITIALIZATION_FAILED;
  246|  10.1k|    }
  247|       |
  248|  5.83k|    uint32_t count = loader_cJSON_GetArraySize(item);
  249|  5.83k|    if (count == 0) {
  ------------------
  |  Branch (249:9): [True: 656, False: 5.17k]
  ------------------
  250|    656|        return VK_SUCCESS;
  251|    656|    }
  252|       |
  253|  5.17k|    VkResult res = create_string_list(inst, count, string_list);
  254|  5.17k|    if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
  ------------------
  |  Branch (254:9): [True: 0, False: 5.17k]
  ------------------
  255|      0|        goto out;
  256|      0|    }
  257|  5.17k|    cJSON *element = NULL;
  258|   767k|    cJSON_ArrayForEach(element, item) {
  ------------------
  |  |  213|   769k|    for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
  |  |  ------------------
  |  |  |  Branch (213:20): [True: 5.17k, False: 0]
  |  |  |  Branch (213:61): [True: 767k, False: 2.29k]
  |  |  ------------------
  ------------------
  259|   767k|        if (element->type != cJSON_String) {
  ------------------
  |  |  101|   767k|#define cJSON_String (1 << 4)
  ------------------
  |  Branch (259:13): [True: 2.88k, False: 764k]
  ------------------
  260|  2.88k|            return VK_ERROR_INITIALIZATION_FAILED;
  261|  2.88k|        }
  262|   767k|        bool out_of_memory = false;
  263|   764k|        char *out_data = loader_cJSON_Print(element, &out_of_memory);
  264|   764k|        if (out_of_memory) {
  ------------------
  |  Branch (264:13): [True: 0, False: 764k]
  ------------------
  265|      0|            res = VK_ERROR_OUT_OF_HOST_MEMORY;
  266|      0|            goto out;
  267|      0|        }
  268|   764k|        res = append_str_to_string_list(inst, string_list, out_data);
  269|   764k|        if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
  ------------------
  |  Branch (269:13): [True: 0, False: 764k]
  ------------------
  270|      0|            goto out;
  271|      0|        }
  272|   764k|    }
  273|  2.29k|out:
  274|  2.29k|    if (res == VK_ERROR_OUT_OF_HOST_MEMORY && NULL != string_list->list) {
  ------------------
  |  Branch (274:9): [True: 0, False: 2.29k]
  |  Branch (274:47): [True: 0, False: 0]
  ------------------
  275|      0|        free_string_list(inst, string_list);
  276|      0|    }
  277|       |
  278|  2.29k|    return res;
  279|  5.17k|}
loader_json.c:loader_read_entire_file:
  110|  8.10k|                                        char **out_buff) {
  111|  8.10k|    FILE *file = NULL;
  112|  8.10k|    struct stat stats = {0};
  113|  8.10k|    VkResult res = VK_SUCCESS;
  114|       |
  115|       |    // fprintf(stderr, "loader_get_json: Reading JSON file %s\n", filename);
  116|  8.10k|    file = fopen(filename, "rb");
  117|  8.10k|#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
  118|  8.10k|    if (file == NULL) {
  ------------------
  |  Branch (118:9): [True: 54, False: 8.04k]
  ------------------
  119|     54|        create_callback_file(filename);
  120|     54|        file = fopen(filename, "rb");
  121|     54|    }
  122|  8.10k|#endif
  123|  8.10k|    if (NULL == file) {
  ------------------
  |  Branch (123:9): [True: 54, False: 8.04k]
  ------------------
  124|     54|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Failed to open JSON file %s", filename);
  125|     54|        res = VK_ERROR_INITIALIZATION_FAILED;
  126|     54|        goto out;
  127|     54|    }
  128|  8.04k|    if (-1 == fstat(fileno(file), &stats)) {
  ------------------
  |  Branch (128:9): [True: 0, False: 8.04k]
  ------------------
  129|      0|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Failed to read file size of JSON file %s", filename);
  130|      0|        res = VK_ERROR_INITIALIZATION_FAILED;
  131|      0|        goto out;
  132|      0|    }
  133|  8.04k|    *out_buff = (char *)loader_instance_heap_calloc(inst, stats.st_size + 1, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
  134|  8.04k|    if (NULL == *out_buff) {
  ------------------
  |  Branch (134:9): [True: 0, False: 8.04k]
  ------------------
  135|      0|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Failed to allocate memory to read JSON file %s", filename);
  136|      0|        res = VK_ERROR_OUT_OF_HOST_MEMORY;
  137|      0|        goto out;
  138|      0|    }
  139|  8.04k|    if (stats.st_size != (long int)fread(*out_buff, sizeof(char), stats.st_size, file)) {
  ------------------
  |  Branch (139:9): [True: 47, False: 8.00k]
  ------------------
  140|     47|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Failed to read entire JSON file %s", filename);
  141|     47|        res = VK_ERROR_INITIALIZATION_FAILED;
  142|     47|        goto out;
  143|     47|    }
  144|  8.00k|    *out_len = stats.st_size + 1;
  145|  8.00k|    (*out_buff)[stats.st_size] = '\0';
  146|       |
  147|  8.10k|out:
  148|  8.10k|    if (NULL != file) {
  ------------------
  |  Branch (148:9): [True: 8.04k, False: 54]
  ------------------
  149|  8.04k|        fclose(file);
  150|  8.04k|    }
  151|  8.10k|    return res;
  152|  8.00k|}

loader_init_global_debug_level:
   42|      2|void loader_init_global_debug_level(void) {
   43|      2|    char *env, *orig;
   44|       |
   45|      2|    if (g_loader_debug > 0) return;
  ------------------
  |  Branch (45:9): [True: 0, False: 2]
  ------------------
   46|       |
   47|      2|    g_loader_debug = 0;
   48|       |
   49|       |    // Parse comma-separated debug options
   50|      2|    orig = env = loader_getenv("VK_LOADER_DEBUG", NULL);
   51|      2|    while (env) {
  ------------------
  |  Branch (51:12): [True: 0, False: 2]
  ------------------
   52|      0|        char *p = strchr(env, ',');
   53|      0|        size_t len;
   54|       |
   55|      0|        if (p) {
  ------------------
  |  Branch (55:13): [True: 0, False: 0]
  ------------------
   56|      0|            len = p - env;
   57|      0|        } else {
   58|      0|            len = strlen(env);
   59|      0|        }
   60|       |
   61|      0|        if (len > 0) {
  ------------------
  |  Branch (61:13): [True: 0, False: 0]
  ------------------
   62|      0|            if (strncmp(env, "all", len) == 0) {
  ------------------
  |  Branch (62:17): [True: 0, False: 0]
  ------------------
   63|      0|                g_loader_debug = ~0u;
   64|      0|            } else if (strncmp(env, "warn", len) == 0) {
  ------------------
  |  Branch (64:24): [True: 0, False: 0]
  ------------------
   65|      0|                g_loader_debug |= VULKAN_LOADER_WARN_BIT;
   66|      0|            } else if (strncmp(env, "info", len) == 0) {
  ------------------
  |  Branch (66:24): [True: 0, False: 0]
  ------------------
   67|      0|                g_loader_debug |= VULKAN_LOADER_INFO_BIT;
   68|      0|            } else if (strncmp(env, "perf", len) == 0) {
  ------------------
  |  Branch (68:24): [True: 0, False: 0]
  ------------------
   69|      0|                g_loader_debug |= VULKAN_LOADER_PERF_BIT;
   70|      0|            } else if (strncmp(env, "error", len) == 0) {
  ------------------
  |  Branch (70:24): [True: 0, False: 0]
  ------------------
   71|      0|                g_loader_debug |= VULKAN_LOADER_ERROR_BIT;
   72|      0|            } else if (strncmp(env, "debug", len) == 0) {
  ------------------
  |  Branch (72:24): [True: 0, False: 0]
  ------------------
   73|      0|                g_loader_debug |= VULKAN_LOADER_DEBUG_BIT;
   74|      0|            } else if (strncmp(env, "layer", len) == 0) {
  ------------------
  |  Branch (74:24): [True: 0, False: 0]
  ------------------
   75|      0|                g_loader_debug |= VULKAN_LOADER_LAYER_BIT;
   76|      0|            } else if (strncmp(env, "driver", len) == 0 || strncmp(env, "implem", len) == 0 || strncmp(env, "icd", len) == 0) {
  ------------------
  |  Branch (76:24): [True: 0, False: 0]
  |  Branch (76:60): [True: 0, False: 0]
  |  Branch (76:96): [True: 0, False: 0]
  ------------------
   77|      0|                g_loader_debug |= VULKAN_LOADER_DRIVER_BIT;
   78|      0|            }
   79|      0|        }
   80|       |
   81|      0|        if (!p) break;
  ------------------
  |  Branch (81:13): [True: 0, False: 0]
  ------------------
   82|       |
   83|      0|        env = p + 1;
   84|      0|    }
   85|       |
   86|       |    loader_free_getenv(orig, NULL);
   87|      2|}
loader_set_global_debug_level:
   89|    397|void loader_set_global_debug_level(uint32_t new_loader_debug) { g_loader_debug = new_loader_debug; }
generate_debug_flag_str:
   91|    730|void generate_debug_flag_str(VkFlags msg_type, size_t cmd_line_size, char *cmd_line_msg) {
   92|    730|    cmd_line_msg[0] = '\0';
   93|       |
   94|    730|    if ((msg_type & VULKAN_LOADER_ERROR_BIT) != 0) {
  ------------------
  |  Branch (94:9): [True: 57, False: 673]
  ------------------
   95|     57|        loader_strncat(cmd_line_msg, cmd_line_size, "ERROR", sizeof("ERROR"));
   96|     57|    }
   97|    730|    if ((msg_type & VULKAN_LOADER_WARN_BIT) != 0) {
  ------------------
  |  Branch (97:9): [True: 72, False: 658]
  ------------------
   98|     72|        if (strlen(cmd_line_msg) > 0) {
  ------------------
  |  Branch (98:13): [True: 45, False: 27]
  ------------------
   99|     45|            loader_strncat(cmd_line_msg, cmd_line_size, " | ", sizeof(" | "));
  100|     45|        }
  101|     72|        loader_strncat(cmd_line_msg, cmd_line_size, "WARNING", sizeof("WARNING"));
  102|     72|    }
  103|    730|    if ((msg_type & VULKAN_LOADER_INFO_BIT) != 0) {
  ------------------
  |  Branch (103:9): [True: 64, False: 666]
  ------------------
  104|     64|        if (strlen(cmd_line_msg) > 0) {
  ------------------
  |  Branch (104:13): [True: 49, False: 15]
  ------------------
  105|     49|            loader_strncat(cmd_line_msg, cmd_line_size, " | ", sizeof(" | "));
  106|     49|        }
  107|     64|        loader_strncat(cmd_line_msg, cmd_line_size, "INFO", sizeof("INFO"));
  108|     64|    }
  109|    730|    if ((msg_type & VULKAN_LOADER_DEBUG_BIT) != 0) {
  ------------------
  |  Branch (109:9): [True: 66, False: 664]
  ------------------
  110|     66|        if (strlen(cmd_line_msg) > 0) {
  ------------------
  |  Branch (110:13): [True: 52, False: 14]
  ------------------
  111|     52|            loader_strncat(cmd_line_msg, cmd_line_size, " | ", sizeof(" | "));
  112|     52|        }
  113|     66|        loader_strncat(cmd_line_msg, cmd_line_size, "DEBUG", sizeof("DEBUG"));
  114|     66|    }
  115|    730|    if ((msg_type & VULKAN_LOADER_PERF_BIT) != 0) {
  ------------------
  |  Branch (115:9): [True: 65, False: 665]
  ------------------
  116|     65|        if (strlen(cmd_line_msg) > 0) {
  ------------------
  |  Branch (116:13): [True: 50, False: 15]
  ------------------
  117|     50|            loader_strncat(cmd_line_msg, cmd_line_size, " | ", sizeof(" | "));
  118|     50|        }
  119|     65|        loader_strncat(cmd_line_msg, cmd_line_size, "PERF", sizeof("PERF"));
  120|     65|    }
  121|    730|    if ((msg_type & VULKAN_LOADER_DRIVER_BIT) != 0) {
  ------------------
  |  Branch (121:9): [True: 58, False: 672]
  ------------------
  122|     58|        if (strlen(cmd_line_msg) > 0) {
  ------------------
  |  Branch (122:13): [True: 42, False: 16]
  ------------------
  123|     42|            loader_strncat(cmd_line_msg, cmd_line_size, " | ", sizeof(" | "));
  124|     42|        }
  125|     58|        loader_strncat(cmd_line_msg, cmd_line_size, "DRIVER", sizeof("DRIVER"));
  126|     58|    }
  127|    730|    if ((msg_type & VULKAN_LOADER_LAYER_BIT) != 0) {
  ------------------
  |  Branch (127:9): [True: 68, False: 662]
  ------------------
  128|     68|        if (strlen(cmd_line_msg) > 0) {
  ------------------
  |  Branch (128:13): [True: 53, False: 15]
  ------------------
  129|     53|            loader_strncat(cmd_line_msg, cmd_line_size, " | ", sizeof(" | "));
  130|     53|        }
  131|     68|        loader_strncat(cmd_line_msg, cmd_line_size, "LAYER", sizeof("LAYER"));
  132|     68|    }
  133|       |
  134|    730|#undef STRNCAT_TO_BUFFER
  135|    730|}
loader_log:
  138|   628k|    loader_log(const struct loader_instance *inst, VkFlags msg_type, int32_t msg_code, const char *format, ...) {
  139|   628k|    (void)msg_code;
  140|   628k|    char msg[512] = {0};
  141|       |
  142|   628k|    va_list ap;
  143|   628k|    va_start(ap, format);
  144|   628k|    int ret = vsnprintf(msg, sizeof(msg), format, ap);
  145|   628k|    if ((ret >= (int)sizeof(msg)) || ret < 0) {
  ------------------
  |  Branch (145:9): [True: 371, False: 628k]
  |  Branch (145:38): [True: 0, False: 628k]
  ------------------
  146|    371|        msg[sizeof(msg) - 1] = '\0';
  147|    371|    }
  148|   628k|    va_end(ap);
  149|       |
  150|   628k|    if (inst) {
  ------------------
  |  Branch (150:9): [True: 0, False: 628k]
  ------------------
  151|      0|        VkDebugUtilsMessageSeverityFlagBitsEXT severity = 0;
  152|      0|        VkDebugUtilsMessageTypeFlagsEXT type = 0;
  153|      0|        VkDebugUtilsMessengerCallbackDataEXT callback_data = {0};
  154|      0|        VkDebugUtilsObjectNameInfoEXT object_name = {0};
  155|       |
  156|      0|        if ((msg_type & VULKAN_LOADER_INFO_BIT) != 0) {
  ------------------
  |  Branch (156:13): [True: 0, False: 0]
  ------------------
  157|      0|            severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
  158|      0|        } else if ((msg_type & VULKAN_LOADER_WARN_BIT) != 0) {
  ------------------
  |  Branch (158:20): [True: 0, False: 0]
  ------------------
  159|      0|            severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
  160|      0|        } else if ((msg_type & VULKAN_LOADER_ERROR_BIT) != 0) {
  ------------------
  |  Branch (160:20): [True: 0, False: 0]
  ------------------
  161|      0|            severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
  162|      0|        } else if ((msg_type & VULKAN_LOADER_DEBUG_BIT) != 0) {
  ------------------
  |  Branch (162:20): [True: 0, False: 0]
  ------------------
  163|      0|            severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT;
  164|      0|        } else if ((msg_type & VULKAN_LOADER_LAYER_BIT) != 0 || (msg_type & VULKAN_LOADER_DRIVER_BIT) != 0) {
  ------------------
  |  Branch (164:20): [True: 0, False: 0]
  |  Branch (164:65): [True: 0, False: 0]
  ------------------
  165|       |            // Just driver or just layer bit should be treated as an info message in debug utils.
  166|      0|            severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
  167|      0|        }
  168|       |
  169|      0|        if ((msg_type & VULKAN_LOADER_PERF_BIT) != 0) {
  ------------------
  |  Branch (169:13): [True: 0, False: 0]
  ------------------
  170|      0|            type = VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
  171|      0|        } else if ((msg_type & VULKAN_LOADER_VALIDATION_BIT) != 0) {
  ------------------
  |  Branch (171:20): [True: 0, False: 0]
  ------------------
  172|       |            // For loader logging, if it's a validation message, we still want to also keep the general flag as well
  173|       |            // so messages of type validation can still be triggered for general message callbacks.
  174|      0|            type = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
  175|      0|        } else {
  176|      0|            type = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
  177|      0|        }
  178|       |
  179|      0|        callback_data.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT;
  180|      0|        callback_data.pMessageIdName = "Loader Message";
  181|      0|        callback_data.pMessage = msg;
  182|      0|        callback_data.objectCount = 1;
  183|      0|        callback_data.pObjects = &object_name;
  184|      0|        object_name.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
  185|      0|        object_name.objectType = VK_OBJECT_TYPE_INSTANCE;
  186|      0|        object_name.objectHandle = (uint64_t)(uintptr_t)inst;
  187|       |
  188|      0|        util_SubmitDebugUtilsMessageEXT(inst, severity, type, &callback_data);
  189|      0|    }
  190|       |
  191|       |    // Always log to stderr if this is a fatal error
  192|   628k|    if (0 == (msg_type & VULKAN_LOADER_FATAL_ERROR_BIT)) {
  ------------------
  |  Branch (192:9): [True: 628k, False: 0]
  ------------------
  193|   628k|        if (inst && inst->settings.settings_active && inst->settings.debug_level > 0) {
  ------------------
  |  Branch (193:13): [True: 0, False: 628k]
  |  Branch (193:21): [True: 0, False: 0]
  |  Branch (193:55): [True: 0, False: 0]
  ------------------
  194|       |            // Exit early if the current instance settings have some debugging options but do match the current msg_type
  195|      0|            if (0 == (msg_type & inst->settings.debug_level)) {
  ------------------
  |  Branch (195:17): [True: 0, False: 0]
  ------------------
  196|      0|                return;
  197|      0|            }
  198|       |            // Check the global settings and if that doesn't say to skip, check the environment variable
  199|   628k|        } else if (0 == (msg_type & g_loader_debug)) {
  ------------------
  |  Branch (199:20): [True: 19.4k, False: 609k]
  ------------------
  200|  19.4k|            return;
  201|  19.4k|        }
  202|   628k|    }
  203|       |
  204|       |#if defined(DEBUG)
  205|       |    int debug_flag_mask =
  206|       |        msg_type & (VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_DEBUG_BIT);
  207|       |    assert((debug_flag_mask == 0 || debug_flag_mask == VULKAN_LOADER_ERROR_BIT || debug_flag_mask == VULKAN_LOADER_WARN_BIT ||
  208|       |            debug_flag_mask == VULKAN_LOADER_INFO_BIT || debug_flag_mask == VULKAN_LOADER_DEBUG_BIT) &&
  209|       |           "This log has more than one exclusive debug flags (error, warn, info, debug) set");
  210|       |#endif
  211|       |
  212|       |    // Only need enough space to create the filter description header for log messages
  213|       |    // Also use the same header for all output
  214|   609k|    char cmd_line_msg[64] = {0};
  215|   609k|    size_t cmd_line_size = sizeof(cmd_line_msg);
  216|       |
  217|   609k|    loader_strncat(cmd_line_msg, cmd_line_size, "[Vulkan Loader] ", sizeof("[Vulkan Loader] "));
  218|       |
  219|   609k|    bool need_separator = false;
  220|   609k|    if ((msg_type & VULKAN_LOADER_ERROR_BIT) != 0) {
  ------------------
  |  Branch (220:9): [True: 902, False: 608k]
  ------------------
  221|    902|        loader_strncat(cmd_line_msg, cmd_line_size, "ERROR", sizeof("ERROR"));
  222|    902|        need_separator = true;
  223|   608k|    } else if ((msg_type & VULKAN_LOADER_WARN_BIT) != 0) {
  ------------------
  |  Branch (223:16): [True: 0, False: 608k]
  ------------------
  224|      0|        loader_strncat(cmd_line_msg, cmd_line_size, "WARNING", sizeof("WARNING"));
  225|      0|        need_separator = true;
  226|   608k|    } else if ((msg_type & VULKAN_LOADER_INFO_BIT) != 0) {
  ------------------
  |  Branch (226:16): [True: 1.65k, False: 606k]
  ------------------
  227|  1.65k|        loader_strncat(cmd_line_msg, cmd_line_size, "INFO", sizeof("INFO"));
  228|  1.65k|        need_separator = true;
  229|   606k|    } else if ((msg_type & VULKAN_LOADER_DEBUG_BIT) != 0) {
  ------------------
  |  Branch (229:16): [True: 606k, False: 0]
  ------------------
  230|   606k|        loader_strncat(cmd_line_msg, cmd_line_size, "DEBUG", sizeof("DEBUG"));
  231|   606k|        need_separator = true;
  232|   606k|    }
  233|       |
  234|   609k|    if ((msg_type & VULKAN_LOADER_PERF_BIT) != 0) {
  ------------------
  |  Branch (234:9): [True: 0, False: 609k]
  ------------------
  235|      0|        if (need_separator) {
  ------------------
  |  Branch (235:13): [True: 0, False: 0]
  ------------------
  236|      0|            loader_strncat(cmd_line_msg, cmd_line_size, " | ", sizeof(" | "));
  237|      0|        }
  238|      0|        loader_strncat(cmd_line_msg, cmd_line_size, "PERF", sizeof("PERF"));
  239|   609k|    } else if ((msg_type & VULKAN_LOADER_DRIVER_BIT) != 0) {
  ------------------
  |  Branch (239:16): [True: 0, False: 609k]
  ------------------
  240|      0|        if (need_separator) {
  ------------------
  |  Branch (240:13): [True: 0, False: 0]
  ------------------
  241|      0|            loader_strncat(cmd_line_msg, cmd_line_size, " | ", sizeof(" | "));
  242|      0|        }
  243|      0|        loader_strncat(cmd_line_msg, cmd_line_size, "DRIVER", sizeof("DRIVER"));
  244|   609k|    } else if ((msg_type & VULKAN_LOADER_LAYER_BIT) != 0) {
  ------------------
  |  Branch (244:16): [True: 0, False: 609k]
  ------------------
  245|      0|        if (need_separator) {
  ------------------
  |  Branch (245:13): [True: 0, False: 0]
  ------------------
  246|      0|            loader_strncat(cmd_line_msg, cmd_line_size, " | ", sizeof(" | "));
  247|      0|        }
  248|      0|        loader_strncat(cmd_line_msg, cmd_line_size, "LAYER", sizeof("LAYER"));
  249|      0|    }
  250|       |
  251|   609k|    loader_strncat(cmd_line_msg, cmd_line_size, ": ", sizeof(": "));
  252|   609k|    size_t num_used = strlen(cmd_line_msg);
  253|       |
  254|       |    // Justifies the output to at least 29 spaces
  255|   609k|    if (num_used < 32) {
  ------------------
  |  Branch (255:9): [True: 609k, False: 0]
  ------------------
  256|   609k|        const char space_buffer[] = "                                ";
  257|       |        // Only write (32 - num_used) spaces
  258|   609k|        loader_strncat(cmd_line_msg, cmd_line_size, space_buffer, sizeof(space_buffer) - 1 - num_used);
  259|   609k|    }
  260|       |    // Assert that we didn't write more than what is available in cmd_line_msg
  261|   609k|    assert(cmd_line_size > num_used);
  262|       |
  263|       |    //fputs(cmd_line_msg, stderr);
  264|       |    //fputs(msg, stderr);
  265|       |    //fputc('\n', stderr);
  266|       |#if defined(WIN32)
  267|       |    OutputDebugString(cmd_line_msg);
  268|       |    OutputDebugString(msg);
  269|       |    OutputDebugString("\n");
  270|       |#endif
  271|   609k|}

free_layer_configuration:
   41|   189k|void free_layer_configuration(const struct loader_instance* inst, loader_settings_layer_configuration* layer_configuration) {
   42|   189k|    loader_instance_heap_free(inst, layer_configuration->name);
   43|   189k|    loader_instance_heap_free(inst, layer_configuration->path);
   44|   189k|    memset(layer_configuration, 0, sizeof(loader_settings_layer_configuration));
   45|   189k|}
free_loader_settings:
   57|  10.4k|void free_loader_settings(const struct loader_instance* inst, loader_settings* settings) {
   58|  10.4k|    if (NULL != settings->layer_configurations) {
  ------------------
  |  Branch (58:9): [True: 878, False: 9.53k]
  ------------------
   59|   157k|        for (uint32_t i = 0; i < settings->layer_configuration_count; i++) {
  ------------------
  |  Branch (59:30): [True: 156k, False: 878]
  ------------------
   60|   156k|            free_layer_configuration(inst, &settings->layer_configurations[i]);
   61|   156k|        }
   62|    878|        loader_instance_heap_free(inst, settings->layer_configurations);
   63|    878|    }
   64|  10.4k|    if (NULL != settings->additional_drivers) {
  ------------------
  |  Branch (64:9): [True: 0, False: 10.4k]
  ------------------
   65|      0|        for (uint32_t i = 0; i < settings->additional_driver_count; i++) {
  ------------------
  |  Branch (65:30): [True: 0, False: 0]
  ------------------
   66|      0|            free_driver_configuration(inst, &settings->additional_drivers[i]);
   67|      0|        }
   68|      0|        loader_instance_heap_free(inst, settings->additional_drivers);
   69|      0|    }
   70|  10.4k|    if (NULL != settings->device_configurations) {
  ------------------
  |  Branch (70:9): [True: 0, False: 10.4k]
  ------------------
   71|      0|        for (uint32_t i = 0; i < settings->device_configuration_count; i++) {
  ------------------
  |  Branch (71:30): [True: 0, False: 0]
  ------------------
   72|      0|            free_device_configuration(inst, &settings->device_configurations[i]);
   73|      0|        }
   74|      0|        loader_instance_heap_free(inst, settings->device_configurations);
   75|      0|    }
   76|  10.4k|    loader_instance_heap_free(inst, settings->settings_file_path);
   77|  10.4k|    memset(settings, 0, sizeof(loader_settings));
   78|  10.4k|}
parse_control_string:
   80|   169k|loader_settings_layer_control parse_control_string(char* control_string) {
   81|   169k|    loader_settings_layer_control layer_control = LOADER_SETTINGS_LAYER_CONTROL_DEFAULT;
   82|   169k|    if (strcmp(control_string, "auto") == 0)
  ------------------
  |  Branch (82:9): [True: 659, False: 168k]
  ------------------
   83|    659|        layer_control = LOADER_SETTINGS_LAYER_CONTROL_DEFAULT;
   84|   168k|    else if (strcmp(control_string, "on") == 0)
  ------------------
  |  Branch (84:14): [True: 791, False: 167k]
  ------------------
   85|    791|        layer_control = LOADER_SETTINGS_LAYER_CONTROL_ON;
   86|   167k|    else if (strcmp(control_string, "off") == 0)
  ------------------
  |  Branch (86:14): [True: 145k, False: 22.4k]
  ------------------
   87|   145k|        layer_control = LOADER_SETTINGS_LAYER_CONTROL_OFF;
   88|  22.4k|    else if (strcmp(control_string, "unordered_layer_location") == 0)
  ------------------
  |  Branch (88:14): [True: 3.89k, False: 18.5k]
  ------------------
   89|  3.89k|        layer_control = LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION;
   90|   169k|    return layer_control;
   91|   169k|}
loader_settings_layer_control_to_string:
   93|   125k|const char* loader_settings_layer_control_to_string(loader_settings_layer_control control) {
   94|   125k|    switch (control) {
   95|  6.69k|        case (LOADER_SETTINGS_LAYER_CONTROL_DEFAULT):
  ------------------
  |  Branch (95:9): [True: 6.69k, False: 118k]
  ------------------
   96|  6.69k|            return "auto";
   97|    301|        case (LOADER_SETTINGS_LAYER_CONTROL_ON):
  ------------------
  |  Branch (97:9): [True: 301, False: 125k]
  ------------------
   98|    301|            return "on";
   99|   115k|        case (LOADER_SETTINGS_LAYER_CONTROL_OFF):
  ------------------
  |  Branch (99:9): [True: 115k, False: 9.96k]
  ------------------
  100|   115k|            return "off";
  101|  2.96k|        case (LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION):
  ------------------
  |  Branch (101:9): [True: 2.96k, False: 122k]
  ------------------
  102|  2.96k|            return "unordered_layer_location";
  103|      0|        default:
  ------------------
  |  Branch (103:9): [True: 0, False: 125k]
  ------------------
  104|      0|            return "UNKNOWN_LAYER_CONTROl";
  105|   125k|    }
  106|   125k|}
parse_log_filters_from_strings:
  108|  1.21k|uint32_t parse_log_filters_from_strings(struct loader_string_list* log_filters) {
  109|  1.21k|    uint32_t filters = 0;
  110|   764k|    for (uint32_t i = 0; i < log_filters->count; i++) {
  ------------------
  |  Branch (110:26): [True: 763k, False: 1.21k]
  ------------------
  111|   763k|        if (strcmp(log_filters->list[i], "all") == 0)
  ------------------
  |  Branch (111:13): [True: 1.03k, False: 762k]
  ------------------
  112|  1.03k|            filters |= VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_PERF_BIT | VULKAN_LOADER_ERROR_BIT |
  113|  1.03k|                       VULKAN_LOADER_DEBUG_BIT | VULKAN_LOADER_LAYER_BIT | VULKAN_LOADER_DRIVER_BIT | VULKAN_LOADER_VALIDATION_BIT;
  114|   762k|        else if (strcmp(log_filters->list[i], "info") == 0)
  ------------------
  |  Branch (114:18): [True: 2.77k, False: 759k]
  ------------------
  115|  2.77k|            filters |= VULKAN_LOADER_INFO_BIT;
  116|   759k|        else if (strcmp(log_filters->list[i], "warn") == 0)
  ------------------
  |  Branch (116:18): [True: 30.7k, False: 728k]
  ------------------
  117|  30.7k|            filters |= VULKAN_LOADER_WARN_BIT;
  118|   728k|        else if (strcmp(log_filters->list[i], "perf") == 0)
  ------------------
  |  Branch (118:18): [True: 1.72k, False: 726k]
  ------------------
  119|  1.72k|            filters |= VULKAN_LOADER_PERF_BIT;
  120|   726k|        else if (strcmp(log_filters->list[i], "error") == 0)
  ------------------
  |  Branch (120:18): [True: 1.31k, False: 725k]
  ------------------
  121|  1.31k|            filters |= VULKAN_LOADER_ERROR_BIT;
  122|   725k|        else if (strcmp(log_filters->list[i], "debug") == 0)
  ------------------
  |  Branch (122:18): [True: 1.34k, False: 724k]
  ------------------
  123|  1.34k|            filters |= VULKAN_LOADER_DEBUG_BIT;
  124|   724k|        else if (strcmp(log_filters->list[i], "layer") == 0)
  ------------------
  |  Branch (124:18): [True: 1.38k, False: 722k]
  ------------------
  125|  1.38k|            filters |= VULKAN_LOADER_LAYER_BIT;
  126|   722k|        else if (strcmp(log_filters->list[i], "driver") == 0)
  ------------------
  |  Branch (126:18): [True: 1.33k, False: 721k]
  ------------------
  127|  1.33k|            filters |= VULKAN_LOADER_DRIVER_BIT;
  128|   721k|        else if (strcmp(log_filters->list[i], "validation") == 0)
  ------------------
  |  Branch (128:18): [True: 2.92k, False: 718k]
  ------------------
  129|  2.92k|            filters |= VULKAN_LOADER_VALIDATION_BIT;
  130|   763k|    }
  131|  1.21k|    return filters;
  132|  1.21k|}
parse_layer_configuration:
  147|   169k|                                   loader_settings_layer_configuration* layer_configuration) {
  148|   169k|    char* control_string = NULL;
  149|   169k|    VkResult res = loader_parse_json_string(layer_configuration_json, "control", &control_string);
  150|   169k|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (150:9): [True: 53, False: 169k]
  ------------------
  151|     53|        goto out;
  152|     53|    }
  153|   169k|    layer_configuration->control = parse_control_string(control_string);
  154|   169k|    loader_instance_heap_free(inst, control_string);
  155|       |
  156|       |    // If that is the only value - do no further parsing
  157|   169k|    if (layer_configuration->control == LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION) {
  ------------------
  |  Branch (157:9): [True: 3.89k, False: 165k]
  ------------------
  158|  3.89k|        goto out;
  159|  3.89k|    }
  160|       |
  161|   165k|    res = loader_parse_json_string(layer_configuration_json, "name", &(layer_configuration->name));
  162|   165k|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (162:9): [True: 656, False: 164k]
  ------------------
  163|    656|        goto out;
  164|    656|    }
  165|       |
  166|   164k|    res = loader_parse_json_string(layer_configuration_json, "path", &(layer_configuration->path));
  167|   164k|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (167:9): [True: 29, False: 164k]
  ------------------
  168|     29|        goto out;
  169|     29|    }
  170|       |
  171|   164k|    cJSON* treat_as_implicit_manifest = loader_cJSON_GetObjectItem(layer_configuration_json, "treat_as_implicit_manifest");
  172|   164k|    if (treat_as_implicit_manifest && treat_as_implicit_manifest->type == cJSON_True) {
  ------------------
  |  |   98|  1.72k|#define cJSON_True (1 << 1)
  ------------------
  |  Branch (172:9): [True: 1.72k, False: 162k]
  |  Branch (172:39): [True: 660, False: 1.06k]
  ------------------
  173|    660|        layer_configuration->treat_as_implicit_manifest = true;
  174|    660|    }
  175|   169k|out:
  176|   169k|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (176:9): [True: 738, False: 168k]
  ------------------
  177|    738|        free_layer_configuration(inst, layer_configuration);
  178|    738|    }
  179|   169k|    return res;
  180|   164k|}
parse_layer_configurations:
  182|  3.07k|VkResult parse_layer_configurations(const struct loader_instance* inst, cJSON* settings_object, loader_settings* loader_settings) {
  183|  3.07k|    VkResult res = VK_SUCCESS;
  184|       |
  185|  3.07k|    cJSON* layer_configurations = loader_cJSON_GetObjectItem(settings_object, "layers");
  186|       |    // If the layers object isn't present, return early with success to allow the settings file to still apply
  187|  3.07k|    if (NULL == layer_configurations) {
  ------------------
  |  Branch (187:9): [True: 1.34k, False: 1.73k]
  ------------------
  188|  1.34k|        return VK_SUCCESS;
  189|  1.34k|    }
  190|       |
  191|  1.73k|    uint32_t layer_configurations_count = loader_cJSON_GetArraySize(layer_configurations);
  192|  1.73k|    if (layer_configurations_count == 0) {
  ------------------
  |  Branch (192:9): [True: 47, False: 1.68k]
  ------------------
  193|     47|        loader_settings->layer_configurations_active = true;
  194|     47|        return VK_SUCCESS;
  195|     47|    }
  196|       |
  197|  1.68k|    loader_settings->layer_configuration_count = layer_configurations_count;
  198|       |
  199|  1.68k|    loader_settings->layer_configurations = loader_instance_heap_calloc(
  200|  1.68k|        inst, sizeof(loader_settings_layer_configuration) * layer_configurations_count, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  201|  1.68k|    if (NULL == loader_settings->layer_configurations) {
  ------------------
  |  Branch (201:9): [True: 0, False: 1.68k]
  ------------------
  202|      0|        res = VK_ERROR_OUT_OF_HOST_MEMORY;
  203|      0|        goto out;
  204|      0|    }
  205|       |
  206|  1.68k|    cJSON* layer = NULL;
  207|  1.68k|    size_t i = 0;
  208|   169k|    cJSON_ArrayForEach(layer, layer_configurations) {
  ------------------
  |  |  213|   170k|    for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
  |  |  ------------------
  |  |  |  Branch (213:20): [True: 1.68k, False: 0]
  |  |  |  Branch (213:61): [True: 169k, False: 878]
  |  |  ------------------
  ------------------
  209|   169k|        if (layer->type != cJSON_Object) {
  ------------------
  |  |  103|   169k|#define cJSON_Object (1 << 6)
  ------------------
  |  Branch (209:13): [True: 70, False: 169k]
  ------------------
  210|     70|            res = VK_ERROR_INITIALIZATION_FAILED;
  211|     70|            goto out;
  212|     70|        }
  213|   169k|        res = parse_layer_configuration(inst, layer, &(loader_settings->layer_configurations[i++]));
  214|   169k|        if (VK_SUCCESS != res) {
  ------------------
  |  Branch (214:13): [True: 738, False: 168k]
  ------------------
  215|    738|            goto out;
  216|    738|        }
  217|   169k|    }
  218|    878|    loader_settings->layer_configurations_active = true;
  219|  1.68k|out:
  220|  1.68k|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (220:9): [True: 808, False: 878]
  ------------------
  221|    808|        if (loader_settings->layer_configurations) {
  ------------------
  |  Branch (221:13): [True: 808, False: 0]
  ------------------
  222|  32.4k|            for (size_t index = 0; index < loader_settings->layer_configuration_count; index++) {
  ------------------
  |  Branch (222:36): [True: 31.6k, False: 808]
  ------------------
  223|  31.6k|                free_layer_configuration(inst, &(loader_settings->layer_configurations[index]));
  224|  31.6k|            }
  225|    808|            loader_settings->layer_configuration_count = 0;
  226|    808|            loader_instance_heap_free(inst, loader_settings->layer_configurations);
  227|    808|            loader_settings->layer_configurations = NULL;
  228|    808|        }
  229|    808|    }
  230|       |
  231|  1.68k|    return res;
  232|    878|}
parse_additional_drivers:
  248|  3.07k|VkResult parse_additional_drivers(const struct loader_instance* inst, cJSON* settings_object, loader_settings* loader_settings) {
  249|  3.07k|    VkResult res = VK_SUCCESS;
  250|       |
  251|  3.07k|    cJSON* additional_drivers_use_exclusively_json =
  252|  3.07k|        loader_cJSON_GetObjectItem(settings_object, "additional_drivers_use_exclusively");
  253|  3.07k|    if (additional_drivers_use_exclusively_json && additional_drivers_use_exclusively_json->type == cJSON_True) {
  ------------------
  |  |   98|      0|#define cJSON_True (1 << 1)
  ------------------
  |  Branch (253:9): [True: 0, False: 3.07k]
  |  Branch (253:52): [True: 0, False: 0]
  ------------------
  254|      0|        loader_settings->additional_drivers_use_exclusively = true;
  255|      0|    }
  256|       |
  257|  3.07k|    cJSON* additional_drivers_json = loader_cJSON_GetObjectItem(settings_object, "additional_drivers");
  258|  3.07k|    if (NULL == additional_drivers_json) {
  ------------------
  |  Branch (258:9): [True: 3.07k, False: 0]
  ------------------
  259|  3.07k|        return VK_SUCCESS;
  260|  3.07k|    }
  261|       |
  262|      0|    uint32_t additional_driver_count = loader_cJSON_GetArraySize(additional_drivers_json);
  263|      0|    if (additional_driver_count == 0) {
  ------------------
  |  Branch (263:9): [True: 0, False: 0]
  ------------------
  264|      0|        return VK_SUCCESS;
  265|      0|    }
  266|       |
  267|      0|    loader_settings->additional_driver_count = additional_driver_count;
  268|       |
  269|      0|    loader_settings->additional_drivers = loader_instance_heap_calloc(
  270|      0|        inst, sizeof(loader_settings_driver_configuration) * additional_driver_count, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  271|      0|    if (NULL == loader_settings->additional_drivers) {
  ------------------
  |  Branch (271:9): [True: 0, False: 0]
  ------------------
  272|      0|        res = VK_ERROR_OUT_OF_HOST_MEMORY;
  273|      0|        goto out;
  274|      0|    }
  275|       |
  276|      0|    cJSON* driver = NULL;
  277|      0|    size_t i = 0;
  278|      0|    cJSON_ArrayForEach(driver, additional_drivers_json) {
  ------------------
  |  |  213|      0|    for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
  |  |  ------------------
  |  |  |  Branch (213:20): [True: 0, False: 0]
  |  |  |  Branch (213:61): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  279|      0|        if (driver->type != cJSON_Object) {
  ------------------
  |  |  103|      0|#define cJSON_Object (1 << 6)
  ------------------
  |  Branch (279:13): [True: 0, False: 0]
  ------------------
  280|      0|            res = VK_ERROR_INITIALIZATION_FAILED;
  281|      0|            goto out;
  282|      0|        }
  283|      0|        res = parse_additional_driver(inst, driver, &(loader_settings->additional_drivers[i++]));
  284|      0|        if (VK_SUCCESS != res) {
  ------------------
  |  Branch (284:13): [True: 0, False: 0]
  ------------------
  285|      0|            goto out;
  286|      0|        }
  287|      0|    }
  288|      0|out:
  289|      0|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (289:9): [True: 0, False: 0]
  ------------------
  290|      0|        if (loader_settings->additional_drivers) {
  ------------------
  |  Branch (290:13): [True: 0, False: 0]
  ------------------
  291|      0|            for (size_t index = 0; index < loader_settings->additional_driver_count; index++) {
  ------------------
  |  Branch (291:36): [True: 0, False: 0]
  ------------------
  292|      0|                free_driver_configuration(inst, &(loader_settings->additional_drivers[index]));
  293|      0|            }
  294|      0|            loader_settings->additional_driver_count = 0;
  295|      0|            loader_instance_heap_free(inst, loader_settings->additional_drivers);
  296|       |            loader_settings->additional_drivers = NULL;
  297|      0|        }
  298|      0|    }
  299|      0|    return res;
  300|      0|}
parse_device_configurations:
  375|  3.07k|VkResult parse_device_configurations(const struct loader_instance* inst, cJSON* settings_object, loader_settings* loader_settings) {
  376|  3.07k|    VkResult res = VK_SUCCESS;
  377|       |
  378|  3.07k|    cJSON* device_configurations = loader_cJSON_GetObjectItem(settings_object, "device_configurations");
  379|  3.07k|    if (NULL == device_configurations) {
  ------------------
  |  Branch (379:9): [True: 3.07k, False: 0]
  ------------------
  380|  3.07k|        return VK_SUCCESS;
  381|  3.07k|    }
  382|       |
  383|      0|    uint32_t device_configuration_count = loader_cJSON_GetArraySize(device_configurations);
  384|      0|    if (device_configuration_count == 0) {
  ------------------
  |  Branch (384:9): [True: 0, False: 0]
  ------------------
  385|      0|        loader_settings->device_configurations_active = true;
  386|      0|        return VK_SUCCESS;
  387|      0|    }
  388|       |
  389|      0|    loader_settings->device_configuration_count = device_configuration_count;
  390|       |
  391|      0|    loader_settings->device_configurations = loader_instance_heap_calloc(
  392|      0|        inst, sizeof(loader_settings_device_configuration) * device_configuration_count, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  393|      0|    if (NULL == loader_settings->device_configurations) {
  ------------------
  |  Branch (393:9): [True: 0, False: 0]
  ------------------
  394|      0|        res = VK_ERROR_OUT_OF_HOST_MEMORY;
  395|      0|        goto out;
  396|      0|    }
  397|       |
  398|      0|    cJSON* device = NULL;
  399|      0|    size_t i = 0;
  400|      0|    cJSON_ArrayForEach(device, device_configurations) {
  ------------------
  |  |  213|      0|    for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
  |  |  ------------------
  |  |  |  Branch (213:20): [True: 0, False: 0]
  |  |  |  Branch (213:61): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  401|      0|        if (device->type != cJSON_Object) {
  ------------------
  |  |  103|      0|#define cJSON_Object (1 << 6)
  ------------------
  |  Branch (401:13): [True: 0, False: 0]
  ------------------
  402|      0|            res = VK_ERROR_INITIALIZATION_FAILED;
  403|      0|            goto out;
  404|      0|        }
  405|      0|        res = parse_device_configuration(inst, device, &(loader_settings->device_configurations[i]));
  406|      0|        if (res == VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (406:13): [True: 0, False: 0]
  ------------------
  407|      0|            goto out;
  408|      0|        } else if (res != VK_SUCCESS) {
  ------------------
  |  Branch (408:20): [True: 0, False: 0]
  ------------------
  409|       |            // Skip a malformed entry rather than discarding every device configuration in the file
  410|      0|            res = VK_SUCCESS;
  411|      0|            continue;
  412|      0|        }
  413|      0|        i++;
  414|      0|    }
  415|       |    // Only the first i entries were successfully parsed; the trailing entries are unpopulated
  416|      0|    loader_settings->device_configuration_count = (uint32_t)i;
  417|      0|    loader_settings->device_configurations_active = true;
  418|      0|out:
  419|      0|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (419:9): [True: 0, False: 0]
  ------------------
  420|      0|        if (loader_settings->device_configurations) {
  ------------------
  |  Branch (420:13): [True: 0, False: 0]
  ------------------
  421|      0|            for (size_t index = 0; index < loader_settings->device_configuration_count; index++) {
  ------------------
  |  Branch (421:36): [True: 0, False: 0]
  ------------------
  422|      0|                free_device_configuration(inst, &(loader_settings->device_configurations[index]));
  423|      0|            }
  424|      0|            loader_settings->device_configuration_count = 0;
  425|      0|            loader_instance_heap_free(inst, loader_settings->device_configurations);
  426|       |            loader_settings->device_configurations = NULL;
  427|      0|        }
  428|      0|    }
  429|      0|    return res;
  430|      0|}
check_if_settings_path_exists:
  437|  42.8k|                                       char** settings_file_path) {
  438|  42.8k|    if (NULL == base || NULL == suffix) {
  ------------------
  |  Branch (438:9): [True: 18.8k, False: 24.0k]
  |  Branch (438:25): [True: 0, False: 24.0k]
  ------------------
  439|  18.8k|        return VK_ERROR_INITIALIZATION_FAILED;
  440|  18.8k|    }
  441|       |
  442|  24.0k|    size_t base_len = strlen(base);
  443|  24.0k|    size_t suffix_len = strlen(suffix);
  444|       |
  445|  24.0k|    uint32_t start = 0;
  446|  24.0k|    uint32_t stop = 0;
  447|  41.2k|    while (base[start] != '\0' && start < base_len && stop < base_len) {
  ------------------
  |  Branch (447:12): [True: 41.2k, False: 0]
  |  Branch (447:35): [True: 41.2k, False: 0]
  |  Branch (447:55): [True: 25.3k, False: 15.9k]
  ------------------
  448|  25.3k|        start = stop;
  449|  25.3k|        stop = start + 1;
  450|   144k|        while (base[stop] != PATH_SEPARATOR && base[stop] != '\0' && stop < base_len) {
  ------------------
  |  |  150|   288k|#define PATH_SEPARATOR ':'
  ------------------
  |  Branch (450:16): [True: 143k, False: 1.30k]
  |  Branch (450:48): [True: 119k, False: 24.0k]
  |  Branch (450:70): [True: 119k, False: 0]
  ------------------
  451|   119k|            stop++;
  452|   119k|        }
  453|       |
  454|  25.3k|        size_t segment_len = (stop - start);
  455|  25.3k|        if (segment_len <= 1) {
  ------------------
  |  Branch (455:13): [True: 0, False: 25.3k]
  ------------------
  456|       |            // segment is *just* a PATH_SEPARATOR, skip it
  457|      0|            continue;
  458|      0|        }
  459|  25.3k|        size_t path_len = segment_len + suffix_len + 1;
  460|  25.3k|        *settings_file_path = loader_instance_heap_calloc(inst, path_len, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
  461|  25.3k|        if (NULL == *settings_file_path) {
  ------------------
  |  Branch (461:13): [True: 0, False: 25.3k]
  ------------------
  462|      0|            return VK_ERROR_OUT_OF_HOST_MEMORY;
  463|      0|        }
  464|  25.3k|        loader_strncpy(*settings_file_path, path_len, base + start, segment_len);
  465|  25.3k|        loader_strncat(*settings_file_path, path_len, suffix, suffix_len);
  466|       |
  467|  25.3k|        if (loader_platform_file_exists(*settings_file_path)) {
  ------------------
  |  Branch (467:13): [True: 8.10k, False: 17.2k]
  ------------------
  468|  8.10k|            return VK_SUCCESS;
  469|  8.10k|        }
  470|  17.2k|        loader_instance_heap_free(inst, *settings_file_path);
  471|  17.2k|        *settings_file_path = NULL;
  472|  17.2k|    }
  473|       |
  474|  15.9k|    return VK_ERROR_INITIALIZATION_FAILED;
  475|  24.0k|}
get_unix_settings_path:
  478|  9.40k|VkResult get_unix_settings_path(const struct loader_instance* inst, char** settings_file_path) {
  479|       |    // First, get XDG env-vars we use. Don't need to worry about free'ing because on linux getenv is non-allocating
  480|  9.40k|    char* xdg_config_home = loader_secure_getenv("XDG_CONFIG_HOME", inst);
  481|  9.40k|    char* xdg_config_dirs = loader_secure_getenv("XDG_CONFIG_DIRS", inst);
  482|  9.40k|    char* xdg_data_home = loader_secure_getenv("XDG_DATA_HOME", inst);
  483|  9.40k|    char* xdg_data_dirs = loader_secure_getenv("XDG_DATA_DIRS", inst);
  484|       |
  485|       |    // Use fallback directories for xdg_config_dirs and xdg_data_dirs if they are NULL.
  486|  9.40k|#if !defined(__Fuchsia__) && !defined(__QNX__)
  487|  9.40k|    if (NULL == xdg_config_dirs || '\0' == xdg_config_dirs[0]) {
  ------------------
  |  Branch (487:9): [True: 9.40k, False: 0]
  |  Branch (487:36): [True: 0, False: 0]
  ------------------
  488|  9.40k|        xdg_config_dirs = FALLBACK_CONFIG_DIRS;
  489|  9.40k|    }
  490|  9.40k|#endif
  491|       |
  492|  9.40k|#if !defined(__Fuchsia__) && !defined(__QNX__)
  493|  9.40k|    if (NULL == xdg_data_dirs || '\0' == xdg_data_dirs[0]) {
  ------------------
  |  Branch (493:9): [True: 9.40k, False: 0]
  |  Branch (493:34): [True: 0, False: 0]
  ------------------
  494|  9.40k|        xdg_data_dirs = FALLBACK_DATA_DIRS;
  495|  9.40k|    }
  496|  9.40k|#endif
  497|       |
  498|  9.40k|    VkResult res = check_if_settings_path_exists(
  499|  9.40k|        inst, xdg_config_home, "/" VULKAN_DIR "/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME, settings_file_path);
  ------------------
  |  |  141|  9.40k|#define VK_LOADER_SETTINGS_FILENAME "vk_loader_settings.json"
  ------------------
  500|  9.40k|    if (res == VK_SUCCESS) {
  ------------------
  |  Branch (500:9): [True: 0, False: 9.40k]
  ------------------
  501|      0|        return res;
  502|      0|    }
  503|       |
  504|  9.40k|    res = check_if_settings_path_exists(inst, xdg_data_home, "/" VULKAN_DIR "/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME,
  ------------------
  |  |  141|  9.40k|#define VK_LOADER_SETTINGS_FILENAME "vk_loader_settings.json"
  ------------------
  505|  9.40k|                                        settings_file_path);
  506|  9.40k|    if (res == VK_SUCCESS) {
  ------------------
  |  Branch (506:9): [True: 0, False: 9.40k]
  ------------------
  507|      0|        return res;
  508|      0|    }
  509|       |
  510|       |    // Check home if either xdg_config_home or xdg_data_home wasn't set
  511|  9.40k|    char* home = loader_secure_getenv("HOME", inst);
  512|  9.40k|    if (home != NULL) {
  ------------------
  |  Branch (512:9): [True: 9.40k, False: 0]
  ------------------
  513|  9.40k|        if (NULL == xdg_config_home || '\0' == xdg_config_home[0]) {
  ------------------
  |  Branch (513:13): [True: 9.40k, False: 0]
  |  Branch (513:40): [True: 0, False: 0]
  ------------------
  514|  9.40k|            res = check_if_settings_path_exists(
  515|  9.40k|                inst, home, "/.config/" VULKAN_DIR "/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME, settings_file_path);
  ------------------
  |  |  141|  9.40k|#define VK_LOADER_SETTINGS_FILENAME "vk_loader_settings.json"
  ------------------
  516|  9.40k|            if (res == VK_SUCCESS) {
  ------------------
  |  Branch (516:17): [True: 0, False: 9.40k]
  ------------------
  517|      0|                return res;
  518|      0|            }
  519|  9.40k|        }
  520|  9.40k|        if (NULL == xdg_data_home || '\0' == xdg_data_home[0]) {
  ------------------
  |  Branch (520:13): [True: 9.40k, False: 0]
  |  Branch (520:38): [True: 0, False: 0]
  ------------------
  521|  9.40k|            res = check_if_settings_path_exists(
  522|  9.40k|                inst, home, "/.local/share/" VULKAN_DIR "/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME, settings_file_path);
  ------------------
  |  |  141|  9.40k|#define VK_LOADER_SETTINGS_FILENAME "vk_loader_settings.json"
  ------------------
  523|  9.40k|            if (res == VK_SUCCESS) {
  ------------------
  |  Branch (523:17): [True: 8.10k, False: 1.30k]
  ------------------
  524|  8.10k|                return res;
  525|  8.10k|            }
  526|  9.40k|        }
  527|  9.40k|    }
  528|       |
  529|  1.30k|    res = check_if_settings_path_exists(inst, xdg_config_dirs, "/" VULKAN_DIR "/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME,
  ------------------
  |  |  141|  1.30k|#define VK_LOADER_SETTINGS_FILENAME "vk_loader_settings.json"
  ------------------
  530|  1.30k|                                        settings_file_path);
  531|  1.30k|    if (res == VK_SUCCESS) {
  ------------------
  |  Branch (531:9): [True: 0, False: 1.30k]
  ------------------
  532|      0|        return res;
  533|      0|    }
  534|       |
  535|  1.30k|    res = check_if_settings_path_exists(inst, SYSCONFDIR, "/" VULKAN_DIR "/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME,
  ------------------
  |  |  141|  1.30k|#define VK_LOADER_SETTINGS_FILENAME "vk_loader_settings.json"
  ------------------
  536|  1.30k|                                        settings_file_path);
  537|  1.30k|    if (res == VK_SUCCESS) {
  ------------------
  |  Branch (537:9): [True: 0, False: 1.30k]
  ------------------
  538|      0|        return res;
  539|      0|    }
  540|  1.30k|#if defined(EXTRASYSCONFDIR)
  541|       |
  542|  1.30k|    res = check_if_settings_path_exists(inst, EXTRASYSCONFDIR, "/" VULKAN_DIR "/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME,
  ------------------
  |  |  141|  1.30k|#define VK_LOADER_SETTINGS_FILENAME "vk_loader_settings.json"
  ------------------
  543|  1.30k|                                        settings_file_path);
  544|  1.30k|    if (res == VK_SUCCESS) {
  ------------------
  |  Branch (544:9): [True: 0, False: 1.30k]
  ------------------
  545|      0|        return res;
  546|      0|    }
  547|  1.30k|#endif
  548|  1.30k|    res = check_if_settings_path_exists(inst, xdg_data_dirs, "/" VULKAN_DIR "/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME,
  ------------------
  |  |  141|  1.30k|#define VK_LOADER_SETTINGS_FILENAME "vk_loader_settings.json"
  ------------------
  549|  1.30k|                                        settings_file_path);
  550|  1.30k|    if (res == VK_SUCCESS) {
  ------------------
  |  Branch (550:9): [True: 0, False: 1.30k]
  ------------------
  551|      0|        return res;
  552|      0|    }
  553|       |
  554|  1.30k|    return VK_ERROR_INITIALIZATION_FAILED;
  555|  1.30k|}
check_if_layer_configurations_are_equal:
  558|  33.8k|bool check_if_layer_configurations_are_equal(loader_settings_layer_configuration* a, loader_settings_layer_configuration* b) {
  559|  33.8k|    if (!a->name || !b->name || 0 != strcmp(a->name, b->name)) {
  ------------------
  |  Branch (559:9): [True: 1.76k, False: 32.1k]
  |  Branch (559:21): [True: 0, False: 32.1k]
  |  Branch (559:33): [True: 0, False: 32.1k]
  ------------------
  560|  1.76k|        return false;
  561|  1.76k|    }
  562|  32.1k|    if (!a->path || !b->path || 0 != strcmp(a->path, b->path)) {
  ------------------
  |  Branch (562:9): [True: 0, False: 32.1k]
  |  Branch (562:21): [True: 0, False: 32.1k]
  |  Branch (562:33): [True: 0, False: 32.1k]
  ------------------
  563|      0|        return false;
  564|      0|    }
  565|  32.1k|    return a->control == b->control && a->treat_as_implicit_manifest == b->treat_as_implicit_manifest;
  ------------------
  |  Branch (565:12): [True: 32.1k, False: 0]
  |  Branch (565:40): [True: 32.1k, False: 0]
  ------------------
  566|  32.1k|}
check_if_settings_are_equal:
  588|  7.27k|bool check_if_settings_are_equal(loader_settings* a, loader_settings* b) {
  589|       |    // If either pointer is null, return true
  590|  7.27k|    if (NULL == a || NULL == b) return false;
  ------------------
  |  Branch (590:9): [True: 0, False: 7.27k]
  |  Branch (590:22): [True: 0, False: 7.27k]
  ------------------
  591|  7.27k|    bool are_equal = true;
  592|  7.27k|    are_equal &= a->settings_active == b->settings_active;
  593|  7.27k|    are_equal &= a->has_unordered_layer_location == b->has_unordered_layer_location;
  594|  7.27k|    are_equal &= a->debug_level == b->debug_level;
  595|  7.27k|    are_equal &= a->layer_configurations_active == b->layer_configurations_active;
  596|  7.27k|    are_equal &= a->layer_configuration_count == b->layer_configuration_count;
  597|  7.27k|    are_equal &= a->additional_drivers_use_exclusively == b->additional_drivers_use_exclusively;
  598|  7.27k|    are_equal &= a->additional_driver_count == b->additional_driver_count;
  599|  7.27k|    are_equal &= a->device_configurations_active == b->device_configurations_active;
  600|  7.27k|    are_equal &= a->device_configuration_count == b->device_configuration_count;
  601|  7.27k|    if (!are_equal) return false;
  ------------------
  |  Branch (601:9): [True: 568, False: 6.70k]
  ------------------
  602|  40.5k|    for (uint32_t i = 0; i < a->layer_configuration_count && i < b->layer_configuration_count; i++) {
  ------------------
  |  Branch (602:26): [True: 33.8k, False: 6.70k]
  |  Branch (602:62): [True: 33.8k, False: 0]
  ------------------
  603|  33.8k|        are_equal &= check_if_layer_configurations_are_equal(&a->layer_configurations[i], &b->layer_configurations[i]);
  604|  33.8k|    }
  605|  6.70k|    for (uint32_t i = 0; i < a->additional_driver_count && i < b->additional_driver_count; i++) {
  ------------------
  |  Branch (605:26): [True: 0, False: 6.70k]
  |  Branch (605:60): [True: 0, False: 0]
  ------------------
  606|      0|        are_equal &= check_if_driver_configurations_are_equal(&a->additional_drivers[i], &b->additional_drivers[i]);
  607|      0|    }
  608|  6.70k|    for (uint32_t i = 0; i < a->device_configuration_count && i < b->device_configuration_count; i++) {
  ------------------
  |  Branch (608:26): [True: 0, False: 6.70k]
  |  Branch (608:63): [True: 0, False: 0]
  ------------------
  609|      0|        are_equal &= check_if_device_configurations_are_equal(&a->device_configurations[i], &b->device_configurations[i]);
  610|      0|    }
  611|  6.70k|    return are_equal;
  612|  7.27k|}
log_settings:
  614|    730|void log_settings(const struct loader_instance* inst, loader_settings* settings) {
  615|    730|    if (settings == NULL) {
  ------------------
  |  Branch (615:9): [True: 0, False: 730]
  ------------------
  616|      0|        return;
  617|      0|    }
  618|    730|    loader_log(inst, VULKAN_LOADER_INFO_BIT, 0, "Using layer configurations found in loader settings from %s",
  619|    730|               settings->settings_file_path);
  620|       |
  621|    730|    char cmd_line_msg[64] = {0};
  622|    730|    size_t cmd_line_size = sizeof(cmd_line_msg);
  623|       |
  624|    730|    cmd_line_msg[0] = '\0';
  625|       |
  626|    730|    generate_debug_flag_str(settings->debug_level, cmd_line_size, cmd_line_msg);
  627|    730|    if (strlen(cmd_line_msg)) {
  ------------------
  |  Branch (627:9): [True: 159, False: 571]
  ------------------
  628|    159|        loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Loader Settings Filters for Logging to Standard Error: %s", cmd_line_msg);
  629|    159|    }
  630|    730|    if (settings->layer_configurations_active) {
  ------------------
  |  Branch (630:9): [True: 587, False: 143]
  ------------------
  631|    587|        loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Layer Configurations count = %d", settings->layer_configuration_count);
  632|   126k|        for (uint32_t i = 0; i < settings->layer_configuration_count; i++) {
  ------------------
  |  Branch (632:30): [True: 125k, False: 587]
  ------------------
  633|   125k|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "---- Layer Configuration [%d] ----", i);
  634|   125k|            if (settings->layer_configurations[i].control != LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION) {
  ------------------
  |  Branch (634:17): [True: 122k, False: 2.96k]
  ------------------
  635|   122k|                loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Name: %s", settings->layer_configurations[i].name);
  636|   122k|                loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Path: %s", settings->layer_configurations[i].path);
  637|   122k|                loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Layer Type: %s",
  638|   122k|                           settings->layer_configurations[i].treat_as_implicit_manifest ? "Implicit" : "Explicit");
  ------------------
  |  Branch (638:28): [True: 503, False: 122k]
  ------------------
  639|   122k|            }
  640|   125k|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Control: %s",
  641|   125k|                       loader_settings_layer_control_to_string(settings->layer_configurations[i].control));
  642|   125k|        }
  643|    587|    }
  644|    730|    if (settings->additional_driver_count > 0) {
  ------------------
  |  Branch (644:9): [True: 0, False: 730]
  ------------------
  645|      0|        loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "----");
  646|      0|        loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Use Additional Drivers Exclusively = %s",
  647|      0|                   settings->additional_drivers_use_exclusively ? "true" : "false");
  ------------------
  |  Branch (647:20): [True: 0, False: 0]
  ------------------
  648|      0|        loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Additional Driver Configurations count = %d",
  649|      0|                   settings->additional_driver_count);
  650|      0|        for (uint32_t i = 0; i < settings->additional_driver_count; i++) {
  ------------------
  |  Branch (650:30): [True: 0, False: 0]
  ------------------
  651|      0|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "---- Driver Configuration [%d] ----", i);
  652|      0|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Path: %s", settings->additional_drivers[i].path);
  653|      0|        }
  654|      0|    }
  655|    730|    if (settings->device_configurations_active) {
  ------------------
  |  Branch (655:9): [True: 0, False: 730]
  ------------------
  656|      0|        loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "----");
  657|      0|        loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Device Configurations count = %d", settings->device_configuration_count);
  658|      0|        for (uint32_t i = 0; i < settings->device_configuration_count; i++) {
  ------------------
  |  Branch (658:30): [True: 0, False: 0]
  ------------------
  659|      0|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "---- Device Configuration [%d] ----", i);
  660|      0|            char device_uuid_str[UUID_STR_LEN] = {0};
  661|      0|            loader_log_generate_uuid_string(settings->device_configurations[i].deviceUUID, device_uuid_str);
  662|      0|            char driver_uuid_str[UUID_STR_LEN] = {0};
  663|      0|            loader_log_generate_uuid_string(settings->device_configurations[i].driverUUID, driver_uuid_str);
  664|      0|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "deviceUUID: %s", device_uuid_str);
  665|      0|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "driverUUID: %s", driver_uuid_str);
  666|      0|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "driverVersion: %d", settings->device_configurations[i].driverVersion);
  667|      0|            if ('\0' != settings->device_configurations[i].deviceName[0]) {
  ------------------
  |  Branch (667:17): [True: 0, False: 0]
  ------------------
  668|      0|                loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "deviceName: %s", settings->device_configurations[i].deviceName);
  669|      0|            }
  670|      0|            if ('\0' != settings->device_configurations[i].driverName[0]) {
  ------------------
  |  Branch (670:17): [True: 0, False: 0]
  ------------------
  671|      0|                loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "driverName: %s", settings->device_configurations[i].driverName);
  672|      0|            }
  673|      0|        }
  674|      0|    }
  675|    730|    loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "---------------------------------");
  676|    730|}
get_loader_settings:
  681|  9.40k|VkResult get_loader_settings(const struct loader_instance* inst, loader_settings* loader_settings) {
  682|  9.40k|    VkResult res = VK_SUCCESS;
  683|  9.40k|    cJSON* json = NULL;
  684|  9.40k|    char* file_format_version_string = NULL;
  685|  9.40k|    char* settings_file_path = NULL;
  686|       |#if defined(WIN32)
  687|       |    res = windows_get_loader_settings_file_path(inst, &settings_file_path);
  688|       |    if (res != VK_SUCCESS) {
  689|       |        loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
  690|       |                   "No valid vk_loader_settings.json file found, no loader settings will be active");
  691|       |        goto out;
  692|       |    }
  693|       |
  694|       |#elif COMMON_UNIX_PLATFORMS
  695|       |    res = get_unix_settings_path(inst, &settings_file_path);
  696|  9.40k|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (696:9): [True: 1.30k, False: 8.10k]
  ------------------
  697|  1.30k|        loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
  698|  1.30k|                   "No valid vk_loader_settings.json file found, no loader settings will be active");
  699|  1.30k|        goto out;
  700|  1.30k|    }
  701|       |#else
  702|       |#warning "Unsupported platform - must specify platform specific location for vk_loader_settings.json"
  703|       |#endif
  704|       |
  705|  8.10k|    res = loader_get_json(inst, settings_file_path, &json);
  706|       |    // Make sure sure the top level json value is an object
  707|  8.10k|    if (res != VK_SUCCESS || NULL == json || json->type != cJSON_Object) {
  ------------------
  |  |  103|  5.14k|#define cJSON_Object (1 << 6)
  ------------------
  |  Branch (707:9): [True: 101, False: 8.00k]
  |  Branch (707:30): [True: 2.85k, False: 5.14k]
  |  Branch (707:46): [True: 825, False: 4.32k]
  ------------------
  708|  3.77k|        goto out;
  709|  3.77k|    }
  710|       |
  711|  4.32k|    res = loader_parse_json_string(json, "file_format_version", &file_format_version_string);
  712|  4.32k|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (712:9): [True: 52, False: 4.27k]
  ------------------
  713|     52|        if (res != VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (713:13): [True: 52, False: 0]
  ------------------
  714|     52|            loader_log(
  715|     52|                inst, VULKAN_LOADER_DEBUG_BIT, 0,
  716|     52|                "Loader settings file from %s missing required field file_format_version - no loader settings will be active",
  717|     52|                settings_file_path);
  718|     52|        }
  719|     52|        goto out;
  720|     52|    }
  721|       |
  722|       |    // Because the file may contain either a "settings_array" or a single "settings" object, we need to create a cJSON so that we
  723|       |    // can iterate on both cases with common code
  724|  4.27k|    cJSON settings_iter_parent = {0};
  725|       |
  726|  4.27k|    cJSON* settings_array = loader_cJSON_GetObjectItem(json, "settings_array");
  727|  4.27k|    cJSON* single_settings_object = loader_cJSON_GetObjectItem(json, "settings");
  728|  4.27k|    if (NULL != settings_array) {
  ------------------
  |  Branch (728:9): [True: 2.97k, False: 1.29k]
  ------------------
  729|  2.97k|        memcpy(&settings_iter_parent, settings_array, sizeof(cJSON));
  730|  2.97k|    } else if (NULL != single_settings_object) {
  ------------------
  |  Branch (730:16): [True: 626, False: 673]
  ------------------
  731|    626|        settings_iter_parent.child = single_settings_object;
  732|    673|    } else {
  733|    673|        loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0,
  734|    673|                   "Loader settings file from %s missing required settings objects: Either one of the \"settings\" or "
  735|    673|                   "\"settings_array\" objects must be present - no loader settings will be active",
  736|    673|                   settings_file_path);
  737|    673|        res = VK_ERROR_INITIALIZATION_FAILED;
  738|    673|        goto out;
  739|    673|    }
  740|       |
  741|       |    // Corresponds to the settings object that has no app keys
  742|  3.59k|    cJSON* global_settings = NULL;
  743|       |    // Corresponds to the settings object which has a matching app key
  744|  3.59k|    cJSON* settings_to_use = NULL;
  745|       |
  746|  3.59k|    char current_process_path[1024];
  747|  3.59k|    bool valid_exe_path = NULL != loader_platform_executable_path(current_process_path, 1024);
  748|       |
  749|  3.59k|    cJSON* settings_object_iter = NULL;
  750|  7.43k|    cJSON_ArrayForEach(settings_object_iter, &settings_iter_parent) {
  ------------------
  |  |  213|  10.9k|    for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
  |  |  ------------------
  |  |  |  Branch (213:20): [True: 3.59k, Folded]
  |  |  |  Branch (213:61): [True: 7.43k, False: 3.52k]
  |  |  ------------------
  ------------------
  751|  7.43k|        if (settings_object_iter->type != cJSON_Object) {
  ------------------
  |  |  103|  7.43k|#define cJSON_Object (1 << 6)
  ------------------
  |  Branch (751:13): [True: 73, False: 7.36k]
  ------------------
  752|     73|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0,
  753|     73|                       "Loader settings file from %s has a settings element that is not an object", settings_file_path);
  754|     73|            break;
  755|     73|        }
  756|       |
  757|  7.36k|        cJSON* app_keys = loader_cJSON_GetObjectItem(settings_object_iter, "app_keys");
  758|  7.36k|        if (NULL == app_keys) {
  ------------------
  |  Branch (758:13): [True: 4.85k, False: 2.51k]
  ------------------
  759|       |            // use the first 'global' settings that has no app keys as the global one
  760|  4.85k|            if (global_settings == NULL) {
  ------------------
  |  Branch (760:17): [True: 3.07k, False: 1.77k]
  ------------------
  761|  3.07k|                global_settings = settings_object_iter;
  762|  3.07k|            }
  763|  4.85k|            continue;
  764|  4.85k|        }
  765|       |        // No sense iterating if we couldn't get the executable path
  766|  2.51k|        if (!valid_exe_path) {
  ------------------
  |  Branch (766:13): [True: 0, False: 2.51k]
  ------------------
  767|      0|            break;
  768|      0|        }
  769|  2.51k|        cJSON* app_key = NULL;
  770|  4.11k|        cJSON_ArrayForEach(app_key, app_keys) {
  ------------------
  |  |  213|  6.63k|    for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
  |  |  ------------------
  |  |  |  Branch (213:20): [True: 2.51k, False: 0]
  |  |  |  Branch (213:61): [True: 4.11k, False: 2.51k]
  |  |  ------------------
  ------------------
  771|  4.11k|            char* app_key_str = loader_cJSON_GetStringValue(app_key);
  772|  4.11k|            if (app_key_str && strcmp(current_process_path, app_key_str) == 0) {
  ------------------
  |  Branch (772:17): [True: 2.36k, False: 1.75k]
  |  Branch (772:32): [True: 0, False: 2.36k]
  ------------------
  773|      0|                settings_to_use = settings_object_iter;
  774|      0|                break;
  775|      0|            }
  776|  4.11k|        }
  777|       |
  778|       |        // Break if we have found a matching current_process_path
  779|  2.51k|        if (NULL != settings_to_use) {
  ------------------
  |  Branch (779:13): [True: 0, False: 2.51k]
  ------------------
  780|      0|            break;
  781|      0|        }
  782|  2.51k|    }
  783|       |
  784|       |    // No app specific settings match - either use global settings or exit
  785|  3.59k|    if (settings_to_use == NULL) {
  ------------------
  |  Branch (785:9): [True: 3.59k, False: 0]
  ------------------
  786|  3.59k|        if (global_settings == NULL) {
  ------------------
  |  Branch (786:13): [True: 520, False: 3.07k]
  ------------------
  787|    520|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0,
  788|    520|                       "Loader settings file from %s missing global settings and none of the app specific settings matched the "
  789|    520|                       "current application - no loader settings will be active",
  790|    520|                       settings_file_path);
  791|    520|            goto out;  // No global settings were found - exit
  792|  3.07k|        } else {
  793|  3.07k|            settings_to_use = global_settings;  // Global settings are present - use it
  794|  3.07k|        }
  795|  3.59k|    }
  796|       |
  797|       |    // optional
  798|  3.07k|    cJSON* stderr_filter = loader_cJSON_GetObjectItem(settings_to_use, "stderr_log");
  799|  3.07k|    if (NULL != stderr_filter) {
  ------------------
  |  Branch (799:9): [True: 1.21k, False: 1.86k]
  ------------------
  800|  1.21k|        struct loader_string_list stderr_log = {0};
  801|  1.21k|        VkResult stderr_log_result = VK_SUCCESS;
  802|  1.21k|        stderr_log_result = loader_parse_json_array_of_strings(inst, settings_to_use, "stderr_log", &stderr_log);
  803|  1.21k|        if (VK_ERROR_OUT_OF_HOST_MEMORY == stderr_log_result) {
  ------------------
  |  Branch (803:13): [True: 0, False: 1.21k]
  ------------------
  804|      0|            res = VK_ERROR_OUT_OF_HOST_MEMORY;
  805|      0|            goto out;
  806|      0|        }
  807|  1.21k|        loader_settings->debug_level = parse_log_filters_from_strings(&stderr_log);
  808|  1.21k|        free_string_list(inst, &stderr_log);
  809|  1.21k|    }
  810|       |
  811|       |    // optional
  812|  3.07k|    cJSON* logs_to_use = loader_cJSON_GetObjectItem(settings_to_use, "log_locations");
  813|  3.07k|    if (NULL != logs_to_use) {
  ------------------
  |  Branch (813:9): [True: 175, False: 2.90k]
  ------------------
  814|    175|        cJSON* log_element = NULL;
  815|  7.38k|        cJSON_ArrayForEach(log_element, logs_to_use) {
  ------------------
  |  |  213|  7.55k|    for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
  |  |  ------------------
  |  |  |  Branch (213:20): [True: 175, False: 0]
  |  |  |  Branch (213:61): [True: 7.38k, False: 175]
  |  |  ------------------
  ------------------
  816|       |            // bool is_valid = true;
  817|  7.38k|            struct loader_string_list log_destinations = {0};
  818|  7.38k|            VkResult parse_dest_res = loader_parse_json_array_of_strings(inst, log_element, "destinations", &log_destinations);
  819|  7.38k|            if (parse_dest_res != VK_SUCCESS) {
  ------------------
  |  Branch (819:17): [True: 7.37k, False: 1]
  ------------------
  820|       |                // is_valid = false;
  821|  7.37k|            }
  822|  7.38k|            free_string_list(inst, &log_destinations);
  823|  7.38k|            struct loader_string_list log_filters = {0};
  824|  7.38k|            VkResult parse_filters_res = loader_parse_json_array_of_strings(inst, log_element, "filters", &log_filters);
  825|  7.38k|            if (parse_filters_res != VK_SUCCESS) {
  ------------------
  |  Branch (825:17): [True: 5.63k, False: 1.74k]
  ------------------
  826|       |                // is_valid = false;
  827|  5.63k|            }
  828|  7.38k|            free_string_list(inst, &log_filters);
  829|  7.38k|        }
  830|    175|    }
  831|       |
  832|  3.07k|    VkResult layer_configurations_res = parse_layer_configurations(inst, settings_to_use, loader_settings);
  833|  3.07k|    if (VK_ERROR_OUT_OF_HOST_MEMORY == layer_configurations_res) {
  ------------------
  |  Branch (833:9): [True: 0, False: 3.07k]
  ------------------
  834|      0|        res = layer_configurations_res;
  835|      0|        goto out;
  836|      0|    }
  837|       |
  838|       |    // Determine if there exists a layer configuration indicating where to put layers not contained in the settings file
  839|       |    // LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION
  840|   154k|    for (uint32_t i = 0; i < loader_settings->layer_configuration_count; i++) {
  ------------------
  |  Branch (840:26): [True: 152k, False: 2.78k]
  ------------------
  841|   152k|        if (loader_settings->layer_configurations[i].control == LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION) {
  ------------------
  |  Branch (841:13): [True: 296, False: 151k]
  ------------------
  842|    296|            loader_settings->has_unordered_layer_location = true;
  843|    296|            break;
  844|    296|        }
  845|   152k|    }
  846|       |
  847|  3.07k|    VkResult additional_drivers_res = parse_additional_drivers(inst, settings_to_use, loader_settings);
  848|  3.07k|    if (VK_ERROR_OUT_OF_HOST_MEMORY == additional_drivers_res) {
  ------------------
  |  Branch (848:9): [True: 0, False: 3.07k]
  ------------------
  849|      0|        res = additional_drivers_res;
  850|      0|        goto out;
  851|      0|    }
  852|       |
  853|  3.07k|    VkResult device_configurations_res = parse_device_configurations(inst, settings_to_use, loader_settings);
  854|  3.07k|    if (VK_ERROR_OUT_OF_HOST_MEMORY == device_configurations_res) {
  ------------------
  |  Branch (854:9): [True: 0, False: 3.07k]
  ------------------
  855|      0|        res = device_configurations_res;
  856|      0|        goto out;
  857|      0|    }
  858|       |
  859|       |    // Only consider the settings active if there is at least one "setting" active.
  860|       |    // Those are either logging, layers, additional_drivers, or device_configurations.
  861|  3.07k|    if (loader_settings->debug_level != 0 || loader_settings->layer_configurations_active ||
  ------------------
  |  Branch (861:9): [True: 397, False: 2.68k]
  |  Branch (861:46): [True: 856, False: 1.82k]
  ------------------
  862|  1.82k|        loader_settings->additional_driver_count != 0 || loader_settings->device_configurations_active) {
  ------------------
  |  Branch (862:9): [True: 0, False: 1.82k]
  |  Branch (862:58): [True: 0, False: 1.82k]
  ------------------
  863|  1.25k|        loader_settings->settings_file_path = settings_file_path;
  864|  1.25k|        settings_file_path = NULL;
  865|  1.25k|        loader_settings->settings_active = true;
  866|  1.82k|    } else {
  867|  1.82k|        loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
  868|  1.82k|                   "vk_loader_settings.json file found at \"%s\" but did not contain any valid settings.", settings_file_path);
  869|  1.82k|    }
  870|  9.40k|out:
  871|  9.40k|    if (NULL != json) {
  ------------------
  |  Branch (871:9): [True: 5.14k, False: 4.25k]
  ------------------
  872|  5.14k|        loader_cJSON_Delete(json);
  873|  5.14k|    }
  874|       |
  875|  9.40k|    loader_instance_heap_free(inst, settings_file_path);
  876|       |
  877|  9.40k|    loader_instance_heap_free(inst, file_format_version_string);
  878|  9.40k|    return res;
  879|  3.07k|}
update_global_loader_settings:
  881|  9.40k|TEST_FUNCTION_EXPORT VkResult update_global_loader_settings(void) {
  882|  9.40k|    loader_settings settings = {0};
  883|  9.40k|    VkResult res = get_loader_settings(NULL, &settings);
  884|  9.40k|    loader_platform_thread_lock_mutex(&global_loader_settings_lock);
  885|       |
  886|  9.40k|    if (res == VK_SUCCESS) {
  ------------------
  |  Branch (886:9): [True: 7.27k, False: 2.13k]
  ------------------
  887|  7.27k|        if (!check_if_settings_are_equal(&settings, &global_loader_settings)) {
  ------------------
  |  Branch (887:13): [True: 730, False: 6.54k]
  ------------------
  888|    730|            log_settings(NULL, &settings);
  889|    730|        }
  890|  7.27k|        free_loader_settings(NULL, &global_loader_settings);
  891|  7.27k|        memcpy(&global_loader_settings, &settings, sizeof(loader_settings));
  892|  7.27k|        if (global_loader_settings.settings_active && global_loader_settings.debug_level > 0) {
  ------------------
  |  Branch (892:13): [True: 1.25k, False: 6.02k]
  |  Branch (892:55): [True: 397, False: 856]
  ------------------
  893|    397|            loader_set_global_debug_level(global_loader_settings.debug_level);
  894|    397|        }
  895|  7.27k|    }
  896|  9.40k|    loader_platform_thread_unlock_mutex(&global_loader_settings_lock);
  897|  9.40k|    return res;
  898|  9.40k|}
init_global_loader_settings:
  900|      2|void init_global_loader_settings(void) {
  901|      2|    loader_platform_thread_create_mutex(&global_loader_settings_lock);
  902|       |    // Free out the global settings in case the process was loaded & unloaded
  903|       |    free_loader_settings(NULL, &global_loader_settings);
  904|      2|}
teardown_global_loader_settings:
  905|  3.13k|void teardown_global_loader_settings(void) {
  906|       |    free_loader_settings(NULL, &global_loader_settings);
  907|  3.13k|    loader_platform_thread_delete_mutex(&global_loader_settings_lock);
  908|  3.13k|}
should_skip_logging_global_messages:
  910|  3.13k|bool should_skip_logging_global_messages(VkFlags msg_type) {
  911|  3.13k|    loader_platform_thread_lock_mutex(&global_loader_settings_lock);
  912|  3.13k|    bool should_skip = global_loader_settings.settings_active && 0 != (msg_type & global_loader_settings.debug_level);
  ------------------
  |  Branch (912:24): [True: 488, False: 2.64k]
  |  Branch (912:66): [True: 0, False: 488]
  ------------------
  913|  3.13k|    loader_platform_thread_unlock_mutex(&global_loader_settings_lock);
  914|  3.13k|    return should_skip;
  915|  3.13k|}
get_current_settings_and_lock:
  920|  6.27k|const loader_settings* get_current_settings_and_lock(const struct loader_instance* inst) {
  921|  6.27k|    if (inst) {
  ------------------
  |  Branch (921:9): [True: 0, False: 6.27k]
  ------------------
  922|      0|        return &inst->settings;
  923|      0|    }
  924|  6.27k|    loader_platform_thread_lock_mutex(&global_loader_settings_lock);
  925|  6.27k|    return &global_loader_settings;
  926|  6.27k|}
release_current_settings_lock:
  928|  6.27k|void release_current_settings_lock(const struct loader_instance* inst) {
  929|  6.27k|    if (inst == NULL) {
  ------------------
  |  Branch (929:9): [True: 6.27k, False: 0]
  ------------------
  930|  6.27k|        loader_platform_thread_unlock_mutex(&global_loader_settings_lock);
  931|  6.27k|    }
  932|  6.27k|}
get_settings_layers:
  935|  3.13k|                                                  bool* should_search_for_other_layers) {
  936|  3.13k|    VkResult res = VK_SUCCESS;
  937|  3.13k|    *should_search_for_other_layers = true;  // default to true
  938|       |
  939|  3.13k|    const loader_settings* settings = get_current_settings_and_lock(inst);
  940|       |
  941|  3.13k|    if (NULL == settings || !settings->settings_active || !settings->layer_configurations_active) {
  ------------------
  |  Branch (941:9): [True: 0, False: 3.13k]
  |  Branch (941:29): [True: 2.64k, False: 488]
  |  Branch (941:59): [True: 112, False: 376]
  ------------------
  942|  2.75k|        goto out;
  943|  2.75k|    }
  944|       |
  945|       |    // Assume the list doesn't contain LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION at first
  946|    376|    *should_search_for_other_layers = false;
  947|       |
  948|   121k|    for (uint32_t i = 0; i < settings->layer_configuration_count; i++) {
  ------------------
  |  Branch (948:26): [True: 121k, False: 376]
  ------------------
  949|   121k|        loader_settings_layer_configuration* layer_config = &settings->layer_configurations[i];
  950|       |
  951|       |        // If we encountered a layer that should be forced off, we add it to the settings_layers list but only
  952|       |        // with the data required to compare it with layers not in the settings file (aka name and manifest path)
  953|   121k|        if (layer_config->control == LOADER_SETTINGS_LAYER_CONTROL_OFF) {
  ------------------
  |  Branch (953:13): [True: 114k, False: 7.01k]
  ------------------
  954|   114k|            struct loader_layer_properties props = {0};
  955|   114k|            props.settings_control_value = LOADER_SETTINGS_LAYER_CONTROL_OFF;
  956|   114k|            loader_strncpy(props.info.layerName, VK_MAX_EXTENSION_NAME_SIZE, layer_config->name, VK_MAX_EXTENSION_NAME_SIZE);
  957|   114k|            props.info.layerName[VK_MAX_EXTENSION_NAME_SIZE - 1] = '\0';
  958|   114k|            res = loader_copy_to_new_str(inst, layer_config->path, &props.manifest_file_name);
  959|   114k|            if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
  ------------------
  |  Branch (959:17): [True: 0, False: 114k]
  ------------------
  960|      0|                goto out;
  961|      0|            }
  962|   114k|            res = loader_append_layer_property(inst, settings_layers, &props);
  963|   114k|            if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
  ------------------
  |  Branch (963:17): [True: 0, False: 114k]
  ------------------
  964|      0|                loader_free_layer_properties(inst, &props);
  965|      0|                goto out;
  966|      0|            }
  967|   114k|            continue;
  968|   114k|        }
  969|       |
  970|       |        // The special layer location that indicates where unordered layers should go only should have the
  971|       |        // settings_control_value set - everything else should be NULL
  972|  7.01k|        if (layer_config->control == LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION) {
  ------------------
  |  Branch (972:13): [True: 1.18k, False: 5.83k]
  ------------------
  973|  1.18k|            struct loader_layer_properties props = {0};
  974|  1.18k|            props.settings_control_value = LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION;
  975|  1.18k|            res = loader_append_layer_property(inst, settings_layers, &props);
  976|  1.18k|            if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
  ------------------
  |  Branch (976:17): [True: 0, False: 1.18k]
  ------------------
  977|      0|                loader_free_layer_properties(inst, &props);
  978|      0|                goto out;
  979|      0|            }
  980|  1.18k|            *should_search_for_other_layers = true;
  981|  1.18k|            continue;
  982|  1.18k|        }
  983|       |
  984|  5.83k|        if (layer_config->path == NULL) {
  ------------------
  |  Branch (984:13): [True: 0, False: 5.83k]
  ------------------
  985|      0|            continue;
  986|      0|        }
  987|       |
  988|  5.83k|        if (!is_json(layer_config->path, strlen(layer_config->path))) {
  ------------------
  |  Branch (988:13): [True: 5.83k, False: 0]
  ------------------
  989|  5.83k|            continue;
  990|  5.83k|        }
  991|       |
  992|      0|        cJSON* json = NULL;
  993|      0|        VkResult local_res = loader_get_json(inst, layer_config->path, &json);
  994|      0|        if (VK_ERROR_OUT_OF_HOST_MEMORY == local_res) {
  ------------------
  |  Branch (994:13): [True: 0, False: 0]
  ------------------
  995|      0|            res = VK_ERROR_OUT_OF_HOST_MEMORY;
  996|      0|            goto out;
  997|      0|        } else if (VK_SUCCESS != local_res || NULL == json) {
  ------------------
  |  Branch (997:20): [True: 0, False: 0]
  |  Branch (997:47): [True: 0, False: 0]
  ------------------
  998|      0|            continue;
  999|      0|        }
 1000|       |
 1001|       |        // Makes it possible to know if a new layer was added or not, since the only return value is VkResult
 1002|      0|        uint32_t count_before_adding = settings_layers->count;
 1003|       |
 1004|      0|        local_res =
 1005|      0|            loader_add_layer_properties(inst, settings_layers, json, layer_config->treat_as_implicit_manifest, layer_config->path);
 1006|      0|        loader_cJSON_Delete(json);
 1007|       |
 1008|       |        // If the error is anything other than out of memory we still want to try to load the other layers
 1009|      0|        if (VK_ERROR_OUT_OF_HOST_MEMORY == local_res) {
  ------------------
  |  Branch (1009:13): [True: 0, False: 0]
  ------------------
 1010|      0|            res = VK_ERROR_OUT_OF_HOST_MEMORY;
 1011|      0|            goto out;
 1012|      0|        } else if (local_res != VK_SUCCESS || count_before_adding == settings_layers->count) {
  ------------------
  |  Branch (1012:20): [True: 0, False: 0]
  |  Branch (1012:47): [True: 0, False: 0]
  ------------------
 1013|       |            // Indicates something was wrong with the layer, can't add it to the list
 1014|      0|            continue;
 1015|      0|        }
 1016|       |
 1017|      0|        for (uint32_t j = count_before_adding; j < settings_layers->count; j++) {
  ------------------
  |  Branch (1017:48): [True: 0, False: 0]
  ------------------
 1018|      0|            struct loader_layer_properties* newly_added_layer = &settings_layers->list[j];
 1019|      0|            newly_added_layer->settings_control_value = layer_config->control;
 1020|       |            // If the manifest file found has a name that differs from the one in the settings, remove this layer from
 1021|       |            // consideration
 1022|      0|            if (strncmp(newly_added_layer->info.layerName, layer_config->name, VK_MAX_EXTENSION_NAME_SIZE) != 0) {
  ------------------
  |  Branch (1022:17): [True: 0, False: 0]
  ------------------
 1023|      0|                loader_remove_layer_in_list(inst, settings_layers, j);
 1024|      0|                j--;
 1025|      0|                continue;
 1026|      0|            }
 1027|      0|            bool should_remove = false;
 1028|       |            // Make sure the layer isn't already in the list
 1029|      0|            for (uint32_t k = 0; k < j; k++) {
  ------------------
  |  Branch (1029:34): [True: 0, False: 0]
  ------------------
 1030|      0|                if (0 == strncmp(settings_layers->list[k].info.layerName, newly_added_layer->info.layerName,
  ------------------
  |  Branch (1030:21): [True: 0, False: 0]
  ------------------
 1031|      0|                                 VK_MAX_EXTENSION_NAME_SIZE)) {
 1032|      0|                    if (0 == (newly_added_layer->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER) &&
  ------------------
  |  Branch (1032:25): [True: 0, False: 0]
  ------------------
 1033|      0|                        settings_layers->list[k].lib_name != NULL && newly_added_layer->lib_name != NULL &&
  ------------------
  |  Branch (1033:25): [True: 0, False: 0]
  |  Branch (1033:70): [True: 0, False: 0]
  ------------------
 1034|      0|                        strcmp(settings_layers->list[k].lib_name, newly_added_layer->lib_name) == 0) {
  ------------------
  |  Branch (1034:25): [True: 0, False: 0]
  ------------------
 1035|      0|                        should_remove = true;
 1036|      0|                        break;
 1037|      0|                    }
 1038|      0|                }
 1039|      0|            }
 1040|      0|            if (should_remove) {
  ------------------
  |  Branch (1040:17): [True: 0, False: 0]
  ------------------
 1041|      0|                loader_remove_layer_in_list(inst, settings_layers, j);
 1042|      0|                j--;
 1043|      0|            }
 1044|      0|        }
 1045|      0|    }
 1046|       |
 1047|  3.13k|out:
 1048|  3.13k|    release_current_settings_lock(inst);
 1049|  3.13k|    return res;
 1050|    376|}

loader.c:loader_strncpy:
  464|   114k|static inline char *loader_strncpy(char *dest, size_t dest_sz, const char *src, size_t count) {
  465|   114k|    (void)dest_sz;
  466|   114k|    return strncpy(dest, src, count);
  467|   114k|}
loader.c:loader_platform_thread_create_mutex:
  447|      4|static inline void loader_platform_thread_create_mutex(loader_platform_thread_mutex *pMutex) {
  448|      4|    pthread_mutexattr_t attr;
  449|      4|    pthread_mutexattr_init(&attr);
  450|      4|    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
  451|      4|    pthread_mutex_init(pMutex, &attr);
  452|      4|}
log.c:loader_strncat:
  460|  2.43M|static inline char *loader_strncat(char *dest, size_t dest_sz, const char *src, size_t count) {
  461|  2.43M|    (void)dest_sz;
  462|  2.43M|    return strncat(dest, src, count);
  463|  2.43M|}
settings.c:loader_strncpy:
  464|   139k|static inline char *loader_strncpy(char *dest, size_t dest_sz, const char *src, size_t count) {
  465|   139k|    (void)dest_sz;
  466|   139k|    return strncpy(dest, src, count);
  467|   139k|}
settings.c:loader_strncat:
  460|  25.3k|static inline char *loader_strncat(char *dest, size_t dest_sz, const char *src, size_t count) {
  461|  25.3k|    (void)dest_sz;
  462|  25.3k|    return strncat(dest, src, count);
  463|  25.3k|}
settings.c:loader_platform_file_exists:
  285|  25.3k|static inline bool loader_platform_file_exists(const char *path) {
  286|  25.3k|    if (access(path, F_OK))
  ------------------
  |  Branch (286:9): [True: 17.2k, False: 8.10k]
  ------------------
  287|  17.2k|        return false;
  288|  8.10k|    else
  289|  8.10k|        return true;
  290|  25.3k|}
settings.c:loader_platform_executable_path:
  306|  3.59k|static inline char *loader_platform_executable_path(char *buffer, size_t size) {
  307|  3.59k|    ssize_t count = readlink("/proc/self/exe", buffer, size);
  308|  3.59k|    if (count == -1) return NULL;
  ------------------
  |  Branch (308:9): [True: 0, False: 3.59k]
  ------------------
  309|  3.59k|    if (count == 0) return NULL;
  ------------------
  |  Branch (309:9): [True: 0, False: 3.59k]
  ------------------
  310|       |    // readlink does not append a null terminator and returns up to size bytes, so a target of size or more
  311|       |    // would leave no room for the terminator and buffer[count] would write past the end.
  312|  3.59k|    if ((size_t)count >= size) return NULL;
  ------------------
  |  Branch (312:9): [True: 0, False: 3.59k]
  ------------------
  313|  3.59k|    buffer[count] = '\0';
  314|  3.59k|    return buffer;
  315|  3.59k|}
settings.c:loader_platform_thread_lock_mutex:
  453|  18.8k|static inline void loader_platform_thread_lock_mutex(loader_platform_thread_mutex *pMutex) { pthread_mutex_lock(pMutex); }
settings.c:loader_platform_thread_unlock_mutex:
  454|  18.8k|static inline void loader_platform_thread_unlock_mutex(loader_platform_thread_mutex *pMutex) { pthread_mutex_unlock(pMutex); }
settings.c:loader_platform_thread_create_mutex:
  447|      2|static inline void loader_platform_thread_create_mutex(loader_platform_thread_mutex *pMutex) {
  448|      2|    pthread_mutexattr_t attr;
  449|      2|    pthread_mutexattr_init(&attr);
  450|      2|    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
  451|      2|    pthread_mutex_init(pMutex, &attr);
  452|      2|}
settings.c:loader_platform_thread_delete_mutex:
  455|  3.13k|static inline void loader_platform_thread_delete_mutex(loader_platform_thread_mutex *pMutex) { pthread_mutex_destroy(pMutex); }

