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

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

loader_calloc:
   51|  10.0M|void *loader_calloc(const VkAllocationCallbacks *pAllocator, size_t size, VkSystemAllocationScope allocation_scope) {
   52|  10.0M|    void *pMemory = NULL;
   53|       |#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
   54|       |    {
   55|       |#else
   56|  10.0M|    if (pAllocator && pAllocator->pfnAllocation) {
  ------------------
  |  Branch (56:9): [True: 0, False: 10.0M]
  |  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|  10.0M|    } else {
   64|  10.0M|#endif
   65|  10.0M|        pMemory = calloc(1, size);
   66|  10.0M|    }
   67|       |
   68|  10.0M|    return pMemory;
   69|  10.0M|}
loader_free:
   71|  12.3M|void loader_free(const VkAllocationCallbacks *pAllocator, void *pMemory) {
   72|  12.3M|    if (pMemory != NULL) {
  ------------------
  |  Branch (72:9): [True: 10.0M, False: 2.23M]
  ------------------
   73|       |#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
   74|       |        {
   75|       |#else
   76|  10.0M|        if (pAllocator && pAllocator->pfnFree) {
  ------------------
  |  Branch (76:13): [True: 0, False: 10.0M]
  |  Branch (76:27): [True: 0, False: 0]
  ------------------
   77|      0|            pAllocator->pfnFree(pAllocator->pUserData, pMemory);
   78|  10.0M|        } else {
   79|  10.0M|#endif
   80|  10.0M|            free(pMemory);
   81|  10.0M|        }
   82|  10.0M|    }
   83|  12.3M|}
loader_realloc:
   86|  2.04M|                     VkSystemAllocationScope allocation_scope) {
   87|  2.04M|    void *pNewMem = NULL;
   88|  2.04M|    if (pMemory == NULL || orig_size == 0) {
  ------------------
  |  Branch (88:9): [True: 0, False: 2.04M]
  |  Branch (88:28): [True: 0, False: 2.04M]
  ------------------
   89|      0|        pNewMem = loader_alloc(pAllocator, size, allocation_scope);
   90|  2.04M|    } else if (size == 0) {
  ------------------
  |  Branch (90:16): [True: 0, False: 2.04M]
  ------------------
   91|      0|        loader_free(pAllocator, pMemory);
   92|       |#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
   93|       |#else
   94|  2.04M|    } else if (pAllocator && pAllocator->pfnReallocation) {
  ------------------
  |  Branch (94:16): [True: 0, False: 2.04M]
  |  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|  2.04M|    } else {
  100|  2.04M|        pNewMem = realloc(pMemory, size);
  101|       |        // Clear out the newly allocated memory
  102|  2.04M|        if (size > orig_size) {
  ------------------
  |  Branch (102:13): [True: 2.46k, False: 2.04M]
  ------------------
  103|  2.46k|            memset((uint8_t *)pNewMem + orig_size, 0, size - orig_size);
  104|  2.46k|        }
  105|  2.04M|    }
  106|  2.04M|    return pNewMem;
  107|  2.04M|}
loader_instance_heap_calloc:
  113|   197k|void *loader_instance_heap_calloc(const struct loader_instance *inst, size_t size, VkSystemAllocationScope allocation_scope) {
  114|   197k|    return loader_calloc(inst ? &inst->alloc_callbacks : NULL, size, allocation_scope);
  ------------------
  |  Branch (114:26): [True: 0, False: 197k]
  ------------------
  115|   197k|}
loader_instance_heap_free:
  117|  4.47M|void loader_instance_heap_free(const struct loader_instance *inst, void *pMemory) {
  118|  4.47M|    loader_free(inst ? &inst->alloc_callbacks : NULL, pMemory);
  ------------------
  |  Branch (118:17): [True: 0, False: 4.47M]
  ------------------
  119|  4.47M|}
loader_instance_heap_realloc:
  121|    238|                                   VkSystemAllocationScope allocation_scope) {
  122|    238|    return loader_realloc(inst ? &inst->alloc_callbacks : NULL, pMemory, orig_size, size, allocation_scope);
  ------------------
  |  Branch (122:27): [True: 0, False: 238]
  ------------------
  123|    238|}

loader_cJSON_GetStringValue:
   98|  19.8k|CJSON_PUBLIC(char *) loader_cJSON_GetStringValue(const cJSON *const item) {
   99|  19.8k|    if (!loader_cJSON_IsString(item)) {
  ------------------
  |  Branch (99:9): [True: 8.63k, False: 11.2k]
  ------------------
  100|  8.63k|        return NULL;
  101|  8.63k|    }
  102|       |
  103|  11.2k|    return item->valuestring;
  104|  19.8k|}
loader_cJSON_Delete:
  151|   636k|TEST_FUNCTION_EXPORT CJSON_PUBLIC(void) loader_cJSON_Delete(cJSON *item) {
  152|   636k|    cJSON *next = NULL;
  153|  4.72M|    while (item != NULL) {
  ------------------
  |  Branch (153:12): [True: 4.08M, False: 636k]
  ------------------
  154|  4.08M|        next = item->next;
  155|  4.08M|        if (!(item->type & cJSON_IsReference) && (item->child != NULL)) {
  ------------------
  |  |  106|  4.08M|#define cJSON_IsReference 256
  ------------------
  |  Branch (155:13): [True: 4.08M, False: 0]
  |  Branch (155:50): [True: 477k, False: 3.61M]
  ------------------
  156|   477k|            loader_cJSON_Delete(item->child);
  157|   477k|        }
  158|  4.08M|        if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) {
  ------------------
  |  |  106|  4.08M|#define cJSON_IsReference 256
  ------------------
  |  Branch (158:13): [True: 4.08M, False: 0]
  |  Branch (158:50): [True: 2.43M, False: 1.65M]
  ------------------
  159|  2.43M|            loader_free(item->pAllocator, item->valuestring);
  160|  2.43M|            item->valuestring = NULL;
  161|  2.43M|        }
  162|  4.08M|        if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) {
  ------------------
  |  |  107|  4.08M|#define cJSON_StringIsConst 512
  ------------------
  |  Branch (162:13): [True: 4.08M, False: 0]
  |  Branch (162:52): [True: 1.32M, False: 2.76M]
  ------------------
  163|  1.32M|            loader_free(item->pAllocator, item->string);
  164|       |            item->string = NULL;
  165|  1.32M|        }
  166|  4.08M|        loader_free(item->pAllocator, item);
  167|  4.08M|        item = next;
  168|  4.08M|    }
  169|   636k|}
loader_cJSON_ParseWithLengthOpts:
  821|  9.24k|                                 const char **return_parse_end, cJSON_bool require_null_terminated, bool *out_of_memory) {
  822|  9.24k|    parse_buffer buffer = {0, 0, 0, 0, 0};
  823|  9.24k|    cJSON *item = NULL;
  824|       |
  825|       |    /* reset error position */
  826|       |    // global_error.json = NULL;
  827|       |    // global_error.position = 0;
  828|       |
  829|  9.24k|    if (value == NULL || 0 == buffer_length) {
  ------------------
  |  Branch (829:9): [True: 0, False: 9.24k]
  |  Branch (829:26): [True: 0, False: 9.24k]
  ------------------
  830|      0|        goto fail;
  831|      0|    }
  832|       |
  833|  9.24k|    buffer.content = (const unsigned char *)value;
  834|  9.24k|    buffer.length = buffer_length;
  835|  9.24k|    buffer.offset = 0;
  836|  9.24k|    buffer.pAllocator = pAllocator;
  837|       |
  838|  9.24k|    item = cJSON_New_Item(pAllocator);
  839|  9.24k|    if (item == NULL) /* memory fail */
  ------------------
  |  Branch (839:9): [True: 0, False: 9.24k]
  ------------------
  840|      0|    {
  841|      0|        *out_of_memory = true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
  842|      0|        goto fail;
  843|      0|    }
  844|       |
  845|  9.24k|    if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer)), out_of_memory)) {
  ------------------
  |  Branch (845:9): [True: 4.33k, False: 4.91k]
  ------------------
  846|       |        /* parse failure. ep is set. */
  847|  4.33k|        goto fail;
  848|  4.33k|    }
  849|       |
  850|       |    /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
  851|  4.91k|    if (require_null_terminated) {
  ------------------
  |  Branch (851:9): [True: 0, False: 4.91k]
  ------------------
  852|      0|        buffer_skip_whitespace(&buffer);
  853|      0|        if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0') {
  ------------------
  |  |  195|      0|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (853:13): [True: 0, False: 0]
  |  Branch (853:49): [True: 0, False: 0]
  ------------------
  854|      0|            goto fail;
  855|      0|        }
  856|      0|    }
  857|  4.91k|    if (return_parse_end) {
  ------------------
  |  Branch (857:9): [True: 0, False: 4.91k]
  ------------------
  858|      0|        *return_parse_end = (const char *)buffer_at_offset(&buffer);
  ------------------
  |  |  195|      0|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  859|      0|    }
  860|       |
  861|  4.91k|    return item;
  862|       |
  863|  4.33k|fail:
  864|  4.33k|    if (item != NULL) {
  ------------------
  |  Branch (864:9): [True: 4.33k, False: 0]
  ------------------
  865|  4.33k|        loader_cJSON_Delete(item);
  866|  4.33k|    }
  867|       |
  868|  4.33k|    if (value != NULL) {
  ------------------
  |  Branch (868:9): [True: 4.33k, False: 0]
  ------------------
  869|  4.33k|        error local_error;
  870|  4.33k|        local_error.json = (const unsigned char *)value;
  871|  4.33k|        local_error.position = 0;
  872|       |
  873|  4.33k|        if (buffer.offset < buffer.length) {
  ------------------
  |  Branch (873:13): [True: 4.06k, False: 272]
  ------------------
  874|  4.06k|            local_error.position = buffer.offset;
  875|  4.06k|        } else if (buffer.length > 0) {
  ------------------
  |  Branch (875:20): [True: 272, False: 0]
  ------------------
  876|    272|            local_error.position = buffer.length - 1;
  877|    272|        }
  878|       |
  879|  4.33k|        if (return_parse_end != NULL) {
  ------------------
  |  Branch (879:13): [True: 0, False: 4.33k]
  ------------------
  880|      0|            *return_parse_end = (const char *)local_error.json + local_error.position;
  881|      0|        }
  882|       |
  883|       |        // global_error = local_error;
  884|  4.33k|    }
  885|       |
  886|       |    return NULL;
  887|  4.91k|}
loader_cJSON_ParseWithLength:
  896|  9.24k|                             bool *out_of_memory) {
  897|  9.24k|    return loader_cJSON_ParseWithLengthOpts(pAllocator, value, buffer_length, 0, 0, out_of_memory);
  898|  9.24k|}
loader_cJSON_Print:
  950|  2.04M|TEST_FUNCTION_EXPORT CJSON_PUBLIC(char *) loader_cJSON_Print(const cJSON *item, bool *out_of_memory) {
  951|  2.04M|    return (char *)print(item, true, out_of_memory);
  ------------------
  |  |   67|  2.04M|#define true ((cJSON_bool)1)
  ------------------
  952|  2.04M|}
loader_cJSON_PrintPreallocated:
  987|  8.87k|loader_cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format) {
  988|  8.87k|    printbuffer p = {0, 0, 0, 0, 0, 0, 0};
  989|       |
  990|  8.87k|    if ((length < 0) || (buffer == NULL)) {
  ------------------
  |  Branch (990:9): [True: 0, False: 8.87k]
  |  Branch (990:25): [True: 0, False: 8.87k]
  ------------------
  991|      0|        return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
  992|      0|    }
  993|       |
  994|  8.87k|    p.buffer = (unsigned char *)buffer;
  995|  8.87k|    p.length = (size_t)length;
  996|  8.87k|    p.offset = 0;
  997|  8.87k|    p.noalloc = true;
  ------------------
  |  |   67|  8.87k|#define true ((cJSON_bool)1)
  ------------------
  998|  8.87k|    p.format = format;
  999|  8.87k|    p.pAllocator = item->pAllocator;
 1000|  8.87k|    bool out_of_memory = false;
  ------------------
  |  |   72|  8.87k|#define false ((cJSON_bool)0)
  ------------------
 1001|  8.87k|    return print_value(item, &p, &out_of_memory);
 1002|  8.87k|}
loader_cJSON_GetArraySize:
 1454|  7.93k|CJSON_PUBLIC(int) loader_cJSON_GetArraySize(const cJSON *array) {
 1455|  7.93k|    cJSON *child = NULL;
 1456|  7.93k|    size_t size = 0;
 1457|       |
 1458|  7.93k|    if (array == NULL) {
  ------------------
  |  Branch (1458:9): [True: 0, False: 7.93k]
  ------------------
 1459|      0|        return 0;
 1460|      0|    }
 1461|       |
 1462|  7.93k|    child = array->child;
 1463|       |
 1464|  1.66M|    while (child != NULL) {
  ------------------
  |  Branch (1464:12): [True: 1.65M, False: 7.93k]
  ------------------
 1465|  1.65M|        size++;
 1466|  1.65M|        child = child->next;
 1467|  1.65M|    }
 1468|       |
 1469|       |    /* FIXME: Can overflow here. Cannot be fixed without breaking the API */
 1470|       |
 1471|  7.93k|    return (int)size;
 1472|  7.93k|}
loader_cJSON_GetObjectItem:
 1524|  1.30M|CJSON_PUBLIC(cJSON *) loader_cJSON_GetObjectItem(const cJSON *const object, const char *const string) {
 1525|  1.30M|    return get_object_item(object, string, false);
  ------------------
  |  |   72|  1.30M|#define false ((cJSON_bool)0)
  ------------------
 1526|  1.30M|}
loader_cJSON_IsString:
 1667|  19.8k|CJSON_PUBLIC(cJSON_bool) loader_cJSON_IsString(const cJSON *const item) {
 1668|  19.8k|    if (item == NULL) {
  ------------------
  |  Branch (1668:9): [True: 7.23k, False: 12.5k]
  ------------------
 1669|  7.23k|        return false;
  ------------------
  |  |   72|  7.23k|#define false ((cJSON_bool)0)
  ------------------
 1670|  7.23k|    }
 1671|       |
 1672|  12.5k|    return (item->type & 0xFF) == cJSON_String;
  ------------------
  |  |  101|  12.5k|#define cJSON_String (1 << 4)
  ------------------
 1673|  19.8k|}
cJSON.c:cJSON_New_Item:
  142|  4.08M|static cJSON *cJSON_New_Item(const VkAllocationCallbacks *pAllocator) {
  143|  4.08M|    cJSON *node = (cJSON *)loader_calloc(pAllocator, sizeof(cJSON), VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
  144|  4.08M|    if (NULL != node) {
  ------------------
  |  Branch (144:9): [True: 4.08M, False: 0]
  ------------------
  145|  4.08M|        node->pAllocator = pAllocator;
  146|  4.08M|    }
  147|  4.08M|    return node;
  148|  4.08M|}
cJSON.c:buffer_skip_whitespace:
  769|  11.3M|static parse_buffer *buffer_skip_whitespace(parse_buffer *const buffer) {
  770|  11.3M|    if ((buffer == NULL) || (buffer->content == NULL)) {
  ------------------
  |  Branch (770:9): [True: 0, False: 11.3M]
  |  Branch (770:29): [True: 0, False: 11.3M]
  ------------------
  771|      0|        return NULL;
  772|      0|    }
  773|       |
  774|  11.3M|    if (cannot_access_at_index(buffer, 0)) {
  ------------------
  |  |  193|  11.3M|#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
  |  |  ------------------
  |  |  |  |  192|  11.3M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (192:45): [True: 11.3M, False: 0]
  |  |  |  |  |  Branch (192:65): [True: 11.3M, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  775|      0|        return buffer;
  776|      0|    }
  777|       |
  778|  15.0M|    while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) {
  ------------------
  |  |  192|  30.1M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 15.0M, False: 0]
  |  |  |  Branch (192:65): [True: 15.0M, False: 2.51k]
  |  |  ------------------
  ------------------
                  while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) {
  ------------------
  |  |  195|  15.0M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (778:46): [True: 3.75M, False: 11.3M]
  ------------------
  779|  3.75M|        buffer->offset++;
  780|  3.75M|    }
  781|       |
  782|  11.3M|    if (buffer->offset == buffer->length) {
  ------------------
  |  Branch (782:9): [True: 2.51k, False: 11.3M]
  ------------------
  783|  2.51k|        buffer->offset--;
  784|  2.51k|    }
  785|       |
  786|  11.3M|    return buffer;
  787|  11.3M|}
cJSON.c:skip_utf8_bom:
  790|  9.24k|static parse_buffer *skip_utf8_bom(parse_buffer *const buffer) {
  791|  9.24k|    if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0)) {
  ------------------
  |  Branch (791:9): [True: 0, False: 9.24k]
  |  Branch (791:29): [True: 0, False: 9.24k]
  |  Branch (791:58): [True: 0, False: 9.24k]
  ------------------
  792|      0|        return NULL;
  793|      0|    }
  794|       |
  795|  9.24k|    if (can_access_at_index(buffer, 4) && (strncmp((const char *)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0)) {
  ------------------
  |  |  192|  18.4k|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 9.24k, False: 0]
  |  |  |  Branch (192:65): [True: 7.88k, False: 1.36k]
  |  |  ------------------
  ------------------
                  if (can_access_at_index(buffer, 4) && (strncmp((const char *)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0)) {
  ------------------
  |  |  195|  7.88k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (795:43): [True: 115, False: 7.76k]
  ------------------
  796|    115|        buffer->offset += 3;
  797|    115|    }
  798|       |
  799|  9.24k|    return buffer;
  800|  9.24k|}
cJSON.c:print:
  902|  2.04M|static unsigned char *print(const cJSON *const item, cJSON_bool format, bool *out_of_memory) {
  903|  2.04M|    static const size_t default_buffer_size = 256;
  904|  2.04M|    printbuffer buffer[1];
  905|  2.04M|    unsigned char *printed = NULL;
  906|       |
  907|  2.04M|    memset(buffer, 0, sizeof(buffer));
  908|       |
  909|       |    /* create buffer */
  910|  2.04M|    buffer->buffer = (unsigned char *)loader_calloc(item->pAllocator, default_buffer_size, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  911|  2.04M|    buffer->length = default_buffer_size;
  912|  2.04M|    buffer->format = format;
  913|  2.04M|    buffer->pAllocator = item->pAllocator;
  914|  2.04M|    if (buffer->buffer == NULL) {
  ------------------
  |  Branch (914:9): [True: 0, False: 2.04M]
  ------------------
  915|      0|        *out_of_memory = true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
  916|      0|        goto fail;
  917|      0|    }
  918|       |
  919|       |    /* print the value */
  920|  2.04M|    if (!print_value(item, buffer, out_of_memory)) {
  ------------------
  |  Branch (920:9): [True: 0, False: 2.04M]
  ------------------
  921|      0|        goto fail;
  922|      0|    }
  923|  2.04M|    update_offset(buffer);
  924|       |
  925|  2.04M|    printed = (unsigned char *)loader_realloc(item->pAllocator, buffer->buffer, buffer->length, buffer->offset + 1,
  926|  2.04M|                                              VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  927|  2.04M|    if (printed == NULL) {
  ------------------
  |  Branch (927:9): [True: 0, False: 2.04M]
  ------------------
  928|      0|        *out_of_memory = true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
  929|      0|        goto fail;
  930|      0|    }
  931|  2.04M|    buffer->buffer = NULL;
  932|       |
  933|  2.04M|    return printed;
  934|       |
  935|      0|fail:
  936|      0|    if (buffer->buffer != NULL) {
  ------------------
  |  Branch (936:9): [True: 0, False: 0]
  ------------------
  937|      0|        loader_free(item->pAllocator, buffer->buffer);
  938|      0|        buffer->buffer = NULL;
  939|      0|    }
  940|       |
  941|      0|    if (printed != NULL) {
  ------------------
  |  Branch (941:9): [True: 0, False: 0]
  ------------------
  942|      0|        loader_free(item->pAllocator, printed);
  943|      0|        printed = NULL;
  944|      0|    }
  945|       |
  946|       |    return NULL;
  947|  2.04M|}
cJSON.c:update_offset:
  331|  2.04M|static void update_offset(printbuffer *const buffer) {
  332|  2.04M|    const unsigned char *buffer_pointer = NULL;
  333|  2.04M|    if ((buffer == NULL) || (buffer->buffer == NULL)) {
  ------------------
  |  Branch (333:9): [True: 0, False: 2.04M]
  |  Branch (333:29): [True: 0, False: 2.04M]
  ------------------
  334|      0|        return;
  335|      0|    }
  336|  2.04M|    buffer_pointer = buffer->buffer + buffer->offset;
  337|       |
  338|  2.04M|    buffer->offset += strlen((const char *)buffer_pointer);
  339|  2.04M|}
cJSON.c:parse_value:
 1005|  4.08M|static cJSON_bool parse_value(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory) {
 1006|  4.08M|    if ((input_buffer == NULL) || (input_buffer->content == NULL)) {
  ------------------
  |  Branch (1006:9): [True: 0, False: 4.08M]
  |  Branch (1006:35): [True: 0, False: 4.08M]
  ------------------
 1007|      0|        return false; /* no input */
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1008|      0|    }
 1009|       |
 1010|       |    /* parse the different types of values */
 1011|       |    /* null */
 1012|  4.08M|    if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "null", 4) == 0)) {
  ------------------
  |  |  190|  8.17M|#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (190:33): [True: 4.08M, False: 0]
  |  |  |  Branch (190:53): [True: 4.08M, False: 2.69k]
  |  |  ------------------
  ------------------
                  if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "null", 4) == 0)) {
  ------------------
  |  |  195|  4.08M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1012:38): [True: 1.37k, False: 4.08M]
  ------------------
 1013|  1.37k|        item->type = cJSON_NULL;
  ------------------
  |  |   99|  1.37k|#define cJSON_NULL (1 << 2)
  ------------------
 1014|  1.37k|        input_buffer->offset += 4;
 1015|  1.37k|        return true;
  ------------------
  |  |   67|  1.37k|#define true ((cJSON_bool)1)
  ------------------
 1016|  1.37k|    }
 1017|       |    /* false */
 1018|  4.08M|    if (can_read(input_buffer, 5) && (strncmp((const char *)buffer_at_offset(input_buffer), "false", 5) == 0)) {
  ------------------
  |  |  190|  8.17M|#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (190:33): [True: 4.08M, False: 0]
  |  |  |  Branch (190:53): [True: 4.08M, False: 3.35k]
  |  |  ------------------
  ------------------
                  if (can_read(input_buffer, 5) && (strncmp((const char *)buffer_at_offset(input_buffer), "false", 5) == 0)) {
  ------------------
  |  |  195|  4.08M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1018:38): [True: 1.14k, False: 4.08M]
  ------------------
 1019|  1.14k|        item->type = cJSON_False;
  ------------------
  |  |   97|  1.14k|#define cJSON_False (1 << 0)
  ------------------
 1020|  1.14k|        input_buffer->offset += 5;
 1021|  1.14k|        return true;
  ------------------
  |  |   67|  1.14k|#define true ((cJSON_bool)1)
  ------------------
 1022|  1.14k|    }
 1023|       |    /* true */
 1024|  4.08M|    if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "true", 4) == 0)) {
  ------------------
  |  |  190|  8.17M|#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (190:33): [True: 4.08M, False: 0]
  |  |  |  Branch (190:53): [True: 4.08M, False: 2.69k]
  |  |  ------------------
  ------------------
                  if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "true", 4) == 0)) {
  ------------------
  |  |  195|  4.08M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1024:38): [True: 9.43k, False: 4.07M]
  ------------------
 1025|  9.43k|        item->type = cJSON_True;
  ------------------
  |  |   98|  9.43k|#define cJSON_True (1 << 1)
  ------------------
 1026|  9.43k|        item->valueint = 1;
 1027|  9.43k|        input_buffer->offset += 4;
 1028|  9.43k|        return true;
  ------------------
  |  |   67|  9.43k|#define true ((cJSON_bool)1)
  ------------------
 1029|  9.43k|    }
 1030|       |    /* string */
 1031|  4.07M|    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) {
  ------------------
  |  |  192|  8.15M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 4.07M, False: 0]
  |  |  |  Branch (192:65): [True: 4.07M, False: 0]
  |  |  ------------------
  ------------------
                  if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) {
  ------------------
  |  |  195|  4.07M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1031:49): [True: 2.43M, False: 1.64M]
  ------------------
 1032|  2.43M|        return parse_string(item, input_buffer, out_of_memory);
 1033|  2.43M|    }
 1034|       |    /* number */
 1035|  1.64M|    if (can_access_at_index(input_buffer, 0) &&
  ------------------
  |  |  192|  3.28M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 1.64M, False: 0]
  |  |  |  Branch (192:65): [True: 1.64M, False: 0]
  |  |  ------------------
  ------------------
 1036|  1.64M|        ((buffer_at_offset(input_buffer)[0] == '-') ||
  ------------------
  |  |  195|  1.64M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1036:10): [True: 132k, False: 1.51M]
  ------------------
 1037|  1.51M|         ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9')))) {
  ------------------
  |  |  195|  1.51M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
                       ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9')))) {
  ------------------
  |  |  195|  1.50M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1037:11): [True: 1.50M, False: 1.34k]
  |  Branch (1037:57): [True: 862k, False: 646k]
  ------------------
 1038|   995k|        return parse_number(item, input_buffer);
 1039|   995k|    }
 1040|       |    /* array */
 1041|   647k|    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '[')) {
  ------------------
  |  |  192|  1.29M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 647k, False: 0]
  |  |  |  Branch (192:65): [True: 647k, False: 0]
  |  |  ------------------
  ------------------
                  if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '[')) {
  ------------------
  |  |  195|   647k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1041:49): [True: 166k, False: 481k]
  ------------------
 1042|   166k|        return parse_array(item, input_buffer, out_of_memory);
 1043|   166k|    }
 1044|       |    /* object */
 1045|   481k|    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) {
  ------------------
  |  |  192|   962k|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 481k, False: 0]
  |  |  |  Branch (192:65): [True: 481k, False: 0]
  |  |  ------------------
  ------------------
                  if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) {
  ------------------
  |  |  195|   481k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1045:49): [True: 478k, False: 2.62k]
  ------------------
 1046|   478k|        return parse_object(item, input_buffer, out_of_memory);
 1047|   478k|    }
 1048|       |
 1049|  2.62k|    return false;
  ------------------
  |  |   72|  2.62k|#define false ((cJSON_bool)0)
  ------------------
 1050|   481k|}
cJSON.c:parse_string:
  533|  3.76M|static cJSON_bool parse_string(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory) {
  534|  3.76M|    const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1;
  ------------------
  |  |  195|  3.76M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  535|  3.76M|    const unsigned char *input_end = buffer_at_offset(input_buffer) + 1;
  ------------------
  |  |  195|  3.76M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  536|  3.76M|    unsigned char *output_pointer = NULL;
  537|  3.76M|    unsigned char *output = NULL;
  538|       |
  539|       |    /* not a string */
  540|  3.76M|    if (buffer_at_offset(input_buffer)[0] != '\"') {
  ------------------
  |  |  195|  3.76M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (540:9): [True: 305, False: 3.76M]
  ------------------
  541|    305|        goto fail;
  542|    305|    }
  543|       |
  544|  3.76M|    {
  545|       |        /* calculate approximate size of the output (overestimate) */
  546|  3.76M|        size_t allocation_length = 0;
  547|  3.76M|        size_t skipped_bytes = 0;
  548|  70.6M|        while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"')) {
  ------------------
  |  Branch (548:16): [True: 70.6M, False: 193]
  |  Branch (548:88): [True: 66.9M, False: 3.76M]
  ------------------
  549|       |            /* is escape sequence */
  550|  66.9M|            if (input_end[0] == '\\') {
  ------------------
  |  Branch (550:17): [True: 1.11M, False: 65.8M]
  ------------------
  551|  1.11M|                if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length) {
  ------------------
  |  Branch (551:21): [True: 0, False: 1.11M]
  ------------------
  552|       |                    /* prevent buffer overflow when last input character is a backslash */
  553|      0|                    goto fail;
  554|      0|                }
  555|  1.11M|                skipped_bytes++;
  556|  1.11M|                input_end++;
  557|  1.11M|            }
  558|  66.9M|            input_end++;
  559|  66.9M|        }
  560|  3.76M|        if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"')) {
  ------------------
  |  Branch (560:13): [True: 193, False: 3.76M]
  |  Branch (560:86): [True: 0, False: 3.76M]
  ------------------
  561|    193|            goto fail; /* string ended unexpectedly */
  562|    193|        }
  563|       |
  564|       |        /* This is at most how much we need for the output */
  565|  3.76M|        allocation_length = (size_t)(input_end - buffer_at_offset(input_buffer)) - skipped_bytes;
  ------------------
  |  |  195|  3.76M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  566|  3.76M|        output = (unsigned char *)loader_calloc(input_buffer->pAllocator, allocation_length + sizeof(""),
  567|  3.76M|                                                VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
  568|  3.76M|        if (output == NULL) {
  ------------------
  |  Branch (568:13): [True: 0, False: 3.76M]
  ------------------
  569|      0|            *out_of_memory = true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
  570|      0|            goto fail; /* allocation failure */
  571|      0|        }
  572|  3.76M|    }
  573|       |
  574|  3.76M|    output_pointer = output;
  575|       |    /* loop through the string literal */
  576|  50.5M|    while (input_pointer < input_end) {
  ------------------
  |  Branch (576:12): [True: 46.7M, False: 3.76M]
  ------------------
  577|  46.7M|        if (*input_pointer != '\\') {
  ------------------
  |  Branch (577:13): [True: 46.1M, False: 609k]
  ------------------
  578|  46.1M|            *output_pointer++ = *input_pointer++;
  579|  46.1M|        }
  580|       |        /* escape sequence */
  581|   609k|        else {
  582|   609k|            unsigned char sequence_length = 2;
  583|   609k|            if ((input_end - input_pointer) < 1) {
  ------------------
  |  Branch (583:17): [True: 0, False: 609k]
  ------------------
  584|      0|                goto fail;
  585|      0|            }
  586|       |
  587|   609k|            switch (input_pointer[1]) {
  588|  1.04k|                case 'b':
  ------------------
  |  Branch (588:17): [True: 1.04k, False: 608k]
  ------------------
  589|  1.04k|                    *output_pointer++ = '\b';
  590|  1.04k|                    break;
  591|  7.39k|                case 'f':
  ------------------
  |  Branch (591:17): [True: 7.39k, False: 601k]
  ------------------
  592|  7.39k|                    *output_pointer++ = '\f';
  593|  7.39k|                    break;
  594|  1.05k|                case 'n':
  ------------------
  |  Branch (594:17): [True: 1.05k, False: 608k]
  ------------------
  595|  1.05k|                    *output_pointer++ = '\n';
  596|  1.05k|                    break;
  597|  1.39k|                case 'r':
  ------------------
  |  Branch (597:17): [True: 1.39k, False: 607k]
  ------------------
  598|  1.39k|                    *output_pointer++ = '\r';
  599|  1.39k|                    break;
  600|  2.29k|                case 't':
  ------------------
  |  Branch (600:17): [True: 2.29k, False: 606k]
  ------------------
  601|  2.29k|                    *output_pointer++ = '\t';
  602|  2.29k|                    break;
  603|  2.37k|                case '\"':
  ------------------
  |  Branch (603:17): [True: 2.37k, False: 606k]
  ------------------
  604|  19.5k|                case '\\':
  ------------------
  |  Branch (604:17): [True: 17.1k, False: 592k]
  ------------------
  605|  20.5k|                case '/':
  ------------------
  |  Branch (605:17): [True: 976, False: 608k]
  ------------------
  606|  20.5k|                    *output_pointer++ = input_pointer[1];
  607|  20.5k|                    break;
  608|       |
  609|       |                /* UTF-16 literal */
  610|   575k|                case 'u':
  ------------------
  |  Branch (610:17): [True: 575k, False: 33.7k]
  ------------------
  611|   575k|                    sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer);
  612|   575k|                    if (sequence_length == 0) {
  ------------------
  |  Branch (612:25): [True: 268, False: 575k]
  ------------------
  613|       |                        /* failed to convert UTF16-literal to UTF-8 */
  614|    268|                        goto fail;
  615|    268|                    }
  616|   575k|                    break;
  617|       |
  618|   575k|                default:
  ------------------
  |  Branch (618:17): [True: 73, False: 609k]
  ------------------
  619|     73|                    goto fail;
  620|   609k|            }
  621|   608k|            input_pointer += sequence_length;
  622|   608k|        }
  623|  46.7M|    }
  624|       |
  625|       |    /* zero terminate the output */
  626|  3.76M|    *output_pointer = '\0';
  627|       |
  628|  3.76M|    item->type = cJSON_String;
  ------------------
  |  |  101|  3.76M|#define cJSON_String (1 << 4)
  ------------------
  629|  3.76M|    item->valuestring = (char *)output;
  630|       |
  631|  3.76M|    input_buffer->offset = (size_t)(input_end - input_buffer->content);
  632|  3.76M|    input_buffer->offset++;
  633|       |
  634|  3.76M|    return true;
  ------------------
  |  |   67|  3.76M|#define true ((cJSON_bool)1)
  ------------------
  635|       |
  636|    839|fail:
  637|    839|    if (output != NULL) {
  ------------------
  |  Branch (637:9): [True: 341, False: 498]
  ------------------
  638|    341|        loader_free(input_buffer->pAllocator, output);
  639|    341|        output = NULL;
  640|    341|    }
  641|       |
  642|    839|    if (input_pointer != NULL) {
  ------------------
  |  Branch (642:9): [True: 839, False: 0]
  ------------------
  643|    839|        input_buffer->offset = (size_t)(input_pointer - input_buffer->content);
  644|    839|    }
  645|       |
  646|    839|    return false;
  ------------------
  |  |   72|    839|#define false ((cJSON_bool)0)
  ------------------
  647|  3.76M|}
cJSON.c:utf16_literal_to_utf8:
  435|   575k|                                           unsigned char **output_pointer) {
  436|   575k|    long unsigned int codepoint = 0;
  437|   575k|    unsigned int first_code = 0;
  438|   575k|    const unsigned char *first_sequence = input_pointer;
  439|   575k|    unsigned char utf8_length = 0;
  440|   575k|    unsigned char utf8_position = 0;
  441|   575k|    unsigned char sequence_length = 0;
  442|   575k|    unsigned char first_byte_mark = 0;
  443|       |
  444|   575k|    if ((input_end - first_sequence) < 6) {
  ------------------
  |  Branch (444:9): [True: 15, False: 575k]
  ------------------
  445|       |        /* input ends unexpectedly */
  446|     15|        goto fail;
  447|     15|    }
  448|       |
  449|       |    /* get the first utf16 sequence */
  450|   575k|    first_code = parse_hex4(first_sequence + 2);
  451|       |
  452|       |    /* check that the code is valid */
  453|   575k|    if (((first_code >= 0xDC00) && (first_code <= 0xDFFF))) {
  ------------------
  |  Branch (453:10): [True: 399k, False: 176k]
  |  Branch (453:36): [True: 26, False: 399k]
  ------------------
  454|     26|        goto fail;
  455|     26|    }
  456|       |
  457|       |    /* UTF16 surrogate pair */
  458|   575k|    if ((first_code >= 0xD800) && (first_code <= 0xDBFF)) {
  ------------------
  |  Branch (458:9): [True: 403k, False: 171k]
  |  Branch (458:35): [True: 4.70k, False: 399k]
  ------------------
  459|  4.70k|        const unsigned char *second_sequence = first_sequence + 6;
  460|  4.70k|        unsigned int second_code = 0;
  461|  4.70k|        sequence_length = 12; /* \uXXXX\uXXXX */
  462|       |
  463|  4.70k|        if ((input_end - second_sequence) < 6) {
  ------------------
  |  Branch (463:13): [True: 20, False: 4.68k]
  ------------------
  464|       |            /* input ends unexpectedly */
  465|     20|            goto fail;
  466|     20|        }
  467|       |
  468|  4.68k|        if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u')) {
  ------------------
  |  Branch (468:13): [True: 62, False: 4.62k]
  |  Branch (468:45): [True: 32, False: 4.59k]
  ------------------
  469|       |            /* missing second half of the surrogate pair */
  470|     94|            goto fail;
  471|     94|        }
  472|       |
  473|       |        /* get the second utf16 sequence */
  474|  4.59k|        second_code = parse_hex4(second_sequence + 2);
  475|       |        /* check that the code is valid */
  476|  4.59k|        if ((second_code < 0xDC00) || (second_code > 0xDFFF)) {
  ------------------
  |  Branch (476:13): [True: 102, False: 4.49k]
  |  Branch (476:39): [True: 11, False: 4.47k]
  ------------------
  477|       |            /* invalid second half of the surrogate pair */
  478|    113|            goto fail;
  479|    113|        }
  480|       |
  481|       |        /* calculate the unicode codepoint from the surrogate pair */
  482|  4.47k|        codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF));
  483|   570k|    } else {
  484|   570k|        sequence_length = 6; /* \uXXXX */
  485|   570k|        codepoint = first_code;
  486|   570k|    }
  487|       |
  488|       |    /* encode as UTF-8
  489|       |     * takes at maximum 4 bytes to encode:
  490|       |     * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
  491|   575k|    if (codepoint < 0x80) {
  ------------------
  |  Branch (491:9): [True: 150k, False: 424k]
  ------------------
  492|       |        /* normal ascii, encoding 0xxxxxxx */
  493|   150k|        utf8_length = 1;
  494|   424k|    } else if (codepoint < 0x800) {
  ------------------
  |  Branch (494:16): [True: 12.1k, False: 412k]
  ------------------
  495|       |        /* two bytes, encoding 110xxxxx 10xxxxxx */
  496|  12.1k|        utf8_length = 2;
  497|  12.1k|        first_byte_mark = 0xC0; /* 11000000 */
  498|   412k|    } else if (codepoint < 0x10000) {
  ------------------
  |  Branch (498:16): [True: 408k, False: 4.47k]
  ------------------
  499|       |        /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */
  500|   408k|        utf8_length = 3;
  501|   408k|        first_byte_mark = 0xE0; /* 11100000 */
  502|   408k|    } else if (codepoint <= 0x10FFFF) {
  ------------------
  |  Branch (502:16): [True: 4.47k, False: 0]
  ------------------
  503|       |        /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */
  504|  4.47k|        utf8_length = 4;
  505|  4.47k|        first_byte_mark = 0xF0; /* 11110000 */
  506|  4.47k|    } else {
  507|       |        /* invalid unicode codepoint */
  508|      0|        goto fail;
  509|      0|    }
  510|       |
  511|       |    /* encode as utf8 */
  512|  1.41M|    for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--) {
  ------------------
  |  Branch (512:60): [True: 841k, False: 575k]
  ------------------
  513|       |        /* 10xxxxxx */
  514|   841k|        (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF);
  515|   841k|        codepoint >>= 6;
  516|   841k|    }
  517|       |    /* encode first byte */
  518|   575k|    if (utf8_length > 1) {
  ------------------
  |  Branch (518:9): [True: 424k, False: 150k]
  ------------------
  519|   424k|        (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF);
  520|   424k|    } else {
  521|   150k|        (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F);
  522|   150k|    }
  523|       |
  524|   575k|    *output_pointer += utf8_length;
  525|       |
  526|   575k|    return sequence_length;
  527|       |
  528|    268|fail:
  529|    268|    return 0;
  530|   575k|}
cJSON.c:parse_hex4:
  406|   579k|static unsigned parse_hex4(const unsigned char *const input) {
  407|   579k|    unsigned int h = 0;
  408|   579k|    size_t i = 0;
  409|       |
  410|  2.49M|    for (i = 0; i < 4; i++) {
  ------------------
  |  Branch (410:17): [True: 2.06M, False: 430k]
  ------------------
  411|       |        /* parse digit */
  412|  2.06M|        if ((input[i] >= '0') && (input[i] <= '9')) {
  ------------------
  |  Branch (412:13): [True: 2.03M, False: 33.7k]
  |  Branch (412:34): [True: 1.32M, False: 710k]
  ------------------
  413|  1.32M|            h += (unsigned int)input[i] - '0';
  414|  1.32M|        } else if ((input[i] >= 'A') && (input[i] <= 'F')) {
  ------------------
  |  Branch (414:20): [True: 672k, False: 72.1k]
  |  Branch (414:41): [True: 78.5k, False: 593k]
  ------------------
  415|  78.5k|            h += (unsigned int)10 + input[i] - 'A';
  416|   666k|        } else if ((input[i] >= 'a') && (input[i] <= 'f')) {
  ------------------
  |  Branch (416:20): [True: 558k, False: 107k]
  |  Branch (416:41): [True: 516k, False: 41.9k]
  ------------------
  417|   516k|            h += (unsigned int)10 + input[i] - 'a';
  418|   516k|        } else /* invalid */
  419|   149k|        {
  420|   149k|            return 0;
  421|   149k|        }
  422|       |
  423|  1.91M|        if (i < 3) {
  ------------------
  |  Branch (423:13): [True: 1.48M, False: 430k]
  ------------------
  424|       |            /* shift left to make place for the next nibble */
  425|  1.48M|            h = h << 4;
  426|  1.48M|        }
  427|  1.91M|    }
  428|       |
  429|   430k|    return h;
  430|   579k|}
cJSON.c:parse_number:
  198|   995k|static cJSON_bool parse_number(cJSON *const item, parse_buffer *const input_buffer) {
  199|   995k|    double number = 0;
  200|   995k|    unsigned char *after_end = NULL;
  201|   995k|    unsigned char number_c_string[64];
  202|   995k|    unsigned char decimal_point = get_decimal_point();
  203|   995k|    size_t i = 0;
  204|       |
  205|   995k|    if ((input_buffer == NULL) || (input_buffer->content == NULL)) {
  ------------------
  |  Branch (205:9): [True: 0, False: 995k]
  |  Branch (205:35): [True: 0, False: 995k]
  ------------------
  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|  8.11M|    for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++) {
  ------------------
  |  |  192|  8.11M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 8.11M, False: 0]
  |  |  |  Branch (192:65): [True: 8.11M, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (212:17): [True: 8.11M, False: 1.06k]
  ------------------
  213|  8.11M|        switch (buffer_at_offset(input_buffer)[i]) {
  ------------------
  |  |  195|  8.11M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  214|   923k|            case '0':
  ------------------
  |  Branch (214:13): [True: 923k, False: 7.18M]
  ------------------
  215|  1.62M|            case '1':
  ------------------
  |  Branch (215:13): [True: 700k, False: 7.41M]
  ------------------
  216|  2.11M|            case '2':
  ------------------
  |  Branch (216:13): [True: 489k, False: 7.62M]
  ------------------
  217|  2.85M|            case '3':
  ------------------
  |  Branch (217:13): [True: 746k, False: 7.36M]
  ------------------
  218|  3.56M|            case '4':
  ------------------
  |  Branch (218:13): [True: 707k, False: 7.40M]
  ------------------
  219|  3.87M|            case '5':
  ------------------
  |  Branch (219:13): [True: 309k, False: 7.80M]
  ------------------
  220|  4.67M|            case '6':
  ------------------
  |  Branch (220:13): [True: 793k, False: 7.31M]
  ------------------
  221|  6.02M|            case '7':
  ------------------
  |  Branch (221:13): [True: 1.35M, False: 6.76M]
  ------------------
  222|  6.41M|            case '8':
  ------------------
  |  Branch (222:13): [True: 396k, False: 7.71M]
  ------------------
  223|  6.89M|            case '9':
  ------------------
  |  Branch (223:13): [True: 472k, False: 7.63M]
  ------------------
  224|  6.89M|            case '+':
  ------------------
  |  Branch (224:13): [True: 5.60k, False: 8.10M]
  ------------------
  225|  7.03M|            case '-':
  ------------------
  |  Branch (225:13): [True: 136k, False: 7.97M]
  ------------------
  226|  7.04M|            case 'e':
  ------------------
  |  Branch (226:13): [True: 15.1k, False: 8.09M]
  ------------------
  227|  7.05M|            case 'E':
  ------------------
  |  Branch (227:13): [True: 8.77k, False: 8.10M]
  ------------------
  228|  7.05M|                number_c_string[i] = buffer_at_offset(input_buffer)[i];
  ------------------
  |  |  195|  7.05M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  229|  7.05M|                break;
  230|       |
  231|  62.2k|            case '.':
  ------------------
  |  Branch (231:13): [True: 62.2k, False: 8.04M]
  ------------------
  232|  62.2k|                number_c_string[i] = decimal_point;
  233|  62.2k|                break;
  234|       |
  235|   994k|            default:
  ------------------
  |  Branch (235:13): [True: 994k, False: 7.11M]
  ------------------
  236|   994k|                goto loop_end;
  237|  8.11M|        }
  238|  8.11M|    }
  239|   995k|loop_end:
  240|   995k|    number_c_string[i] = '\0';
  241|       |
  242|   995k|    number = strtod((const char *)number_c_string, (char **)&after_end);
  243|   995k|    if (number_c_string == after_end) {
  ------------------
  |  Branch (243:9): [True: 74, False: 995k]
  ------------------
  244|     74|        return false; /* parse_error */
  ------------------
  |  |   72|     74|#define false ((cJSON_bool)0)
  ------------------
  245|     74|    }
  246|       |
  247|   995k|    item->valuedouble = number;
  248|       |
  249|       |    /* use saturation in case of overflow */
  250|   995k|    if (number >= INT_MAX) {
  ------------------
  |  Branch (250:9): [True: 61.0k, False: 934k]
  ------------------
  251|  61.0k|        item->valueint = INT_MAX;
  252|   934k|    } else if (number <= (double)INT_MIN) {
  ------------------
  |  Branch (252:16): [True: 126k, False: 807k]
  ------------------
  253|   126k|        item->valueint = INT_MIN;
  254|   807k|    } else {
  255|   807k|        item->valueint = (int)number;
  256|   807k|    }
  257|       |
  258|   995k|    item->type = cJSON_Number;
  ------------------
  |  |  100|   995k|#define cJSON_Number (1 << 3)
  ------------------
  259|       |
  260|   995k|    input_buffer->offset += (size_t)(after_end - number_c_string);
  261|   995k|    return true;
  ------------------
  |  |   67|   995k|#define true ((cJSON_bool)1)
  ------------------
  262|   995k|}
cJSON.c:get_decimal_point:
  172|   995k|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|   995k|    return '.';
  178|   995k|#endif
  179|   995k|}
cJSON.c:parse_array:
 1118|   166k|static cJSON_bool parse_array(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory) {
 1119|   166k|    cJSON *head = NULL; /* head of the linked list */
 1120|   166k|    cJSON *current_item = NULL;
 1121|       |
 1122|   166k|    if (input_buffer->depth >= CJSON_NESTING_LIMIT) {
  ------------------
  |  |  138|   166k|#define CJSON_NESTING_LIMIT 1000
  ------------------
  |  Branch (1122:9): [True: 4, False: 166k]
  ------------------
 1123|      4|        return false; /* to deeply nested */
  ------------------
  |  |   72|      4|#define false ((cJSON_bool)0)
  ------------------
 1124|      4|    }
 1125|   166k|    input_buffer->depth++;
 1126|       |
 1127|   166k|    if (buffer_at_offset(input_buffer)[0] != '[') {
  ------------------
  |  |  195|   166k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1127:9): [True: 0, False: 166k]
  ------------------
 1128|       |        /* not an array */
 1129|      0|        goto fail;
 1130|      0|    }
 1131|       |
 1132|   166k|    input_buffer->offset++;
 1133|   166k|    buffer_skip_whitespace(input_buffer);
 1134|   166k|    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']')) {
  ------------------
  |  |  192|   332k|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 166k, False: 0]
  |  |  |  Branch (192:65): [True: 166k, False: 0]
  |  |  ------------------
  ------------------
                  if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']')) {
  ------------------
  |  |  195|   166k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1134:49): [True: 13.1k, False: 153k]
  ------------------
 1135|       |        /* empty array */
 1136|  13.1k|        goto success;
 1137|  13.1k|    }
 1138|       |
 1139|       |    /* check if we skipped to the end of the buffer */
 1140|   153k|    if (cannot_access_at_index(input_buffer, 0)) {
  ------------------
  |  |  193|   153k|#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
  |  |  ------------------
  |  |  |  |  192|   153k|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (192:45): [True: 153k, False: 0]
  |  |  |  |  |  Branch (192:65): [True: 153k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1141|      0|        input_buffer->offset--;
 1142|      0|        goto fail;
 1143|      0|    }
 1144|       |
 1145|       |    /* step back to character in front of the first element */
 1146|   153k|    input_buffer->offset--;
 1147|       |    /* loop through the comma separated array elements */
 1148|  2.75M|    do {
 1149|       |        /* allocate next item */
 1150|  2.75M|        cJSON *new_item = cJSON_New_Item(input_buffer->pAllocator);
 1151|  2.75M|        if (new_item == NULL) {
  ------------------
  |  Branch (1151:13): [True: 0, False: 2.75M]
  ------------------
 1152|      0|            *out_of_memory = true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
 1153|      0|            goto fail; /* allocation failure */
 1154|      0|        }
 1155|       |
 1156|       |        /* attach next item to list */
 1157|  2.75M|        if (head == NULL) {
  ------------------
  |  Branch (1157:13): [True: 153k, False: 2.59M]
  ------------------
 1158|       |            /* start the linked list */
 1159|   153k|            current_item = head = new_item;
 1160|  2.59M|        } else {
 1161|       |            /* add to the end and advance */
 1162|  2.59M|            current_item->next = new_item;
 1163|  2.59M|            new_item->prev = current_item;
 1164|  2.59M|            current_item = new_item;
 1165|  2.59M|        }
 1166|       |
 1167|       |        /* parse next value */
 1168|  2.75M|        input_buffer->offset++;
 1169|  2.75M|        buffer_skip_whitespace(input_buffer);
 1170|  2.75M|        if (!parse_value(current_item, input_buffer, out_of_memory)) {
  ------------------
  |  Branch (1170:13): [True: 136k, False: 2.61M]
  ------------------
 1171|   136k|            goto fail; /* failed to parse value */
 1172|   136k|        }
 1173|  2.61M|        buffer_skip_whitespace(input_buffer);
 1174|  2.61M|    } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
  ------------------
  |  |  192|  5.22M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 2.61M, False: 0]
  |  |  |  Branch (192:65): [True: 2.61M, False: 0]
  |  |  ------------------
  ------------------
                  } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
  ------------------
  |  |  195|  2.61M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1174:54): [True: 2.59M, False: 16.5k]
  ------------------
 1175|       |
 1176|  16.5k|    if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') {
  ------------------
  |  |  193|  33.0k|#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
  |  |  ------------------
  |  |  |  |  192|  16.5k|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (192:45): [True: 16.5k, False: 0]
  |  |  |  |  |  Branch (192:65): [True: 16.5k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
                  if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') {
  ------------------
  |  |  195|  16.5k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1176:52): [True: 680, False: 15.8k]
  ------------------
 1177|    680|        goto fail; /* expected end of array */
 1178|    680|    }
 1179|       |
 1180|  28.9k|success:
 1181|  28.9k|    input_buffer->depth--;
 1182|       |
 1183|  28.9k|    if (head != NULL) {
  ------------------
  |  Branch (1183:9): [True: 15.8k, False: 13.1k]
  ------------------
 1184|  15.8k|        head->prev = current_item;
 1185|  15.8k|    }
 1186|       |
 1187|  28.9k|    item->type = cJSON_Array;
  ------------------
  |  |  102|  28.9k|#define cJSON_Array (1 << 5)
  ------------------
 1188|  28.9k|    item->child = head;
 1189|       |
 1190|  28.9k|    input_buffer->offset++;
 1191|       |
 1192|  28.9k|    return true;
  ------------------
  |  |   67|  28.9k|#define true ((cJSON_bool)1)
  ------------------
 1193|       |
 1194|   137k|fail:
 1195|   137k|    if (head != NULL) {
  ------------------
  |  Branch (1195:9): [True: 137k, False: 0]
  ------------------
 1196|   137k|        loader_cJSON_Delete(head);
 1197|   137k|    }
 1198|       |
 1199|   137k|    return false;
  ------------------
  |  |   72|   137k|#define false ((cJSON_bool)0)
  ------------------
 1200|  16.5k|}
cJSON.c:parse_object:
 1256|   478k|static cJSON_bool parse_object(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory) {
 1257|   478k|    cJSON *head = NULL; /* linked list head */
 1258|   478k|    cJSON *current_item = NULL;
 1259|       |
 1260|   478k|    if (input_buffer->depth >= CJSON_NESTING_LIMIT) {
  ------------------
  |  |  138|   478k|#define CJSON_NESTING_LIMIT 1000
  ------------------
  |  Branch (1260:9): [True: 9, False: 478k]
  ------------------
 1261|      9|        return false; /* to deeply nested */
  ------------------
  |  |   72|      9|#define false ((cJSON_bool)0)
  ------------------
 1262|      9|    }
 1263|   478k|    input_buffer->depth++;
 1264|       |
 1265|   478k|    if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) {
  ------------------
  |  |  193|   957k|#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
  |  |  ------------------
  |  |  |  |  192|   478k|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (192:45): [True: 478k, False: 0]
  |  |  |  |  |  Branch (192:65): [True: 478k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
                  if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) {
  ------------------
  |  |  195|   478k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1265:52): [True: 0, False: 478k]
  ------------------
 1266|      0|        goto fail; /* not an object */
 1267|      0|    }
 1268|       |
 1269|   478k|    input_buffer->offset++;
 1270|   478k|    buffer_skip_whitespace(input_buffer);
 1271|   478k|    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) {
  ------------------
  |  |  192|   957k|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 478k, False: 0]
  |  |  |  Branch (192:65): [True: 478k, False: 0]
  |  |  ------------------
  ------------------
                  if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) {
  ------------------
  |  |  195|   478k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1271:49): [True: 4.35k, False: 474k]
  ------------------
 1272|  4.35k|        goto success; /* empty object */
 1273|  4.35k|    }
 1274|       |
 1275|       |    /* check if we skipped to the end of the buffer */
 1276|   474k|    if (cannot_access_at_index(input_buffer, 0)) {
  ------------------
  |  |  193|   474k|#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
  |  |  ------------------
  |  |  |  |  192|   474k|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (192:45): [True: 474k, False: 0]
  |  |  |  |  |  Branch (192:65): [True: 474k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1277|      0|        input_buffer->offset--;
 1278|      0|        goto fail;
 1279|      0|    }
 1280|       |
 1281|       |    /* step back to character in front of the first element */
 1282|   474k|    input_buffer->offset--;
 1283|       |    /* loop through the comma separated array elements */
 1284|  1.32M|    do {
 1285|       |        /* allocate next item */
 1286|  1.32M|        cJSON *new_item = cJSON_New_Item(input_buffer->pAllocator);
 1287|  1.32M|        if (new_item == NULL) {
  ------------------
  |  Branch (1287:13): [True: 0, False: 1.32M]
  ------------------
 1288|      0|            *out_of_memory = true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
 1289|      0|            goto fail; /* allocation failure */
 1290|      0|        }
 1291|       |
 1292|       |        /* attach next item to list */
 1293|  1.32M|        if (head == NULL) {
  ------------------
  |  Branch (1293:13): [True: 474k, False: 855k]
  ------------------
 1294|       |            /* start the linked list */
 1295|   474k|            current_item = head = new_item;
 1296|   855k|        } else {
 1297|       |            /* add to the end and advance */
 1298|   855k|            current_item->next = new_item;
 1299|   855k|            new_item->prev = current_item;
 1300|   855k|            current_item = new_item;
 1301|   855k|        }
 1302|       |
 1303|  1.32M|        if (cannot_access_at_index(input_buffer, 1)) {
  ------------------
  |  |  193|  1.32M|#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
  |  |  ------------------
  |  |  |  |  192|  1.32M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (192:45): [True: 1.32M, False: 0]
  |  |  |  |  |  Branch (192:65): [True: 1.32M, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1304|      0|            goto fail; /* nothing comes after the comma */
 1305|      0|        }
 1306|       |
 1307|       |        /* parse the name of the child */
 1308|  1.32M|        input_buffer->offset++;
 1309|  1.32M|        buffer_skip_whitespace(input_buffer);
 1310|  1.32M|        if (!parse_string(current_item, input_buffer, out_of_memory)) {
  ------------------
  |  Branch (1310:13): [True: 406, False: 1.32M]
  ------------------
 1311|    406|            goto fail; /* failed to parse name */
 1312|    406|        }
 1313|  1.32M|        buffer_skip_whitespace(input_buffer);
 1314|       |
 1315|       |        /* swap valuestring and string, because we parsed the name */
 1316|  1.32M|        current_item->string = current_item->valuestring;
 1317|  1.32M|        current_item->valuestring = NULL;
 1318|       |
 1319|  1.32M|        if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) {
  ------------------
  |  |  193|  2.65M|#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
  |  |  ------------------
  |  |  |  |  192|  1.32M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (192:45): [True: 1.32M, False: 0]
  |  |  |  |  |  Branch (192:65): [True: 1.32M, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
                      if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) {
  ------------------
  |  |  195|  1.32M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1319:56): [True: 49, False: 1.32M]
  ------------------
 1320|     49|            goto fail; /* invalid object */
 1321|     49|        }
 1322|       |
 1323|       |        /* parse the value */
 1324|  1.32M|        input_buffer->offset++;
 1325|  1.32M|        buffer_skip_whitespace(input_buffer);
 1326|  1.32M|        if (!parse_value(current_item, input_buffer, out_of_memory)) {
  ------------------
  |  Branch (1326:13): [True: 12.4k, False: 1.31M]
  ------------------
 1327|  12.4k|            goto fail; /* failed to parse value */
 1328|  12.4k|        }
 1329|  1.31M|        buffer_skip_whitespace(input_buffer);
 1330|  1.31M|    } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
  ------------------
  |  |  192|  2.63M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 1.31M, False: 0]
  |  |  |  Branch (192:65): [True: 1.31M, False: 0]
  |  |  ------------------
  ------------------
                  } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
  ------------------
  |  |  195|  1.31M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1330:54): [True: 855k, False: 461k]
  ------------------
 1331|       |
 1332|   461k|    if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) {
  ------------------
  |  |  193|   923k|#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
  |  |  ------------------
  |  |  |  |  192|   461k|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (192:45): [True: 461k, False: 0]
  |  |  |  |  |  Branch (192:65): [True: 461k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
                  if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) {
  ------------------
  |  |  195|   461k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1332:52): [True: 55, False: 461k]
  ------------------
 1333|     55|        goto fail; /* expected end of object */
 1334|     55|    }
 1335|       |
 1336|   465k|success:
 1337|   465k|    input_buffer->depth--;
 1338|       |
 1339|   465k|    if (head != NULL) {
  ------------------
  |  Branch (1339:9): [True: 461k, False: 4.35k]
  ------------------
 1340|   461k|        head->prev = current_item;
 1341|   461k|    }
 1342|       |
 1343|   465k|    item->type = cJSON_Object;
  ------------------
  |  |  103|   465k|#define cJSON_Object (1 << 6)
  ------------------
 1344|   465k|    item->child = head;
 1345|       |
 1346|   465k|    input_buffer->offset++;
 1347|   465k|    return true;
  ------------------
  |  |   67|   465k|#define true ((cJSON_bool)1)
  ------------------
 1348|       |
 1349|  12.9k|fail:
 1350|  12.9k|    if (head != NULL) {
  ------------------
  |  Branch (1350:9): [True: 12.9k, False: 0]
  ------------------
 1351|  12.9k|        loader_cJSON_Delete(head);
 1352|  12.9k|    }
 1353|       |
 1354|  12.9k|    return false;
  ------------------
  |  |   72|  12.9k|#define false ((cJSON_bool)0)
  ------------------
 1355|   461k|}
cJSON.c:print_value:
 1053|  2.05M|static cJSON_bool print_value(const cJSON *const item, printbuffer *const output_buffer, bool *out_of_memory) {
 1054|  2.05M|    unsigned char *output = NULL;
 1055|       |
 1056|  2.05M|    if ((item == NULL) || (output_buffer == NULL)) {
  ------------------
  |  Branch (1056:9): [True: 0, False: 2.05M]
  |  Branch (1056:27): [True: 0, False: 2.05M]
  ------------------
 1057|      0|        return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1058|      0|    }
 1059|       |
 1060|  2.05M|    switch ((item->type) & 0xFF) {
 1061|      0|        case cJSON_NULL:
  ------------------
  |  |   99|      0|#define cJSON_NULL (1 << 2)
  ------------------
  |  Branch (1061:9): [True: 0, False: 2.05M]
  ------------------
 1062|      0|            output = ensure(output_buffer, 5, out_of_memory);
 1063|      0|            if (output == NULL) {
  ------------------
  |  Branch (1063:17): [True: 0, False: 0]
  ------------------
 1064|      0|                return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1065|      0|            }
 1066|      0|            strcpy((char *)output, "null");
 1067|      0|            return true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
 1068|       |
 1069|      0|        case cJSON_False:
  ------------------
  |  |   97|      0|#define cJSON_False (1 << 0)
  ------------------
  |  Branch (1069:9): [True: 0, False: 2.05M]
  ------------------
 1070|      0|            output = ensure(output_buffer, 6, out_of_memory);
 1071|      0|            if (output == NULL) {
  ------------------
  |  Branch (1071:17): [True: 0, False: 0]
  ------------------
 1072|      0|                return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1073|      0|            }
 1074|      0|            strcpy((char *)output, "false");
 1075|      0|            return true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
 1076|       |
 1077|      0|        case cJSON_True:
  ------------------
  |  |   98|      0|#define cJSON_True (1 << 1)
  ------------------
  |  Branch (1077:9): [True: 0, False: 2.05M]
  ------------------
 1078|      0|            output = ensure(output_buffer, 5, out_of_memory);
 1079|      0|            if (output == NULL) {
  ------------------
  |  Branch (1079:17): [True: 0, False: 0]
  ------------------
 1080|      0|                return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1081|      0|            }
 1082|      0|            strcpy((char *)output, "true");
 1083|      0|            return true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
 1084|       |
 1085|      0|        case cJSON_Number:
  ------------------
  |  |  100|      0|#define cJSON_Number (1 << 3)
  ------------------
  |  Branch (1085:9): [True: 0, False: 2.05M]
  ------------------
 1086|      0|            return print_number(item, output_buffer, out_of_memory);
 1087|       |
 1088|      0|        case cJSON_Raw: {
  ------------------
  |  |  104|      0|#define cJSON_Raw (1 << 7) /* raw json */
  ------------------
  |  Branch (1088:9): [True: 0, False: 2.05M]
  ------------------
 1089|      0|            size_t raw_length = 0;
 1090|      0|            if (item->valuestring == NULL) {
  ------------------
  |  Branch (1090:17): [True: 0, False: 0]
  ------------------
 1091|      0|                return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1092|      0|            }
 1093|       |
 1094|      0|            raw_length = strlen(item->valuestring) + sizeof("");
 1095|      0|            output = ensure(output_buffer, raw_length, out_of_memory);
 1096|      0|            if (output == NULL) {
  ------------------
  |  Branch (1096:17): [True: 0, False: 0]
  ------------------
 1097|      0|                return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1098|      0|            }
 1099|      0|            memcpy(output, item->valuestring, raw_length);
 1100|      0|            return true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
 1101|      0|        }
 1102|       |
 1103|  2.05M|        case cJSON_String:
  ------------------
  |  |  101|  2.05M|#define cJSON_String (1 << 4)
  ------------------
  |  Branch (1103:9): [True: 2.05M, False: 0]
  ------------------
 1104|  2.05M|            return print_string(item, output_buffer, out_of_memory);
 1105|       |
 1106|      0|        case cJSON_Array:
  ------------------
  |  |  102|      0|#define cJSON_Array (1 << 5)
  ------------------
  |  Branch (1106:9): [True: 0, False: 2.05M]
  ------------------
 1107|      0|            return print_array(item, output_buffer, out_of_memory);
 1108|       |
 1109|      0|        case cJSON_Object:
  ------------------
  |  |  103|      0|#define cJSON_Object (1 << 6)
  ------------------
  |  Branch (1109:9): [True: 0, False: 2.05M]
  ------------------
 1110|      0|            return print_object(item, output_buffer, out_of_memory);
 1111|       |
 1112|      0|        default:
  ------------------
  |  Branch (1112:9): [True: 0, False: 2.05M]
  ------------------
 1113|      0|            return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1114|  2.05M|    }
 1115|  2.05M|}
cJSON.c:ensure:
  275|  2.05M|static unsigned char *ensure(printbuffer *const p, size_t needed, bool *out_of_memory) {
  276|  2.05M|    unsigned char *newbuffer = NULL;
  277|  2.05M|    size_t newsize = 0;
  278|       |
  279|  2.05M|    if ((p == NULL) || (p->buffer == NULL)) {
  ------------------
  |  Branch (279:9): [True: 0, False: 2.05M]
  |  Branch (279:24): [True: 0, False: 2.05M]
  ------------------
  280|      0|        return NULL;
  281|      0|    }
  282|       |
  283|  2.05M|    if ((p->length > 0) && (p->offset >= p->length)) {
  ------------------
  |  Branch (283:9): [True: 2.05M, False: 0]
  |  Branch (283:28): [True: 0, False: 2.05M]
  ------------------
  284|       |        /* make sure that offset is valid */
  285|      0|        return NULL;
  286|      0|    }
  287|       |
  288|  2.05M|    if (needed > INT_MAX) {
  ------------------
  |  Branch (288:9): [True: 0, False: 2.05M]
  ------------------
  289|       |        /* sizes bigger than INT_MAX are currently not supported */
  290|      0|        return NULL;
  291|      0|    }
  292|       |
  293|  2.05M|    needed += p->offset + 1;
  294|  2.05M|    if (needed <= p->length) {
  ------------------
  |  Branch (294:9): [True: 2.05M, False: 2.29k]
  ------------------
  295|  2.05M|        return p->buffer + p->offset;
  296|  2.05M|    }
  297|       |
  298|  2.29k|    if (p->noalloc) {
  ------------------
  |  Branch (298:9): [True: 69, False: 2.22k]
  ------------------
  299|     69|        return NULL;
  300|     69|    }
  301|       |
  302|       |    /* calculate new buffer size */
  303|  2.22k|    if (needed > (INT_MAX / 2)) {
  ------------------
  |  Branch (303:9): [True: 0, False: 2.22k]
  ------------------
  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.22k|    } else {
  311|  2.22k|        newsize = needed * 2;
  312|  2.22k|    }
  313|       |
  314|  2.22k|    newbuffer = (unsigned char *)loader_realloc(p->pAllocator, p->buffer, p->length, newsize, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  315|  2.22k|    if (newbuffer == NULL) {
  ------------------
  |  Branch (315:9): [True: 0, False: 2.22k]
  ------------------
  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.22k|    p->length = newsize;
  325|  2.22k|    p->buffer = newbuffer;
  326|       |
  327|  2.22k|    return newbuffer + p->offset;
  328|  2.22k|}
cJSON.c:print_string:
  756|  2.05M|static cJSON_bool print_string(const cJSON *const item, printbuffer *const p, bool *out_of_memory) {
  757|  2.05M|    return print_string_ptr((unsigned char *)item->valuestring, p, out_of_memory);
  758|  2.05M|}
cJSON.c:print_string_ptr:
  650|  2.05M|static cJSON_bool print_string_ptr(const unsigned char *const input, printbuffer *const output_buffer, bool *out_of_memory) {
  651|  2.05M|    const unsigned char *input_pointer = NULL;
  652|  2.05M|    unsigned char *output = NULL;
  653|  2.05M|    unsigned char *output_pointer = NULL;
  654|  2.05M|    size_t output_length = 0;
  655|       |    /* numbers of additional characters needed for escaping */
  656|  2.05M|    size_t escape_characters = 0;
  657|       |
  658|  2.05M|    if (output_buffer == NULL) {
  ------------------
  |  Branch (658:9): [True: 0, False: 2.05M]
  ------------------
  659|      0|        return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
  660|      0|    }
  661|       |
  662|       |    /* empty string */
  663|  2.05M|    if (input == NULL) {
  ------------------
  |  Branch (663:9): [True: 0, False: 2.05M]
  ------------------
  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|  15.3M|    for (input_pointer = input; *input_pointer; input_pointer++) {
  ------------------
  |  Branch (673:33): [True: 13.2M, False: 2.05M]
  ------------------
  674|  13.2M|        switch (*input_pointer) {
  675|    973|            case '\"':
  ------------------
  |  Branch (675:13): [True: 973, False: 13.2M]
  ------------------
  676|  6.76k|            case '\\':
  ------------------
  |  Branch (676:13): [True: 5.79k, False: 13.2M]
  ------------------
  677|  25.0k|            case '\b':
  ------------------
  |  Branch (677:13): [True: 18.2k, False: 13.2M]
  ------------------
  678|  30.5k|            case '\f':
  ------------------
  |  Branch (678:13): [True: 5.58k, False: 13.2M]
  ------------------
  679|  81.9k|            case '\n':
  ------------------
  |  Branch (679:13): [True: 51.4k, False: 13.1M]
  ------------------
  680|  84.1k|            case '\r':
  ------------------
  |  Branch (680:13): [True: 2.16k, False: 13.2M]
  ------------------
  681|  92.9k|            case '\t':
  ------------------
  |  Branch (681:13): [True: 8.81k, False: 13.2M]
  ------------------
  682|       |                /* one character escape sequence */
  683|  92.9k|                escape_characters++;
  684|  92.9k|                break;
  685|  13.1M|            default:
  ------------------
  |  Branch (685:13): [True: 13.1M, False: 92.9k]
  ------------------
  686|  13.1M|                if (*input_pointer < 32) {
  ------------------
  |  Branch (686:21): [True: 10.8M, False: 2.31M]
  ------------------
  687|       |                    /* UTF-16 escape sequence uXXXX */
  688|  10.8M|                    escape_characters += 5;
  689|  10.8M|                }
  690|  13.1M|                break;
  691|  13.2M|        }
  692|  13.2M|    }
  693|  2.05M|    output_length = (size_t)(input_pointer - input) + escape_characters;
  694|       |
  695|  2.05M|    output = ensure(output_buffer, output_length + sizeof(""), out_of_memory);
  696|  2.05M|    if (output == NULL) {
  ------------------
  |  Branch (696:9): [True: 69, False: 2.05M]
  ------------------
  697|     69|        return false;
  ------------------
  |  |   72|     69|#define false ((cJSON_bool)0)
  ------------------
  698|     69|    }
  699|       |
  700|       |    /* no characters have to be escaped */
  701|  2.05M|    if (escape_characters == 0) {
  ------------------
  |  Branch (701:9): [True: 2.01M, False: 42.4k]
  ------------------
  702|  2.01M|        memcpy(output, input, output_length);
  703|  2.01M|        output[output_length] = '\0';
  704|       |
  705|  2.01M|        return true;
  ------------------
  |  |   67|  2.01M|#define true ((cJSON_bool)1)
  ------------------
  706|  2.01M|    }
  707|       |
  708|  42.4k|    output_pointer = output;
  709|       |    /* copy the string */
  710|  11.4M|    for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++) {
  ------------------
  |  Branch (710:33): [True: 11.3M, False: 42.4k]
  ------------------
  711|  11.3M|        if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\')) {
  ------------------
  |  Branch (711:13): [True: 454k, False: 10.9M]
  |  Branch (711:38): [True: 453k, False: 973]
  |  Branch (711:66): [True: 447k, False: 5.79k]
  ------------------
  712|       |            /* normal character, copy */
  713|   447k|            *output_pointer = *input_pointer;
  714|  10.9M|        } 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|  10.9M|            switch (*input_pointer) {
  721|  5.79k|                case '\\':
  ------------------
  |  Branch (721:17): [True: 5.79k, False: 10.9M]
  ------------------
  722|  5.79k|                    *output_pointer = '\\';
  723|  5.79k|                    break;
  724|    973|                case '\"':
  ------------------
  |  Branch (724:17): [True: 973, False: 10.9M]
  ------------------
  725|    973|                    *output_pointer = '\"';
  726|    973|                    break;
  727|  18.2k|                case '\b':
  ------------------
  |  Branch (727:17): [True: 18.2k, False: 10.9M]
  ------------------
  728|  18.2k|                    *output_pointer = '\b';
  729|  18.2k|                    break;
  730|  5.58k|                case '\f':
  ------------------
  |  Branch (730:17): [True: 5.58k, False: 10.9M]
  ------------------
  731|  5.58k|                    *output_pointer = '\f';
  732|  5.58k|                    break;
  733|  51.3k|                case '\n':
  ------------------
  |  Branch (733:17): [True: 51.3k, False: 10.8M]
  ------------------
  734|  51.3k|                    *output_pointer = '\n';
  735|  51.3k|                    break;
  736|  2.16k|                case '\r':
  ------------------
  |  Branch (736:17): [True: 2.16k, False: 10.9M]
  ------------------
  737|  2.16k|                    *output_pointer = '\r';
  738|  2.16k|                    break;
  739|  8.80k|                case '\t':
  ------------------
  |  Branch (739:17): [True: 8.80k, False: 10.9M]
  ------------------
  740|  8.80k|                    *output_pointer = '\t';
  741|  8.80k|                    break;
  742|  10.8M|                default:
  ------------------
  |  Branch (742:17): [True: 10.8M, False: 92.9k]
  ------------------
  743|       |                    /* escape and print as unicode codepoint */
  744|  10.8M|                    snprintf((char *)output_pointer, output_length - (size_t)(output_pointer - output), "u%04x", *input_pointer);
  745|  10.8M|                    output_pointer += 4;
  746|  10.8M|                    break;
  747|  10.9M|            }
  748|  10.9M|        }
  749|  11.3M|    }
  750|  42.4k|    output[output_length] = '\0';
  751|       |
  752|  42.4k|    return true;
  ------------------
  |  |   67|  42.4k|#define true ((cJSON_bool)1)
  ------------------
  753|  42.4k|}
cJSON.c:get_object_item:
 1498|  1.30M|static cJSON *get_object_item(const cJSON *const object, const char *const name, const cJSON_bool case_sensitive) {
 1499|  1.30M|    cJSON *current_element = NULL;
 1500|       |
 1501|  1.30M|    if ((object == NULL) || (name == NULL)) {
  ------------------
  |  Branch (1501:9): [True: 0, False: 1.30M]
  |  Branch (1501:29): [True: 0, False: 1.30M]
  ------------------
 1502|      0|        return NULL;
 1503|      0|    }
 1504|       |
 1505|  1.30M|    current_element = object->child;
 1506|  1.30M|    if (case_sensitive) {
  ------------------
  |  Branch (1506:9): [True: 0, False: 1.30M]
  ------------------
 1507|      0|        while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0)) {
  ------------------
  |  Branch (1507:16): [True: 0, False: 0]
  |  Branch (1507:45): [True: 0, False: 0]
  |  Branch (1507:82): [True: 0, False: 0]
  ------------------
 1508|      0|            current_element = current_element->next;
 1509|      0|        }
 1510|  1.30M|    } else {
 1511|  3.31M|        while ((current_element != NULL) &&
  ------------------
  |  Branch (1511:16): [True: 2.96M, False: 347k]
  ------------------
 1512|  2.96M|               (case_insensitive_strcmp((const unsigned char *)name, (const unsigned char *)(current_element->string)) != 0)) {
  ------------------
  |  Branch (1512:16): [True: 2.00M, False: 961k]
  ------------------
 1513|  2.00M|            current_element = current_element->next;
 1514|  2.00M|        }
 1515|  1.30M|    }
 1516|       |
 1517|  1.30M|    if ((current_element == NULL) || (current_element->string == NULL)) {
  ------------------
  |  Branch (1517:9): [True: 347k, False: 961k]
  |  Branch (1517:38): [True: 0, False: 961k]
  ------------------
 1518|   347k|        return NULL;
 1519|   347k|    }
 1520|       |
 1521|   961k|    return current_element;
 1522|  1.30M|}
cJSON.c:case_insensitive_strcmp:
  120|  2.96M|static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2) {
  121|  2.96M|    if ((string1 == NULL) || (string2 == NULL)) {
  ------------------
  |  Branch (121:9): [True: 0, False: 2.96M]
  |  Branch (121:30): [True: 438, False: 2.96M]
  ------------------
  122|    438|        return 1;
  123|    438|    }
  124|       |
  125|  2.96M|    if (string1 == string2) {
  ------------------
  |  Branch (125:9): [True: 0, False: 2.96M]
  ------------------
  126|      0|        return 0;
  127|      0|    }
  128|       |
  129|  7.99M|    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: 7.99M]
  |  Branch (129:12): [True: 5.98M, False: 2.00M]
  |  Branch (129:33): [True: 0, False: 0]
  |  Branch (129:33): [True: 0, False: 0]
  |  Branch (129:33): [Folded, False: 7.99M]
  ------------------
  130|  5.98M|        if (*string1 == '\0') {
  ------------------
  |  Branch (130:13): [True: 961k, False: 5.02M]
  ------------------
  131|   961k|            return 0;
  132|   961k|        }
  133|  5.98M|    }
  134|       |
  135|  2.00M|    return tolower(*string1) - tolower(*string2);
  ------------------
  |  Branch (135:12): [True: 0, False: 0]
  |  Branch (135:12): [True: 0, False: 0]
  |  Branch (135:12): [Folded, False: 2.00M]
  |  Branch (135:32): [True: 0, False: 0]
  |  Branch (135:32): [True: 0, False: 0]
  |  Branch (135:32): [Folded, False: 2.00M]
  ------------------
  136|  2.96M|}

loader_make_full_version:
  121|    106|loader_api_version loader_make_full_version(uint32_t version) {
  122|    106|    loader_api_version out_version;
  123|    106|    out_version.major = VK_API_VERSION_MAJOR(version);
  124|    106|    out_version.minor = VK_API_VERSION_MINOR(version);
  125|       |    out_version.patch = VK_API_VERSION_PATCH(version);
  126|    106|    return out_version;
  127|    106|}
loader_combine_version:
  129|    208|loader_api_version loader_combine_version(uint32_t major, uint32_t minor, uint32_t patch) {
  130|    208|    loader_api_version out_version;
  131|    208|    out_version.major = (uint16_t)major;
  132|    208|    out_version.minor = (uint16_t)minor;
  133|    208|    out_version.patch = (uint16_t)patch;
  134|    208|    return out_version;
  135|    208|}
loader_check_version_meets_required:
  138|    208|bool loader_check_version_meets_required(loader_api_version required, loader_api_version version) {
  139|       |    // major version is satisfied
  140|    208|    return (version.major > required.major) ||
  ------------------
  |  Branch (140:12): [True: 34, False: 174]
  ------------------
  141|       |           // major version is equal, minor version is patch version is greater to minimum minor
  142|    174|           (version.major == required.major && version.minor > required.minor) ||
  ------------------
  |  Branch (142:13): [True: 34, False: 140]
  |  Branch (142:48): [True: 13, False: 21]
  ------------------
  143|       |           // major and minor version are equal, patch version is greater or equal to minimum patch
  144|    161|           (version.major == required.major && version.minor == required.minor && version.patch >= required.patch);
  ------------------
  |  Branch (144:13): [True: 21, False: 140]
  |  Branch (144:48): [True: 21, False: 0]
  |  Branch (144:83): [True: 9, False: 12]
  ------------------
  145|    208|}
loader_free_layer_properties:
  248|   154k|void loader_free_layer_properties(const struct loader_instance *inst, struct loader_layer_properties *layer_properties) {
  249|   154k|    loader_instance_heap_free(inst, layer_properties->manifest_file_name);
  250|   154k|    loader_instance_heap_free(inst, layer_properties->lib_name);
  251|   154k|    loader_instance_heap_free(inst, layer_properties->functions.str_gipa);
  252|   154k|    loader_instance_heap_free(inst, layer_properties->functions.str_gdpa);
  253|   154k|    loader_instance_heap_free(inst, layer_properties->functions.str_negotiate_interface);
  254|   154k|    loader_destroy_generic_list(inst, (struct loader_generic_list *)&layer_properties->instance_extension_list);
  255|   154k|    if (layer_properties->device_extension_list.capacity > 0 && NULL != layer_properties->device_extension_list.list) {
  ------------------
  |  Branch (255:9): [True: 16, False: 154k]
  |  Branch (255:65): [True: 16, False: 0]
  ------------------
  256|     33|        for (uint32_t i = 0; i < layer_properties->device_extension_list.count; i++) {
  ------------------
  |  Branch (256:30): [True: 17, False: 16]
  ------------------
  257|     17|            free_string_list(inst, &layer_properties->device_extension_list.list[i].entrypoints);
  258|     17|        }
  259|     16|    }
  260|   154k|    loader_destroy_generic_list(inst, (struct loader_generic_list *)&layer_properties->device_extension_list);
  261|   154k|    loader_instance_heap_free(inst, layer_properties->disable_env_var.name);
  262|   154k|    loader_instance_heap_free(inst, layer_properties->disable_env_var.value);
  263|   154k|    loader_instance_heap_free(inst, layer_properties->enable_env_var.name);
  264|   154k|    loader_instance_heap_free(inst, layer_properties->enable_env_var.value);
  265|   154k|    free_string_list(inst, &layer_properties->component_layer_names);
  266|   154k|    loader_instance_heap_free(inst, layer_properties->pre_instance_functions.enumerate_instance_extension_properties);
  267|   154k|    loader_instance_heap_free(inst, layer_properties->pre_instance_functions.enumerate_instance_layer_properties);
  268|   154k|    loader_instance_heap_free(inst, layer_properties->pre_instance_functions.enumerate_instance_version);
  269|   154k|    free_string_list(inst, &layer_properties->override_paths);
  270|   154k|    free_string_list(inst, &layer_properties->blacklist_layer_names);
  271|   154k|    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|   154k|    memset(layer_properties, 0, sizeof(struct loader_layer_properties));
  275|   154k|}
loader_copy_to_new_str:
  287|   152k|VkResult loader_copy_to_new_str(const struct loader_instance *inst, const char *source_str, char **dest_str) {
  288|   152k|    assert(source_str && dest_str);
  289|   152k|    size_t str_len = strlen(source_str) + 1;
  290|   152k|    *dest_str = loader_instance_heap_calloc(inst, str_len, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  291|   152k|    if (NULL == *dest_str) return VK_ERROR_OUT_OF_HOST_MEMORY;
  ------------------
  |  Branch (291:9): [True: 0, False: 152k]
  ------------------
  292|   152k|    loader_strncpy(*dest_str, str_len, source_str, str_len);
  293|   152k|    (*dest_str)[str_len - 1] = 0;
  294|   152k|    return VK_SUCCESS;
  295|   152k|}
create_string_list:
  297|  5.28k|VkResult create_string_list(const struct loader_instance *inst, uint32_t allocated_count, struct loader_string_list *string_list) {
  298|  5.28k|    assert(string_list);
  299|  5.28k|    string_list->list = loader_instance_heap_calloc(inst, sizeof(char *) * allocated_count, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  300|  5.28k|    if (NULL == string_list->list) {
  ------------------
  |  Branch (300:9): [True: 0, False: 5.28k]
  ------------------
  301|      0|        return VK_ERROR_OUT_OF_HOST_MEMORY;
  302|      0|    }
  303|  5.28k|    string_list->allocated_count = allocated_count;
  304|  5.28k|    string_list->count = 0;
  305|  5.28k|    return VK_SUCCESS;
  306|  5.28k|}
increase_str_capacity_by_at_least_one:
  308|  1.11M|VkResult increase_str_capacity_by_at_least_one(const struct loader_instance *inst, struct loader_string_list *string_list) {
  309|  1.11M|    assert(string_list);
  310|  1.11M|    if (string_list->allocated_count == 0) {
  ------------------
  |  Branch (310:9): [True: 0, False: 1.11M]
  ------------------
  311|      0|        string_list->allocated_count = 32;
  312|      0|        string_list->list =
  313|      0|            loader_instance_heap_calloc(inst, sizeof(char *) * string_list->allocated_count, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  314|      0|        if (NULL == string_list->list) {
  ------------------
  |  Branch (314:13): [True: 0, False: 0]
  ------------------
  315|      0|            return VK_ERROR_OUT_OF_HOST_MEMORY;
  316|      0|        }
  317|  1.11M|    } else if (string_list->count + 1 > string_list->allocated_count) {
  ------------------
  |  Branch (317:16): [True: 0, False: 1.11M]
  ------------------
  318|      0|        uint32_t new_allocated_count = string_list->allocated_count * 2;
  319|      0|        void *new_ptr = loader_instance_heap_realloc(inst, string_list->list, sizeof(char *) * string_list->allocated_count,
  320|      0|                                                     sizeof(char *) * new_allocated_count, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  321|      0|        if (NULL == new_ptr) {
  ------------------
  |  Branch (321:13): [True: 0, False: 0]
  ------------------
  322|      0|            return VK_ERROR_OUT_OF_HOST_MEMORY;
  323|      0|        }
  324|      0|        string_list->list = new_ptr;
  325|      0|        string_list->allocated_count *= 2;
  326|      0|    }
  327|  1.11M|    return VK_SUCCESS;
  328|  1.11M|}
append_str_to_string_list:
  330|  1.11M|VkResult append_str_to_string_list(const struct loader_instance *inst, struct loader_string_list *string_list, char *str) {
  331|  1.11M|    assert(string_list && str);
  332|  1.11M|    VkResult res = increase_str_capacity_by_at_least_one(inst, string_list);
  333|  1.11M|    if (res == VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (333:9): [True: 0, False: 1.11M]
  ------------------
  334|      0|        loader_instance_heap_free(inst, str);  // Must clean up in case of failure
  335|      0|        return res;
  336|      0|    }
  337|  1.11M|    string_list->list[string_list->count++] = str;
  338|  1.11M|    return VK_SUCCESS;
  339|  1.11M|}
free_string_list:
  379|   634k|void free_string_list(const struct loader_instance *inst, struct loader_string_list *string_list) {
  380|   634k|    assert(string_list);
  381|   634k|    if (string_list->list) {
  ------------------
  |  Branch (381:9): [True: 5.28k, False: 629k]
  ------------------
  382|  1.12M|        for (uint32_t i = 0; i < string_list->count; i++) {
  ------------------
  |  Branch (382:30): [True: 1.11M, False: 5.28k]
  ------------------
  383|  1.11M|            loader_instance_heap_free(inst, string_list->list[i]);
  384|       |            string_list->list[i] = NULL;
  385|  1.11M|        }
  386|  5.28k|        loader_instance_heap_free(inst, string_list->list);
  387|  5.28k|    }
  388|   634k|    memset(string_list, 0, sizeof(struct loader_string_list));
  389|   634k|}
loader_parse_version_string:
  665|    359|uint32_t loader_parse_version_string(char *vers_str) {
  666|    359|    uint32_t variant = 0, major = 0, minor = 0, patch = 0;
  667|    359|    char *vers_tok;
  668|    359|    char *context = NULL;
  669|    359|    if (!vers_str) {
  ------------------
  |  Branch (669:9): [True: 0, False: 359]
  ------------------
  670|      0|        return 0;
  671|      0|    }
  672|       |
  673|    359|    vers_tok = thread_safe_strtok(vers_str, ".\"\n\r", &context);
  674|    359|    if (NULL != vers_tok) {
  ------------------
  |  Branch (674:9): [True: 329, False: 30]
  ------------------
  675|    329|        major = (uint16_t)atoi(vers_tok);
  676|    329|        vers_tok = thread_safe_strtok(NULL, ".\"\n\r", &context);
  677|    329|        if (NULL != vers_tok) {
  ------------------
  |  Branch (677:13): [True: 266, False: 63]
  ------------------
  678|    266|            minor = (uint16_t)atoi(vers_tok);
  679|    266|            vers_tok = thread_safe_strtok(NULL, ".\"\n\r", &context);
  680|    266|            if (NULL != vers_tok) {
  ------------------
  |  Branch (680:17): [True: 215, False: 51]
  ------------------
  681|    215|                patch = (uint16_t)atoi(vers_tok);
  682|    215|                vers_tok = thread_safe_strtok(NULL, ".\"\n\r", &context);
  683|       |                // check that we are using a 4 part version string
  684|    215|                if (NULL != vers_tok) {
  ------------------
  |  Branch (684:21): [True: 0, False: 215]
  ------------------
  685|       |                    // if we are, move the values over into the correct place
  686|      0|                    variant = major;
  687|      0|                    major = minor;
  688|      0|                    minor = patch;
  689|      0|                    patch = (uint16_t)atoi(vers_tok);
  690|      0|                }
  691|    215|            }
  692|    266|        }
  693|    329|    }
  694|       |
  695|       |    return VK_MAKE_API_VERSION(variant, major, minor, patch);
  696|    359|}
compare_vk_extension_properties:
  698|      3|bool compare_vk_extension_properties(const VkExtensionProperties *op1, const VkExtensionProperties *op2) {
  699|      3|    return strcmp(op1->extensionName, op2->extensionName) == 0 ? true : false;
  ------------------
  |  Branch (699:12): [True: 2, False: 1]
  ------------------
  700|      3|}
has_vk_extension_property:
  712|      3|bool has_vk_extension_property(const VkExtensionProperties *vk_ext_prop, const struct loader_extension_list *ext_list) {
  713|      3|    for (uint32_t i = 0; i < ext_list->count; i++) {
  ------------------
  |  Branch (713:26): [True: 0, False: 3]
  ------------------
  714|      0|        if (compare_vk_extension_properties(&ext_list->list[i], vk_ext_prop)) return true;
  ------------------
  |  Branch (714:13): [True: 0, False: 0]
  ------------------
  715|      0|    }
  716|      3|    return false;
  717|      3|}
has_vk_dev_ext_property:
  720|     19|bool has_vk_dev_ext_property(const VkExtensionProperties *ext_prop, const struct loader_device_extension_list *ext_list) {
  721|     20|    for (uint32_t i = 0; i < ext_list->count; i++) {
  ------------------
  |  Branch (721:26): [True: 3, False: 17]
  ------------------
  722|      3|        if (compare_vk_extension_properties(&ext_list->list[i].props, ext_prop)) return true;
  ------------------
  |  Branch (722:13): [True: 2, False: 1]
  ------------------
  723|      3|    }
  724|     17|    return false;
  725|     19|}
loader_append_layer_property:
  728|   149k|                                      struct loader_layer_properties *layer_property) {
  729|   149k|    VkResult res = VK_SUCCESS;
  730|   149k|    if (layer_list->capacity == 0) {
  ------------------
  |  Branch (730:9): [True: 182, False: 149k]
  ------------------
  731|    182|        res = loader_init_generic_list(inst, (struct loader_generic_list *)layer_list, sizeof(struct loader_layer_properties));
  732|    182|        if (VK_SUCCESS != res) {
  ------------------
  |  Branch (732:13): [True: 0, False: 182]
  ------------------
  733|      0|            goto out;
  734|      0|        }
  735|    182|    }
  736|       |
  737|       |    // Ensure enough room to add an entry
  738|   149k|    if ((layer_list->count + 1) * sizeof(struct loader_layer_properties) > layer_list->capacity) {
  ------------------
  |  Branch (738:9): [True: 238, False: 149k]
  ------------------
  739|    238|        void *new_ptr = loader_instance_heap_realloc(inst, layer_list->list, layer_list->capacity, layer_list->capacity * 2,
  740|    238|                                                     VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  741|    238|        if (NULL == new_ptr) {
  ------------------
  |  Branch (741:13): [True: 0, False: 238]
  ------------------
  742|      0|            loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_append_layer_property: realloc failed for layer list");
  743|      0|            res = VK_ERROR_OUT_OF_HOST_MEMORY;
  744|      0|            goto out;
  745|      0|        }
  746|    238|        layer_list->list = new_ptr;
  747|    238|        layer_list->capacity *= 2;
  748|    238|    }
  749|   149k|    memcpy(&layer_list->list[layer_list->count], layer_property, sizeof(struct loader_layer_properties));
  750|   149k|    layer_list->count++;
  751|   149k|    memset(layer_property, 0, sizeof(struct loader_layer_properties));
  752|   149k|out:
  753|   149k|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (753:9): [True: 0, False: 149k]
  ------------------
  754|      0|        loader_free_layer_properties(inst, layer_property);
  755|      0|    }
  756|   149k|    return res;
  757|   149k|}
loader_delete_layer_list_and_properties:
  816|  3.19k|                                                                  struct loader_layer_list *layer_list) {
  817|  3.19k|    uint32_t i;
  818|  3.19k|    if (!layer_list) return;
  ------------------
  |  Branch (818:9): [True: 0, False: 3.19k]
  ------------------
  819|       |
  820|   151k|    for (i = 0; i < layer_list->count; i++) {
  ------------------
  |  Branch (820:17): [True: 148k, False: 3.19k]
  ------------------
  821|   148k|        if (layer_list->list[i].lib_handle) {
  ------------------
  |  Branch (821:13): [True: 0, False: 148k]
  ------------------
  822|      0|            loader_platform_close_library(layer_list->list[i].lib_handle);
  823|      0|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT | VULKAN_LOADER_LAYER_BIT, 0, "Unloading layer library %s",
  824|      0|                       layer_list->list[i].lib_name);
  825|      0|            layer_list->list[i].lib_handle = NULL;
  826|      0|        }
  827|   148k|        loader_free_layer_properties(inst, &(layer_list->list[i]));
  828|   148k|    }
  829|  3.19k|    layer_list->count = 0;
  830|       |
  831|  3.19k|    if (layer_list->capacity > 0) {
  ------------------
  |  Branch (831:9): [True: 182, False: 3.01k]
  ------------------
  832|    182|        layer_list->capacity = 0;
  833|    182|        loader_instance_heap_free(inst, layer_list->list);
  834|    182|    }
  835|  3.19k|    memset(layer_list, 0, sizeof(struct loader_layer_list));
  836|  3.19k|}
loader_remove_layer_in_list:
  839|    585|                                 uint32_t layer_to_remove) {
  840|    585|    if (layer_list == NULL || layer_to_remove >= layer_list->count) {
  ------------------
  |  Branch (840:9): [True: 0, False: 585]
  |  Branch (840:31): [True: 0, False: 585]
  ------------------
  841|      0|        return;
  842|      0|    }
  843|    585|    loader_free_layer_properties(inst, &(layer_list->list[layer_to_remove]));
  844|       |
  845|       |    // Remove the current invalid meta-layer from the layer list.  Use memmove since we are
  846|       |    // overlapping the source and destination addresses.
  847|    585|    if (layer_to_remove + 1 <= layer_list->count) {
  ------------------
  |  Branch (847:9): [True: 585, False: 0]
  ------------------
  848|    585|        memmove(&layer_list->list[layer_to_remove], &layer_list->list[layer_to_remove + 1],
  849|    585|                sizeof(struct loader_layer_properties) * (layer_list->count - 1 - layer_to_remove));
  850|    585|    }
  851|       |    // Decrement the count (because we now have one less) and decrement the loop index since we need to
  852|       |    // re-check this index.
  853|    585|    layer_list->count--;
  854|    585|}
loader_init_generic_list:
 1035|    201|VkResult loader_init_generic_list(const struct loader_instance *inst, struct loader_generic_list *list_info, size_t element_size) {
 1036|    201|    size_t capacity = 32 * element_size;
 1037|    201|    list_info->count = 0;
 1038|    201|    list_info->capacity = 0;
 1039|    201|    list_info->list = loader_instance_heap_calloc(inst, capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
 1040|    201|    if (list_info->list == NULL) {
  ------------------
  |  Branch (1040:9): [True: 0, False: 201]
  ------------------
 1041|      0|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_init_generic_list: Failed to allocate space for generic list");
 1042|      0|        return VK_ERROR_OUT_OF_HOST_MEMORY;
 1043|      0|    }
 1044|    201|    list_info->capacity = capacity;
 1045|    201|    return VK_SUCCESS;
 1046|    201|}
loader_destroy_generic_list:
 1060|   308k|void loader_destroy_generic_list(const struct loader_instance *inst, struct loader_generic_list *list) {
 1061|   308k|    loader_instance_heap_free(inst, list->list);
 1062|   308k|    memset(list, 0, sizeof(struct loader_generic_list));
 1063|   308k|}
loader_add_to_ext_list:
 1116|      3|                                uint32_t prop_list_count, const VkExtensionProperties *props) {
 1117|      3|    if (ext_list->list == NULL || ext_list->capacity == 0) {
  ------------------
  |  Branch (1117:9): [True: 3, False: 0]
  |  Branch (1117:35): [True: 0, False: 0]
  ------------------
 1118|      3|        VkResult res = loader_init_generic_list(inst, (struct loader_generic_list *)ext_list, sizeof(VkExtensionProperties));
 1119|      3|        if (VK_SUCCESS != res) {
  ------------------
  |  Branch (1119:13): [True: 0, False: 3]
  ------------------
 1120|      0|            return res;
 1121|      0|        }
 1122|      3|    }
 1123|       |
 1124|      6|    for (uint32_t i = 0; i < prop_list_count; i++) {
  ------------------
  |  Branch (1124:26): [True: 3, False: 3]
  ------------------
 1125|      3|        const VkExtensionProperties *cur_ext = &props[i];
 1126|       |
 1127|       |        // look for duplicates
 1128|      3|        if (has_vk_extension_property(cur_ext, ext_list)) {
  ------------------
  |  Branch (1128:13): [True: 0, False: 3]
  ------------------
 1129|      0|            continue;
 1130|      0|        }
 1131|       |
 1132|       |        // add to list at end
 1133|       |        // check for enough capacity
 1134|      3|        if (ext_list->count * sizeof(VkExtensionProperties) >= ext_list->capacity) {
  ------------------
  |  Branch (1134:13): [True: 0, False: 3]
  ------------------
 1135|      0|            void *new_ptr = loader_instance_heap_realloc(inst, ext_list->list, ext_list->capacity, ext_list->capacity * 2,
 1136|      0|                                                         VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
 1137|      0|            if (new_ptr == NULL) {
  ------------------
  |  Branch (1137:17): [True: 0, False: 0]
  ------------------
 1138|      0|                loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
 1139|      0|                           "loader_add_to_ext_list: Failed to reallocate space for extension list");
 1140|      0|                return VK_ERROR_OUT_OF_HOST_MEMORY;
 1141|      0|            }
 1142|      0|            ext_list->list = new_ptr;
 1143|       |
 1144|       |            // double capacity
 1145|      0|            ext_list->capacity *= 2;
 1146|      0|        }
 1147|       |
 1148|      3|        memcpy(&ext_list->list[ext_list->count], cur_ext, sizeof(VkExtensionProperties));
 1149|      3|        ext_list->count++;
 1150|      3|    }
 1151|      3|    return VK_SUCCESS;
 1152|      3|}
loader_add_to_dev_ext_list:
 1159|     19|                                    const VkExtensionProperties *props, struct loader_string_list *entrys) {
 1160|     19|    VkResult res = VK_SUCCESS;
 1161|     19|    bool should_free_entrys = true;
 1162|     19|    if (ext_list->list == NULL || ext_list->capacity == 0) {
  ------------------
  |  Branch (1162:9): [True: 16, False: 3]
  |  Branch (1162:35): [True: 0, False: 3]
  ------------------
 1163|     16|        res = loader_init_generic_list(inst, (struct loader_generic_list *)ext_list, sizeof(struct loader_dev_ext_props));
 1164|     16|        if (VK_SUCCESS != res) {
  ------------------
  |  Branch (1164:13): [True: 0, False: 16]
  ------------------
 1165|      0|            goto out;
 1166|      0|        }
 1167|     16|    }
 1168|       |
 1169|       |    // look for duplicates
 1170|     19|    if (has_vk_dev_ext_property(props, ext_list)) {
  ------------------
  |  Branch (1170:9): [True: 2, False: 17]
  ------------------
 1171|      2|        goto out;
 1172|      2|    }
 1173|       |
 1174|     17|    uint32_t idx = ext_list->count;
 1175|       |    // add to list at end
 1176|       |    // check for enough capacity
 1177|     17|    if (idx * sizeof(struct loader_dev_ext_props) >= ext_list->capacity) {
  ------------------
  |  Branch (1177:9): [True: 0, False: 17]
  ------------------
 1178|      0|        void *new_ptr = loader_instance_heap_realloc(inst, ext_list->list, ext_list->capacity, ext_list->capacity * 2,
 1179|      0|                                                     VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
 1180|       |
 1181|      0|        if (NULL == new_ptr) {
  ------------------
  |  Branch (1181:13): [True: 0, False: 0]
  ------------------
 1182|      0|            loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
 1183|      0|                       "loader_add_to_dev_ext_list: Failed to reallocate space for device extension list");
 1184|      0|            res = VK_ERROR_OUT_OF_HOST_MEMORY;
 1185|      0|            goto out;
 1186|      0|        }
 1187|      0|        ext_list->list = new_ptr;
 1188|       |
 1189|       |        // double capacity
 1190|      0|        ext_list->capacity *= 2;
 1191|      0|    }
 1192|       |
 1193|     17|    memcpy(&ext_list->list[idx].props, props, sizeof(*props));
 1194|     17|    if (entrys) {
  ------------------
  |  Branch (1194:9): [True: 1, False: 16]
  ------------------
 1195|      1|        ext_list->list[idx].entrypoints = *entrys;
 1196|      1|        should_free_entrys = false;
 1197|      1|    }
 1198|     17|    ext_list->count++;
 1199|     19|out:
 1200|     19|    if (NULL != entrys && should_free_entrys) {
  ------------------
  |  Branch (1200:9): [True: 3, False: 16]
  |  Branch (1200:27): [True: 2, False: 1]
  ------------------
 1201|      2|        free_string_list(inst, entrys);
 1202|      2|    }
 1203|     19|    return res;
 1204|     17|}
loader_initialize:
 2298|      2|void loader_initialize(void) {
 2299|      2|    loader_platform_thread_create_mutex(&loader_lock);
 2300|      2|    loader_platform_thread_create_mutex(&loader_preload_icd_lock);
 2301|      2|    init_global_loader_settings();
 2302|      2|#endif
 2303|       |
 2304|       |    // initialize logging
 2305|      2|    loader_init_global_debug_level();
 2306|       |#if defined(_WIN32)
 2307|       |    windows_initialization();
 2308|       |#endif
 2309|       |
 2310|      2|    loader_api_version version = loader_make_full_version(VK_HEADER_VERSION_COMPLETE);
 2311|      2|    loader_log(NULL, VULKAN_LOADER_INFO_BIT, 0, "Vulkan Loader Version %d.%d.%d", version.major, version.minor, version.patch);
 2312|       |
 2313|       |#if defined(GIT_BRANCH_NAME) && defined(GIT_TAG_INFO)
 2314|       |    loader_log(NULL, VULKAN_LOADER_INFO_BIT, 0, "[Vulkan Loader Git - Tag: " GIT_BRANCH_NAME ", Branch/Commit: " GIT_TAG_INFO "]");
 2315|       |#endif
 2316|       |
 2317|      2|    char *loader_disable_dynamic_library_unloading_env_var = loader_getenv("VK_LOADER_DISABLE_DYNAMIC_LIBRARY_UNLOADING", NULL);
 2318|      2|    if (loader_disable_dynamic_library_unloading_env_var &&
  ------------------
  |  Branch (2318:9): [True: 0, False: 2]
  ------------------
 2319|      0|        0 == strncmp(loader_disable_dynamic_library_unloading_env_var, "1", 2)) {
  ------------------
  |  Branch (2319:9): [True: 0, False: 0]
  ------------------
 2320|      0|        loader_disable_dynamic_library_unloading = true;
 2321|      0|        loader_log(NULL, VULKAN_LOADER_WARN_BIT, 0, "Vulkan Loader: library unloading is disabled");
 2322|      2|    } else {
 2323|      2|        loader_disable_dynamic_library_unloading = false;
 2324|      2|    }
 2325|      2|    loader_free_getenv(loader_disable_dynamic_library_unloading_env_var, NULL);
 2326|       |#if defined(LOADER_USE_UNSAFE_FILE_SEARCH)
 2327|       |    loader_log(NULL, VULKAN_LOADER_WARN_BIT, 0, "Vulkan Loader: unsafe searching is enabled");
 2328|       |#endif
 2329|       |#if defined(_WIN32)
 2330|       |    return TRUE;
 2331|       |#endif
 2332|      2|}
loader_init_library:
 2369|      2|__attribute__((constructor)) void loader_init_library(void) { loader_initialize(); }
combine_manifest_directory_and_library_path:
 2405|    122|                                                     const char *manifest_file_path, char **out_fullpath) {
 2406|    122|    assert(library_path && manifest_file_path && out_fullpath);
 2407|    122|    if (loader_platform_is_path_absolute(library_path)) {
  ------------------
  |  Branch (2407:9): [True: 24, False: 98]
  ------------------
 2408|     24|        *out_fullpath = library_path;
 2409|     24|        return VK_SUCCESS;
 2410|     24|    }
 2411|     98|    VkResult res = VK_SUCCESS;
 2412|       |
 2413|     98|    size_t library_path_len = strlen(library_path);
 2414|     98|    size_t manifest_file_path_str_len = strlen(manifest_file_path);
 2415|     98|    bool library_path_contains_directory_symbol = false;
 2416|  2.34k|    for (size_t i = 0; i < library_path_len; i++) {
  ------------------
  |  Branch (2416:24): [True: 2.34k, False: 8]
  ------------------
 2417|  2.34k|        if (library_path[i] == DIRECTORY_SYMBOL) {
  ------------------
  |  |  151|  2.34k|#define DIRECTORY_SYMBOL '/'
  ------------------
  |  Branch (2417:13): [True: 90, False: 2.25k]
  ------------------
 2418|     90|            library_path_contains_directory_symbol = true;
 2419|     90|            break;
 2420|     90|        }
 2421|  2.34k|    }
 2422|       |    // Means that the library_path is neither absolute nor relative - thus we should not modify it at all
 2423|     98|    if (!library_path_contains_directory_symbol) {
  ------------------
  |  Branch (2423:9): [True: 8, False: 90]
  ------------------
 2424|      8|        *out_fullpath = library_path;
 2425|      8|        return VK_SUCCESS;
 2426|      8|    }
 2427|       |    // must include both a directory symbol and the null terminator
 2428|     90|    size_t new_str_len = library_path_len + manifest_file_path_str_len + 1 + 1;
 2429|       |
 2430|     90|    *out_fullpath = loader_instance_heap_calloc(inst, new_str_len, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
 2431|     90|    if (NULL == *out_fullpath) {
  ------------------
  |  Branch (2431:9): [True: 0, False: 90]
  ------------------
 2432|      0|        res = VK_ERROR_OUT_OF_HOST_MEMORY;
 2433|      0|        goto out;
 2434|      0|    }
 2435|     90|    size_t cur_loc_in_out_fullpath = 0;
 2436|       |    // look for the last occurrence of DIRECTORY_SYMBOL in manifest_file_path
 2437|     90|    size_t last_directory_symbol = 0;
 2438|     90|    bool found_directory_symbol = false;
 2439|    758|    for (size_t i = 0; i < manifest_file_path_str_len; i++) {
  ------------------
  |  Branch (2439:24): [True: 668, False: 90]
  ------------------
 2440|    668|        if (manifest_file_path[i] == DIRECTORY_SYMBOL) {
  ------------------
  |  |  151|    668|#define DIRECTORY_SYMBOL '/'
  ------------------
  |  Branch (2440:13): [True: 2, False: 666]
  ------------------
 2441|      2|            last_directory_symbol = i + 1;  // we want to include the symbol
 2442|      2|            found_directory_symbol = true;
 2443|       |            // dont break because we want to find the last occurrence
 2444|      2|        }
 2445|    668|    }
 2446|       |    // Add manifest_file_path up to the last directory symbol
 2447|     90|    if (found_directory_symbol) {
  ------------------
  |  Branch (2447:9): [True: 2, False: 88]
  ------------------
 2448|      2|        loader_strncpy(*out_fullpath, new_str_len, manifest_file_path, last_directory_symbol);
 2449|      2|        cur_loc_in_out_fullpath += last_directory_symbol;
 2450|      2|    }
 2451|     90|    loader_strncpy(&(*out_fullpath)[cur_loc_in_out_fullpath], new_str_len - cur_loc_in_out_fullpath, library_path,
 2452|     90|                   library_path_len);
 2453|     90|    cur_loc_in_out_fullpath += library_path_len + 1;
 2454|     90|    (*out_fullpath)[cur_loc_in_out_fullpath] = '\0';
 2455|       |
 2456|     90|out:
 2457|     90|    loader_instance_heap_free(inst, library_path);
 2458|       |
 2459|     90|    return res;
 2460|     90|}
loader_read_layer_json:
 2743|  12.0k|                                cJSON *layer_node, loader_api_version version, bool is_implicit, char *filename) {
 2744|  12.0k|    assert(layer_instance_list);
 2745|  12.0k|    char *library_path = NULL;
 2746|  12.0k|    VkResult result = VK_SUCCESS;
 2747|  12.0k|    struct loader_layer_properties props = {0};
 2748|       |
 2749|  12.0k|    result = loader_copy_to_new_str(inst, filename, &props.manifest_file_name);
 2750|  12.0k|    if (result == VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (2750:9): [True: 0, False: 12.0k]
  ------------------
 2751|      0|        goto out;
 2752|      0|    }
 2753|       |
 2754|       |    // Parse name
 2755|       |
 2756|  12.0k|    result = loader_parse_json_string_to_existing_str(layer_node, "name", VK_MAX_EXTENSION_NAME_SIZE, props.info.layerName);
 2757|  12.0k|    if (VK_ERROR_INITIALIZATION_FAILED == result) {
  ------------------
  |  Branch (2757:9): [True: 3.53k, False: 8.55k]
  ------------------
 2758|  3.53k|        loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2759|  3.53k|                   "Layer located at %s didn't find required layer value \"name\" in manifest JSON file, skipping this layer",
 2760|  3.53k|                   filename);
 2761|  3.53k|        goto out;
 2762|  3.53k|    }
 2763|       |
 2764|       |    // Check if this layer's name matches the override layer name, set is_override to true if so.
 2765|  8.55k|    if (!strcmp(props.info.layerName, VK_OVERRIDE_LAYER_NAME)) {
  ------------------
  |  |  138|  8.55k|#define VK_OVERRIDE_LAYER_NAME "VK_LAYER_LUNARG_override"
  ------------------
  |  Branch (2765:9): [True: 1, False: 8.55k]
  ------------------
 2766|      1|        props.is_override = true;
 2767|      1|    }
 2768|       |
 2769|  8.55k|    if (0 != strncmp(props.info.layerName, "VK_LAYER_", 9)) {
  ------------------
  |  Branch (2769:9): [True: 8.49k, False: 62]
  ------------------
 2770|  8.49k|        loader_log(inst, VULKAN_LOADER_WARN_BIT, 0, "Layer name %s does not conform to naming standard (Policy #LLP_LAYER_3)",
 2771|  8.49k|                   props.info.layerName);
 2772|  8.49k|    }
 2773|       |
 2774|       |    // Parse type
 2775|  8.55k|    char *type = loader_cJSON_GetStringValue(loader_cJSON_GetObjectItem(layer_node, "type"));
 2776|  8.55k|    if (NULL == type) {
  ------------------
  |  Branch (2776:9): [True: 179, False: 8.37k]
  ------------------
 2777|    179|        loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2778|    179|                   "Layer located at %s didn't find required layer value \"type\" in manifest JSON file, skipping this layer",
 2779|    179|                   filename);
 2780|    179|        result = VK_ERROR_INITIALIZATION_FAILED;
 2781|    179|        goto out;
 2782|    179|    }
 2783|       |
 2784|       |    // Add list entry
 2785|  8.37k|    if (!strcmp(type, "DEVICE")) {
  ------------------
  |  Branch (2785:9): [True: 0, False: 8.37k]
  ------------------
 2786|      0|        loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0, "Device layers are deprecated. Skipping layer %s",
 2787|      0|                   props.info.layerName);
 2788|      0|        result = VK_ERROR_INITIALIZATION_FAILED;
 2789|      0|        goto out;
 2790|      0|    }
 2791|       |
 2792|       |    // Allow either GLOBAL or INSTANCE type interchangeably to handle layers that must work with older loaders
 2793|  8.37k|    if (!strcmp(type, "INSTANCE") || !strcmp(type, "GLOBAL")) {
  ------------------
  |  Branch (2793:9): [True: 6.97k, False: 1.40k]
  |  Branch (2793:38): [True: 181, False: 1.22k]
  ------------------
 2794|  7.15k|        props.type_flags = VK_LAYER_TYPE_FLAG_INSTANCE_LAYER;
 2795|  7.15k|        if (!is_implicit) {
  ------------------
  |  Branch (2795:13): [True: 7.14k, False: 11]
  ------------------
 2796|  7.14k|            props.type_flags |= VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER;
 2797|  7.14k|        }
 2798|  7.15k|    } else {
 2799|  1.22k|        result = VK_ERROR_INITIALIZATION_FAILED;
 2800|  1.22k|        goto out;
 2801|  1.22k|    }
 2802|       |
 2803|       |    // Parse api_version
 2804|  7.15k|    char *api_version = loader_cJSON_GetStringValue(loader_cJSON_GetObjectItem(layer_node, "api_version"));
 2805|  7.15k|    if (NULL == api_version) {
  ------------------
  |  Branch (2805:9): [True: 6.89k, False: 255]
  ------------------
 2806|  6.89k|        loader_log(
 2807|  6.89k|            inst, VULKAN_LOADER_WARN_BIT, 0,
 2808|  6.89k|            "Layer located at %s didn't find required layer value \"api_version\" in manifest JSON file, skipping this layer",
 2809|  6.89k|            filename);
 2810|  6.89k|        goto out;
 2811|  6.89k|    }
 2812|       |
 2813|    255|    props.info.specVersion = loader_parse_version_string(api_version);
 2814|       |
 2815|       |    // Make sure the layer's manifest doesn't contain a non zero variant value
 2816|    255|    if (VK_API_VERSION_VARIANT(props.info.specVersion) != 0) {
  ------------------
  |  Branch (2816:9): [True: 0, False: 255]
  ------------------
 2817|      0|        loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 2818|      0|                   "Layer \"%s\" has an \'api_version\' field which contains a non-zero variant value of %d. "
 2819|      0|                   " Skipping Layer.",
 2820|      0|                   props.info.layerName, VK_API_VERSION_VARIANT(props.info.specVersion));
 2821|      0|        result = VK_ERROR_INITIALIZATION_FAILED;
 2822|      0|        goto out;
 2823|      0|    }
 2824|       |
 2825|       |    // Parse implementation_version
 2826|    255|    char *implementation_version = loader_cJSON_GetStringValue(loader_cJSON_GetObjectItem(layer_node, "implementation_version"));
 2827|    255|    if (NULL == implementation_version) {
  ------------------
  |  Branch (2827:9): [True: 17, False: 238]
  ------------------
 2828|     17|        loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2829|     17|                   "Layer located at %s didn't find required layer value \"implementation_version\" in manifest JSON file, "
 2830|     17|                   "skipping this layer",
 2831|     17|                   filename);
 2832|     17|        goto out;
 2833|     17|    }
 2834|    238|    props.info.implementationVersion = atoi(implementation_version);
 2835|       |
 2836|       |    // Parse description
 2837|       |
 2838|    238|    result = loader_parse_json_string_to_existing_str(layer_node, "description", VK_MAX_DESCRIPTION_SIZE, props.info.description);
 2839|    238|    if (VK_ERROR_INITIALIZATION_FAILED == result) {
  ------------------
  |  Branch (2839:9): [True: 4, False: 234]
  ------------------
 2840|      4|        loader_log(
 2841|      4|            inst, VULKAN_LOADER_WARN_BIT, 0,
 2842|      4|            "Layer located at %s didn't find required layer value \"description\" in manifest JSON file, skipping this layer",
 2843|      4|            filename);
 2844|      4|        goto out;
 2845|      4|    }
 2846|       |
 2847|       |    // Parse library_path
 2848|       |
 2849|       |    // Library path no longer required unless component_layers is also not defined
 2850|    234|    result = loader_parse_json_string(layer_node, "library_path", &library_path);
 2851|    234|    if (result == VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (2851:9): [True: 0, False: 234]
  ------------------
 2852|      0|        loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2853|      0|                   "Skipping layer \"%s\" due to problem accessing the library_path value in the manifest JSON file",
 2854|      0|                   props.info.layerName);
 2855|      0|        result = VK_ERROR_OUT_OF_HOST_MEMORY;
 2856|      0|        goto out;
 2857|      0|    }
 2858|    234|    if (NULL != library_path) {
  ------------------
  |  Branch (2858:9): [True: 130, False: 104]
  ------------------
 2859|    130|        if (NULL != loader_cJSON_GetObjectItem(layer_node, "component_layers")) {
  ------------------
  |  Branch (2859:13): [True: 8, False: 122]
  ------------------
 2860|      8|            loader_log(
 2861|      8|                inst, VULKAN_LOADER_WARN_BIT, 0,
 2862|      8|                "Layer \"%s\" contains meta-layer-specific component_layers, but also defining layer library path.  Both are not "
 2863|      8|                "compatible, so skipping this layer",
 2864|      8|                props.info.layerName);
 2865|      8|            result = VK_ERROR_INITIALIZATION_FAILED;
 2866|      8|            loader_instance_heap_free(inst, library_path);
 2867|      8|            goto out;
 2868|      8|        }
 2869|       |
 2870|       |        // This function takes ownership of library_path_str - so we don't need to clean it up
 2871|    122|        result = combine_manifest_directory_and_library_path(inst, library_path, filename, &props.lib_name);
 2872|    122|        if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (2872:13): [True: 0, False: 122]
  ------------------
 2873|    122|    }
 2874|       |
 2875|       |    // Parse component_layers
 2876|       |
 2877|    226|    if (NULL == library_path) {
  ------------------
  |  Branch (2877:9): [True: 104, False: 122]
  ------------------
 2878|    104|        if (!loader_check_version_meets_required(LOADER_VERSION_1_1_0, version)) {
  ------------------
  |  |  261|    104|#define LOADER_VERSION_1_1_0 loader_combine_version(1, 1, 0)
  ------------------
  |  Branch (2878:13): [True: 96, False: 8]
  ------------------
 2879|     96|            loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2880|     96|                       "Layer \"%s\" contains meta-layer-specific component_layers, but using older JSON file version.",
 2881|     96|                       props.info.layerName);
 2882|     96|        }
 2883|       |
 2884|    104|        result = loader_parse_json_array_of_strings(inst, layer_node, "component_layers", &(props.component_layer_names));
 2885|    104|        if (VK_ERROR_OUT_OF_HOST_MEMORY == result) {
  ------------------
  |  Branch (2885:13): [True: 0, False: 104]
  ------------------
 2886|      0|            goto out;
 2887|      0|        }
 2888|    104|        if (VK_ERROR_INITIALIZATION_FAILED == result) {
  ------------------
  |  Branch (2888:13): [True: 80, False: 24]
  ------------------
 2889|     80|            loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2890|     80|                       "Layer \"%s\" is missing both library_path and component_layers fields.  One or the other MUST be defined.  "
 2891|     80|                       "Skipping this layer",
 2892|     80|                       props.info.layerName);
 2893|     80|            goto out;
 2894|     80|        }
 2895|       |        // This is now, officially, a meta-layer
 2896|     24|        props.type_flags |= VK_LAYER_TYPE_FLAG_META_LAYER;
 2897|     24|        loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0, "Encountered meta-layer \"%s\"",
 2898|     24|                   props.info.layerName);
 2899|     24|    }
 2900|       |
 2901|       |    // Parse blacklisted_layers
 2902|       |
 2903|    146|    if (props.is_override) {
  ------------------
  |  Branch (2903:9): [True: 0, False: 146]
  ------------------
 2904|      0|        result = loader_parse_json_array_of_strings(inst, layer_node, "blacklisted_layers", &(props.blacklist_layer_names));
 2905|      0|        if (VK_ERROR_OUT_OF_HOST_MEMORY == result) {
  ------------------
  |  Branch (2905:13): [True: 0, False: 0]
  ------------------
 2906|      0|            goto out;
 2907|      0|        }
 2908|      0|    }
 2909|       |
 2910|       |    // Parse override_paths
 2911|       |
 2912|    146|    result = loader_parse_json_array_of_strings(inst, layer_node, "override_paths", &(props.override_paths));
 2913|    146|    if (VK_ERROR_OUT_OF_HOST_MEMORY == result) {
  ------------------
  |  Branch (2913:9): [True: 0, False: 146]
  ------------------
 2914|      0|        goto out;
 2915|      0|    }
 2916|    146|    if (NULL != props.override_paths.list && !loader_check_version_meets_required(loader_combine_version(1, 1, 0), version)) {
  ------------------
  |  Branch (2916:9): [True: 0, False: 146]
  |  Branch (2916:46): [True: 0, False: 0]
  ------------------
 2917|      0|        loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2918|      0|                   "Layer \"%s\" contains meta-layer-specific override paths, but using older JSON file version.",
 2919|      0|                   props.info.layerName);
 2920|      0|    }
 2921|       |
 2922|       |    // Parse disable_environment
 2923|       |
 2924|    146|    if (is_implicit) {
  ------------------
  |  Branch (2924:9): [True: 11, False: 135]
  ------------------
 2925|     11|        cJSON *disable_environment = loader_cJSON_GetObjectItem(layer_node, "disable_environment");
 2926|     11|        if (disable_environment == NULL) {
  ------------------
  |  Branch (2926:13): [True: 2, False: 9]
  ------------------
 2927|      2|            loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2928|      2|                       "Layer \"%s\" doesn't contain required layer object disable_environment in the manifest JSON file, skipping "
 2929|      2|                       "this layer",
 2930|      2|                       props.info.layerName);
 2931|      2|            result = VK_ERROR_INITIALIZATION_FAILED;
 2932|      2|            goto out;
 2933|      2|        }
 2934|       |
 2935|      9|        if (!disable_environment->child || disable_environment->child->type != cJSON_String ||
  ------------------
  |  |  101|     18|#define cJSON_String (1 << 4)
  ------------------
  |  Branch (2935:13): [True: 0, False: 9]
  |  Branch (2935:44): [True: 0, False: 9]
  ------------------
 2936|      9|            !disable_environment->child->string || !disable_environment->child->valuestring) {
  ------------------
  |  Branch (2936:13): [True: 0, False: 9]
  |  Branch (2936:52): [True: 0, False: 9]
  ------------------
 2937|      0|            loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2938|      0|                       "Layer \"%s\" doesn't contain required child value in object disable_environment in the manifest JSON file, "
 2939|      0|                       "skipping this layer (Policy #LLP_LAYER_9)",
 2940|      0|                       props.info.layerName);
 2941|      0|            result = VK_ERROR_INITIALIZATION_FAILED;
 2942|      0|            goto out;
 2943|      0|        }
 2944|      9|        result = loader_copy_to_new_str(inst, disable_environment->child->string, &(props.disable_env_var.name));
 2945|      9|        if (VK_SUCCESS != result) goto out;
  ------------------
  |  Branch (2945:13): [True: 0, False: 9]
  ------------------
 2946|      9|        result = loader_copy_to_new_str(inst, disable_environment->child->valuestring, &(props.disable_env_var.value));
 2947|      9|        if (VK_SUCCESS != result) goto out;
  ------------------
  |  Branch (2947:13): [True: 0, False: 9]
  ------------------
 2948|      9|    }
 2949|       |
 2950|       |    // Now get all optional items and objects and put in list:
 2951|       |    // functions
 2952|       |    // instance_extensions
 2953|       |    // device_extensions
 2954|       |    // enable_environment (implicit layers only)
 2955|       |    // library_arch
 2956|       |
 2957|       |    // Layer interface functions
 2958|       |    //    vkGetInstanceProcAddr
 2959|       |    //    vkGetDeviceProcAddr
 2960|       |    //    vkNegotiateLoaderLayerInterfaceVersion (starting with JSON file 1.1.0)
 2961|    144|    cJSON *functions = loader_cJSON_GetObjectItem(layer_node, "functions");
 2962|    144|    if (functions != NULL) {
  ------------------
  |  Branch (2962:9): [True: 0, False: 144]
  ------------------
 2963|      0|        if (loader_check_version_meets_required(loader_combine_version(1, 1, 0), version)) {
  ------------------
  |  Branch (2963:13): [True: 0, False: 0]
  ------------------
 2964|      0|            result = loader_parse_json_string(functions, "vkNegotiateLoaderLayerInterfaceVersion",
 2965|      0|                                              &props.functions.str_negotiate_interface);
 2966|      0|            if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (2966:17): [True: 0, False: 0]
  ------------------
 2967|      0|        }
 2968|      0|        result = loader_parse_json_string(functions, "vkGetInstanceProcAddr", &props.functions.str_gipa);
 2969|      0|        if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (2969:13): [True: 0, False: 0]
  ------------------
 2970|       |
 2971|      0|        if (NULL == props.functions.str_negotiate_interface && props.functions.str_gipa &&
  ------------------
  |  Branch (2971:13): [True: 0, False: 0]
  |  Branch (2971:64): [True: 0, False: 0]
  ------------------
 2972|      0|            loader_check_version_meets_required(loader_combine_version(1, 1, 0), version)) {
  ------------------
  |  Branch (2972:13): [True: 0, False: 0]
  ------------------
 2973|      0|            loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
 2974|      0|                       "Layer \"%s\" using deprecated \'vkGetInstanceProcAddr\' tag which was deprecated starting with JSON "
 2975|      0|                       "file version 1.1.0. The new vkNegotiateLoaderLayerInterfaceVersion function is preferred, though for "
 2976|      0|                       "compatibility reasons it may be desirable to continue using the deprecated tag.",
 2977|      0|                       props.info.layerName);
 2978|      0|        }
 2979|       |
 2980|      0|        result = loader_parse_json_string(functions, "vkGetDeviceProcAddr", &props.functions.str_gdpa);
 2981|      0|        if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (2981:13): [True: 0, False: 0]
  ------------------
 2982|       |
 2983|      0|        if (NULL == props.functions.str_negotiate_interface && props.functions.str_gdpa &&
  ------------------
  |  Branch (2983:13): [True: 0, False: 0]
  |  Branch (2983:64): [True: 0, False: 0]
  ------------------
 2984|      0|            loader_check_version_meets_required(loader_combine_version(1, 1, 0), version)) {
  ------------------
  |  Branch (2984:13): [True: 0, False: 0]
  ------------------
 2985|      0|            loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
 2986|      0|                       "Layer \"%s\" using deprecated \'vkGetDeviceProcAddr\' tag which was deprecated starting with JSON "
 2987|      0|                       "file version 1.1.0. The new vkNegotiateLoaderLayerInterfaceVersion function is preferred, though for "
 2988|      0|                       "compatibility reasons it may be desirable to continue using the deprecated tag.",
 2989|      0|                       props.info.layerName);
 2990|      0|        }
 2991|      0|    }
 2992|       |
 2993|       |    // instance_extensions
 2994|       |    //   array of {
 2995|       |    //     name
 2996|       |    //     spec_version
 2997|       |    //   }
 2998|       |
 2999|    144|    cJSON *instance_extensions = loader_cJSON_GetObjectItem(layer_node, "instance_extensions");
 3000|    144|    if (instance_extensions != NULL && instance_extensions->type == cJSON_Array) {
  ------------------
  |  |  102|      5|#define cJSON_Array (1 << 5)
  ------------------
  |  Branch (3000:9): [True: 5, False: 139]
  |  Branch (3000:40): [True: 3, False: 2]
  ------------------
 3001|      3|        cJSON *ext_item = NULL;
 3002|      6|        cJSON_ArrayForEach(ext_item, instance_extensions) {
  ------------------
  |  |  213|      9|    for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
  |  |  ------------------
  |  |  |  Branch (213:20): [True: 3, False: 0]
  |  |  |  Branch (213:61): [True: 6, False: 3]
  |  |  ------------------
  ------------------
 3003|      6|            if (ext_item->type != cJSON_Object) {
  ------------------
  |  |  103|      6|#define cJSON_Object (1 << 6)
  ------------------
  |  Branch (3003:17): [True: 3, False: 3]
  ------------------
 3004|      3|                continue;
 3005|      3|            }
 3006|       |
 3007|      3|            VkExtensionProperties ext_prop = {0};
 3008|      3|            result = loader_parse_json_string_to_existing_str(ext_item, "name", VK_MAX_EXTENSION_NAME_SIZE, ext_prop.extensionName);
 3009|      3|            if (result == VK_ERROR_INITIALIZATION_FAILED) {
  ------------------
  |  Branch (3009:17): [True: 0, False: 3]
  ------------------
 3010|      0|                continue;
 3011|      0|            }
 3012|      3|            char *spec_version = NULL;
 3013|      3|            result = loader_parse_json_string(ext_item, "spec_version", &spec_version);
 3014|      3|            if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (3014:17): [True: 0, False: 3]
  ------------------
 3015|      3|            if (NULL != spec_version) {
  ------------------
  |  Branch (3015:17): [True: 0, False: 3]
  ------------------
 3016|      0|                ext_prop.specVersion = atoi(spec_version);
 3017|      0|            }
 3018|      3|            loader_instance_heap_free(inst, spec_version);
 3019|      3|            bool ext_unsupported = wsi_unsupported_instance_extension(&ext_prop);
 3020|      3|            if (!ext_unsupported) {
  ------------------
  |  Branch (3020:17): [True: 3, False: 0]
  ------------------
 3021|      3|                loader_add_to_ext_list(inst, &props.instance_extension_list, 1, &ext_prop);
 3022|      3|            }
 3023|      3|        }
 3024|      3|    }
 3025|       |
 3026|       |    // device_extensions
 3027|       |    //   array of {
 3028|       |    //     name
 3029|       |    //     spec_version
 3030|       |    //     entrypoints
 3031|       |    //   }
 3032|    144|    cJSON *device_extensions = loader_cJSON_GetObjectItem(layer_node, "device_extensions");
 3033|    144|    if (device_extensions != NULL && device_extensions->type == cJSON_Array) {
  ------------------
  |  |  102|     24|#define cJSON_Array (1 << 5)
  ------------------
  |  Branch (3033:9): [True: 24, False: 120]
  |  Branch (3033:38): [True: 20, False: 4]
  ------------------
 3034|     20|        cJSON *ext_item = NULL;
 3035|     40|        cJSON_ArrayForEach(ext_item, device_extensions) {
  ------------------
  |  |  213|     60|    for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
  |  |  ------------------
  |  |  |  Branch (213:20): [True: 20, False: 0]
  |  |  |  Branch (213:61): [True: 40, False: 20]
  |  |  ------------------
  ------------------
 3036|     40|            if (ext_item->type != cJSON_Object) {
  ------------------
  |  |  103|     40|#define cJSON_Object (1 << 6)
  ------------------
  |  Branch (3036:17): [True: 18, False: 22]
  ------------------
 3037|     18|                continue;
 3038|     18|            }
 3039|       |
 3040|     22|            VkExtensionProperties ext_prop = {0};
 3041|     22|            result = loader_parse_json_string_to_existing_str(ext_item, "name", VK_MAX_EXTENSION_NAME_SIZE, ext_prop.extensionName);
 3042|     22|            if (result == VK_ERROR_INITIALIZATION_FAILED) {
  ------------------
  |  Branch (3042:17): [True: 3, False: 19]
  ------------------
 3043|      3|                continue;
 3044|      3|            }
 3045|       |
 3046|     19|            char *spec_version = NULL;
 3047|     19|            result = loader_parse_json_string(ext_item, "spec_version", &spec_version);
 3048|     19|            if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (3048:17): [True: 0, False: 19]
  ------------------
 3049|     19|            if (NULL != spec_version) {
  ------------------
  |  Branch (3049:17): [True: 0, False: 19]
  ------------------
 3050|      0|                ext_prop.specVersion = atoi(spec_version);
 3051|      0|            }
 3052|     19|            loader_instance_heap_free(inst, spec_version);
 3053|       |
 3054|     19|            cJSON *entrypoints = loader_cJSON_GetObjectItem(ext_item, "entrypoints");
 3055|     19|            if (entrypoints == NULL) {
  ------------------
  |  Branch (3055:17): [True: 16, False: 3]
  ------------------
 3056|     16|                result = loader_add_to_dev_ext_list(inst, &props.device_extension_list, &ext_prop, NULL);
 3057|     16|                if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (3057:21): [True: 0, False: 16]
  ------------------
 3058|     16|                continue;
 3059|     16|            }
 3060|       |
 3061|      3|            struct loader_string_list entrys = {0};
 3062|      3|            result = loader_parse_json_array_of_strings(inst, ext_item, "entrypoints", &entrys);
 3063|      3|            if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (3063:17): [True: 0, False: 3]
  ------------------
 3064|      3|            result = loader_add_to_dev_ext_list(inst, &props.device_extension_list, &ext_prop, &entrys);
 3065|      3|            if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (3065:17): [True: 0, False: 3]
  ------------------
 3066|      3|        }
 3067|     20|    }
 3068|    144|    if (is_implicit) {
  ------------------
  |  Branch (3068:9): [True: 9, False: 135]
  ------------------
 3069|      9|        cJSON *enable_environment = loader_cJSON_GetObjectItem(layer_node, "enable_environment");
 3070|       |
 3071|       |        // enable_environment is optional
 3072|      9|        if (enable_environment && enable_environment->child && enable_environment->child->type == cJSON_String &&
  ------------------
  |  |  101|     18|#define cJSON_String (1 << 4)
  ------------------
  |  Branch (3072:13): [True: 9, False: 0]
  |  Branch (3072:35): [True: 9, False: 0]
  |  Branch (3072:64): [True: 9, False: 0]
  ------------------
 3073|      9|            enable_environment->child->string && enable_environment->child->valuestring) {
  ------------------
  |  Branch (3073:13): [True: 9, False: 0]
  |  Branch (3073:50): [True: 9, False: 0]
  ------------------
 3074|      9|            result = loader_copy_to_new_str(inst, enable_environment->child->string, &(props.enable_env_var.name));
 3075|      9|            if (VK_SUCCESS != result) goto out;
  ------------------
  |  Branch (3075:17): [True: 0, False: 9]
  ------------------
 3076|      9|            result = loader_copy_to_new_str(inst, enable_environment->child->valuestring, &(props.enable_env_var.value));
 3077|      9|            if (VK_SUCCESS != result) goto out;
  ------------------
  |  Branch (3077:17): [True: 0, False: 9]
  ------------------
 3078|      9|        }
 3079|      9|    }
 3080|       |
 3081|       |    // Read in the pre-instance stuff
 3082|    144|    cJSON *pre_instance = loader_cJSON_GetObjectItem(layer_node, "pre_instance_functions");
 3083|    144|    if (NULL != pre_instance) {
  ------------------
  |  Branch (3083:9): [True: 0, False: 144]
  ------------------
 3084|       |        // Supported versions started in 1.1.2, so anything newer
 3085|      0|        if (!loader_check_version_meets_required(loader_combine_version(1, 1, 2), version)) {
  ------------------
  |  Branch (3085:13): [True: 0, False: 0]
  ------------------
 3086|      0|            loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
 3087|      0|                       "Found pre_instance_functions section in layer from \"%s\". This section is only valid in manifest version "
 3088|      0|                       "1.1.2 or later. The section will be ignored",
 3089|      0|                       filename);
 3090|      0|        } else if (!is_implicit) {
  ------------------
  |  Branch (3090:20): [True: 0, False: 0]
  ------------------
 3091|      0|            loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 3092|      0|                       "Found pre_instance_functions section in explicit layer from \"%s\". This section is only valid in implicit "
 3093|      0|                       "layers. The section will be ignored",
 3094|      0|                       filename);
 3095|      0|        } else {
 3096|      0|            result = loader_parse_json_string(pre_instance, "vkEnumerateInstanceExtensionProperties",
 3097|      0|                                              &props.pre_instance_functions.enumerate_instance_extension_properties);
 3098|      0|            if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (3098:17): [True: 0, False: 0]
  ------------------
 3099|       |
 3100|      0|            result = loader_parse_json_string(pre_instance, "vkEnumerateInstanceLayerProperties",
 3101|      0|                                              &props.pre_instance_functions.enumerate_instance_layer_properties);
 3102|      0|            if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (3102:17): [True: 0, False: 0]
  ------------------
 3103|       |
 3104|      0|            result = loader_parse_json_string(pre_instance, "vkEnumerateInstanceVersion",
 3105|      0|                                              &props.pre_instance_functions.enumerate_instance_version);
 3106|      0|            if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (3106:17): [True: 0, False: 0]
  ------------------
 3107|      0|        }
 3108|      0|    }
 3109|       |
 3110|    144|    if (loader_cJSON_GetObjectItem(layer_node, "app_keys")) {
  ------------------
  |  Branch (3110:9): [True: 0, False: 144]
  ------------------
 3111|      0|        if (!props.is_override) {
  ------------------
  |  Branch (3111:13): [True: 0, False: 0]
  ------------------
 3112|      0|            loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 3113|      0|                       "Layer %s contains app_keys, but any app_keys can only be provided by the override meta layer. "
 3114|      0|                       "These will be ignored.",
 3115|      0|                       props.info.layerName);
 3116|      0|        }
 3117|       |
 3118|      0|        result = loader_parse_json_array_of_strings(inst, layer_node, "app_keys", &props.app_key_paths);
 3119|      0|        if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (3119:13): [True: 0, False: 0]
  ------------------
 3120|      0|    }
 3121|       |
 3122|    144|    char *library_arch = loader_cJSON_GetStringValue(loader_cJSON_GetObjectItem(layer_node, "library_arch"));
 3123|    144|    if (NULL != library_arch) {
  ------------------
  |  Branch (3123:9): [True: 0, False: 144]
  ------------------
 3124|      0|        if ((strncmp(library_arch, "32", 2) == 0 && sizeof(void *) != 4) ||
  ------------------
  |  Branch (3124:14): [True: 0, False: 0]
  |  Branch (3124:53): [True: 0, Folded]
  ------------------
 3125|      0|            (strncmp(library_arch, "64", 2) == 0 && sizeof(void *) != 8)) {
  ------------------
  |  Branch (3125:14): [True: 0, False: 0]
  |  Branch (3125:53): [Folded, False: 0]
  ------------------
 3126|      0|            loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
 3127|      0|                       "The library architecture in layer %s doesn't match the current running architecture, skipping this layer",
 3128|      0|                       filename);
 3129|      0|            result = VK_ERROR_INITIALIZATION_FAILED;
 3130|      0|            goto out;
 3131|      0|        }
 3132|      0|    }
 3133|       |
 3134|    144|    result = VK_SUCCESS;
 3135|       |
 3136|  12.0k|out:
 3137|       |    // Try to append the layer property
 3138|  12.0k|    if (VK_SUCCESS == result) {
  ------------------
  |  Branch (3138:9): [True: 7.05k, False: 5.02k]
  ------------------
 3139|  7.05k|        result = loader_append_layer_property(inst, layer_instance_list, &props);
 3140|  7.05k|    }
 3141|       |    // If appending fails - free all the memory allocated in it
 3142|  12.0k|    if (VK_SUCCESS != result) {
  ------------------
  |  Branch (3142:9): [True: 5.02k, False: 7.05k]
  ------------------
 3143|  5.02k|        loader_free_layer_properties(inst, &props);
 3144|  5.02k|    }
 3145|  12.0k|    return result;
 3146|    144|}
is_valid_layer_json_version:
 3148|    104|bool is_valid_layer_json_version(const loader_api_version *layer_json) {
 3149|       |    // Supported versions are: 1.0.0, 1.0.1, 1.1.0 - 1.1.2, and 1.2.0 - 1.2.1.
 3150|    104|    if ((layer_json->major == 1 && layer_json->minor == 2 && layer_json->patch < 2) ||
  ------------------
  |  Branch (3150:10): [True: 31, False: 73]
  |  Branch (3150:36): [True: 3, False: 28]
  |  Branch (3150:62): [True: 0, False: 3]
  ------------------
 3151|    104|        (layer_json->major == 1 && layer_json->minor == 1 && layer_json->patch < 3) ||
  ------------------
  |  Branch (3151:10): [True: 31, False: 73]
  |  Branch (3151:36): [True: 0, False: 31]
  |  Branch (3151:62): [True: 0, False: 0]
  ------------------
 3152|    104|        (layer_json->major == 1 && layer_json->minor == 0 && layer_json->patch < 2)) {
  ------------------
  |  Branch (3152:10): [True: 31, False: 73]
  |  Branch (3152:36): [True: 21, False: 10]
  |  Branch (3152:62): [True: 12, False: 9]
  ------------------
 3153|     12|        return true;
 3154|     12|    }
 3155|     92|    return false;
 3156|    104|}
loader_add_layer_properties:
 3168|    108|                                     bool is_implicit, char *filename) {
 3169|       |    // The following Fields in layer manifest file that are required:
 3170|       |    //   - "file_format_version"
 3171|       |    //   - If more than one "layer" object are used, then the "layers" array is
 3172|       |    //     required
 3173|    108|    VkResult result = VK_ERROR_INITIALIZATION_FAILED;
 3174|       |    // Make sure sure the top level json value is an object
 3175|    108|    if (!json || json->type != cJSON_Object) {
  ------------------
  |  |  103|    108|#define cJSON_Object (1 << 6)
  ------------------
  |  Branch (3175:9): [True: 0, False: 108]
  |  Branch (3175:18): [True: 4, False: 104]
  ------------------
 3176|      4|        goto out;
 3177|      4|    }
 3178|    104|    char *file_vers = loader_cJSON_GetStringValue(loader_cJSON_GetObjectItem(json, "file_format_version"));
 3179|    104|    if (NULL == file_vers) {
  ------------------
  |  Branch (3179:9): [True: 0, False: 104]
  ------------------
 3180|      0|        loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 3181|      0|                   "loader_add_layer_properties: Manifest %s missing required field file_format_version", filename);
 3182|      0|        goto out;
 3183|      0|    }
 3184|       |
 3185|    104|    loader_log(inst, VULKAN_LOADER_INFO_BIT, 0, "Found manifest file %s (file version %s)", filename, file_vers);
 3186|       |    // Get the major/minor/and patch as integers for easier comparison
 3187|    104|    loader_api_version json_version = loader_make_full_version(loader_parse_version_string(file_vers));
 3188|       |
 3189|    104|    if (!is_valid_layer_json_version(&json_version)) {
  ------------------
  |  Branch (3189:9): [True: 92, False: 12]
  ------------------
 3190|     92|        loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 3191|     92|                   "loader_add_layer_properties: %s has unknown layer manifest file version %d.%d.%d.  May cause errors.", filename,
 3192|     92|                   json_version.major, json_version.minor, json_version.patch);
 3193|     92|    }
 3194|       |
 3195|       |    // If "layers" is present, read in the array of layer objects
 3196|    104|    cJSON *layers_node = loader_cJSON_GetObjectItem(json, "layers");
 3197|    104|    if (layers_node != NULL) {
  ------------------
  |  Branch (3197:9): [True: 97, False: 7]
  ------------------
 3198|       |        // Supported versions started in 1.0.1, so anything newer
 3199|     97|        if (!loader_check_version_meets_required(loader_combine_version(1, 0, 1), json_version)) {
  ------------------
  |  Branch (3199:13): [True: 55, False: 42]
  ------------------
 3200|     55|            loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 3201|     55|                       "loader_add_layer_properties: \'layers\' tag not supported until file version 1.0.1, but %s is reporting "
 3202|     55|                       "version %s",
 3203|     55|                       filename, file_vers);
 3204|     55|        }
 3205|     97|        cJSON *layer_node = NULL;
 3206|  12.0k|        cJSON_ArrayForEach(layer_node, layers_node) {
  ------------------
  |  |  213|  12.1k|    for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
  |  |  ------------------
  |  |  |  Branch (213:20): [True: 97, False: 0]
  |  |  |  Branch (213:61): [True: 12.0k, False: 75]
  |  |  ------------------
  ------------------
 3207|  12.0k|            if (layer_node->type != cJSON_Object) {
  ------------------
  |  |  103|  12.0k|#define cJSON_Object (1 << 6)
  ------------------
  |  Branch (3207:17): [True: 22, False: 12.0k]
  ------------------
 3208|     22|                loader_log(
 3209|     22|                    inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 3210|     22|                    "loader_add_layer_properties: Array element in \"layers\" field in manifest JSON file %s is not an object.  "
 3211|     22|                    "Skipping this file",
 3212|     22|                    filename);
 3213|     22|                goto out;
 3214|     22|            }
 3215|  12.0k|            result = loader_read_layer_json(inst, layer_instance_list, layer_node, json_version, is_implicit, filename);
 3216|  12.0k|        }
 3217|     97|    } else {
 3218|       |        // Otherwise, try to read in individual layers
 3219|      7|        cJSON *layer_node = loader_cJSON_GetObjectItem(json, "layer");
 3220|      7|        if (layer_node == NULL) {
  ------------------
  |  Branch (3220:13): [True: 0, False: 7]
  ------------------
 3221|       |            // Don't warn if this happens to be an ICD manifest
 3222|      0|            if (loader_cJSON_GetObjectItem(json, "ICD") == NULL) {
  ------------------
  |  Branch (3222:17): [True: 0, False: 0]
  ------------------
 3223|      0|                loader_log(
 3224|      0|                    inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 3225|      0|                    "loader_add_layer_properties: Can not find 'layer' object in manifest JSON file %s.  Skipping this file.",
 3226|      0|                    filename);
 3227|      0|            }
 3228|      0|            goto out;
 3229|      0|        }
 3230|       |        // Loop through all "layer" objects in the file to get a count of them
 3231|       |        // first.
 3232|      7|        uint16_t layer_count = 0;
 3233|      7|        cJSON *tempNode = layer_node;
 3234|     45|        do {
 3235|     45|            tempNode = tempNode->next;
 3236|     45|            layer_count++;
 3237|     45|        } while (tempNode != NULL);
  ------------------
  |  Branch (3237:18): [True: 38, False: 7]
  ------------------
 3238|       |
 3239|       |        // Throw a warning if we encounter multiple "layer" objects in file
 3240|       |        // versions newer than 1.0.0.  Having multiple objects with the same
 3241|       |        // name at the same level is actually a JSON standard violation.
 3242|      7|        if (layer_count > 1 && loader_check_version_meets_required(loader_combine_version(1, 0, 1), json_version)) {
  ------------------
  |  Branch (3242:13): [True: 7, False: 0]
  |  Branch (3242:32): [True: 6, False: 1]
  ------------------
 3243|      6|            loader_log(inst, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 3244|      6|                       "loader_add_layer_properties: Multiple 'layer' nodes are deprecated starting in file version \"1.0.1\".  "
 3245|      6|                       "Please use 'layers' : [] array instead in %s.",
 3246|      6|                       filename);
 3247|      6|        } else {
 3248|     27|            do {
 3249|     27|                result = loader_read_layer_json(inst, layer_instance_list, layer_node, json_version, is_implicit, filename);
 3250|     27|                layer_node = layer_node->next;
 3251|     27|            } while (layer_node != NULL);
  ------------------
  |  Branch (3251:22): [True: 26, False: 1]
  ------------------
 3252|      1|        }
 3253|      7|    }
 3254|       |
 3255|    108|out:
 3256|       |
 3257|    108|    return result;
 3258|    104|}

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.9k|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.9k|    char *out;
   66|  47.9k|#if defined(HAVE_SECURE_GETENV) && !defined(LOADER_USE_UNSAFE_FILE_SEARCH)
   67|  47.9k|    (void)inst;
   68|  47.9k|    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.9k|    return out;
   79|  47.9k|#endif
   80|  47.9k|}
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:
  148|  14.3k|TEST_FUNCTION_EXPORT VkResult loader_get_json(const struct loader_instance *inst, const char *filename, cJSON **json) {
  149|  14.3k|    char *json_buf = NULL;
  150|  14.3k|    VkResult res = VK_SUCCESS;
  151|       |
  152|  14.3k|    assert(json != NULL);
  153|       |
  154|  14.3k|    size_t json_len = 0;
  155|  14.3k|    *json = NULL;
  156|  14.3k|    res = loader_read_entire_file(inst, filename, &json_len, &json_buf);
  157|  14.3k|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (157:9): [True: 5.07k, False: 9.24k]
  ------------------
  158|  5.07k|        goto out;
  159|  5.07k|    }
  160|  14.3k|    bool out_of_memory = false;
  161|       |    // Parse text from file
  162|  9.24k|    *json = loader_cJSON_ParseWithLength(inst ? &inst->alloc_callbacks : NULL, json_buf, json_len, &out_of_memory);
  ------------------
  |  Branch (162:42): [True: 0, False: 9.24k]
  ------------------
  163|  9.24k|    if (out_of_memory) {
  ------------------
  |  Branch (163:9): [True: 0, False: 9.24k]
  ------------------
  164|      0|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Out of Memory error occurred while parsing JSON file %s.",
  165|      0|                   filename);
  166|      0|        res = VK_ERROR_OUT_OF_HOST_MEMORY;
  167|      0|        goto out;
  168|  9.24k|    } else if (*json == NULL) {
  ------------------
  |  Branch (168:16): [True: 4.33k, False: 4.91k]
  ------------------
  169|  4.33k|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Invalid JSON file %s.", filename);
  170|  4.33k|        goto out;
  171|  4.33k|    }
  172|       |
  173|  14.3k|out:
  174|  14.3k|    loader_instance_heap_free(inst, json_buf);
  175|  14.3k|    if (res != VK_SUCCESS && *json != NULL) {
  ------------------
  |  Branch (175:9): [True: 5.07k, False: 9.24k]
  |  Branch (175:30): [True: 0, False: 5.07k]
  ------------------
  176|      0|        loader_cJSON_Delete(*json);
  177|      0|        *json = NULL;
  178|      0|    }
  179|       |
  180|  14.3k|    return res;
  181|  9.24k|}
loader_parse_json_string_to_existing_str:
  183|  12.3k|VkResult loader_parse_json_string_to_existing_str(cJSON *object, const char *key, size_t out_str_len, char *out_string) {
  184|  12.3k|    if (NULL == key) {
  ------------------
  |  Branch (184:9): [True: 0, False: 12.3k]
  ------------------
  185|      0|        return VK_ERROR_INITIALIZATION_FAILED;
  186|      0|    }
  187|  12.3k|    cJSON *item = loader_cJSON_GetObjectItem(object, key);
  188|  12.3k|    if (NULL == item) {
  ------------------
  |  Branch (188:9): [True: 1.95k, False: 10.3k]
  ------------------
  189|  1.95k|        return VK_ERROR_INITIALIZATION_FAILED;
  190|  1.95k|    }
  191|       |
  192|  10.3k|    if (item->type != cJSON_String || item->valuestring == NULL) {
  ------------------
  |  |  101|  20.7k|#define cJSON_String (1 << 4)
  ------------------
  |  Branch (192:9): [True: 1.51k, False: 8.87k]
  |  Branch (192:39): [True: 0, False: 8.87k]
  ------------------
  193|  1.51k|        return VK_ERROR_INITIALIZATION_FAILED;
  194|  1.51k|    }
  195|  10.3k|    bool out_of_memory = false;
  196|  8.87k|    bool success = loader_cJSON_PrintPreallocated(item, out_string, (int)out_str_len, cJSON_False);
  ------------------
  |  |   97|  8.87k|#define cJSON_False (1 << 0)
  ------------------
  197|  8.87k|    if (out_of_memory) {
  ------------------
  |  Branch (197:9): [True: 0, False: 8.87k]
  ------------------
  198|      0|        return VK_ERROR_OUT_OF_HOST_MEMORY;
  199|      0|    }
  200|  8.87k|    if (!success) {
  ------------------
  |  Branch (200:9): [True: 69, False: 8.80k]
  ------------------
  201|     69|        return VK_ERROR_INITIALIZATION_FAILED;
  202|     69|    }
  203|  8.80k|    return VK_SUCCESS;
  204|  8.87k|}
loader_parse_json_string:
  206|   926k|VkResult loader_parse_json_string(cJSON *object, const char *key, char **out_string) {
  207|   926k|    if (NULL == key) {
  ------------------
  |  Branch (207:9): [True: 0, False: 926k]
  ------------------
  208|      0|        return VK_ERROR_INITIALIZATION_FAILED;
  209|      0|    }
  210|       |
  211|   926k|    cJSON *item = loader_cJSON_GetObjectItem(object, key);
  212|   926k|    if (NULL == item || NULL == item->valuestring) {
  ------------------
  |  Branch (212:9): [True: 780, False: 925k]
  |  Branch (212:25): [True: 5, False: 925k]
  ------------------
  213|    785|        return VK_ERROR_INITIALIZATION_FAILED;
  214|    785|    }
  215|       |
  216|   926k|    bool out_of_memory = false;
  217|   925k|    char *str = loader_cJSON_Print(item, &out_of_memory);
  218|   925k|    if (out_of_memory || NULL == str) {
  ------------------
  |  Branch (218:9): [True: 0, False: 925k]
  |  Branch (218:26): [True: 0, False: 925k]
  ------------------
  219|      0|        return VK_ERROR_OUT_OF_HOST_MEMORY;
  220|      0|    }
  221|   925k|    if (NULL != out_string) {
  ------------------
  |  Branch (221:9): [True: 925k, False: 0]
  ------------------
  222|   925k|        *out_string = str;
  223|   925k|    }
  224|   925k|    return VK_SUCCESS;
  225|   925k|}
loader_parse_json_array_of_strings:
  227|  18.0k|                                            struct loader_string_list *string_list) {
  228|  18.0k|    if (NULL == key) {
  ------------------
  |  Branch (228:9): [True: 0, False: 18.0k]
  ------------------
  229|      0|        return VK_ERROR_INITIALIZATION_FAILED;
  230|      0|    }
  231|  18.0k|    cJSON *item = loader_cJSON_GetObjectItem(object, key);
  232|  18.0k|    if (NULL == item) {
  ------------------
  |  Branch (232:9): [True: 11.6k, False: 6.35k]
  ------------------
  233|  11.6k|        return VK_ERROR_INITIALIZATION_FAILED;
  234|  11.6k|    }
  235|       |
  236|  6.35k|    uint32_t count = loader_cJSON_GetArraySize(item);
  237|  6.35k|    if (count == 0) {
  ------------------
  |  Branch (237:9): [True: 1.07k, False: 5.28k]
  ------------------
  238|  1.07k|        return VK_SUCCESS;
  239|  1.07k|    }
  240|       |
  241|  5.28k|    VkResult res = create_string_list(inst, count, string_list);
  242|  5.28k|    if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
  ------------------
  |  Branch (242:9): [True: 0, False: 5.28k]
  ------------------
  243|      0|        goto out;
  244|      0|    }
  245|  5.28k|    cJSON *element = NULL;
  246|  1.12M|    cJSON_ArrayForEach(element, item) {
  ------------------
  |  |  213|  1.12M|    for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
  |  |  ------------------
  |  |  |  Branch (213:20): [True: 5.28k, False: 0]
  |  |  |  Branch (213:61): [True: 1.12M, False: 1.89k]
  |  |  ------------------
  ------------------
  247|  1.12M|        if (element->type != cJSON_String) {
  ------------------
  |  |  101|  1.12M|#define cJSON_String (1 << 4)
  ------------------
  |  Branch (247:13): [True: 3.38k, False: 1.11M]
  ------------------
  248|  3.38k|            return VK_ERROR_INITIALIZATION_FAILED;
  249|  3.38k|        }
  250|  1.12M|        bool out_of_memory = false;
  251|  1.11M|        char *out_data = loader_cJSON_Print(element, &out_of_memory);
  252|  1.11M|        if (out_of_memory) {
  ------------------
  |  Branch (252:13): [True: 0, False: 1.11M]
  ------------------
  253|      0|            res = VK_ERROR_OUT_OF_HOST_MEMORY;
  254|      0|            goto out;
  255|      0|        }
  256|  1.11M|        res = append_str_to_string_list(inst, string_list, out_data);
  257|  1.11M|        if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
  ------------------
  |  Branch (257:13): [True: 0, False: 1.11M]
  ------------------
  258|      0|            goto out;
  259|      0|        }
  260|  1.11M|    }
  261|  1.89k|out:
  262|  1.89k|    if (res == VK_ERROR_OUT_OF_HOST_MEMORY && NULL != string_list->list) {
  ------------------
  |  Branch (262:9): [True: 0, False: 1.89k]
  |  Branch (262:47): [True: 0, False: 0]
  ------------------
  263|      0|        free_string_list(inst, string_list);
  264|      0|    }
  265|       |
  266|  1.89k|    return res;
  267|  5.28k|}
loader_json.c:loader_read_entire_file:
   98|  14.3k|                                        char **out_buff) {
   99|  14.3k|    FILE *file = NULL;
  100|  14.3k|    struct stat stats = {0};
  101|  14.3k|    VkResult res = VK_SUCCESS;
  102|       |
  103|       |    // fprintf(stderr, "loader_get_json: Reading JSON file %s\n", filename);
  104|  14.3k|    file = fopen(filename, "rb");
  105|  14.3k|#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
  106|  14.3k|    if (file == NULL) {
  ------------------
  |  Branch (106:9): [True: 3.87k, False: 10.4k]
  ------------------
  107|  3.87k|        create_callback_file(filename);
  108|  3.87k|        file = fopen(filename, "rb");
  109|  3.87k|    }
  110|  14.3k|#endif
  111|  14.3k|    if (NULL == file) {
  ------------------
  |  Branch (111:9): [True: 3.87k, False: 10.4k]
  ------------------
  112|  3.87k|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Failed to open JSON file %s", filename);
  113|  3.87k|        res = VK_ERROR_INITIALIZATION_FAILED;
  114|  3.87k|        goto out;
  115|  3.87k|    }
  116|  10.4k|    if (-1 == fstat(fileno(file), &stats)) {
  ------------------
  |  Branch (116:9): [True: 0, False: 10.4k]
  ------------------
  117|      0|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Failed to read file size of JSON file %s", filename);
  118|      0|        res = VK_ERROR_INITIALIZATION_FAILED;
  119|      0|        goto out;
  120|      0|    }
  121|  10.4k|    *out_buff = (char *)loader_instance_heap_calloc(inst, stats.st_size + 1, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
  122|  10.4k|    if (NULL == *out_buff) {
  ------------------
  |  Branch (122:9): [True: 0, False: 10.4k]
  ------------------
  123|      0|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Failed to allocate memory to read JSON file %s", filename);
  124|      0|        res = VK_ERROR_OUT_OF_HOST_MEMORY;
  125|      0|        goto out;
  126|      0|    }
  127|  10.4k|    if (stats.st_size != (long int)fread(*out_buff, sizeof(char), stats.st_size, file)) {
  ------------------
  |  Branch (127:9): [True: 1.19k, False: 9.24k]
  ------------------
  128|  1.19k|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Failed to read entire JSON file %s", filename);
  129|  1.19k|        res = VK_ERROR_INITIALIZATION_FAILED;
  130|  1.19k|        goto out;
  131|  1.19k|    }
  132|  9.24k|    *out_len = stats.st_size + 1;
  133|  9.24k|    (*out_buff)[stats.st_size] = '\0';
  134|       |
  135|  14.3k|out:
  136|  14.3k|    if (NULL != file) {
  ------------------
  |  Branch (136:9): [True: 10.4k, False: 3.87k]
  ------------------
  137|  10.4k|        fclose(file);
  138|  10.4k|    }
  139|  14.3k|    return res;
  140|  9.24k|}

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|    306|void loader_set_global_debug_level(uint32_t new_loader_debug) { g_loader_debug = new_loader_debug; }
generate_debug_flag_str:
   91|    674|void generate_debug_flag_str(VkFlags msg_type, size_t cmd_line_size, char *cmd_line_msg) {
   92|    674|    cmd_line_msg[0] = '\0';
   93|       |
   94|    674|    if ((msg_type & VULKAN_LOADER_ERROR_BIT) != 0) {
  ------------------
  |  Branch (94:9): [True: 46, False: 628]
  ------------------
   95|     46|        loader_strncat(cmd_line_msg, cmd_line_size, "ERROR", sizeof("ERROR"));
   96|     46|    }
   97|    674|    if ((msg_type & VULKAN_LOADER_WARN_BIT) != 0) {
  ------------------
  |  Branch (97:9): [True: 60, False: 614]
  ------------------
   98|     60|        if (strlen(cmd_line_msg) > 0) {
  ------------------
  |  Branch (98:13): [True: 38, False: 22]
  ------------------
   99|     38|            loader_strncat(cmd_line_msg, cmd_line_size, " | ", sizeof(" | "));
  100|     38|        }
  101|     60|        loader_strncat(cmd_line_msg, cmd_line_size, "WARNING", sizeof("WARNING"));
  102|     60|    }
  103|    674|    if ((msg_type & VULKAN_LOADER_INFO_BIT) != 0) {
  ------------------
  |  Branch (103:9): [True: 55, False: 619]
  ------------------
  104|     55|        if (strlen(cmd_line_msg) > 0) {
  ------------------
  |  Branch (104:13): [True: 42, False: 13]
  ------------------
  105|     42|            loader_strncat(cmd_line_msg, cmd_line_size, " | ", sizeof(" | "));
  106|     42|        }
  107|     55|        loader_strncat(cmd_line_msg, cmd_line_size, "INFO", sizeof("INFO"));
  108|     55|    }
  109|    674|    if ((msg_type & VULKAN_LOADER_DEBUG_BIT) != 0) {
  ------------------
  |  Branch (109:9): [True: 55, False: 619]
  ------------------
  110|     55|        if (strlen(cmd_line_msg) > 0) {
  ------------------
  |  Branch (110:13): [True: 43, False: 12]
  ------------------
  111|     43|            loader_strncat(cmd_line_msg, cmd_line_size, " | ", sizeof(" | "));
  112|     43|        }
  113|     55|        loader_strncat(cmd_line_msg, cmd_line_size, "DEBUG", sizeof("DEBUG"));
  114|     55|    }
  115|    674|    if ((msg_type & VULKAN_LOADER_PERF_BIT) != 0) {
  ------------------
  |  Branch (115:9): [True: 48, False: 626]
  ------------------
  116|     48|        if (strlen(cmd_line_msg) > 0) {
  ------------------
  |  Branch (116:13): [True: 39, False: 9]
  ------------------
  117|     39|            loader_strncat(cmd_line_msg, cmd_line_size, " | ", sizeof(" | "));
  118|     39|        }
  119|     48|        loader_strncat(cmd_line_msg, cmd_line_size, "PERF", sizeof("PERF"));
  120|     48|    }
  121|    674|    if ((msg_type & VULKAN_LOADER_DRIVER_BIT) != 0) {
  ------------------
  |  Branch (121:9): [True: 45, False: 629]
  ------------------
  122|     45|        if (strlen(cmd_line_msg) > 0) {
  ------------------
  |  Branch (122:13): [True: 34, False: 11]
  ------------------
  123|     34|            loader_strncat(cmd_line_msg, cmd_line_size, " | ", sizeof(" | "));
  124|     34|        }
  125|     45|        loader_strncat(cmd_line_msg, cmd_line_size, "DRIVER", sizeof("DRIVER"));
  126|     45|    }
  127|    674|    if ((msg_type & VULKAN_LOADER_LAYER_BIT) != 0) {
  ------------------
  |  Branch (127:9): [True: 56, False: 618]
  ------------------
  128|     56|        if (strlen(cmd_line_msg) > 0) {
  ------------------
  |  Branch (128:13): [True: 42, False: 14]
  ------------------
  129|     42|            loader_strncat(cmd_line_msg, cmd_line_size, " | ", sizeof(" | "));
  130|     42|        }
  131|     56|        loader_strncat(cmd_line_msg, cmd_line_size, "LAYER", sizeof("LAYER"));
  132|     56|    }
  133|       |
  134|    674|#undef STRNCAT_TO_BUFFER
  135|    674|}
loader_log:
  138|   901k|    loader_log(const struct loader_instance *inst, VkFlags msg_type, int32_t msg_code, const char *format, ...) {
  139|   901k|    (void)msg_code;
  140|   901k|    char msg[512] = {0};
  141|       |
  142|   901k|    va_list ap;
  143|   901k|    va_start(ap, format);
  144|   901k|    int ret = vsnprintf(msg, sizeof(msg), format, ap);
  145|   901k|    if ((ret >= (int)sizeof(msg)) || ret < 0) {
  ------------------
  |  Branch (145:9): [True: 190, False: 901k]
  |  Branch (145:38): [True: 0, False: 901k]
  ------------------
  146|    190|        msg[sizeof(msg) - 1] = '\0';
  147|    190|    }
  148|   901k|    va_end(ap);
  149|       |
  150|   901k|    if (inst) {
  ------------------
  |  Branch (150:9): [True: 0, False: 901k]
  ------------------
  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|   901k|    if (0 == (msg_type & VULKAN_LOADER_FATAL_ERROR_BIT)) {
  ------------------
  |  Branch (192:9): [True: 901k, False: 0]
  ------------------
  193|   901k|        if (inst && inst->settings.settings_active && inst->settings.debug_level > 0) {
  ------------------
  |  Branch (193:13): [True: 0, False: 901k]
  |  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|   901k|        } else if (0 == (msg_type & g_loader_debug)) {
  ------------------
  |  Branch (199:20): [True: 93.7k, False: 807k]
  ------------------
  200|  93.7k|            return;
  201|  93.7k|        }
  202|   901k|    }
  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|   807k|    char cmd_line_msg[64] = {0};
  215|   807k|    size_t cmd_line_size = sizeof(cmd_line_msg);
  216|       |
  217|   807k|    loader_strncat(cmd_line_msg, cmd_line_size, "[Vulkan Loader] ", sizeof("[Vulkan Loader] "));
  218|       |
  219|   807k|    bool need_separator = false;
  220|   807k|    if ((msg_type & VULKAN_LOADER_ERROR_BIT) != 0) {
  ------------------
  |  Branch (220:9): [True: 3.20k, False: 804k]
  ------------------
  221|  3.20k|        loader_strncat(cmd_line_msg, cmd_line_size, "ERROR", sizeof("ERROR"));
  222|  3.20k|        need_separator = true;
  223|   804k|    } else if ((msg_type & VULKAN_LOADER_WARN_BIT) != 0) {
  ------------------
  |  Branch (223:16): [True: 16.1k, False: 788k]
  ------------------
  224|  16.1k|        loader_strncat(cmd_line_msg, cmd_line_size, "WARNING", sizeof("WARNING"));
  225|  16.1k|        need_separator = true;
  226|   788k|    } else if ((msg_type & VULKAN_LOADER_INFO_BIT) != 0) {
  ------------------
  |  Branch (226:16): [True: 1.77k, False: 786k]
  ------------------
  227|  1.77k|        loader_strncat(cmd_line_msg, cmd_line_size, "INFO", sizeof("INFO"));
  228|  1.77k|        need_separator = true;
  229|   786k|    } else if ((msg_type & VULKAN_LOADER_DEBUG_BIT) != 0) {
  ------------------
  |  Branch (229:16): [True: 786k, False: 0]
  ------------------
  230|   786k|        loader_strncat(cmd_line_msg, cmd_line_size, "DEBUG", sizeof("DEBUG"));
  231|   786k|        need_separator = true;
  232|   786k|    }
  233|       |
  234|   807k|    if ((msg_type & VULKAN_LOADER_PERF_BIT) != 0) {
  ------------------
  |  Branch (234:9): [True: 0, False: 807k]
  ------------------
  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|   807k|    } else if ((msg_type & VULKAN_LOADER_DRIVER_BIT) != 0) {
  ------------------
  |  Branch (239:16): [True: 0, False: 807k]
  ------------------
  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|   807k|    } else if ((msg_type & VULKAN_LOADER_LAYER_BIT) != 0) {
  ------------------
  |  Branch (244:16): [True: 146, False: 807k]
  ------------------
  245|    146|        if (need_separator) {
  ------------------
  |  Branch (245:13): [True: 146, False: 0]
  ------------------
  246|    146|            loader_strncat(cmd_line_msg, cmd_line_size, " | ", sizeof(" | "));
  247|    146|        }
  248|    146|        loader_strncat(cmd_line_msg, cmd_line_size, "LAYER", sizeof("LAYER"));
  249|    146|    }
  250|       |
  251|   807k|    loader_strncat(cmd_line_msg, cmd_line_size, ": ", sizeof(": "));
  252|   807k|    size_t num_used = strlen(cmd_line_msg);
  253|       |
  254|       |    // Justifies the output to at least 29 spaces
  255|   807k|    if (num_used < 32) {
  ------------------
  |  Branch (255:9): [True: 807k, False: 61]
  ------------------
  256|   807k|        const char space_buffer[] = "                                ";
  257|       |        // Only write (32 - num_used) spaces
  258|   807k|        loader_strncat(cmd_line_msg, cmd_line_size, space_buffer, sizeof(space_buffer) - 1 - num_used);
  259|   807k|    }
  260|       |    // Assert that we didn't write more than what is available in cmd_line_msg
  261|   807k|    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|   807k|}

free_layer_configuration:
   41|   406k|void free_layer_configuration(const struct loader_instance* inst, loader_settings_layer_configuration* layer_configuration) {
   42|   406k|    loader_instance_heap_free(inst, layer_configuration->name);
   43|   406k|    loader_instance_heap_free(inst, layer_configuration->path);
   44|   406k|    memset(layer_configuration, 0, sizeof(loader_settings_layer_configuration));
   45|   406k|}
free_loader_settings:
   57|  10.1k|void free_loader_settings(const struct loader_instance* inst, loader_settings* settings) {
   58|  10.1k|    if (NULL != settings->layer_configurations) {
  ------------------
  |  Branch (58:9): [True: 861, False: 9.33k]
  ------------------
   59|   300k|        for (uint32_t i = 0; i < settings->layer_configuration_count; i++) {
  ------------------
  |  Branch (59:30): [True: 299k, False: 861]
  ------------------
   60|   299k|            free_layer_configuration(inst, &settings->layer_configurations[i]);
   61|   299k|        }
   62|    861|        loader_instance_heap_free(inst, settings->layer_configurations);
   63|    861|    }
   64|  10.1k|    if (NULL != settings->additional_drivers) {
  ------------------
  |  Branch (64:9): [True: 0, False: 10.1k]
  ------------------
   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.1k|    if (NULL != settings->device_configurations) {
  ------------------
  |  Branch (70:9): [True: 0, False: 10.1k]
  ------------------
   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.1k|    loader_instance_heap_free(inst, settings->settings_file_path);
   77|  10.1k|    memset(settings, 0, sizeof(loader_settings));
   78|  10.1k|}
parse_control_string:
   80|   311k|loader_settings_layer_control parse_control_string(char* control_string) {
   81|   311k|    loader_settings_layer_control layer_control = LOADER_SETTINGS_LAYER_CONTROL_DEFAULT;
   82|   311k|    if (strcmp(control_string, "auto") == 0)
  ------------------
  |  Branch (82:9): [True: 1.07k, False: 310k]
  ------------------
   83|  1.07k|        layer_control = LOADER_SETTINGS_LAYER_CONTROL_DEFAULT;
   84|   310k|    else if (strcmp(control_string, "on") == 0)
  ------------------
  |  Branch (84:14): [True: 1.00k, False: 309k]
  ------------------
   85|  1.00k|        layer_control = LOADER_SETTINGS_LAYER_CONTROL_ON;
   86|   309k|    else if (strcmp(control_string, "off") == 0)
  ------------------
  |  Branch (86:14): [True: 284k, False: 24.7k]
  ------------------
   87|   284k|        layer_control = LOADER_SETTINGS_LAYER_CONTROL_OFF;
   88|  24.7k|    else if (strcmp(control_string, "unordered_layer_location") == 0)
  ------------------
  |  Branch (88:14): [True: 5.54k, False: 19.2k]
  ------------------
   89|  5.54k|        layer_control = LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION;
   90|   311k|    return layer_control;
   91|   311k|}
loader_settings_layer_control_to_string:
   93|   176k|const char* loader_settings_layer_control_to_string(loader_settings_layer_control control) {
   94|   176k|    switch (control) {
   95|  7.02k|        case (LOADER_SETTINGS_LAYER_CONTROL_DEFAULT):
  ------------------
  |  Branch (95:9): [True: 7.02k, False: 169k]
  ------------------
   96|  7.02k|            return "auto";
   97|    195|        case (LOADER_SETTINGS_LAYER_CONTROL_ON):
  ------------------
  |  Branch (97:9): [True: 195, False: 176k]
  ------------------
   98|    195|            return "on";
   99|   164k|        case (LOADER_SETTINGS_LAYER_CONTROL_OFF):
  ------------------
  |  Branch (99:9): [True: 164k, False: 12.2k]
  ------------------
  100|   164k|            return "off";
  101|  5.03k|        case (LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION):
  ------------------
  |  Branch (101:9): [True: 5.03k, False: 171k]
  ------------------
  102|  5.03k|            return "unordered_layer_location";
  103|      0|        default:
  ------------------
  |  Branch (103:9): [True: 0, False: 176k]
  ------------------
  104|      0|            return "UNKNOWN_LAYER_CONTROl";
  105|   176k|    }
  106|   176k|}
parse_log_filters_from_strings:
  108|    931|uint32_t parse_log_filters_from_strings(struct loader_string_list* log_filters) {
  109|    931|    uint32_t filters = 0;
  110|  1.11M|    for (uint32_t i = 0; i < log_filters->count; i++) {
  ------------------
  |  Branch (110:26): [True: 1.11M, False: 931]
  ------------------
  111|  1.11M|        if (strcmp(log_filters->list[i], "all") == 0)
  ------------------
  |  Branch (111:13): [True: 1.20k, False: 1.11M]
  ------------------
  112|  1.20k|            filters |= VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_PERF_BIT | VULKAN_LOADER_ERROR_BIT |
  113|  1.20k|                       VULKAN_LOADER_DEBUG_BIT | VULKAN_LOADER_LAYER_BIT | VULKAN_LOADER_DRIVER_BIT | VULKAN_LOADER_VALIDATION_BIT;
  114|  1.11M|        else if (strcmp(log_filters->list[i], "info") == 0)
  ------------------
  |  Branch (114:18): [True: 3.31k, False: 1.11M]
  ------------------
  115|  3.31k|            filters |= VULKAN_LOADER_INFO_BIT;
  116|  1.11M|        else if (strcmp(log_filters->list[i], "warn") == 0)
  ------------------
  |  Branch (116:18): [True: 42.1k, False: 1.07M]
  ------------------
  117|  42.1k|            filters |= VULKAN_LOADER_WARN_BIT;
  118|  1.07M|        else if (strcmp(log_filters->list[i], "perf") == 0)
  ------------------
  |  Branch (118:18): [True: 1.49k, False: 1.07M]
  ------------------
  119|  1.49k|            filters |= VULKAN_LOADER_PERF_BIT;
  120|  1.07M|        else if (strcmp(log_filters->list[i], "error") == 0)
  ------------------
  |  Branch (120:18): [True: 1.11k, False: 1.06M]
  ------------------
  121|  1.11k|            filters |= VULKAN_LOADER_ERROR_BIT;
  122|  1.06M|        else if (strcmp(log_filters->list[i], "debug") == 0)
  ------------------
  |  Branch (122:18): [True: 1.88k, False: 1.06M]
  ------------------
  123|  1.88k|            filters |= VULKAN_LOADER_DEBUG_BIT;
  124|  1.06M|        else if (strcmp(log_filters->list[i], "layer") == 0)
  ------------------
  |  Branch (124:18): [True: 1.87k, False: 1.06M]
  ------------------
  125|  1.87k|            filters |= VULKAN_LOADER_LAYER_BIT;
  126|  1.06M|        else if (strcmp(log_filters->list[i], "driver") == 0)
  ------------------
  |  Branch (126:18): [True: 1.30k, False: 1.06M]
  ------------------
  127|  1.30k|            filters |= VULKAN_LOADER_DRIVER_BIT;
  128|  1.06M|        else if (strcmp(log_filters->list[i], "validation") == 0)
  ------------------
  |  Branch (128:18): [True: 3.96k, False: 1.06M]
  ------------------
  129|  3.96k|            filters |= VULKAN_LOADER_VALIDATION_BIT;
  130|  1.11M|    }
  131|    931|    return filters;
  132|    931|}
parse_layer_configuration:
  147|   311k|                                   loader_settings_layer_configuration* layer_configuration) {
  148|   311k|    char* control_string = NULL;
  149|   311k|    VkResult res = loader_parse_json_string(layer_configuration_json, "control", &control_string);
  150|   311k|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (150:9): [True: 53, False: 311k]
  ------------------
  151|     53|        goto out;
  152|     53|    }
  153|   311k|    layer_configuration->control = parse_control_string(control_string);
  154|   311k|    loader_instance_heap_free(inst, control_string);
  155|       |
  156|       |    // If that is the only value - do no further parsing
  157|   311k|    if (layer_configuration->control == LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION) {
  ------------------
  |  Branch (157:9): [True: 5.54k, False: 305k]
  ------------------
  158|  5.54k|        goto out;
  159|  5.54k|    }
  160|       |
  161|   305k|    res = loader_parse_json_string(layer_configuration_json, "name", &(layer_configuration->name));
  162|   305k|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (162:9): [True: 509, False: 305k]
  ------------------
  163|    509|        goto out;
  164|    509|    }
  165|       |
  166|   305k|    res = loader_parse_json_string(layer_configuration_json, "path", &(layer_configuration->path));
  167|   305k|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (167:9): [True: 36, False: 305k]
  ------------------
  168|     36|        goto out;
  169|     36|    }
  170|       |
  171|   305k|    cJSON* treat_as_implicit_manifest = loader_cJSON_GetObjectItem(layer_configuration_json, "treat_as_implicit_manifest");
  172|   305k|    if (treat_as_implicit_manifest && treat_as_implicit_manifest->type == cJSON_True) {
  ------------------
  |  |   98|  1.86k|#define cJSON_True (1 << 1)
  ------------------
  |  Branch (172:9): [True: 1.86k, False: 303k]
  |  Branch (172:39): [True: 898, False: 969]
  ------------------
  173|    898|        layer_configuration->treat_as_implicit_manifest = true;
  174|    898|    }
  175|   311k|out:
  176|   311k|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (176:9): [True: 598, False: 310k]
  ------------------
  177|    598|        free_layer_configuration(inst, layer_configuration);
  178|    598|    }
  179|   311k|    return res;
  180|   305k|}
parse_layer_configurations:
  182|  2.62k|VkResult parse_layer_configurations(const struct loader_instance* inst, cJSON* settings_object, loader_settings* loader_settings) {
  183|  2.62k|    VkResult res = VK_SUCCESS;
  184|       |
  185|  2.62k|    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|  2.62k|    if (NULL == layer_configurations) {
  ------------------
  |  Branch (187:9): [True: 1.05k, False: 1.57k]
  ------------------
  188|  1.05k|        return VK_SUCCESS;
  189|  1.05k|    }
  190|       |
  191|  1.57k|    uint32_t layer_configurations_count = loader_cJSON_GetArraySize(layer_configurations);
  192|  1.57k|    if (layer_configurations_count == 0) {
  ------------------
  |  Branch (192:9): [True: 42, False: 1.52k]
  ------------------
  193|     42|        loader_settings->layer_configurations_active = true;
  194|     42|        return VK_SUCCESS;
  195|     42|    }
  196|       |
  197|  1.52k|    loader_settings->layer_configuration_count = layer_configurations_count;
  198|       |
  199|  1.52k|    loader_settings->layer_configurations = loader_instance_heap_calloc(
  200|  1.52k|        inst, sizeof(loader_settings_layer_configuration) * layer_configurations_count, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  201|  1.52k|    if (NULL == loader_settings->layer_configurations) {
  ------------------
  |  Branch (201:9): [True: 0, False: 1.52k]
  ------------------
  202|      0|        res = VK_ERROR_OUT_OF_HOST_MEMORY;
  203|      0|        goto out;
  204|      0|    }
  205|       |
  206|  1.52k|    cJSON* layer = NULL;
  207|  1.52k|    size_t i = 0;
  208|   311k|    cJSON_ArrayForEach(layer, layer_configurations) {
  ------------------
  |  |  213|   312k|    for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
  |  |  ------------------
  |  |  |  Branch (213:20): [True: 1.52k, False: 0]
  |  |  |  Branch (213:61): [True: 311k, False: 861]
  |  |  ------------------
  ------------------
  209|   311k|        if (layer->type != cJSON_Object) {
  ------------------
  |  |  103|   311k|#define cJSON_Object (1 << 6)
  ------------------
  |  Branch (209:13): [True: 70, False: 311k]
  ------------------
  210|     70|            res = VK_ERROR_INITIALIZATION_FAILED;
  211|     70|            goto out;
  212|     70|        }
  213|   311k|        res = parse_layer_configuration(inst, layer, &(loader_settings->layer_configurations[i++]));
  214|   311k|        if (VK_SUCCESS != res) {
  ------------------
  |  Branch (214:13): [True: 598, False: 310k]
  ------------------
  215|    598|            goto out;
  216|    598|        }
  217|   311k|    }
  218|    861|    loader_settings->layer_configurations_active = true;
  219|  1.52k|out:
  220|  1.52k|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (220:9): [True: 668, False: 861]
  ------------------
  221|    668|        if (loader_settings->layer_configurations) {
  ------------------
  |  Branch (221:13): [True: 668, False: 0]
  ------------------
  222|   106k|            for (size_t index = 0; index < loader_settings->layer_configuration_count; index++) {
  ------------------
  |  Branch (222:36): [True: 106k, False: 668]
  ------------------
  223|   106k|                free_layer_configuration(inst, &(loader_settings->layer_configurations[index]));
  224|   106k|            }
  225|    668|            loader_settings->layer_configuration_count = 0;
  226|    668|            loader_instance_heap_free(inst, loader_settings->layer_configurations);
  227|    668|            loader_settings->layer_configurations = NULL;
  228|    668|        }
  229|    668|    }
  230|       |
  231|  1.52k|    return res;
  232|    861|}
parse_additional_drivers:
  248|  2.62k|VkResult parse_additional_drivers(const struct loader_instance* inst, cJSON* settings_object, loader_settings* loader_settings) {
  249|  2.62k|    VkResult res = VK_SUCCESS;
  250|       |
  251|  2.62k|    cJSON* additional_drivers_use_exclusively_json =
  252|  2.62k|        loader_cJSON_GetObjectItem(settings_object, "additional_drivers_use_exclusively");
  253|  2.62k|    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: 2.62k]
  |  Branch (253:52): [True: 0, False: 0]
  ------------------
  254|      0|        loader_settings->additional_drivers_use_exclusively = true;
  255|      0|    }
  256|       |
  257|  2.62k|    cJSON* additional_drivers_json = loader_cJSON_GetObjectItem(settings_object, "additional_drivers");
  258|  2.62k|    if (NULL == additional_drivers_json) {
  ------------------
  |  Branch (258:9): [True: 2.62k, False: 0]
  ------------------
  259|  2.62k|        return VK_SUCCESS;
  260|  2.62k|    }
  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_layer_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|  2.62k|VkResult parse_device_configurations(const struct loader_instance* inst, cJSON* settings_object, loader_settings* loader_settings) {
  376|  2.62k|    VkResult res = VK_SUCCESS;
  377|       |
  378|  2.62k|    cJSON* device_configurations = loader_cJSON_GetObjectItem(settings_object, "device_configurations");
  379|  2.62k|    if (NULL == device_configurations) {
  ------------------
  |  Branch (379:9): [True: 2.62k, False: 0]
  ------------------
  380|  2.62k|        return VK_SUCCESS;
  381|  2.62k|    }
  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|      0|            continue;
  410|      0|        }
  411|      0|        i++;
  412|      0|    }
  413|      0|    loader_settings->device_configurations_active = true;
  414|      0|out:
  415|      0|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (415:9): [True: 0, False: 0]
  ------------------
  416|      0|        if (loader_settings->device_configurations) {
  ------------------
  |  Branch (416:13): [True: 0, False: 0]
  ------------------
  417|      0|            for (size_t index = 0; index < loader_settings->device_configuration_count; index++) {
  ------------------
  |  Branch (417:36): [True: 0, False: 0]
  ------------------
  418|      0|                free_device_configuration(inst, &(loader_settings->device_configurations[index]));
  419|      0|            }
  420|      0|            loader_settings->device_configuration_count = 0;
  421|      0|            loader_instance_heap_free(inst, loader_settings->device_configurations);
  422|       |            loader_settings->device_configurations = NULL;
  423|      0|        }
  424|      0|    }
  425|      0|    return res;
  426|      0|}
check_if_settings_path_exists:
  433|  44.6k|                                       char** settings_file_path) {
  434|  44.6k|    if (NULL == base || NULL == suffix) {
  ------------------
  |  Branch (434:9): [True: 19.1k, False: 25.4k]
  |  Branch (434:25): [True: 0, False: 25.4k]
  ------------------
  435|  19.1k|        return VK_ERROR_INITIALIZATION_FAILED;
  436|  19.1k|    }
  437|       |
  438|  25.4k|    size_t base_len = strlen(base);
  439|  25.4k|    size_t suffix_len = strlen(suffix);
  440|       |
  441|  25.4k|    uint32_t start = 0;
  442|  25.4k|    uint32_t stop = 0;
  443|  44.4k|    while (base[start] != '\0' && start < base_len && stop < base_len) {
  ------------------
  |  Branch (443:12): [True: 44.4k, False: 0]
  |  Branch (443:35): [True: 44.4k, False: 0]
  |  Branch (443:55): [True: 27.0k, False: 17.4k]
  ------------------
  444|  27.0k|        start = stop;
  445|  27.0k|        stop = start + 1;
  446|   159k|        while (base[stop] != PATH_SEPARATOR && base[stop] != '\0' && stop < base_len) {
  ------------------
  |  |  150|   319k|#define PATH_SEPARATOR ':'
  ------------------
  |  Branch (446:16): [True: 158k, False: 1.57k]
  |  Branch (446:48): [True: 132k, False: 25.4k]
  |  Branch (446:70): [True: 132k, False: 0]
  ------------------
  447|   132k|            stop++;
  448|   132k|        }
  449|       |
  450|  27.0k|        size_t segment_len = (stop - start);
  451|  27.0k|        if (segment_len <= 1) {
  ------------------
  |  Branch (451:13): [True: 0, False: 27.0k]
  ------------------
  452|       |            // segment is *just* a PATH_SEPARATOR, skip it
  453|      0|            continue;
  454|      0|        }
  455|  27.0k|        size_t path_len = segment_len + suffix_len + 1;
  456|  27.0k|        *settings_file_path = loader_instance_heap_calloc(inst, path_len, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
  457|  27.0k|        if (NULL == *settings_file_path) {
  ------------------
  |  Branch (457:13): [True: 0, False: 27.0k]
  ------------------
  458|      0|            return VK_ERROR_OUT_OF_HOST_MEMORY;
  459|      0|        }
  460|  27.0k|        loader_strncpy(*settings_file_path, path_len, base + start, segment_len);
  461|  27.0k|        loader_strncat(*settings_file_path, path_len, suffix, suffix_len);
  462|       |
  463|  27.0k|        if (loader_platform_file_exists(*settings_file_path)) {
  ------------------
  |  Branch (463:13): [True: 8.01k, False: 19.0k]
  ------------------
  464|  8.01k|            return VK_SUCCESS;
  465|  8.01k|        }
  466|  19.0k|        loader_instance_heap_free(inst, *settings_file_path);
  467|  19.0k|        *settings_file_path = NULL;
  468|  19.0k|    }
  469|       |
  470|  17.4k|    return VK_ERROR_INITIALIZATION_FAILED;
  471|  25.4k|}
get_unix_settings_path:
  474|  9.58k|VkResult get_unix_settings_path(const struct loader_instance* inst, char** settings_file_path) {
  475|       |    // First, get XDG env-vars we use. Don't need to worry about free'ing because on linux getenv is non-allocating
  476|  9.58k|    char* xdg_config_home = loader_secure_getenv("XDG_CONFIG_HOME", inst);
  477|  9.58k|    char* xdg_config_dirs = loader_secure_getenv("XDG_CONFIG_DIRS", inst);
  478|  9.58k|    char* xdg_data_home = loader_secure_getenv("XDG_DATA_HOME", inst);
  479|  9.58k|    char* xdg_data_dirs = loader_secure_getenv("XDG_DATA_DIRS", inst);
  480|       |
  481|       |    // Use fallback directories for xdg_config_dirs and xdg_data_dirs if they are NULL.
  482|  9.58k|#if !defined(__Fuchsia__) && !defined(__QNX__)
  483|  9.58k|    if (NULL == xdg_config_dirs || '\0' == xdg_config_dirs[0]) {
  ------------------
  |  Branch (483:9): [True: 9.58k, False: 0]
  |  Branch (483:36): [True: 0, False: 0]
  ------------------
  484|  9.58k|        xdg_config_dirs = FALLBACK_CONFIG_DIRS;
  485|  9.58k|    }
  486|  9.58k|#endif
  487|       |
  488|  9.58k|#if !defined(__Fuchsia__) && !defined(__QNX__)
  489|  9.58k|    if (NULL == xdg_data_dirs || '\0' == xdg_data_dirs[0]) {
  ------------------
  |  Branch (489:9): [True: 9.58k, False: 0]
  |  Branch (489:34): [True: 0, False: 0]
  ------------------
  490|  9.58k|        xdg_data_dirs = FALLBACK_DATA_DIRS;
  491|  9.58k|    }
  492|  9.58k|#endif
  493|       |
  494|  9.58k|    VkResult res = check_if_settings_path_exists(
  495|  9.58k|        inst, xdg_config_home, "/" VULKAN_DIR "/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME, settings_file_path);
  ------------------
  |  |  141|  9.58k|#define VK_LOADER_SETTINGS_FILENAME "vk_loader_settings.json"
  ------------------
  496|  9.58k|    if (res == VK_SUCCESS) {
  ------------------
  |  Branch (496:9): [True: 0, False: 9.58k]
  ------------------
  497|      0|        return res;
  498|      0|    }
  499|       |
  500|  9.58k|    res = check_if_settings_path_exists(inst, xdg_data_home, "/" VULKAN_DIR "/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME,
  ------------------
  |  |  141|  9.58k|#define VK_LOADER_SETTINGS_FILENAME "vk_loader_settings.json"
  ------------------
  501|  9.58k|                                        settings_file_path);
  502|  9.58k|    if (res == VK_SUCCESS) {
  ------------------
  |  Branch (502:9): [True: 0, False: 9.58k]
  ------------------
  503|      0|        return res;
  504|      0|    }
  505|       |
  506|       |    // Check home if either xdg_config_home or xdg_data_home wasn't set
  507|  9.58k|    char* home = loader_secure_getenv("HOME", inst);
  508|  9.58k|    if (home != NULL) {
  ------------------
  |  Branch (508:9): [True: 9.58k, False: 0]
  ------------------
  509|  9.58k|        if (NULL == xdg_config_home || '\0' == xdg_config_home[0]) {
  ------------------
  |  Branch (509:13): [True: 9.58k, False: 0]
  |  Branch (509:40): [True: 0, False: 0]
  ------------------
  510|  9.58k|            res = check_if_settings_path_exists(
  511|  9.58k|                inst, home, "/.config/" VULKAN_DIR "/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME, settings_file_path);
  ------------------
  |  |  141|  9.58k|#define VK_LOADER_SETTINGS_FILENAME "vk_loader_settings.json"
  ------------------
  512|  9.58k|            if (res == VK_SUCCESS) {
  ------------------
  |  Branch (512:17): [True: 0, False: 9.58k]
  ------------------
  513|      0|                return res;
  514|      0|            }
  515|  9.58k|        }
  516|  9.58k|        if (NULL == xdg_data_home || '\0' == xdg_data_home[0]) {
  ------------------
  |  Branch (516:13): [True: 9.58k, False: 0]
  |  Branch (516:38): [True: 0, False: 0]
  ------------------
  517|  9.58k|            res = check_if_settings_path_exists(
  518|  9.58k|                inst, home, "/.local/share/" VULKAN_DIR "/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME, settings_file_path);
  ------------------
  |  |  141|  9.58k|#define VK_LOADER_SETTINGS_FILENAME "vk_loader_settings.json"
  ------------------
  519|  9.58k|            if (res == VK_SUCCESS) {
  ------------------
  |  Branch (519:17): [True: 8.01k, False: 1.57k]
  ------------------
  520|  8.01k|                return res;
  521|  8.01k|            }
  522|  9.58k|        }
  523|  9.58k|    }
  524|       |
  525|  1.57k|    res = check_if_settings_path_exists(inst, xdg_config_dirs, "/" VULKAN_DIR "/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME,
  ------------------
  |  |  141|  1.57k|#define VK_LOADER_SETTINGS_FILENAME "vk_loader_settings.json"
  ------------------
  526|  1.57k|                                        settings_file_path);
  527|  1.57k|    if (res == VK_SUCCESS) {
  ------------------
  |  Branch (527:9): [True: 0, False: 1.57k]
  ------------------
  528|      0|        return res;
  529|      0|    }
  530|       |
  531|  1.57k|    res = check_if_settings_path_exists(inst, SYSCONFDIR, "/" VULKAN_DIR "/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME,
  ------------------
  |  |  141|  1.57k|#define VK_LOADER_SETTINGS_FILENAME "vk_loader_settings.json"
  ------------------
  532|  1.57k|                                        settings_file_path);
  533|  1.57k|    if (res == VK_SUCCESS) {
  ------------------
  |  Branch (533:9): [True: 0, False: 1.57k]
  ------------------
  534|      0|        return res;
  535|      0|    }
  536|  1.57k|#if defined(EXTRASYSCONFDIR)
  537|       |
  538|  1.57k|    res = check_if_settings_path_exists(inst, EXTRASYSCONFDIR, "/" VULKAN_DIR "/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME,
  ------------------
  |  |  141|  1.57k|#define VK_LOADER_SETTINGS_FILENAME "vk_loader_settings.json"
  ------------------
  539|  1.57k|                                        settings_file_path);
  540|  1.57k|    if (res == VK_SUCCESS) {
  ------------------
  |  Branch (540:9): [True: 0, False: 1.57k]
  ------------------
  541|      0|        return res;
  542|      0|    }
  543|  1.57k|#endif
  544|  1.57k|    res = check_if_settings_path_exists(inst, xdg_data_dirs, "/" VULKAN_DIR "/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME,
  ------------------
  |  |  141|  1.57k|#define VK_LOADER_SETTINGS_FILENAME "vk_loader_settings.json"
  ------------------
  545|  1.57k|                                        settings_file_path);
  546|  1.57k|    if (res == VK_SUCCESS) {
  ------------------
  |  Branch (546:9): [True: 0, False: 1.57k]
  ------------------
  547|      0|        return res;
  548|      0|    }
  549|       |
  550|  1.57k|    return VK_ERROR_INITIALIZATION_FAILED;
  551|  1.57k|}
check_if_layer_configurations_are_equal:
  554|   125k|bool check_if_layer_configurations_are_equal(loader_settings_layer_configuration* a, loader_settings_layer_configuration* b) {
  555|   125k|    if (!a->name || !b->name || 0 != strcmp(a->name, b->name)) {
  ------------------
  |  Branch (555:9): [True: 1.25k, False: 123k]
  |  Branch (555:21): [True: 0, False: 123k]
  |  Branch (555:33): [True: 0, False: 123k]
  ------------------
  556|  1.25k|        return false;
  557|  1.25k|    }
  558|   123k|    if (!a->path || !b->path || 0 != strcmp(a->path, b->path)) {
  ------------------
  |  Branch (558:9): [True: 0, False: 123k]
  |  Branch (558:21): [True: 0, False: 123k]
  |  Branch (558:33): [True: 0, False: 123k]
  ------------------
  559|      0|        return false;
  560|      0|    }
  561|   123k|    return a->control == b->control && a->treat_as_implicit_manifest == b->treat_as_implicit_manifest;
  ------------------
  |  Branch (561:12): [True: 123k, False: 0]
  |  Branch (561:40): [True: 123k, False: 0]
  ------------------
  562|   123k|}
check_if_settings_are_equal:
  584|  6.99k|bool check_if_settings_are_equal(loader_settings* a, loader_settings* b) {
  585|       |    // If either pointer is null, return true
  586|  6.99k|    if (NULL == a || NULL == b) return false;
  ------------------
  |  Branch (586:9): [True: 0, False: 6.99k]
  |  Branch (586:22): [True: 0, False: 6.99k]
  ------------------
  587|  6.99k|    bool are_equal = true;
  588|  6.99k|    are_equal &= a->settings_active == b->settings_active;
  589|  6.99k|    are_equal &= a->has_unordered_layer_location == b->has_unordered_layer_location;
  590|  6.99k|    are_equal &= a->debug_level == b->debug_level;
  591|  6.99k|    are_equal &= a->layer_configurations_active == b->layer_configurations_active;
  592|  6.99k|    are_equal &= a->layer_configuration_count == b->layer_configuration_count;
  593|  6.99k|    are_equal &= a->additional_drivers_use_exclusively == b->additional_drivers_use_exclusively;
  594|  6.99k|    are_equal &= a->additional_driver_count == b->additional_driver_count;
  595|  6.99k|    are_equal &= a->device_configurations_active == b->device_configurations_active;
  596|  6.99k|    are_equal &= a->device_configuration_count == b->device_configuration_count;
  597|  6.99k|    if (!are_equal) return false;
  ------------------
  |  Branch (597:9): [True: 546, False: 6.45k]
  ------------------
  598|   131k|    for (uint32_t i = 0; i < a->layer_configuration_count && i < b->layer_configuration_count; i++) {
  ------------------
  |  Branch (598:26): [True: 125k, False: 6.45k]
  |  Branch (598:62): [True: 125k, False: 0]
  ------------------
  599|   125k|        are_equal &= check_if_layer_configurations_are_equal(&a->layer_configurations[i], &b->layer_configurations[i]);
  600|   125k|    }
  601|  6.45k|    for (uint32_t i = 0; i < a->additional_driver_count && i < b->additional_driver_count; i++) {
  ------------------
  |  Branch (601:26): [True: 0, False: 6.45k]
  |  Branch (601:60): [True: 0, False: 0]
  ------------------
  602|      0|        are_equal &= check_if_driver_configurations_are_equal(&a->additional_drivers[i], &b->additional_drivers[i]);
  603|      0|    }
  604|  6.45k|    for (uint32_t i = 0; i < a->device_configuration_count && i < b->device_configuration_count; i++) {
  ------------------
  |  Branch (604:26): [True: 0, False: 6.45k]
  |  Branch (604:63): [True: 0, False: 0]
  ------------------
  605|      0|        are_equal &= check_if_device_configurations_are_equal(&a->device_configurations[i], &b->device_configurations[i]);
  606|      0|    }
  607|  6.45k|    return are_equal;
  608|  6.99k|}
log_settings:
  610|    674|void log_settings(const struct loader_instance* inst, loader_settings* settings) {
  611|    674|    if (settings == NULL) {
  ------------------
  |  Branch (611:9): [True: 0, False: 674]
  ------------------
  612|      0|        return;
  613|      0|    }
  614|    674|    loader_log(inst, VULKAN_LOADER_INFO_BIT, 0, "Using layer configurations found in loader settings from %s",
  615|    674|               settings->settings_file_path);
  616|       |
  617|    674|    char cmd_line_msg[64] = {0};
  618|    674|    size_t cmd_line_size = sizeof(cmd_line_msg);
  619|       |
  620|    674|    cmd_line_msg[0] = '\0';
  621|       |
  622|    674|    generate_debug_flag_str(settings->debug_level, cmd_line_size, cmd_line_msg);
  623|    674|    if (strlen(cmd_line_msg)) {
  ------------------
  |  Branch (623:9): [True: 127, False: 547]
  ------------------
  624|    127|        loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Loader Settings Filters for Logging to Standard Error: %s", cmd_line_msg);
  625|    127|    }
  626|    674|    if (settings->layer_configurations_active) {
  ------------------
  |  Branch (626:9): [True: 538, False: 136]
  ------------------
  627|    538|        loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Layer Configurations count = %d", settings->layer_configuration_count);
  628|   176k|        for (uint32_t i = 0; i < settings->layer_configuration_count; i++) {
  ------------------
  |  Branch (628:30): [True: 176k, False: 538]
  ------------------
  629|   176k|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "---- Layer Configuration [%d] ----", i);
  630|   176k|            if (settings->layer_configurations[i].control != LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION) {
  ------------------
  |  Branch (630:17): [True: 171k, False: 5.03k]
  ------------------
  631|   171k|                loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Name: %s", settings->layer_configurations[i].name);
  632|   171k|                loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Path: %s", settings->layer_configurations[i].path);
  633|   171k|                loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Layer Type: %s",
  634|   171k|                           settings->layer_configurations[i].treat_as_implicit_manifest ? "Implicit" : "Explicit");
  ------------------
  |  Branch (634:28): [True: 138, False: 171k]
  ------------------
  635|   171k|            }
  636|   176k|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Control: %s",
  637|   176k|                       loader_settings_layer_control_to_string(settings->layer_configurations[i].control));
  638|   176k|        }
  639|    538|    }
  640|    674|    if (settings->additional_driver_count > 0) {
  ------------------
  |  Branch (640:9): [True: 0, False: 674]
  ------------------
  641|      0|        loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "----");
  642|      0|        loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Use Additional Drivers Exclusively = %s",
  643|      0|                   settings->additional_drivers_use_exclusively ? "true" : "false");
  ------------------
  |  Branch (643:20): [True: 0, False: 0]
  ------------------
  644|      0|        loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Additional Driver Configurations count = %d",
  645|      0|                   settings->additional_driver_count);
  646|      0|        for (uint32_t i = 0; i < settings->additional_driver_count; i++) {
  ------------------
  |  Branch (646:30): [True: 0, False: 0]
  ------------------
  647|      0|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "---- Driver Configuration [%d] ----", i);
  648|      0|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Path: %s", settings->additional_drivers[i].path);
  649|      0|        }
  650|      0|    }
  651|    674|    if (settings->device_configurations_active) {
  ------------------
  |  Branch (651:9): [True: 0, False: 674]
  ------------------
  652|      0|        loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "----");
  653|      0|        loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Device Configurations count = %d", settings->device_configuration_count);
  654|      0|        for (uint32_t i = 0; i < settings->device_configuration_count; i++) {
  ------------------
  |  Branch (654:30): [True: 0, False: 0]
  ------------------
  655|      0|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "---- Device Configuration [%d] ----", i);
  656|      0|            char device_uuid_str[UUID_STR_LEN] = {0};
  657|      0|            loader_log_generate_uuid_string(settings->device_configurations[i].deviceUUID, device_uuid_str);
  658|      0|            char driver_uuid_str[UUID_STR_LEN] = {0};
  659|      0|            loader_log_generate_uuid_string(settings->device_configurations[i].driverUUID, driver_uuid_str);
  660|      0|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "deviceUUID: %s", device_uuid_str);
  661|      0|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "driverUUID: %s", driver_uuid_str);
  662|      0|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "driverVersion: %d", settings->device_configurations[i].driverVersion);
  663|      0|            if ('\0' != settings->device_configurations[i].deviceName[0]) {
  ------------------
  |  Branch (663:17): [True: 0, False: 0]
  ------------------
  664|      0|                loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "deviceName: %s", settings->device_configurations[i].deviceName);
  665|      0|            }
  666|      0|            if ('\0' != settings->device_configurations[i].driverName[0]) {
  ------------------
  |  Branch (666:17): [True: 0, False: 0]
  ------------------
  667|      0|                loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "driverName: %s", settings->device_configurations[i].driverName);
  668|      0|            }
  669|      0|        }
  670|      0|    }
  671|    674|    loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "---------------------------------");
  672|    674|}
get_loader_settings:
  677|  9.58k|VkResult get_loader_settings(const struct loader_instance* inst, loader_settings* loader_settings) {
  678|  9.58k|    VkResult res = VK_SUCCESS;
  679|  9.58k|    cJSON* json = NULL;
  680|  9.58k|    char* file_format_version_string = NULL;
  681|  9.58k|    char* settings_file_path = NULL;
  682|       |#if defined(WIN32)
  683|       |    res = windows_get_loader_settings_file_path(inst, &settings_file_path);
  684|       |    if (res != VK_SUCCESS) {
  685|       |        loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
  686|       |                   "No valid vk_loader_settings.json file found, no loader settings will be active");
  687|       |        goto out;
  688|       |    }
  689|       |
  690|       |#elif COMMON_UNIX_PLATFORMS
  691|       |    res = get_unix_settings_path(inst, &settings_file_path);
  692|  9.58k|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (692:9): [True: 1.57k, False: 8.01k]
  ------------------
  693|  1.57k|        loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
  694|  1.57k|                   "No valid vk_loader_settings.json file found, no loader settings will be active");
  695|  1.57k|        goto out;
  696|  1.57k|    }
  697|       |#else
  698|       |#warning "Unsupported platform - must specify platform specific location for vk_loader_settings.json"
  699|       |#endif
  700|       |
  701|  8.01k|    res = loader_get_json(inst, settings_file_path, &json);
  702|       |    // Make sure sure the top level json value is an object
  703|  8.01k|    if (res != VK_SUCCESS || NULL == json || json->type != cJSON_Object) {
  ------------------
  |  |  103|  4.80k|#define cJSON_Object (1 << 6)
  ------------------
  |  Branch (703:9): [True: 91, False: 7.92k]
  |  Branch (703:30): [True: 3.11k, False: 4.80k]
  |  Branch (703:46): [True: 922, False: 3.88k]
  ------------------
  704|  4.13k|        goto out;
  705|  4.13k|    }
  706|       |
  707|  3.88k|    res = loader_parse_json_string(json, "file_format_version", &file_format_version_string);
  708|  3.88k|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (708:9): [True: 61, False: 3.82k]
  ------------------
  709|     61|        if (res != VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (709:13): [True: 61, False: 0]
  ------------------
  710|     61|            loader_log(
  711|     61|                inst, VULKAN_LOADER_DEBUG_BIT, 0,
  712|     61|                "Loader settings file from %s missing required field file_format_version - no loader settings will be active",
  713|     61|                settings_file_path);
  714|     61|        }
  715|     61|        goto out;
  716|     61|    }
  717|       |
  718|       |    // Because the file may contain either a "settings_array" or a single "settings" object, we need to create a cJSON so that we
  719|       |    // can iterate on both cases with common code
  720|  3.82k|    cJSON settings_iter_parent = {0};
  721|       |
  722|  3.82k|    cJSON* settings_array = loader_cJSON_GetObjectItem(json, "settings_array");
  723|  3.82k|    cJSON* single_settings_object = loader_cJSON_GetObjectItem(json, "settings");
  724|  3.82k|    if (NULL != settings_array) {
  ------------------
  |  Branch (724:9): [True: 2.47k, False: 1.34k]
  ------------------
  725|  2.47k|        memcpy(&settings_iter_parent, settings_array, sizeof(cJSON));
  726|  2.47k|    } else if (NULL != single_settings_object) {
  ------------------
  |  Branch (726:16): [True: 480, False: 865]
  ------------------
  727|    480|        settings_iter_parent.child = single_settings_object;
  728|    865|    } else {
  729|    865|        loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0,
  730|    865|                   "Loader settings file from %s missing required settings objects: Either one of the \"settings\" or "
  731|    865|                   "\"settings_array\" objects must be present - no loader settings will be active",
  732|    865|                   settings_file_path);
  733|    865|        res = VK_ERROR_INITIALIZATION_FAILED;
  734|    865|        goto out;
  735|    865|    }
  736|       |
  737|       |    // Corresponds to the settings object that has no app keys
  738|  2.95k|    cJSON* global_settings = NULL;
  739|       |    // Corresponds to the settings object which has a matching app key
  740|  2.95k|    cJSON* settings_to_use = NULL;
  741|       |
  742|  2.95k|    char current_process_path[1024];
  743|  2.95k|    bool valid_exe_path = NULL != loader_platform_executable_path(current_process_path, 1024);
  744|       |
  745|  2.95k|    cJSON* settings_object_iter = NULL;
  746|  6.59k|    cJSON_ArrayForEach(settings_object_iter, &settings_iter_parent) {
  ------------------
  |  |  213|  9.49k|    for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
  |  |  ------------------
  |  |  |  Branch (213:20): [True: 2.95k, Folded]
  |  |  |  Branch (213:61): [True: 6.59k, False: 2.89k]
  |  |  ------------------
  ------------------
  747|  6.59k|        if (settings_object_iter->type != cJSON_Object) {
  ------------------
  |  |  103|  6.59k|#define cJSON_Object (1 << 6)
  ------------------
  |  Branch (747:13): [True: 60, False: 6.53k]
  ------------------
  748|     60|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0,
  749|     60|                       "Loader settings file from %s has a settings element that is not an object", settings_file_path);
  750|     60|            break;
  751|     60|        }
  752|       |
  753|  6.53k|        cJSON* app_keys = loader_cJSON_GetObjectItem(settings_object_iter, "app_keys");
  754|  6.53k|        if (NULL == app_keys) {
  ------------------
  |  Branch (754:13): [True: 4.28k, False: 2.25k]
  ------------------
  755|       |            // use the first 'global' settings that has no app keys as the global one
  756|  4.28k|            if (global_settings == NULL) {
  ------------------
  |  Branch (756:17): [True: 2.62k, False: 1.65k]
  ------------------
  757|  2.62k|                global_settings = settings_object_iter;
  758|  2.62k|            }
  759|  4.28k|            continue;
  760|  4.28k|        }
  761|       |        // No sense iterating if we couldn't get the executable path
  762|  2.25k|        if (!valid_exe_path) {
  ------------------
  |  Branch (762:13): [True: 0, False: 2.25k]
  ------------------
  763|      0|            break;
  764|      0|        }
  765|  2.25k|        cJSON* app_key = NULL;
  766|  3.62k|        cJSON_ArrayForEach(app_key, app_keys) {
  ------------------
  |  |  213|  5.88k|    for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
  |  |  ------------------
  |  |  |  Branch (213:20): [True: 2.25k, False: 0]
  |  |  |  Branch (213:61): [True: 3.62k, False: 2.25k]
  |  |  ------------------
  ------------------
  767|  3.62k|            char* app_key_str = loader_cJSON_GetStringValue(app_key);
  768|  3.62k|            if (app_key_str && strcmp(current_process_path, app_key_str) == 0) {
  ------------------
  |  Branch (768:17): [True: 2.23k, False: 1.39k]
  |  Branch (768:32): [True: 0, False: 2.23k]
  ------------------
  769|      0|                settings_to_use = settings_object_iter;
  770|      0|                break;
  771|      0|            }
  772|  3.62k|        }
  773|       |
  774|       |        // Break if we have found a matching current_process_path
  775|  2.25k|        if (NULL != settings_to_use) {
  ------------------
  |  Branch (775:13): [True: 0, False: 2.25k]
  ------------------
  776|      0|            break;
  777|      0|        }
  778|  2.25k|    }
  779|       |
  780|       |    // No app specific settings match - either use global settings or exit
  781|  2.95k|    if (settings_to_use == NULL) {
  ------------------
  |  Branch (781:9): [True: 2.95k, False: 0]
  ------------------
  782|  2.95k|        if (global_settings == NULL) {
  ------------------
  |  Branch (782:13): [True: 331, False: 2.62k]
  ------------------
  783|    331|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0,
  784|    331|                       "Loader settings file from %s missing global settings and none of the app specific settings matched the "
  785|    331|                       "current application - no loader settings will be active",
  786|    331|                       settings_file_path);
  787|    331|            goto out;  // No global settings were found - exit
  788|  2.62k|        } else {
  789|  2.62k|            settings_to_use = global_settings;  // Global settings are present - use it
  790|  2.62k|        }
  791|  2.95k|    }
  792|       |
  793|       |    // optional
  794|  2.62k|    cJSON* stderr_filter = loader_cJSON_GetObjectItem(settings_to_use, "stderr_log");
  795|  2.62k|    if (NULL != stderr_filter) {
  ------------------
  |  Branch (795:9): [True: 931, False: 1.69k]
  ------------------
  796|    931|        struct loader_string_list stderr_log = {0};
  797|    931|        VkResult stderr_log_result = VK_SUCCESS;
  798|    931|        stderr_log_result = loader_parse_json_array_of_strings(inst, settings_to_use, "stderr_log", &stderr_log);
  799|    931|        if (VK_ERROR_OUT_OF_HOST_MEMORY == stderr_log_result) {
  ------------------
  |  Branch (799:13): [True: 0, False: 931]
  ------------------
  800|      0|            res = VK_ERROR_OUT_OF_HOST_MEMORY;
  801|      0|            goto out;
  802|      0|        }
  803|    931|        loader_settings->debug_level = parse_log_filters_from_strings(&stderr_log);
  804|    931|        free_string_list(inst, &stderr_log);
  805|    931|    }
  806|       |
  807|       |    // optional
  808|  2.62k|    cJSON* logs_to_use = loader_cJSON_GetObjectItem(settings_to_use, "log_locations");
  809|  2.62k|    if (NULL != logs_to_use) {
  ------------------
  |  Branch (809:9): [True: 163, False: 2.46k]
  ------------------
  810|    163|        cJSON* log_element = NULL;
  811|  8.40k|        cJSON_ArrayForEach(log_element, logs_to_use) {
  ------------------
  |  |  213|  8.57k|    for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
  |  |  ------------------
  |  |  |  Branch (213:20): [True: 163, False: 0]
  |  |  |  Branch (213:61): [True: 8.40k, False: 163]
  |  |  ------------------
  ------------------
  812|       |            // bool is_valid = true;
  813|  8.40k|            struct loader_string_list log_destinations = {0};
  814|  8.40k|            VkResult parse_dest_res = loader_parse_json_array_of_strings(inst, log_element, "destinations", &log_destinations);
  815|  8.40k|            if (parse_dest_res != VK_SUCCESS) {
  ------------------
  |  Branch (815:17): [True: 8.40k, False: 1]
  ------------------
  816|       |                // is_valid = false;
  817|  8.40k|            }
  818|  8.40k|            free_string_list(inst, &log_destinations);
  819|  8.40k|            struct loader_string_list log_filters = {0};
  820|  8.40k|            VkResult parse_filters_res = loader_parse_json_array_of_strings(inst, log_element, "filters", &log_filters);
  821|  8.40k|            if (parse_filters_res != VK_SUCCESS) {
  ------------------
  |  Branch (821:17): [True: 6.38k, False: 2.02k]
  ------------------
  822|       |                // is_valid = false;
  823|  6.38k|            }
  824|  8.40k|            free_string_list(inst, &log_filters);
  825|  8.40k|        }
  826|    163|    }
  827|       |
  828|  2.62k|    VkResult layer_configurations_res = parse_layer_configurations(inst, settings_to_use, loader_settings);
  829|  2.62k|    if (VK_ERROR_OUT_OF_HOST_MEMORY == layer_configurations_res) {
  ------------------
  |  Branch (829:9): [True: 0, False: 2.62k]
  ------------------
  830|      0|        res = layer_configurations_res;
  831|      0|        goto out;
  832|      0|    }
  833|       |
  834|       |    // Determine if there exists a layer configuration indicating where to put layers not contained in the settings file
  835|       |    // LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION
  836|   296k|    for (uint32_t i = 0; i < loader_settings->layer_configuration_count; i++) {
  ------------------
  |  Branch (836:26): [True: 294k, False: 2.37k]
  ------------------
  837|   294k|        if (loader_settings->layer_configurations[i].control == LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION) {
  ------------------
  |  Branch (837:13): [True: 248, False: 294k]
  ------------------
  838|    248|            loader_settings->has_unordered_layer_location = true;
  839|    248|            break;
  840|    248|        }
  841|   294k|    }
  842|       |
  843|  2.62k|    VkResult additional_drivers_res = parse_additional_drivers(inst, settings_to_use, loader_settings);
  844|  2.62k|    if (VK_ERROR_OUT_OF_HOST_MEMORY == additional_drivers_res) {
  ------------------
  |  Branch (844:9): [True: 0, False: 2.62k]
  ------------------
  845|      0|        res = additional_drivers_res;
  846|      0|        goto out;
  847|      0|    }
  848|       |
  849|  2.62k|    VkResult device_configurations_res = parse_device_configurations(inst, settings_to_use, loader_settings);
  850|  2.62k|    if (VK_ERROR_OUT_OF_HOST_MEMORY == device_configurations_res) {
  ------------------
  |  Branch (850:9): [True: 0, False: 2.62k]
  ------------------
  851|      0|        res = device_configurations_res;
  852|      0|        goto out;
  853|      0|    }
  854|       |
  855|       |    // Only consider the settings active if there is at least one "setting" active.
  856|       |    // Those are either logging, layers, additional_drivers, or device_configurations.
  857|  2.62k|    if (loader_settings->debug_level != 0 || loader_settings->layer_configurations_active ||
  ------------------
  |  Branch (857:9): [True: 306, False: 2.32k]
  |  Branch (857:46): [True: 849, False: 1.47k]
  ------------------
  858|  1.47k|        loader_settings->additional_driver_count != 0 || loader_settings->device_configurations_active) {
  ------------------
  |  Branch (858:9): [True: 0, False: 1.47k]
  |  Branch (858:58): [True: 0, False: 1.47k]
  ------------------
  859|  1.15k|        loader_settings->settings_file_path = settings_file_path;
  860|  1.15k|        settings_file_path = NULL;
  861|  1.15k|        loader_settings->settings_active = true;
  862|  1.47k|    } else {
  863|  1.47k|        loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
  864|  1.47k|                   "vk_loader_settings.json file found at \"%s\" but did not contain any valid settings.", settings_file_path);
  865|  1.47k|    }
  866|  9.58k|out:
  867|  9.58k|    if (NULL != json) {
  ------------------
  |  Branch (867:9): [True: 4.80k, False: 4.78k]
  ------------------
  868|  4.80k|        loader_cJSON_Delete(json);
  869|  4.80k|    }
  870|       |
  871|  9.58k|    loader_instance_heap_free(inst, settings_file_path);
  872|       |
  873|  9.58k|    loader_instance_heap_free(inst, file_format_version_string);
  874|  9.58k|    return res;
  875|  2.62k|}
update_global_loader_settings:
  877|  9.58k|TEST_FUNCTION_EXPORT VkResult update_global_loader_settings(void) {
  878|  9.58k|    loader_settings settings = {0};
  879|  9.58k|    VkResult res = get_loader_settings(NULL, &settings);
  880|  9.58k|    loader_platform_thread_lock_mutex(&global_loader_settings_lock);
  881|       |
  882|  9.58k|    if (res == VK_SUCCESS) {
  ------------------
  |  Branch (882:9): [True: 6.99k, False: 2.58k]
  ------------------
  883|  6.99k|        if (!check_if_settings_are_equal(&settings, &global_loader_settings)) {
  ------------------
  |  Branch (883:13): [True: 674, False: 6.32k]
  ------------------
  884|    674|            log_settings(NULL, &settings);
  885|    674|        }
  886|  6.99k|        free_loader_settings(NULL, &global_loader_settings);
  887|  6.99k|        memcpy(&global_loader_settings, &settings, sizeof(loader_settings));
  888|  6.99k|        if (global_loader_settings.settings_active && global_loader_settings.debug_level > 0) {
  ------------------
  |  Branch (888:13): [True: 1.15k, False: 5.84k]
  |  Branch (888:55): [True: 306, False: 849]
  ------------------
  889|    306|            loader_set_global_debug_level(global_loader_settings.debug_level);
  890|    306|        }
  891|  6.99k|    }
  892|  9.58k|    loader_platform_thread_unlock_mutex(&global_loader_settings_lock);
  893|  9.58k|    return res;
  894|  9.58k|}
init_global_loader_settings:
  896|      2|void init_global_loader_settings(void) {
  897|      2|    loader_platform_thread_create_mutex(&global_loader_settings_lock);
  898|       |    // Free out the global settings in case the process was loaded & unloaded
  899|       |    free_loader_settings(NULL, &global_loader_settings);
  900|      2|}
teardown_global_loader_settings:
  901|  3.19k|void teardown_global_loader_settings(void) {
  902|       |    free_loader_settings(NULL, &global_loader_settings);
  903|  3.19k|    loader_platform_thread_delete_mutex(&global_loader_settings_lock);
  904|  3.19k|}
should_skip_logging_global_messages:
  906|  3.19k|bool should_skip_logging_global_messages(VkFlags msg_type) {
  907|  3.19k|    loader_platform_thread_lock_mutex(&global_loader_settings_lock);
  908|  3.19k|    bool should_skip = global_loader_settings.settings_active && 0 != (msg_type & global_loader_settings.debug_level);
  ------------------
  |  Branch (908:24): [True: 446, False: 2.74k]
  |  Branch (908:66): [True: 0, False: 446]
  ------------------
  909|  3.19k|    loader_platform_thread_unlock_mutex(&global_loader_settings_lock);
  910|  3.19k|    return should_skip;
  911|  3.19k|}
get_current_settings_and_lock:
  916|  6.39k|const loader_settings* get_current_settings_and_lock(const struct loader_instance* inst) {
  917|  6.39k|    if (inst) {
  ------------------
  |  Branch (917:9): [True: 0, False: 6.39k]
  ------------------
  918|      0|        return &inst->settings;
  919|      0|    }
  920|  6.39k|    loader_platform_thread_lock_mutex(&global_loader_settings_lock);
  921|  6.39k|    return &global_loader_settings;
  922|  6.39k|}
release_current_settings_lock:
  924|  6.39k|void release_current_settings_lock(const struct loader_instance* inst) {
  925|  6.39k|    if (inst == NULL) {
  ------------------
  |  Branch (925:9): [True: 6.39k, False: 0]
  ------------------
  926|  6.39k|        loader_platform_thread_unlock_mutex(&global_loader_settings_lock);
  927|  6.39k|    }
  928|  6.39k|}
get_settings_layers:
  931|  3.19k|                                                  bool* should_search_for_other_layers) {
  932|  3.19k|    VkResult res = VK_SUCCESS;
  933|  3.19k|    *should_search_for_other_layers = true;  // default to true
  934|       |
  935|  3.19k|    const loader_settings* settings = get_current_settings_and_lock(inst);
  936|       |
  937|  3.19k|    if (NULL == settings || !settings->settings_active || !settings->layer_configurations_active) {
  ------------------
  |  Branch (937:9): [True: 0, False: 3.19k]
  |  Branch (937:29): [True: 2.74k, False: 446]
  |  Branch (937:59): [True: 93, False: 353]
  ------------------
  938|  2.84k|        goto out;
  939|  2.84k|    }
  940|       |
  941|       |    // Assume the list doesn't contain LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION at first
  942|    353|    *should_search_for_other_layers = false;
  943|       |
  944|   148k|    for (uint32_t i = 0; i < settings->layer_configuration_count; i++) {
  ------------------
  |  Branch (944:26): [True: 148k, False: 353]
  ------------------
  945|   148k|        loader_settings_layer_configuration* layer_config = &settings->layer_configurations[i];
  946|       |
  947|       |        // If we encountered a layer that should be forced off, we add it to the settings_layers list but only
  948|       |        // with the data required to compare it with layers not in the settings file (aka name and manifest path)
  949|   148k|        if (layer_config->control == LOADER_SETTINGS_LAYER_CONTROL_OFF) {
  ------------------
  |  Branch (949:13): [True: 140k, False: 8.00k]
  ------------------
  950|   140k|            struct loader_layer_properties props = {0};
  951|   140k|            props.settings_control_value = LOADER_SETTINGS_LAYER_CONTROL_OFF;
  952|   140k|            loader_strncpy(props.info.layerName, VK_MAX_EXTENSION_NAME_SIZE, layer_config->name, VK_MAX_EXTENSION_NAME_SIZE);
  953|   140k|            props.info.layerName[VK_MAX_EXTENSION_NAME_SIZE - 1] = '\0';
  954|   140k|            res = loader_copy_to_new_str(inst, layer_config->path, &props.manifest_file_name);
  955|   140k|            if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
  ------------------
  |  Branch (955:17): [True: 0, False: 140k]
  ------------------
  956|      0|                goto out;
  957|      0|            }
  958|   140k|            res = loader_append_layer_property(inst, settings_layers, &props);
  959|   140k|            if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
  ------------------
  |  Branch (959:17): [True: 0, False: 140k]
  ------------------
  960|      0|                loader_free_layer_properties(inst, &props);
  961|      0|                goto out;
  962|      0|            }
  963|   140k|            continue;
  964|   140k|        }
  965|       |
  966|       |        // The special layer location that indicates where unordered layers should go only should have the
  967|       |        // settings_control_value set - everything else should be NULL
  968|  8.00k|        if (layer_config->control == LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION) {
  ------------------
  |  Branch (968:13): [True: 1.69k, False: 6.30k]
  ------------------
  969|  1.69k|            struct loader_layer_properties props = {0};
  970|  1.69k|            props.settings_control_value = LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION;
  971|  1.69k|            res = loader_append_layer_property(inst, settings_layers, &props);
  972|  1.69k|            if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
  ------------------
  |  Branch (972:17): [True: 0, False: 1.69k]
  ------------------
  973|      0|                loader_free_layer_properties(inst, &props);
  974|      0|                goto out;
  975|      0|            }
  976|  1.69k|            *should_search_for_other_layers = true;
  977|  1.69k|            continue;
  978|  1.69k|        }
  979|       |
  980|  6.30k|        if (layer_config->path == NULL) {
  ------------------
  |  Branch (980:13): [True: 0, False: 6.30k]
  ------------------
  981|      0|            continue;
  982|      0|        }
  983|       |
  984|  6.30k|        cJSON* json = NULL;
  985|  6.30k|        VkResult local_res = loader_get_json(inst, layer_config->path, &json);
  986|  6.30k|        if (VK_ERROR_OUT_OF_HOST_MEMORY == local_res) {
  ------------------
  |  Branch (986:13): [True: 0, False: 6.30k]
  ------------------
  987|      0|            res = VK_ERROR_OUT_OF_HOST_MEMORY;
  988|      0|            goto out;
  989|  6.30k|        } else if (VK_SUCCESS != local_res || NULL == json) {
  ------------------
  |  Branch (989:20): [True: 4.98k, False: 1.32k]
  |  Branch (989:47): [True: 1.21k, False: 108]
  ------------------
  990|  6.19k|            continue;
  991|  6.19k|        }
  992|       |
  993|       |        // Makes it possible to know if a new layer was added or not, since the only return value is VkResult
  994|    108|        uint32_t count_before_adding = settings_layers->count;
  995|       |
  996|    108|        local_res =
  997|    108|            loader_add_layer_properties(inst, settings_layers, json, layer_config->treat_as_implicit_manifest, layer_config->path);
  998|    108|        loader_cJSON_Delete(json);
  999|       |
 1000|       |        // If the error is anything other than out of memory we still want to try to load the other layers
 1001|    108|        if (VK_ERROR_OUT_OF_HOST_MEMORY == local_res) {
  ------------------
  |  Branch (1001:13): [True: 0, False: 108]
  ------------------
 1002|      0|            res = VK_ERROR_OUT_OF_HOST_MEMORY;
 1003|      0|            goto out;
 1004|    108|        } else if (local_res != VK_SUCCESS || count_before_adding == settings_layers->count) {
  ------------------
  |  Branch (1004:20): [True: 66, False: 42]
  |  Branch (1004:47): [True: 0, False: 42]
  ------------------
 1005|       |            // Indicates something was wrong with the layer, can't add it to the list
 1006|     66|            continue;
 1007|     66|        }
 1008|       |
 1009|    643|        for (uint32_t j = count_before_adding; j < settings_layers->count; j++) {
  ------------------
  |  Branch (1009:48): [True: 601, False: 42]
  ------------------
 1010|    601|            struct loader_layer_properties* newly_added_layer = &settings_layers->list[j];
 1011|    601|            newly_added_layer->settings_control_value = layer_config->control;
 1012|       |            // If the manifest file found has a name that differs from the one in the settings, remove this layer from
 1013|       |            // consideration
 1014|    601|            if (strncmp(newly_added_layer->info.layerName, layer_config->name, VK_MAX_EXTENSION_NAME_SIZE) != 0) {
  ------------------
  |  Branch (1014:17): [True: 577, False: 24]
  ------------------
 1015|    577|                loader_remove_layer_in_list(inst, settings_layers, j);
 1016|    577|                j--;
 1017|    577|                continue;
 1018|    577|            }
 1019|    601|            bool should_remove = false;
 1020|       |            // Make sure the layer isn't already in the list
 1021|     46|            for (uint32_t k = 0; k < j; k++) {
  ------------------
  |  Branch (1021:34): [True: 30, False: 16]
  ------------------
 1022|     30|                if (0 == strncmp(settings_layers->list[k].info.layerName, newly_added_layer->info.layerName,
  ------------------
  |  Branch (1022:21): [True: 28, False: 2]
  ------------------
 1023|     30|                                 VK_MAX_EXTENSION_NAME_SIZE)) {
 1024|     28|                    if (0 == (newly_added_layer->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER) &&
  ------------------
  |  Branch (1024:25): [True: 28, False: 0]
  ------------------
 1025|     28|                        settings_layers->list[k].lib_name != NULL && newly_added_layer->lib_name != NULL &&
  ------------------
  |  Branch (1025:25): [True: 17, False: 11]
  |  Branch (1025:70): [True: 14, False: 3]
  ------------------
 1026|     14|                        strcmp(settings_layers->list[k].lib_name, newly_added_layer->lib_name) == 0) {
  ------------------
  |  Branch (1026:25): [True: 8, False: 6]
  ------------------
 1027|      8|                        should_remove = true;
 1028|      8|                        break;
 1029|      8|                    }
 1030|     28|                }
 1031|     30|            }
 1032|     24|            if (should_remove) {
  ------------------
  |  Branch (1032:17): [True: 8, False: 16]
  ------------------
 1033|      8|                loader_remove_layer_in_list(inst, settings_layers, j);
 1034|      8|                j--;
 1035|      8|            }
 1036|     24|        }
 1037|     42|    }
 1038|       |
 1039|  3.19k|out:
 1040|  3.19k|    release_current_settings_lock(inst);
 1041|  3.19k|    return res;
 1042|    353|}

loader.c:loader_strncpy:
  461|   152k|static inline char *loader_strncpy(char *dest, size_t dest_sz, const char *src, size_t count) {
  462|   152k|    (void)dest_sz;
  463|   152k|    return strncpy(dest, src, count);
  464|   152k|}
loader.c:thread_safe_strtok:
  454|  1.16k|static inline void *thread_safe_strtok(char *str, const char *delim, char **saveptr) { return strtok_r(str, delim, saveptr); }
loader.c:loader_platform_thread_create_mutex:
  444|      4|static inline void loader_platform_thread_create_mutex(loader_platform_thread_mutex *pMutex) {
  445|      4|    pthread_mutexattr_t attr;
  446|      4|    pthread_mutexattr_init(&attr);
  447|      4|    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
  448|      4|    pthread_mutex_init(pMutex, &attr);
  449|      4|}
loader.c:loader_platform_is_path_absolute:
  294|    122|static inline bool loader_platform_is_path_absolute(const char *path) {
  295|    122|    if (path[0] == '/')
  ------------------
  |  Branch (295:9): [True: 24, False: 98]
  ------------------
  296|     24|        return true;
  297|     98|    else
  298|     98|        return false;
  299|    122|}
log.c:loader_strncat:
  457|  3.23M|static inline char *loader_strncat(char *dest, size_t dest_sz, const char *src, size_t count) {
  458|  3.23M|    (void)dest_sz;
  459|  3.23M|    return strncat(dest, src, count);
  460|  3.23M|}
settings.c:loader_strncpy:
  461|   167k|static inline char *loader_strncpy(char *dest, size_t dest_sz, const char *src, size_t count) {
  462|   167k|    (void)dest_sz;
  463|   167k|    return strncpy(dest, src, count);
  464|   167k|}
settings.c:loader_strncat:
  457|  27.0k|static inline char *loader_strncat(char *dest, size_t dest_sz, const char *src, size_t count) {
  458|  27.0k|    (void)dest_sz;
  459|  27.0k|    return strncat(dest, src, count);
  460|  27.0k|}
settings.c:loader_platform_file_exists:
  285|  27.0k|static inline bool loader_platform_file_exists(const char *path) {
  286|  27.0k|    if (access(path, F_OK))
  ------------------
  |  Branch (286:9): [True: 19.0k, False: 8.01k]
  ------------------
  287|  19.0k|        return false;
  288|  8.01k|    else
  289|  8.01k|        return true;
  290|  27.0k|}
settings.c:loader_platform_executable_path:
  306|  2.95k|static inline char *loader_platform_executable_path(char *buffer, size_t size) {
  307|  2.95k|    ssize_t count = readlink("/proc/self/exe", buffer, size);
  308|  2.95k|    if (count == -1) return NULL;
  ------------------
  |  Branch (308:9): [True: 0, False: 2.95k]
  ------------------
  309|  2.95k|    if (count == 0) return NULL;
  ------------------
  |  Branch (309:9): [True: 0, False: 2.95k]
  ------------------
  310|  2.95k|    buffer[count] = '\0';
  311|  2.95k|    return buffer;
  312|  2.95k|}
settings.c:loader_platform_thread_lock_mutex:
  450|  19.1k|static inline void loader_platform_thread_lock_mutex(loader_platform_thread_mutex *pMutex) { pthread_mutex_lock(pMutex); }
settings.c:loader_platform_thread_unlock_mutex:
  451|  19.1k|static inline void loader_platform_thread_unlock_mutex(loader_platform_thread_mutex *pMutex) { pthread_mutex_unlock(pMutex); }
settings.c:loader_platform_thread_create_mutex:
  444|      2|static inline void loader_platform_thread_create_mutex(loader_platform_thread_mutex *pMutex) {
  445|      2|    pthread_mutexattr_t attr;
  446|      2|    pthread_mutexattr_init(&attr);
  447|      2|    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
  448|      2|    pthread_mutex_init(pMutex, &attr);
  449|      2|}
settings.c:loader_platform_thread_delete_mutex:
  452|  3.19k|static inline void loader_platform_thread_delete_mutex(loader_platform_thread_mutex *pMutex) { pthread_mutex_destroy(pMutex); }

wsi_unsupported_instance_extension:
  273|      3|bool wsi_unsupported_instance_extension(const VkExtensionProperties *ext_prop) {
  274|       |#if !defined(VK_USE_PLATFORM_WAYLAND_KHR)
  275|       |    if (!strcmp(ext_prop->extensionName, "VK_KHR_wayland_surface")) return true;
  276|       |#endif  // VK_USE_PLATFORM_WAYLAND_KHR
  277|       |#if !defined(VK_USE_PLATFORM_XCB_KHR)
  278|       |    if (!strcmp(ext_prop->extensionName, "VK_KHR_xcb_surface")) return true;
  279|       |#endif  // VK_USE_PLATFORM_XCB_KHR
  280|       |#if !defined(VK_USE_PLATFORM_XLIB_KHR)
  281|       |    if (!strcmp(ext_prop->extensionName, "VK_KHR_xlib_surface")) return true;
  282|       |#endif  // VK_USE_PLATFORM_XLIB_KHR
  283|      3|#if !defined(VK_USE_PLATFORM_DIRECTFB_EXT)
  284|      3|    if (!strcmp(ext_prop->extensionName, "VK_EXT_directfb_surface")) return true;
  ------------------
  |  Branch (284:9): [True: 0, False: 3]
  ------------------
  285|      3|#endif  // VK_USE_PLATFORM_DIRECTFB_EXT
  286|      3|#if !defined(VK_USE_PLATFORM_SCREEN_QNX)
  287|      3|    if (!strcmp(ext_prop->extensionName, "VK_QNX_screen_surface")) return true;
  ------------------
  |  Branch (287:9): [True: 0, False: 3]
  ------------------
  288|      3|#endif  // VK_USE_PLATFORM_SCREEN_QNX
  289|       |
  290|      3|    return false;
  291|      3|}

