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

LLVMFuzzerInitialize:
   22|      2|int LLVMFuzzerInitialize(int *argc, char ***argv) {
   23|      2|  setenv("HOME", "/tmp", 1);
   24|      2|  system("mkdir -p $HOME/.local/share/vulkan/implicit_layer.d");
   25|      2|  system("mkdir -p $HOME/.local/share/vulkan/loader_settings.d");
   26|      2|  return 0;
   27|      2|}
create_config_file:
   32|  11.3k|int create_config_file(const char* config_path, const char* config_filename, const uint8_t* data, size_t size) {
   33|  11.3k|  char filename[512];
   34|  11.3k|  char path[256];
   35|       |
   36|       |
   37|  11.3k|  sprintf(path, "%s/%s", getenv("HOME"), config_path);
   38|  11.3k|  sprintf(filename, "%s/%s", path, config_filename);
   39|       |
   40|  11.3k|  FILE *fp = fopen(filename, "wb");
   41|  11.3k|  if (!fp) {
  ------------------
  |  Branch (41:7): [True: 0, False: 11.3k]
  ------------------
   42|      0|    return 1;
   43|      0|  }
   44|  11.3k|  fwrite(data, size, 1, fp);
   45|  11.3k|  fclose(fp);
   46|       |
   47|  11.3k|  return 0;
   48|  11.3k|}
remove_config_file:
   53|  11.3k|void remove_config_file(const char* config_path, const char* config_filename) {
   54|  11.3k|  char filename[512];
   55|  11.3k|  sprintf(filename, "%s/%s/%s", getenv("HOME"), config_path, config_filename);
   56|  11.3k|  unlink(filename);
   57|  11.3k|}
LLVMFuzzerTestOneInput:
   62|  5.68k|int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
   63|       |
   64|       |# ifdef SPLIT_INPUT
   65|       |  if (size < 2*sizeof(size_t)) {
   66|       |    return 0;
   67|       |  }
   68|       |
   69|       |  // Split the loaders into two different parts so the files
   70|       |  // are independently seeded with fuzz data.
   71|       |  size_t first_size = (*(size_t*)data) % 64000;
   72|       |  size_t second_size = (*(size_t*)(data + sizeof(size_t))) % 64000;
   73|       |
   74|       |  data += 2*sizeof(size_t); // Move past the first two integers
   75|       |  size -= 2*sizeof(size_t); // Adjust size to account for the first two integers
   76|       |  size_t total_size_needed = first_size + second_size;
   77|       |  if (size <= total_size_needed) {
   78|       |    return 0;
   79|       |  }
   80|       |  int result = create_config_file(".local/share/vulkan/implicit_layer.d", "complex_layer.json", data, first_size);
   81|       |  if (result) {
   82|       |    return 0;
   83|       |  }
   84|       |
   85|       |  data += first_size;
   86|       |
   87|       |  result = create_config_file(".local/share/vulkan/loader_settings.d", "vk_loader_settings.json", data, second_size);
   88|       |  if (result) {
   89|       |    return 0;
   90|       |  }
   91|       |#else
   92|  5.68k|  int result = create_config_file(".local/share/vulkan/implicit_layer.d", "complex_layer.json", data, size);
   93|  5.68k|  if (result) {
  ------------------
  |  Branch (93:7): [True: 0, False: 5.68k]
  ------------------
   94|      0|    return 0;
   95|      0|  }
   96|       |
   97|  5.68k|  result = create_config_file(".local/share/vulkan/loader_settings.d", "vk_loader_settings.json", data, size);
   98|  5.68k|  if (result) {
  ------------------
  |  Branch (98:7): [True: 0, False: 5.68k]
  ------------------
   99|      0|    return 0;
  100|      0|  }
  101|  5.68k|#endif
  102|       |
  103|       |
  104|       |  //printf("Status: %d\n", (int)ms);
  105|  5.68k|  setenv("VK_LOADER_LAYERS_ENABLE", "all", 1);
  106|       |
  107|  5.68k|  uint32_t pPropertyCount = 0;
  108|  5.68k|  VkResult vk_result = vkEnumerateInstanceExtensionProperties("test_auto", &pPropertyCount, NULL);
  109|       |  
  110|  5.68k|  if (vk_result == VK_SUCCESS) {
  ------------------
  |  Branch (110:7): [True: 277, False: 5.40k]
  ------------------
  111|       |  
  112|    277|    VkExtensionProperties* pProperties = (VkExtensionProperties*)malloc(sizeof(VkExtensionProperties) * pPropertyCount); 
  113|       |  
  114|    277|    vkEnumerateInstanceExtensionProperties("test_auto", &pPropertyCount, pProperties);
  115|       |    
  116|    277|    free(pProperties);
  117|    277|  }
  118|       |  // Clean up config files
  119|  5.68k|  remove_config_file(".local/share/vulkan/implicit_layer.d", "complex_layer.json");
  120|  5.68k|  remove_config_file(".local/share/vulkan/loader_settings.d", "vk_loader_settings.json");
  121|       |
  122|  5.68k|  return 0;
  123|  5.68k|}

loader_calloc:
   51|  4.98M|void *loader_calloc(const VkAllocationCallbacks *pAllocator, size_t size, VkSystemAllocationScope allocation_scope) {
   52|  4.98M|    void *pMemory = NULL;
   53|       |#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
   54|       |    {
   55|       |#else
   56|  4.98M|    if (pAllocator && pAllocator->pfnAllocation) {
  ------------------
  |  Branch (56:9): [True: 0, False: 4.98M]
  |  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|  4.98M|    } else {
   64|  4.98M|#endif
   65|  4.98M|        pMemory = calloc(1, size);
   66|  4.98M|    }
   67|       |
   68|  4.98M|    return pMemory;
   69|  4.98M|}
loader_free:
   71|  7.69M|void loader_free(const VkAllocationCallbacks *pAllocator, void *pMemory) {
   72|  7.69M|    if (pMemory != NULL) {
  ------------------
  |  Branch (72:9): [True: 4.98M, False: 2.71M]
  ------------------
   73|       |#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
   74|       |        {
   75|       |#else
   76|  4.98M|        if (pAllocator && pAllocator->pfnFree) {
  ------------------
  |  Branch (76:13): [True: 0, False: 4.98M]
  |  Branch (76:27): [True: 0, False: 0]
  ------------------
   77|      0|            pAllocator->pfnFree(pAllocator->pUserData, pMemory);
   78|  4.98M|        } else {
   79|  4.98M|#endif
   80|  4.98M|            free(pMemory);
   81|  4.98M|        }
   82|  4.98M|    }
   83|  7.69M|}
loader_realloc:
   86|   281k|                     VkSystemAllocationScope allocation_scope) {
   87|   281k|    void *pNewMem = NULL;
   88|   281k|    if (pMemory == NULL || orig_size == 0) {
  ------------------
  |  Branch (88:9): [True: 0, False: 281k]
  |  Branch (88:28): [True: 0, False: 281k]
  ------------------
   89|      0|        pNewMem = loader_alloc(pAllocator, size, allocation_scope);
   90|   281k|    } else if (size == 0) {
  ------------------
  |  Branch (90:16): [True: 0, False: 281k]
  ------------------
   91|      0|        loader_free(pAllocator, pMemory);
   92|       |#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
   93|       |#else
   94|   281k|    } else if (pAllocator && pAllocator->pfnReallocation) {
  ------------------
  |  Branch (94:16): [True: 0, False: 281k]
  |  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|   281k|    } else {
  100|   281k|        pNewMem = realloc(pMemory, size);
  101|       |        // Clear out the newly allocated memory. On failure realloc returns NULL and leaves the original block valid, so
  102|       |        // only write through pNewMem once we know it points at the resized allocation.
  103|   281k|        if (NULL != pNewMem && size > orig_size) {
  ------------------
  |  Branch (103:13): [True: 281k, False: 0]
  |  Branch (103:32): [True: 2.53k, False: 278k]
  ------------------
  104|  2.53k|            memset((uint8_t *)pNewMem + orig_size, 0, size - orig_size);
  105|  2.53k|        }
  106|   281k|    }
  107|   281k|    return pNewMem;
  108|   281k|}
loader_instance_heap_calloc:
  114|   444k|void *loader_instance_heap_calloc(const struct loader_instance *inst, size_t size, VkSystemAllocationScope allocation_scope) {
  115|   444k|    return loader_calloc(inst ? &inst->alloc_callbacks : NULL, size, allocation_scope);
  ------------------
  |  Branch (115:26): [True: 0, False: 444k]
  ------------------
  116|   444k|}
loader_instance_heap_free:
  118|  3.43M|void loader_instance_heap_free(const struct loader_instance *inst, void *pMemory) {
  119|  3.43M|    loader_free(inst ? &inst->alloc_callbacks : NULL, pMemory);
  ------------------
  |  Branch (119:17): [True: 0, False: 3.43M]
  ------------------
  120|  3.43M|}
loader_instance_heap_realloc:
  122|  1.20k|                                   VkSystemAllocationScope allocation_scope) {
  123|  1.20k|    return loader_realloc(inst ? &inst->alloc_callbacks : NULL, pMemory, orig_size, size, allocation_scope);
  ------------------
  |  Branch (123:27): [True: 0, False: 1.20k]
  ------------------
  124|  1.20k|}

loader_cJSON_GetStringValue:
   98|   248k|CJSON_PUBLIC(char *) loader_cJSON_GetStringValue(const cJSON *const item) {
   99|   248k|    if (!loader_cJSON_IsString(item)) {
  ------------------
  |  Branch (99:9): [True: 79.0k, False: 169k]
  ------------------
  100|  79.0k|        return NULL;
  101|  79.0k|    }
  102|       |
  103|   169k|    return item->valuestring;
  104|   248k|}
loader_cJSON_Delete:
  151|   444k|TEST_FUNCTION_EXPORT CJSON_PUBLIC(void) loader_cJSON_Delete(cJSON *item) {
  152|   444k|    cJSON *next = NULL;
  153|  2.52M|    while (item != NULL) {
  ------------------
  |  Branch (153:12): [True: 2.07M, False: 444k]
  ------------------
  154|  2.07M|        next = item->next;
  155|  2.07M|        if (!(item->type & cJSON_IsReference) && (item->child != NULL)) {
  ------------------
  |  |  106|  2.07M|#define cJSON_IsReference 256
  ------------------
  |  Branch (155:13): [True: 2.07M, False: 0]
  |  Branch (155:50): [True: 360k, False: 1.71M]
  ------------------
  156|   360k|            loader_cJSON_Delete(item->child);
  157|   360k|        }
  158|  2.07M|        if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) {
  ------------------
  |  |  106|  2.07M|#define cJSON_IsReference 256
  ------------------
  |  Branch (158:13): [True: 2.07M, False: 0]
  |  Branch (158:50): [True: 1.16M, False: 915k]
  ------------------
  159|  1.16M|            loader_free(item->pAllocator, item->valuestring);
  160|  1.16M|            item->valuestring = NULL;
  161|  1.16M|        }
  162|  2.07M|        if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) {
  ------------------
  |  |  107|  2.07M|#define cJSON_StringIsConst 512
  ------------------
  |  Branch (162:13): [True: 2.07M, False: 0]
  |  Branch (162:52): [True: 1.01M, False: 1.06M]
  ------------------
  163|  1.01M|            loader_free(item->pAllocator, item->string);
  164|       |            item->string = NULL;
  165|  1.01M|        }
  166|  2.07M|        loader_free(item->pAllocator, item);
  167|  2.07M|        item = next;
  168|  2.07M|    }
  169|   444k|}
loader_cJSON_ParseWithLengthOpts:
  824|  20.1k|                                 const char **return_parse_end, cJSON_bool require_null_terminated, bool *out_of_memory) {
  825|  20.1k|    parse_buffer buffer = {0, 0, 0, 0, 0};
  826|  20.1k|    cJSON *item = NULL;
  827|       |
  828|       |    /* reset error position */
  829|       |    // global_error.json = NULL;
  830|       |    // global_error.position = 0;
  831|       |
  832|  20.1k|    if (value == NULL || 0 == buffer_length) {
  ------------------
  |  Branch (832:9): [True: 0, False: 20.1k]
  |  Branch (832:26): [True: 0, False: 20.1k]
  ------------------
  833|      0|        goto fail;
  834|      0|    }
  835|       |
  836|  20.1k|    buffer.content = (const unsigned char *)value;
  837|  20.1k|    buffer.length = buffer_length;
  838|  20.1k|    buffer.offset = 0;
  839|  20.1k|    buffer.pAllocator = pAllocator;
  840|       |
  841|  20.1k|    item = cJSON_New_Item(pAllocator);
  842|  20.1k|    if (item == NULL) /* memory fail */
  ------------------
  |  Branch (842:9): [True: 0, False: 20.1k]
  ------------------
  843|      0|    {
  844|      0|        *out_of_memory = true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
  845|      0|        goto fail;
  846|      0|    }
  847|       |
  848|  20.1k|    if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer)), out_of_memory)) {
  ------------------
  |  Branch (848:9): [True: 8.73k, False: 11.4k]
  ------------------
  849|       |        /* parse failure. ep is set. */
  850|  8.73k|        goto fail;
  851|  8.73k|    }
  852|       |
  853|       |    /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
  854|  11.4k|    if (require_null_terminated) {
  ------------------
  |  Branch (854:9): [True: 0, False: 11.4k]
  ------------------
  855|      0|        buffer_skip_whitespace(&buffer);
  856|      0|        if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0') {
  ------------------
  |  |  195|      0|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (856:13): [True: 0, False: 0]
  |  Branch (856:49): [True: 0, False: 0]
  ------------------
  857|      0|            goto fail;
  858|      0|        }
  859|      0|    }
  860|  11.4k|    if (return_parse_end) {
  ------------------
  |  Branch (860:9): [True: 0, False: 11.4k]
  ------------------
  861|      0|        *return_parse_end = (const char *)buffer_at_offset(&buffer);
  ------------------
  |  |  195|      0|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  862|      0|    }
  863|       |
  864|  11.4k|    return item;
  865|       |
  866|  8.73k|fail:
  867|  8.73k|    if (item != NULL) {
  ------------------
  |  Branch (867:9): [True: 8.73k, False: 0]
  ------------------
  868|  8.73k|        loader_cJSON_Delete(item);
  869|  8.73k|    }
  870|       |
  871|  8.73k|    if (value != NULL) {
  ------------------
  |  Branch (871:9): [True: 8.73k, False: 0]
  ------------------
  872|  8.73k|        error local_error;
  873|  8.73k|        local_error.json = (const unsigned char *)value;
  874|  8.73k|        local_error.position = 0;
  875|       |
  876|  8.73k|        if (buffer.offset < buffer.length) {
  ------------------
  |  Branch (876:13): [True: 8.58k, False: 151]
  ------------------
  877|  8.58k|            local_error.position = buffer.offset;
  878|  8.58k|        } else if (buffer.length > 0) {
  ------------------
  |  Branch (878:20): [True: 151, False: 0]
  ------------------
  879|    151|            local_error.position = buffer.length - 1;
  880|    151|        }
  881|       |
  882|  8.73k|        if (return_parse_end != NULL) {
  ------------------
  |  Branch (882:13): [True: 0, False: 8.73k]
  ------------------
  883|      0|            *return_parse_end = (const char *)local_error.json + local_error.position;
  884|      0|        }
  885|       |
  886|       |        // global_error = local_error;
  887|  8.73k|    }
  888|       |
  889|       |    return NULL;
  890|  11.4k|}
loader_cJSON_ParseWithLength:
  899|  20.1k|                             bool *out_of_memory) {
  900|  20.1k|    return loader_cJSON_ParseWithLengthOpts(pAllocator, value, buffer_length, 0, 0, out_of_memory);
  901|  20.1k|}
loader_cJSON_Print:
  953|   278k|TEST_FUNCTION_EXPORT CJSON_PUBLIC(char *) loader_cJSON_Print(const cJSON *item, bool *out_of_memory) {
  954|   278k|    return (char *)print(item, true, out_of_memory);
  ------------------
  |  |   67|   278k|#define true ((cJSON_bool)1)
  ------------------
  955|   278k|}
loader_cJSON_PrintPreallocated:
  990|   132k|    loader_cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format) {
  991|   132k|    printbuffer p = {0, 0, 0, 0, 0, 0, 0};
  992|       |
  993|   132k|    if ((length < 0) || (buffer == NULL)) {
  ------------------
  |  Branch (993:9): [True: 0, False: 132k]
  |  Branch (993:25): [True: 0, False: 132k]
  ------------------
  994|      0|        return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
  995|      0|    }
  996|       |
  997|   132k|    p.buffer = (unsigned char *)buffer;
  998|   132k|    p.length = (size_t)length;
  999|   132k|    p.offset = 0;
 1000|   132k|    p.noalloc = true;
  ------------------
  |  |   67|   132k|#define true ((cJSON_bool)1)
  ------------------
 1001|   132k|    p.format = format;
 1002|   132k|    p.pAllocator = item->pAllocator;
 1003|   132k|    bool out_of_memory = false;
  ------------------
  |  |   72|   132k|#define false ((cJSON_bool)0)
  ------------------
 1004|   132k|    return print_value(item, &p, &out_of_memory);
 1005|   132k|}
loader_cJSON_GetArraySize:
 1457|  34.6k|CJSON_PUBLIC(int) loader_cJSON_GetArraySize(const cJSON *array) {
 1458|  34.6k|    cJSON *child = NULL;
 1459|  34.6k|    size_t size = 0;
 1460|       |
 1461|  34.6k|    if (array == NULL) {
  ------------------
  |  Branch (1461:9): [True: 0, False: 34.6k]
  ------------------
 1462|      0|        return 0;
 1463|      0|    }
 1464|       |
 1465|  34.6k|    child = array->child;
 1466|       |
 1467|   277k|    while (child != NULL) {
  ------------------
  |  Branch (1467:12): [True: 242k, False: 34.6k]
  ------------------
 1468|   242k|        size++;
 1469|   242k|        child = child->next;
 1470|   242k|    }
 1471|       |
 1472|       |    /* FIXME: Can overflow here. Cannot be fixed without breaking the API */
 1473|       |
 1474|  34.6k|    return (int)size;
 1475|  34.6k|}
loader_cJSON_GetObjectItem:
 1527|   841k|CJSON_PUBLIC(cJSON *) loader_cJSON_GetObjectItem(const cJSON *const object, const char *const string) {
 1528|   841k|    return get_object_item(object, string, false);
  ------------------
  |  |   72|   841k|#define false ((cJSON_bool)0)
  ------------------
 1529|   841k|}
loader_cJSON_IsString:
 1670|   248k|CJSON_PUBLIC(cJSON_bool) loader_cJSON_IsString(const cJSON *const item) {
 1671|   248k|    if (item == NULL) {
  ------------------
  |  Branch (1671:9): [True: 78.5k, False: 170k]
  ------------------
 1672|  78.5k|        return false;
  ------------------
  |  |   72|  78.5k|#define false ((cJSON_bool)0)
  ------------------
 1673|  78.5k|    }
 1674|       |
 1675|   170k|    return (item->type & 0xFF) == cJSON_String;
  ------------------
  |  |  101|   170k|#define cJSON_String (1 << 4)
  ------------------
 1676|   248k|}
cJSON.c:cJSON_New_Item:
  142|  2.07M|static cJSON *cJSON_New_Item(const VkAllocationCallbacks *pAllocator) {
  143|  2.07M|    cJSON *node = (cJSON *)loader_calloc(pAllocator, sizeof(cJSON), VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
  144|  2.07M|    if (NULL != node) {
  ------------------
  |  Branch (144:9): [True: 2.07M, False: 0]
  ------------------
  145|  2.07M|        node->pAllocator = pAllocator;
  146|  2.07M|    }
  147|  2.07M|    return node;
  148|  2.07M|}
cJSON.c:buffer_skip_whitespace:
  772|  6.57M|static parse_buffer *buffer_skip_whitespace(parse_buffer *const buffer) {
  773|  6.57M|    if ((buffer == NULL) || (buffer->content == NULL)) {
  ------------------
  |  Branch (773:9): [True: 0, False: 6.57M]
  |  Branch (773:29): [True: 0, False: 6.57M]
  ------------------
  774|      0|        return NULL;
  775|      0|    }
  776|       |
  777|  6.57M|    if (cannot_access_at_index(buffer, 0)) {
  ------------------
  |  |  193|  6.57M|#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
  |  |  ------------------
  |  |  |  |  192|  6.57M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (192:45): [True: 6.57M, False: 0]
  |  |  |  |  |  Branch (192:65): [True: 6.57M, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  778|      0|        return buffer;
  779|      0|    }
  780|       |
  781|  14.4M|    while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) {
  ------------------
  |  |  192|  28.9M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 14.4M, False: 0]
  |  |  |  Branch (192:65): [True: 14.4M, False: 4.68k]
  |  |  ------------------
  ------------------
                  while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) {
  ------------------
  |  |  195|  14.4M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (781:46): [True: 7.92M, False: 6.56M]
  ------------------
  782|  7.92M|        buffer->offset++;
  783|  7.92M|    }
  784|       |
  785|  6.57M|    if (buffer->offset == buffer->length) {
  ------------------
  |  Branch (785:9): [True: 4.68k, False: 6.56M]
  ------------------
  786|  4.68k|        buffer->offset--;
  787|  4.68k|    }
  788|       |
  789|  6.57M|    return buffer;
  790|  6.57M|}
cJSON.c:skip_utf8_bom:
  793|  20.1k|static parse_buffer *skip_utf8_bom(parse_buffer *const buffer) {
  794|  20.1k|    if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0)) {
  ------------------
  |  Branch (794:9): [True: 0, False: 20.1k]
  |  Branch (794:29): [True: 0, False: 20.1k]
  |  Branch (794:58): [True: 0, False: 20.1k]
  ------------------
  795|      0|        return NULL;
  796|      0|    }
  797|       |
  798|  20.1k|    if (can_access_at_index(buffer, 4) && (strncmp((const char *)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0)) {
  ------------------
  |  |  192|  40.3k|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 20.1k, False: 0]
  |  |  |  Branch (192:65): [True: 12.8k, False: 7.30k]
  |  |  ------------------
  ------------------
                  if (can_access_at_index(buffer, 4) && (strncmp((const char *)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0)) {
  ------------------
  |  |  195|  12.8k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (798:43): [True: 321, False: 12.5k]
  ------------------
  799|    321|        buffer->offset += 3;
  800|    321|    }
  801|       |
  802|  20.1k|    return buffer;
  803|  20.1k|}
cJSON.c:print:
  905|   278k|static unsigned char *print(const cJSON *const item, cJSON_bool format, bool *out_of_memory) {
  906|   278k|    static const size_t default_buffer_size = 256;
  907|   278k|    printbuffer buffer[1];
  908|   278k|    unsigned char *printed = NULL;
  909|       |
  910|   278k|    memset(buffer, 0, sizeof(buffer));
  911|       |
  912|       |    /* create buffer */
  913|   278k|    buffer->buffer = (unsigned char *)loader_calloc(item->pAllocator, default_buffer_size, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  914|   278k|    buffer->length = default_buffer_size;
  915|   278k|    buffer->format = format;
  916|   278k|    buffer->pAllocator = item->pAllocator;
  917|   278k|    if (buffer->buffer == NULL) {
  ------------------
  |  Branch (917:9): [True: 0, False: 278k]
  ------------------
  918|      0|        *out_of_memory = true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
  919|      0|        goto fail;
  920|      0|    }
  921|       |
  922|       |    /* print the value */
  923|   278k|    if (!print_value(item, buffer, out_of_memory)) {
  ------------------
  |  Branch (923:9): [True: 0, False: 278k]
  ------------------
  924|      0|        goto fail;
  925|      0|    }
  926|   278k|    update_offset(buffer);
  927|       |
  928|   278k|    printed = (unsigned char *)loader_realloc(item->pAllocator, buffer->buffer, buffer->length, buffer->offset + 1,
  929|   278k|                                              VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  930|   278k|    if (printed == NULL) {
  ------------------
  |  Branch (930:9): [True: 0, False: 278k]
  ------------------
  931|      0|        *out_of_memory = true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
  932|      0|        goto fail;
  933|      0|    }
  934|   278k|    buffer->buffer = NULL;
  935|       |
  936|   278k|    return printed;
  937|       |
  938|      0|fail:
  939|      0|    if (buffer->buffer != NULL) {
  ------------------
  |  Branch (939:9): [True: 0, False: 0]
  ------------------
  940|      0|        loader_free(item->pAllocator, buffer->buffer);
  941|      0|        buffer->buffer = NULL;
  942|      0|    }
  943|       |
  944|      0|    if (printed != NULL) {
  ------------------
  |  Branch (944:9): [True: 0, False: 0]
  ------------------
  945|      0|        loader_free(item->pAllocator, printed);
  946|      0|        printed = NULL;
  947|      0|    }
  948|       |
  949|       |    return NULL;
  950|   278k|}
cJSON.c:update_offset:
  331|   278k|static void update_offset(printbuffer *const buffer) {
  332|   278k|    const unsigned char *buffer_pointer = NULL;
  333|   278k|    if ((buffer == NULL) || (buffer->buffer == NULL)) {
  ------------------
  |  Branch (333:9): [True: 0, False: 278k]
  |  Branch (333:29): [True: 0, False: 278k]
  ------------------
  334|      0|        return;
  335|      0|    }
  336|   278k|    buffer_pointer = buffer->buffer + buffer->offset;
  337|       |
  338|   278k|    buffer->offset += strlen((const char *)buffer_pointer);
  339|   278k|}
cJSON.c:parse_value:
 1008|  2.07M|static cJSON_bool parse_value(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory) {
 1009|  2.07M|    if ((input_buffer == NULL) || (input_buffer->content == NULL)) {
  ------------------
  |  Branch (1009:9): [True: 0, False: 2.07M]
  |  Branch (1009:35): [True: 0, False: 2.07M]
  ------------------
 1010|      0|        return false; /* no input */
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1011|      0|    }
 1012|       |
 1013|       |    /* parse the different types of values */
 1014|       |    /* null */
 1015|  2.07M|    if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "null", 4) == 0)) {
  ------------------
  |  |  190|  4.15M|#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (190:33): [True: 2.07M, False: 0]
  |  |  |  Branch (190:53): [True: 2.07M, False: 8.03k]
  |  |  ------------------
  ------------------
                  if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "null", 4) == 0)) {
  ------------------
  |  |  195|  2.07M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1015:38): [True: 592, False: 2.06M]
  ------------------
 1016|    592|        item->type = cJSON_NULL;
  ------------------
  |  |   99|    592|#define cJSON_NULL (1 << 2)
  ------------------
 1017|    592|        input_buffer->offset += 4;
 1018|    592|        return true;
  ------------------
  |  |   67|    592|#define true ((cJSON_bool)1)
  ------------------
 1019|    592|    }
 1020|       |    /* false */
 1021|  2.07M|    if (can_read(input_buffer, 5) && (strncmp((const char *)buffer_at_offset(input_buffer), "false", 5) == 0)) {
  ------------------
  |  |  190|  4.15M|#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (190:33): [True: 2.07M, False: 0]
  |  |  |  Branch (190:53): [True: 2.06M, False: 8.53k]
  |  |  ------------------
  ------------------
                  if (can_read(input_buffer, 5) && (strncmp((const char *)buffer_at_offset(input_buffer), "false", 5) == 0)) {
  ------------------
  |  |  195|  2.06M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1021:38): [True: 176, False: 2.06M]
  ------------------
 1022|    176|        item->type = cJSON_False;
  ------------------
  |  |   97|    176|#define cJSON_False (1 << 0)
  ------------------
 1023|    176|        input_buffer->offset += 5;
 1024|    176|        return true;
  ------------------
  |  |   67|    176|#define true ((cJSON_bool)1)
  ------------------
 1025|    176|    }
 1026|       |    /* true */
 1027|  2.07M|    if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "true", 4) == 0)) {
  ------------------
  |  |  190|  4.15M|#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (190:33): [True: 2.07M, False: 0]
  |  |  |  Branch (190:53): [True: 2.06M, False: 8.03k]
  |  |  ------------------
  ------------------
                  if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "true", 4) == 0)) {
  ------------------
  |  |  195|  2.06M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1027:38): [True: 3.37k, False: 2.06M]
  ------------------
 1028|  3.37k|        item->type = cJSON_True;
  ------------------
  |  |   98|  3.37k|#define cJSON_True (1 << 1)
  ------------------
 1029|  3.37k|        item->valueint = 1;
 1030|  3.37k|        input_buffer->offset += 4;
 1031|  3.37k|        return true;
  ------------------
  |  |   67|  3.37k|#define true ((cJSON_bool)1)
  ------------------
 1032|  3.37k|    }
 1033|       |    /* string */
 1034|  2.07M|    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) {
  ------------------
  |  |  192|  4.14M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 2.07M, False: 0]
  |  |  |  Branch (192:65): [True: 2.07M, False: 0]
  |  |  ------------------
  ------------------
                  if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) {
  ------------------
  |  |  195|  2.07M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1034:49): [True: 1.16M, False: 910k]
  ------------------
 1035|  1.16M|        return parse_string(item, input_buffer, out_of_memory);
 1036|  1.16M|    }
 1037|       |    /* number */
 1038|   910k|    if (can_access_at_index(input_buffer, 0) &&
  ------------------
  |  |  192|  1.82M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 910k, False: 0]
  |  |  |  Branch (192:65): [True: 910k, False: 0]
  |  |  ------------------
  ------------------
 1039|   910k|        ((buffer_at_offset(input_buffer)[0] == '-') ||
  ------------------
  |  |  195|   910k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1039:10): [True: 5.71k, False: 904k]
  ------------------
 1040|   904k|         ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9')))) {
  ------------------
  |  |  195|   904k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
                       ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9')))) {
  ------------------
  |  |  195|   900k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1040:11): [True: 900k, False: 4.17k]
  |  Branch (1040:57): [True: 430k, False: 469k]
  ------------------
 1041|   436k|        return parse_number(item, input_buffer);
 1042|   436k|    }
 1043|       |    /* array */
 1044|   474k|    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '[')) {
  ------------------
  |  |  192|   948k|#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]
  |  |  ------------------
  ------------------
                  if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '[')) {
  ------------------
  |  |  195|   474k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1044:49): [True: 144k, False: 329k]
  ------------------
 1045|   144k|        return parse_array(item, input_buffer, out_of_memory);
 1046|   144k|    }
 1047|       |    /* object */
 1048|   329k|    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) {
  ------------------
  |  |  192|   658k|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 329k, False: 0]
  |  |  |  Branch (192:65): [True: 329k, False: 0]
  |  |  ------------------
  ------------------
                  if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) {
  ------------------
  |  |  195|   329k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1048:49): [True: 322k, False: 7.18k]
  ------------------
 1049|   322k|        return parse_object(item, input_buffer, out_of_memory);
 1050|   322k|    }
 1051|       |
 1052|  7.18k|    return false;
  ------------------
  |  |   72|  7.18k|#define false ((cJSON_bool)0)
  ------------------
 1053|   329k|}
cJSON.c:parse_string:
  533|  2.17M|static cJSON_bool parse_string(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory) {
  534|  2.17M|    const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1;
  ------------------
  |  |  195|  2.17M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  535|  2.17M|    const unsigned char *input_end = buffer_at_offset(input_buffer) + 1;
  ------------------
  |  |  195|  2.17M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  536|  2.17M|    unsigned char *output_pointer = NULL;
  537|  2.17M|    unsigned char *output = NULL;
  538|       |
  539|       |    /* not a string */
  540|  2.17M|    if (buffer_at_offset(input_buffer)[0] != '\"') {
  ------------------
  |  |  195|  2.17M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (540:9): [True: 201, False: 2.17M]
  ------------------
  541|    201|        goto fail;
  542|    201|    }
  543|       |
  544|  2.17M|    {
  545|       |        /* calculate approximate size of the output (overestimate) */
  546|  2.17M|        size_t allocation_length = 0;
  547|  2.17M|        size_t skipped_bytes = 0;
  548|  69.9M|        while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"')) {
  ------------------
  |  Branch (548:16): [True: 69.9M, False: 300]
  |  Branch (548:88): [True: 67.8M, False: 2.17M]
  ------------------
  549|       |            /* is escape sequence */
  550|  67.8M|            if (input_end[0] == '\\') {
  ------------------
  |  Branch (550:17): [True: 74.7k, False: 67.7M]
  ------------------
  551|  74.7k|                if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length) {
  ------------------
  |  Branch (551:21): [True: 0, False: 74.7k]
  ------------------
  552|       |                    /* prevent buffer overflow when last input character is a backslash */
  553|      0|                    goto fail;
  554|      0|                }
  555|  74.7k|                skipped_bytes++;
  556|  74.7k|                input_end++;
  557|  74.7k|            }
  558|  67.8M|            input_end++;
  559|  67.8M|        }
  560|  2.17M|        if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"')) {
  ------------------
  |  Branch (560:13): [True: 300, False: 2.17M]
  |  Branch (560:86): [True: 0, False: 2.17M]
  ------------------
  561|    300|            goto fail; /* string ended unexpectedly */
  562|    300|        }
  563|       |
  564|       |        /* This is at most how much we need for the output */
  565|  2.17M|        allocation_length = (size_t)(input_end - buffer_at_offset(input_buffer)) - skipped_bytes;
  ------------------
  |  |  195|  2.17M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  566|  2.17M|        output = (unsigned char *)loader_calloc(input_buffer->pAllocator, allocation_length + sizeof(""),
  567|  2.17M|                                                VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
  568|  2.17M|        if (output == NULL) {
  ------------------
  |  Branch (568:13): [True: 0, False: 2.17M]
  ------------------
  569|      0|            *out_of_memory = true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
  570|      0|            goto fail; /* allocation failure */
  571|      0|        }
  572|  2.17M|    }
  573|       |
  574|  2.17M|    output_pointer = output;
  575|       |    /* loop through the string literal */
  576|  61.0M|    while (input_pointer < input_end) {
  ------------------
  |  Branch (576:12): [True: 58.8M, False: 2.17M]
  ------------------
  577|  58.8M|        if (*input_pointer != '\\') {
  ------------------
  |  Branch (577:13): [True: 58.7M, False: 56.8k]
  ------------------
  578|  58.7M|            *output_pointer++ = *input_pointer++;
  579|  58.7M|        }
  580|       |        /* escape sequence */
  581|  56.8k|        else {
  582|  56.8k|            unsigned char sequence_length = 2;
  583|  56.8k|            if ((input_end - input_pointer) < 1) {
  ------------------
  |  Branch (583:17): [True: 0, False: 56.8k]
  ------------------
  584|      0|                goto fail;
  585|      0|            }
  586|       |
  587|  56.8k|            switch (input_pointer[1]) {
  588|    268|                case 'b':
  ------------------
  |  Branch (588:17): [True: 268, False: 56.6k]
  ------------------
  589|    268|                    *output_pointer++ = '\b';
  590|    268|                    break;
  591|  2.54k|                case 'f':
  ------------------
  |  Branch (591:17): [True: 2.54k, False: 54.3k]
  ------------------
  592|  2.54k|                    *output_pointer++ = '\f';
  593|  2.54k|                    break;
  594|    632|                case 'n':
  ------------------
  |  Branch (594:17): [True: 632, False: 56.2k]
  ------------------
  595|    632|                    *output_pointer++ = '\n';
  596|    632|                    break;
  597|    707|                case 'r':
  ------------------
  |  Branch (597:17): [True: 707, False: 56.1k]
  ------------------
  598|    707|                    *output_pointer++ = '\r';
  599|    707|                    break;
  600|    507|                case 't':
  ------------------
  |  Branch (600:17): [True: 507, False: 56.3k]
  ------------------
  601|    507|                    *output_pointer++ = '\t';
  602|    507|                    break;
  603|    567|                case '\"':
  ------------------
  |  Branch (603:17): [True: 567, False: 56.3k]
  ------------------
  604|  4.47k|                case '\\':
  ------------------
  |  Branch (604:17): [True: 3.91k, False: 52.9k]
  ------------------
  605|  4.71k|                case '/':
  ------------------
  |  Branch (605:17): [True: 240, False: 56.6k]
  ------------------
  606|  4.71k|                    *output_pointer++ = input_pointer[1];
  607|  4.71k|                    break;
  608|       |
  609|       |                /* UTF-16 literal */
  610|  47.4k|                case 'u':
  ------------------
  |  Branch (610:17): [True: 47.4k, False: 9.41k]
  ------------------
  611|  47.4k|                    sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer);
  612|  47.4k|                    if (sequence_length == 0) {
  ------------------
  |  Branch (612:25): [True: 293, False: 47.1k]
  ------------------
  613|       |                        /* failed to convert UTF16-literal to UTF-8 */
  614|    293|                        goto fail;
  615|    293|                    }
  616|  47.1k|                    break;
  617|       |
  618|  47.1k|                default:
  ------------------
  |  Branch (618:17): [True: 39, False: 56.8k]
  ------------------
  619|     39|                    goto fail;
  620|  56.8k|            }
  621|  56.5k|            input_pointer += sequence_length;
  622|  56.5k|        }
  623|  58.8M|    }
  624|       |
  625|       |    /* zero terminate the output */
  626|  2.17M|    *output_pointer = '\0';
  627|       |
  628|  2.17M|    item->type = cJSON_String;
  ------------------
  |  |  101|  2.17M|#define cJSON_String (1 << 4)
  ------------------
  629|  2.17M|    item->valuestring = (char *)output;
  630|       |
  631|  2.17M|    input_buffer->offset = (size_t)(input_end - input_buffer->content);
  632|  2.17M|    input_buffer->offset++;
  633|       |
  634|  2.17M|    return true;
  ------------------
  |  |   67|  2.17M|#define true ((cJSON_bool)1)
  ------------------
  635|       |
  636|    833|fail:
  637|    833|    if (output != NULL) {
  ------------------
  |  Branch (637:9): [True: 332, False: 501]
  ------------------
  638|    332|        loader_free(input_buffer->pAllocator, output);
  639|    332|        output = NULL;
  640|    332|    }
  641|       |
  642|    833|    if (input_pointer != NULL) {
  ------------------
  |  Branch (642:9): [True: 833, False: 0]
  ------------------
  643|    833|        input_buffer->offset = (size_t)(input_pointer - input_buffer->content);
  644|    833|    }
  645|       |
  646|    833|    return false;
  ------------------
  |  |   72|    833|#define false ((cJSON_bool)0)
  ------------------
  647|  2.17M|}
cJSON.c:utf16_literal_to_utf8:
  435|  47.4k|                                           unsigned char **output_pointer) {
  436|  47.4k|    long unsigned int codepoint = 0;
  437|  47.4k|    unsigned int first_code = 0;
  438|  47.4k|    const unsigned char *first_sequence = input_pointer;
  439|  47.4k|    unsigned char utf8_length = 0;
  440|  47.4k|    unsigned char utf8_position = 0;
  441|  47.4k|    unsigned char sequence_length = 0;
  442|  47.4k|    unsigned char first_byte_mark = 0;
  443|       |
  444|  47.4k|    if ((input_end - first_sequence) < 6) {
  ------------------
  |  Branch (444:9): [True: 30, False: 47.4k]
  ------------------
  445|       |        /* input ends unexpectedly */
  446|     30|        goto fail;
  447|     30|    }
  448|       |
  449|       |    /* get the first utf16 sequence */
  450|  47.4k|    first_code = parse_hex4(first_sequence + 2);
  451|       |
  452|       |    /* check that the code is valid */
  453|  47.4k|    if (((first_code >= 0xDC00) && (first_code <= 0xDFFF))) {
  ------------------
  |  Branch (453:10): [True: 3.88k, False: 43.5k]
  |  Branch (453:36): [True: 40, False: 3.84k]
  ------------------
  454|     40|        goto fail;
  455|     40|    }
  456|       |
  457|       |    /* UTF16 surrogate pair */
  458|  47.3k|    if ((first_code >= 0xD800) && (first_code <= 0xDBFF)) {
  ------------------
  |  Branch (458:9): [True: 4.90k, False: 42.4k]
  |  Branch (458:35): [True: 1.05k, False: 3.84k]
  ------------------
  459|  1.05k|        const unsigned char *second_sequence = first_sequence + 6;
  460|  1.05k|        unsigned int second_code = 0;
  461|  1.05k|        sequence_length = 12; /* \uXXXX\uXXXX */
  462|       |
  463|  1.05k|        if ((input_end - second_sequence) < 6) {
  ------------------
  |  Branch (463:13): [True: 30, False: 1.02k]
  ------------------
  464|       |            /* input ends unexpectedly */
  465|     30|            goto fail;
  466|     30|        }
  467|       |
  468|  1.02k|        if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u')) {
  ------------------
  |  Branch (468:13): [True: 46, False: 983]
  |  Branch (468:45): [True: 25, False: 958]
  ------------------
  469|       |            /* missing second half of the surrogate pair */
  470|     71|            goto fail;
  471|     71|        }
  472|       |
  473|       |        /* get the second utf16 sequence */
  474|    958|        second_code = parse_hex4(second_sequence + 2);
  475|       |        /* check that the code is valid */
  476|    958|        if ((second_code < 0xDC00) || (second_code > 0xDFFF)) {
  ------------------
  |  Branch (476:13): [True: 67, False: 891]
  |  Branch (476:39): [True: 55, False: 836]
  ------------------
  477|       |            /* invalid second half of the surrogate pair */
  478|    122|            goto fail;
  479|    122|        }
  480|       |
  481|       |        /* calculate the unicode codepoint from the surrogate pair */
  482|    836|        codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF));
  483|  46.3k|    } else {
  484|  46.3k|        sequence_length = 6; /* \uXXXX */
  485|  46.3k|        codepoint = first_code;
  486|  46.3k|    }
  487|       |
  488|       |    /* encode as UTF-8
  489|       |     * takes at maximum 4 bytes to encode:
  490|       |     * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
  491|  47.1k|    if (codepoint < 0x80) {
  ------------------
  |  Branch (491:9): [True: 34.1k, False: 12.9k]
  ------------------
  492|       |        /* normal ascii, encoding 0xxxxxxx */
  493|  34.1k|        utf8_length = 1;
  494|  34.1k|    } else if (codepoint < 0x800) {
  ------------------
  |  Branch (494:16): [True: 3.55k, False: 9.43k]
  ------------------
  495|       |        /* two bytes, encoding 110xxxxx 10xxxxxx */
  496|  3.55k|        utf8_length = 2;
  497|  3.55k|        first_byte_mark = 0xC0; /* 11000000 */
  498|  9.43k|    } else if (codepoint < 0x10000) {
  ------------------
  |  Branch (498:16): [True: 8.59k, False: 836]
  ------------------
  499|       |        /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */
  500|  8.59k|        utf8_length = 3;
  501|  8.59k|        first_byte_mark = 0xE0; /* 11100000 */
  502|  8.59k|    } else if (codepoint <= 0x10FFFF) {
  ------------------
  |  Branch (502:16): [True: 836, False: 0]
  ------------------
  503|       |        /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */
  504|    836|        utf8_length = 4;
  505|    836|        first_byte_mark = 0xF0; /* 11110000 */
  506|    836|    } else {
  507|       |        /* invalid unicode codepoint */
  508|      0|        goto fail;
  509|      0|    }
  510|       |
  511|       |    /* encode as utf8 */
  512|  70.4k|    for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--) {
  ------------------
  |  Branch (512:60): [True: 23.2k, False: 47.1k]
  ------------------
  513|       |        /* 10xxxxxx */
  514|  23.2k|        (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF);
  515|  23.2k|        codepoint >>= 6;
  516|  23.2k|    }
  517|       |    /* encode first byte */
  518|  47.1k|    if (utf8_length > 1) {
  ------------------
  |  Branch (518:9): [True: 12.9k, False: 34.1k]
  ------------------
  519|  12.9k|        (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF);
  520|  34.1k|    } else {
  521|  34.1k|        (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F);
  522|  34.1k|    }
  523|       |
  524|  47.1k|    *output_pointer += utf8_length;
  525|       |
  526|  47.1k|    return sequence_length;
  527|       |
  528|    293|fail:
  529|    293|    return 0;
  530|  47.1k|}
cJSON.c:parse_hex4:
  406|  48.3k|static unsigned parse_hex4(const unsigned char *const input) {
  407|  48.3k|    unsigned int h = 0;
  408|  48.3k|    size_t i = 0;
  409|       |
  410|   155k|    for (i = 0; i < 4; i++) {
  ------------------
  |  Branch (410:17): [True: 140k, False: 14.4k]
  ------------------
  411|       |        /* parse digit */
  412|   140k|        if ((input[i] >= '0') && (input[i] <= '9')) {
  ------------------
  |  Branch (412:13): [True: 131k, False: 9.82k]
  |  Branch (412:34): [True: 52.0k, False: 79.0k]
  ------------------
  413|  52.0k|            h += (unsigned int)input[i] - '0';
  414|  88.8k|        } else if ((input[i] >= 'A') && (input[i] <= 'F')) {
  ------------------
  |  Branch (414:20): [True: 74.3k, False: 14.4k]
  |  Branch (414:41): [True: 24.7k, False: 49.5k]
  ------------------
  415|  24.7k|            h += (unsigned int)10 + input[i] - 'A';
  416|  64.0k|        } else if ((input[i] >= 'a') && (input[i] <= 'f')) {
  ------------------
  |  Branch (416:20): [True: 38.2k, False: 25.8k]
  |  Branch (416:41): [True: 30.0k, False: 8.15k]
  ------------------
  417|  30.0k|            h += (unsigned int)10 + input[i] - 'a';
  418|  30.0k|        } else /* invalid */
  419|  33.9k|        {
  420|  33.9k|            return 0;
  421|  33.9k|        }
  422|       |
  423|   106k|        if (i < 3) {
  ------------------
  |  Branch (423:13): [True: 92.4k, False: 14.4k]
  ------------------
  424|       |            /* shift left to make place for the next nibble */
  425|  92.4k|            h = h << 4;
  426|  92.4k|        }
  427|   106k|    }
  428|       |
  429|  14.4k|    return h;
  430|  48.3k|}
cJSON.c:parse_number:
  198|   436k|static cJSON_bool parse_number(cJSON *const item, parse_buffer *const input_buffer) {
  199|   436k|    double number = 0;
  200|   436k|    unsigned char *after_end = NULL;
  201|   436k|    unsigned char number_c_string[64];
  202|   436k|    unsigned char decimal_point = get_decimal_point();
  203|   436k|    size_t i = 0;
  204|       |
  205|   436k|    if ((input_buffer == NULL) || (input_buffer->content == NULL)) {
  ------------------
  |  Branch (205:9): [True: 0, False: 436k]
  |  Branch (205:35): [True: 0, False: 436k]
  ------------------
  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|  1.17M|    for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++) {
  ------------------
  |  |  192|  1.17M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 1.17M, False: 0]
  |  |  |  Branch (192:65): [True: 1.17M, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (212:17): [True: 1.17M, False: 453]
  ------------------
  213|  1.17M|        switch (buffer_at_offset(input_buffer)[i]) {
  ------------------
  |  |  195|  1.17M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  214|  72.2k|            case '0':
  ------------------
  |  Branch (214:13): [True: 72.2k, False: 1.10M]
  ------------------
  215|   438k|            case '1':
  ------------------
  |  Branch (215:13): [True: 366k, False: 807k]
  ------------------
  216|   523k|            case '2':
  ------------------
  |  Branch (216:13): [True: 85.0k, False: 1.08M]
  ------------------
  217|   582k|            case '3':
  ------------------
  |  Branch (217:13): [True: 58.3k, False: 1.11M]
  ------------------
  218|   611k|            case '4':
  ------------------
  |  Branch (218:13): [True: 29.5k, False: 1.14M]
  ------------------
  219|   629k|            case '5':
  ------------------
  |  Branch (219:13): [True: 17.3k, False: 1.15M]
  ------------------
  220|   655k|            case '6':
  ------------------
  |  Branch (220:13): [True: 26.0k, False: 1.14M]
  ------------------
  221|   677k|            case '7':
  ------------------
  |  Branch (221:13): [True: 22.8k, False: 1.15M]
  ------------------
  222|   693k|            case '8':
  ------------------
  |  Branch (222:13): [True: 15.9k, False: 1.15M]
  ------------------
  223|   714k|            case '9':
  ------------------
  |  Branch (223:13): [True: 20.5k, False: 1.15M]
  ------------------
  224|   715k|            case '+':
  ------------------
  |  Branch (224:13): [True: 700, False: 1.17M]
  ------------------
  225|   723k|            case '-':
  ------------------
  |  Branch (225:13): [True: 8.72k, False: 1.16M]
  ------------------
  226|   729k|            case 'e':
  ------------------
  |  Branch (226:13): [True: 5.64k, False: 1.16M]
  ------------------
  227|   732k|            case 'E':
  ------------------
  |  Branch (227:13): [True: 3.36k, False: 1.17M]
  ------------------
  228|   732k|                number_c_string[i] = buffer_at_offset(input_buffer)[i];
  ------------------
  |  |  195|   732k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  229|   732k|                break;
  230|       |
  231|  4.89k|            case '.':
  ------------------
  |  Branch (231:13): [True: 4.89k, False: 1.16M]
  ------------------
  232|  4.89k|                number_c_string[i] = decimal_point;
  233|  4.89k|                break;
  234|       |
  235|   435k|            default:
  ------------------
  |  Branch (235:13): [True: 435k, False: 737k]
  ------------------
  236|   435k|                goto loop_end;
  237|  1.17M|        }
  238|  1.17M|    }
  239|   436k|loop_end:
  240|   436k|    number_c_string[i] = '\0';
  241|       |
  242|   436k|    number = strtod((const char *)number_c_string, (char **)&after_end);
  243|   436k|    if (number_c_string == after_end) {
  ------------------
  |  Branch (243:9): [True: 332, False: 435k]
  ------------------
  244|    332|        return false; /* parse_error */
  ------------------
  |  |   72|    332|#define false ((cJSON_bool)0)
  ------------------
  245|    332|    }
  246|       |
  247|   435k|    item->valuedouble = number;
  248|       |
  249|       |    /* use saturation in case of overflow */
  250|   435k|    if (number >= INT_MAX) {
  ------------------
  |  Branch (250:9): [True: 5.57k, False: 430k]
  ------------------
  251|  5.57k|        item->valueint = INT_MAX;
  252|   430k|    } else if (number <= (double)INT_MIN) {
  ------------------
  |  Branch (252:16): [True: 1.78k, False: 428k]
  ------------------
  253|  1.78k|        item->valueint = INT_MIN;
  254|   428k|    } else {
  255|   428k|        item->valueint = (int)number;
  256|   428k|    }
  257|       |
  258|   435k|    item->type = cJSON_Number;
  ------------------
  |  |  100|   435k|#define cJSON_Number (1 << 3)
  ------------------
  259|       |
  260|   435k|    input_buffer->offset += (size_t)(after_end - number_c_string);
  261|   435k|    return true;
  ------------------
  |  |   67|   435k|#define true ((cJSON_bool)1)
  ------------------
  262|   436k|}
cJSON.c:get_decimal_point:
  172|   436k|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|   436k|    return '.';
  178|   436k|#endif
  179|   436k|}
cJSON.c:parse_array:
 1121|   144k|static cJSON_bool parse_array(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory) {
 1122|   144k|    cJSON *head = NULL; /* head of the linked list */
 1123|   144k|    cJSON *current_item = NULL;
 1124|       |
 1125|   144k|    if (input_buffer->depth >= CJSON_NESTING_LIMIT) {
  ------------------
  |  |  138|   144k|#define CJSON_NESTING_LIMIT 1000
  ------------------
  |  Branch (1125:9): [True: 3, False: 144k]
  ------------------
 1126|      3|        return false; /* to deeply nested */
  ------------------
  |  |   72|      3|#define false ((cJSON_bool)0)
  ------------------
 1127|      3|    }
 1128|   144k|    input_buffer->depth++;
 1129|       |
 1130|   144k|    if (buffer_at_offset(input_buffer)[0] != '[') {
  ------------------
  |  |  195|   144k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1130:9): [True: 0, False: 144k]
  ------------------
 1131|       |        /* not an array */
 1132|      0|        goto fail;
 1133|      0|    }
 1134|       |
 1135|   144k|    input_buffer->offset++;
 1136|   144k|    buffer_skip_whitespace(input_buffer);
 1137|   144k|    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']')) {
  ------------------
  |  |  192|   289k|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 144k, False: 0]
  |  |  |  Branch (192:65): [True: 144k, False: 0]
  |  |  ------------------
  ------------------
                  if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']')) {
  ------------------
  |  |  195|   144k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1137:49): [True: 37.7k, False: 106k]
  ------------------
 1138|       |        /* empty array */
 1139|  37.7k|        goto success;
 1140|  37.7k|    }
 1141|       |
 1142|       |    /* check if we skipped to the end of the buffer */
 1143|   106k|    if (cannot_access_at_index(input_buffer, 0)) {
  ------------------
  |  |  193|   106k|#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
  |  |  ------------------
  |  |  |  |  192|   106k|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (192:45): [True: 106k, False: 0]
  |  |  |  |  |  Branch (192:65): [True: 106k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1144|      0|        input_buffer->offset--;
 1145|      0|        goto fail;
 1146|      0|    }
 1147|       |
 1148|       |    /* step back to character in front of the first element */
 1149|   106k|    input_buffer->offset--;
 1150|       |    /* loop through the comma separated array elements */
 1151|  1.04M|    do {
 1152|       |        /* allocate next item */
 1153|  1.04M|        cJSON *new_item = cJSON_New_Item(input_buffer->pAllocator);
 1154|  1.04M|        if (new_item == NULL) {
  ------------------
  |  Branch (1154:13): [True: 0, False: 1.04M]
  ------------------
 1155|      0|            *out_of_memory = true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
 1156|      0|            goto fail; /* allocation failure */
 1157|      0|        }
 1158|       |
 1159|       |        /* attach next item to list */
 1160|  1.04M|        if (head == NULL) {
  ------------------
  |  Branch (1160:13): [True: 106k, False: 935k]
  ------------------
 1161|       |            /* start the linked list */
 1162|   106k|            current_item = head = new_item;
 1163|   935k|        } else {
 1164|       |            /* add to the end and advance */
 1165|   935k|            current_item->next = new_item;
 1166|   935k|            new_item->prev = current_item;
 1167|   935k|            current_item = new_item;
 1168|   935k|        }
 1169|       |
 1170|       |        /* parse next value */
 1171|  1.04M|        input_buffer->offset++;
 1172|  1.04M|        buffer_skip_whitespace(input_buffer);
 1173|  1.04M|        if (!parse_value(current_item, input_buffer, out_of_memory)) {
  ------------------
  |  Branch (1173:13): [True: 59.2k, False: 983k]
  ------------------
 1174|  59.2k|            goto fail; /* failed to parse value */
 1175|  59.2k|        }
 1176|   983k|        buffer_skip_whitespace(input_buffer);
 1177|   983k|    } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
  ------------------
  |  |  192|  1.96M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 983k, False: 0]
  |  |  |  Branch (192:65): [True: 983k, False: 0]
  |  |  ------------------
  ------------------
                  } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
  ------------------
  |  |  195|   983k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1177:54): [True: 935k, False: 47.7k]
  ------------------
 1178|       |
 1179|  47.7k|    if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') {
  ------------------
  |  |  193|  95.4k|#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
  |  |  ------------------
  |  |  |  |  192|  47.7k|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (192:45): [True: 47.7k, False: 0]
  |  |  |  |  |  Branch (192:65): [True: 47.7k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
                  if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') {
  ------------------
  |  |  195|  47.7k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1179:52): [True: 244, False: 47.4k]
  ------------------
 1180|    244|        goto fail; /* expected end of array */
 1181|    244|    }
 1182|       |
 1183|  85.2k|success:
 1184|  85.2k|    input_buffer->depth--;
 1185|       |
 1186|  85.2k|    if (head != NULL) {
  ------------------
  |  Branch (1186:9): [True: 47.4k, False: 37.7k]
  ------------------
 1187|  47.4k|        head->prev = current_item;
 1188|  47.4k|    }
 1189|       |
 1190|  85.2k|    item->type = cJSON_Array;
  ------------------
  |  |  102|  85.2k|#define cJSON_Array (1 << 5)
  ------------------
 1191|  85.2k|    item->child = head;
 1192|       |
 1193|  85.2k|    input_buffer->offset++;
 1194|       |
 1195|  85.2k|    return true;
  ------------------
  |  |   67|  85.2k|#define true ((cJSON_bool)1)
  ------------------
 1196|       |
 1197|  59.4k|fail:
 1198|  59.4k|    if (head != NULL) {
  ------------------
  |  Branch (1198:9): [True: 59.4k, False: 0]
  ------------------
 1199|  59.4k|        loader_cJSON_Delete(head);
 1200|  59.4k|    }
 1201|       |
 1202|  59.4k|    return false;
  ------------------
  |  |   72|  59.4k|#define false ((cJSON_bool)0)
  ------------------
 1203|  47.7k|}
cJSON.c:parse_object:
 1259|   322k|static cJSON_bool parse_object(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory) {
 1260|   322k|    cJSON *head = NULL; /* linked list head */
 1261|   322k|    cJSON *current_item = NULL;
 1262|       |
 1263|   322k|    if (input_buffer->depth >= CJSON_NESTING_LIMIT) {
  ------------------
  |  |  138|   322k|#define CJSON_NESTING_LIMIT 1000
  ------------------
  |  Branch (1263:9): [True: 6, False: 322k]
  ------------------
 1264|      6|        return false; /* to deeply nested */
  ------------------
  |  |   72|      6|#define false ((cJSON_bool)0)
  ------------------
 1265|      6|    }
 1266|   322k|    input_buffer->depth++;
 1267|       |
 1268|   322k|    if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) {
  ------------------
  |  |  193|   644k|#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
  |  |  ------------------
  |  |  |  |  192|   322k|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (192:45): [True: 322k, False: 0]
  |  |  |  |  |  Branch (192:65): [True: 322k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
                  if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) {
  ------------------
  |  |  195|   322k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1268:52): [True: 0, False: 322k]
  ------------------
 1269|      0|        goto fail; /* not an object */
 1270|      0|    }
 1271|       |
 1272|   322k|    input_buffer->offset++;
 1273|   322k|    buffer_skip_whitespace(input_buffer);
 1274|   322k|    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) {
  ------------------
  |  |  192|   644k|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 322k, False: 0]
  |  |  |  Branch (192:65): [True: 322k, False: 0]
  |  |  ------------------
  ------------------
                  if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) {
  ------------------
  |  |  195|   322k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1274:49): [True: 4.99k, False: 317k]
  ------------------
 1275|  4.99k|        goto success; /* empty object */
 1276|  4.99k|    }
 1277|       |
 1278|       |    /* check if we skipped to the end of the buffer */
 1279|   317k|    if (cannot_access_at_index(input_buffer, 0)) {
  ------------------
  |  |  193|   317k|#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
  |  |  ------------------
  |  |  |  |  192|   317k|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (192:45): [True: 317k, False: 0]
  |  |  |  |  |  Branch (192:65): [True: 317k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1280|      0|        input_buffer->offset--;
 1281|      0|        goto fail;
 1282|      0|    }
 1283|       |
 1284|       |    /* step back to character in front of the first element */
 1285|   317k|    input_buffer->offset--;
 1286|       |    /* loop through the comma separated array elements */
 1287|  1.01M|    do {
 1288|       |        /* allocate next item */
 1289|  1.01M|        cJSON *new_item = cJSON_New_Item(input_buffer->pAllocator);
 1290|  1.01M|        if (new_item == NULL) {
  ------------------
  |  Branch (1290:13): [True: 0, False: 1.01M]
  ------------------
 1291|      0|            *out_of_memory = true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
 1292|      0|            goto fail; /* allocation failure */
 1293|      0|        }
 1294|       |
 1295|       |        /* attach next item to list */
 1296|  1.01M|        if (head == NULL) {
  ------------------
  |  Branch (1296:13): [True: 317k, False: 698k]
  ------------------
 1297|       |            /* start the linked list */
 1298|   317k|            current_item = head = new_item;
 1299|   698k|        } else {
 1300|       |            /* add to the end and advance */
 1301|   698k|            current_item->next = new_item;
 1302|   698k|            new_item->prev = current_item;
 1303|   698k|            current_item = new_item;
 1304|   698k|        }
 1305|       |
 1306|  1.01M|        if (cannot_access_at_index(input_buffer, 1)) {
  ------------------
  |  |  193|  1.01M|#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
  |  |  ------------------
  |  |  |  |  192|  1.01M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (192:45): [True: 1.01M, False: 0]
  |  |  |  |  |  Branch (192:65): [True: 1.01M, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1307|      0|            goto fail; /* nothing comes after the comma */
 1308|      0|        }
 1309|       |
 1310|       |        /* parse the name of the child */
 1311|  1.01M|        input_buffer->offset++;
 1312|  1.01M|        buffer_skip_whitespace(input_buffer);
 1313|  1.01M|        if (!parse_string(current_item, input_buffer, out_of_memory)) {
  ------------------
  |  Branch (1313:13): [True: 265, False: 1.01M]
  ------------------
 1314|    265|            goto fail; /* failed to parse name */
 1315|    265|        }
 1316|  1.01M|        buffer_skip_whitespace(input_buffer);
 1317|       |
 1318|       |        /* swap valuestring and string, because we parsed the name */
 1319|  1.01M|        current_item->string = current_item->valuestring;
 1320|  1.01M|        current_item->valuestring = NULL;
 1321|       |
 1322|  1.01M|        if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) {
  ------------------
  |  |  193|  2.03M|#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
  |  |  ------------------
  |  |  |  |  192|  1.01M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (192:45): [True: 1.01M, False: 0]
  |  |  |  |  |  Branch (192:65): [True: 1.01M, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
                      if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) {
  ------------------
  |  |  195|  1.01M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1322:56): [True: 64, False: 1.01M]
  ------------------
 1323|     64|            goto fail; /* invalid object */
 1324|     64|        }
 1325|       |
 1326|       |        /* parse the value */
 1327|  1.01M|        input_buffer->offset++;
 1328|  1.01M|        buffer_skip_whitespace(input_buffer);
 1329|  1.01M|        if (!parse_value(current_item, input_buffer, out_of_memory)) {
  ------------------
  |  Branch (1329:13): [True: 4.23k, False: 1.01M]
  ------------------
 1330|  4.23k|            goto fail; /* failed to parse value */
 1331|  4.23k|        }
 1332|  1.01M|        buffer_skip_whitespace(input_buffer);
 1333|  1.01M|    } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
  ------------------
  |  |  192|  2.02M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 1.01M, False: 0]
  |  |  |  Branch (192:65): [True: 1.01M, False: 0]
  |  |  ------------------
  ------------------
                  } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
  ------------------
  |  |  195|  1.01M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1333:54): [True: 698k, False: 312k]
  ------------------
 1334|       |
 1335|   312k|    if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) {
  ------------------
  |  |  193|   625k|#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
  |  |  ------------------
  |  |  |  |  192|   312k|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (192:45): [True: 312k, False: 0]
  |  |  |  |  |  Branch (192:65): [True: 312k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
                  if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) {
  ------------------
  |  |  195|   312k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1335:52): [True: 68, False: 312k]
  ------------------
 1336|     68|        goto fail; /* expected end of object */
 1337|     68|    }
 1338|       |
 1339|   317k|success:
 1340|   317k|    input_buffer->depth--;
 1341|       |
 1342|   317k|    if (head != NULL) {
  ------------------
  |  Branch (1342:9): [True: 312k, False: 4.99k]
  ------------------
 1343|   312k|        head->prev = current_item;
 1344|   312k|    }
 1345|       |
 1346|   317k|    item->type = cJSON_Object;
  ------------------
  |  |  103|   317k|#define cJSON_Object (1 << 6)
  ------------------
 1347|   317k|    item->child = head;
 1348|       |
 1349|   317k|    input_buffer->offset++;
 1350|   317k|    return true;
  ------------------
  |  |   67|   317k|#define true ((cJSON_bool)1)
  ------------------
 1351|       |
 1352|  4.63k|fail:
 1353|  4.63k|    if (head != NULL) {
  ------------------
  |  Branch (1353:9): [True: 4.63k, False: 0]
  ------------------
 1354|  4.63k|        loader_cJSON_Delete(head);
 1355|  4.63k|    }
 1356|       |
 1357|  4.63k|    return false;
  ------------------
  |  |   72|  4.63k|#define false ((cJSON_bool)0)
  ------------------
 1358|   312k|}
cJSON.c:print_value:
 1056|   411k|static cJSON_bool print_value(const cJSON *const item, printbuffer *const output_buffer, bool *out_of_memory) {
 1057|   411k|    unsigned char *output = NULL;
 1058|       |
 1059|   411k|    if ((item == NULL) || (output_buffer == NULL)) {
  ------------------
  |  Branch (1059:9): [True: 0, False: 411k]
  |  Branch (1059:27): [True: 0, False: 411k]
  ------------------
 1060|      0|        return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1061|      0|    }
 1062|       |
 1063|   411k|    switch ((item->type) & 0xFF) {
 1064|      0|        case cJSON_NULL:
  ------------------
  |  |   99|      0|#define cJSON_NULL (1 << 2)
  ------------------
  |  Branch (1064:9): [True: 0, False: 411k]
  ------------------
 1065|      0|            output = ensure(output_buffer, 5, out_of_memory);
 1066|      0|            if (output == NULL) {
  ------------------
  |  Branch (1066:17): [True: 0, False: 0]
  ------------------
 1067|      0|                return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1068|      0|            }
 1069|      0|            strcpy((char *)output, "null");
 1070|      0|            return true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
 1071|       |
 1072|      0|        case cJSON_False:
  ------------------
  |  |   97|      0|#define cJSON_False (1 << 0)
  ------------------
  |  Branch (1072:9): [True: 0, False: 411k]
  ------------------
 1073|      0|            output = ensure(output_buffer, 6, out_of_memory);
 1074|      0|            if (output == NULL) {
  ------------------
  |  Branch (1074:17): [True: 0, False: 0]
  ------------------
 1075|      0|                return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1076|      0|            }
 1077|      0|            strcpy((char *)output, "false");
 1078|      0|            return true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
 1079|       |
 1080|      0|        case cJSON_True:
  ------------------
  |  |   98|      0|#define cJSON_True (1 << 1)
  ------------------
  |  Branch (1080:9): [True: 0, False: 411k]
  ------------------
 1081|      0|            output = ensure(output_buffer, 5, out_of_memory);
 1082|      0|            if (output == NULL) {
  ------------------
  |  Branch (1082:17): [True: 0, False: 0]
  ------------------
 1083|      0|                return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1084|      0|            }
 1085|      0|            strcpy((char *)output, "true");
 1086|      0|            return true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
 1087|       |
 1088|      0|        case cJSON_Number:
  ------------------
  |  |  100|      0|#define cJSON_Number (1 << 3)
  ------------------
  |  Branch (1088:9): [True: 0, False: 411k]
  ------------------
 1089|      0|            return print_number(item, output_buffer, out_of_memory);
 1090|       |
 1091|      0|        case cJSON_Raw: {
  ------------------
  |  |  104|      0|#define cJSON_Raw (1 << 7) /* raw json */
  ------------------
  |  Branch (1091:9): [True: 0, False: 411k]
  ------------------
 1092|      0|            size_t raw_length = 0;
 1093|      0|            if (item->valuestring == NULL) {
  ------------------
  |  Branch (1093:17): [True: 0, False: 0]
  ------------------
 1094|      0|                return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1095|      0|            }
 1096|       |
 1097|      0|            raw_length = strlen(item->valuestring) + sizeof("");
 1098|      0|            output = ensure(output_buffer, raw_length, out_of_memory);
 1099|      0|            if (output == NULL) {
  ------------------
  |  Branch (1099:17): [True: 0, False: 0]
  ------------------
 1100|      0|                return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1101|      0|            }
 1102|      0|            memcpy(output, item->valuestring, raw_length);
 1103|      0|            return true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
 1104|      0|        }
 1105|       |
 1106|   411k|        case cJSON_String:
  ------------------
  |  |  101|   411k|#define cJSON_String (1 << 4)
  ------------------
  |  Branch (1106:9): [True: 411k, False: 0]
  ------------------
 1107|   411k|            return print_string(item, output_buffer, out_of_memory);
 1108|       |
 1109|      0|        case cJSON_Array:
  ------------------
  |  |  102|      0|#define cJSON_Array (1 << 5)
  ------------------
  |  Branch (1109:9): [True: 0, False: 411k]
  ------------------
 1110|      0|            return print_array(item, output_buffer, out_of_memory);
 1111|       |
 1112|      0|        case cJSON_Object:
  ------------------
  |  |  103|      0|#define cJSON_Object (1 << 6)
  ------------------
  |  Branch (1112:9): [True: 0, False: 411k]
  ------------------
 1113|      0|            return print_object(item, output_buffer, out_of_memory);
 1114|       |
 1115|      0|        default:
  ------------------
  |  Branch (1115:9): [True: 0, False: 411k]
  ------------------
 1116|      0|            return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1117|   411k|    }
 1118|   411k|}
cJSON.c:ensure:
  275|   411k|static unsigned char *ensure(printbuffer *const p, size_t needed, bool *out_of_memory) {
  276|   411k|    unsigned char *newbuffer = NULL;
  277|   411k|    size_t newsize = 0;
  278|       |
  279|   411k|    if ((p == NULL) || (p->buffer == NULL)) {
  ------------------
  |  Branch (279:9): [True: 0, False: 411k]
  |  Branch (279:24): [True: 0, False: 411k]
  ------------------
  280|      0|        return NULL;
  281|      0|    }
  282|       |
  283|   411k|    if ((p->length > 0) && (p->offset >= p->length)) {
  ------------------
  |  Branch (283:9): [True: 411k, False: 0]
  |  Branch (283:28): [True: 0, False: 411k]
  ------------------
  284|       |        /* make sure that offset is valid */
  285|      0|        return NULL;
  286|      0|    }
  287|       |
  288|   411k|    if (needed > INT_MAX) {
  ------------------
  |  Branch (288:9): [True: 0, False: 411k]
  ------------------
  289|       |        /* sizes bigger than INT_MAX are currently not supported */
  290|      0|        return NULL;
  291|      0|    }
  292|       |
  293|   411k|    needed += p->offset + 1;
  294|   411k|    if (needed <= p->length) {
  ------------------
  |  Branch (294:9): [True: 410k, False: 1.36k]
  ------------------
  295|   410k|        return p->buffer + p->offset;
  296|   410k|    }
  297|       |
  298|  1.36k|    if (p->noalloc) {
  ------------------
  |  Branch (298:9): [True: 43, False: 1.32k]
  ------------------
  299|     43|        return NULL;
  300|     43|    }
  301|       |
  302|       |    /* calculate new buffer size */
  303|  1.32k|    if (needed > (INT_MAX / 2)) {
  ------------------
  |  Branch (303:9): [True: 0, False: 1.32k]
  ------------------
  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|  1.32k|    } else {
  311|  1.32k|        newsize = needed * 2;
  312|  1.32k|    }
  313|       |
  314|  1.32k|    newbuffer = (unsigned char *)loader_realloc(p->pAllocator, p->buffer, p->length, newsize, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  315|  1.32k|    if (newbuffer == NULL) {
  ------------------
  |  Branch (315:9): [True: 0, False: 1.32k]
  ------------------
  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|  1.32k|    p->length = newsize;
  325|  1.32k|    p->buffer = newbuffer;
  326|       |
  327|  1.32k|    return newbuffer + p->offset;
  328|  1.32k|}
cJSON.c:print_string:
  759|   411k|static cJSON_bool print_string(const cJSON *const item, printbuffer *const p, bool *out_of_memory) {
  760|   411k|    return print_string_ptr((unsigned char *)item->valuestring, p, out_of_memory);
  761|   411k|}
cJSON.c:print_string_ptr:
  650|   411k|static cJSON_bool print_string_ptr(const unsigned char *const input, printbuffer *const output_buffer, bool *out_of_memory) {
  651|   411k|    const unsigned char *input_pointer = NULL;
  652|   411k|    unsigned char *output = NULL;
  653|   411k|    unsigned char *output_pointer = NULL;
  654|   411k|    size_t output_length = 0;
  655|       |    /* numbers of additional characters needed for escaping */
  656|   411k|    size_t escape_characters = 0;
  657|       |
  658|   411k|    if (output_buffer == NULL) {
  ------------------
  |  Branch (658:9): [True: 0, False: 411k]
  ------------------
  659|      0|        return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
  660|      0|    }
  661|       |
  662|       |    /* empty string */
  663|   411k|    if (input == NULL) {
  ------------------
  |  Branch (663:9): [True: 0, False: 411k]
  ------------------
  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|  8.06M|    for (input_pointer = input; *input_pointer; input_pointer++) {
  ------------------
  |  Branch (673:33): [True: 7.65M, False: 411k]
  ------------------
  674|  7.65M|        switch (*input_pointer) {
  675|    165|            case '\"':
  ------------------
  |  Branch (675:13): [True: 165, False: 7.65M]
  ------------------
  676|    878|            case '\\':
  ------------------
  |  Branch (676:13): [True: 713, False: 7.65M]
  ------------------
  677|  3.03k|            case '\b':
  ------------------
  |  Branch (677:13): [True: 2.15k, False: 7.65M]
  ------------------
  678|  4.20k|            case '\f':
  ------------------
  |  Branch (678:13): [True: 1.17k, False: 7.65M]
  ------------------
  679|  6.77k|            case '\n':
  ------------------
  |  Branch (679:13): [True: 2.57k, False: 7.65M]
  ------------------
  680|  10.4k|            case '\r':
  ------------------
  |  Branch (680:13): [True: 3.62k, False: 7.65M]
  ------------------
  681|  12.9k|            case '\t':
  ------------------
  |  Branch (681:13): [True: 2.58k, False: 7.65M]
  ------------------
  682|       |                /* one character escape sequence */
  683|  12.9k|                escape_characters++;
  684|  12.9k|                break;
  685|  7.64M|            default:
  ------------------
  |  Branch (685:13): [True: 7.64M, False: 12.9k]
  ------------------
  686|  7.64M|                if (*input_pointer < 32) {
  ------------------
  |  Branch (686:21): [True: 4.74M, False: 2.89M]
  ------------------
  687|       |                    /* UTF-16 escape sequence uXXXX */
  688|  4.74M|                    escape_characters += 5;
  689|  4.74M|                }
  690|  7.64M|                break;
  691|  7.65M|        }
  692|  7.65M|    }
  693|   411k|    output_length = (size_t)(input_pointer - input) + escape_characters;
  694|       |
  695|   411k|    output = ensure(output_buffer, output_length + sizeof(""), out_of_memory);
  696|   411k|    if (output == NULL) {
  ------------------
  |  Branch (696:9): [True: 43, False: 411k]
  ------------------
  697|     43|        return false;
  ------------------
  |  |   72|     43|#define false ((cJSON_bool)0)
  ------------------
  698|     43|    }
  699|       |
  700|       |    /* no characters have to be escaped */
  701|   411k|    if (escape_characters == 0) {
  ------------------
  |  Branch (701:9): [True: 386k, False: 24.7k]
  ------------------
  702|   386k|        memcpy(output, input, output_length);
  703|   386k|        output[output_length] = '\0';
  704|       |
  705|   386k|        return true;
  ------------------
  |  |   67|   386k|#define true ((cJSON_bool)1)
  ------------------
  706|   386k|    }
  707|       |
  708|  24.7k|    output_pointer = output;
  709|       |    /* copy the string */
  710|  5.56M|    for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++) {
  ------------------
  |  Branch (710:33): [True: 5.54M, False: 24.7k]
  ------------------
  711|  5.54M|        if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\')) {
  ------------------
  |  Branch (711:13): [True: 789k, False: 4.75M]
  |  Branch (711:38): [True: 789k, False: 165]
  |  Branch (711:66): [True: 788k, False: 713]
  ------------------
  712|       |            /* normal character, copy */
  713|   788k|            *output_pointer = *input_pointer;
  714|  4.75M|        } 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|  4.75M|            switch (*input_pointer) {
  721|    713|                case '\\':
  ------------------
  |  Branch (721:17): [True: 713, False: 4.75M]
  ------------------
  722|    713|                    *output_pointer = '\\';
  723|    713|                    break;
  724|    165|                case '\"':
  ------------------
  |  Branch (724:17): [True: 165, False: 4.75M]
  ------------------
  725|    165|                    *output_pointer = '\"';
  726|    165|                    break;
  727|  2.14k|                case '\b':
  ------------------
  |  Branch (727:17): [True: 2.14k, False: 4.75M]
  ------------------
  728|  2.14k|                    *output_pointer = '\b';
  729|  2.14k|                    break;
  730|  1.16k|                case '\f':
  ------------------
  |  Branch (730:17): [True: 1.16k, False: 4.75M]
  ------------------
  731|  1.16k|                    *output_pointer = '\f';
  732|  1.16k|                    break;
  733|  2.57k|                case '\n':
  ------------------
  |  Branch (733:17): [True: 2.57k, False: 4.75M]
  ------------------
  734|  2.57k|                    *output_pointer = '\n';
  735|  2.57k|                    break;
  736|  3.62k|                case '\r':
  ------------------
  |  Branch (736:17): [True: 3.62k, False: 4.74M]
  ------------------
  737|  3.62k|                    *output_pointer = '\r';
  738|  3.62k|                    break;
  739|  2.29k|                case '\t':
  ------------------
  |  Branch (739:17): [True: 2.29k, False: 4.75M]
  ------------------
  740|  2.29k|                    *output_pointer = '\t';
  741|  2.29k|                    break;
  742|  4.74M|                default:
  ------------------
  |  Branch (742:17): [True: 4.74M, False: 12.6k]
  ------------------
  743|       |                    /* escape and print as unicode codepoint */
  744|  4.74M|                    snprintf((char *)output_pointer, output_length - (size_t)(output_pointer - output), "u%04x", *input_pointer);
  745|  4.74M|                    output_pointer += 4;
  746|  4.74M|                    break;
  747|  4.75M|            }
  748|  4.75M|        }
  749|  5.54M|    }
  750|       |    // The loader-specific escaping above emits one byte where the standard form emits two, so the written
  751|       |    // length is shorter than output_length. Terminate at the actual end, otherwise the bytes between it and
  752|       |    // output_length (uninitialized when the caller buffer is not zeroed) get read back as part of the string.
  753|  24.7k|    *output_pointer = '\0';
  754|       |
  755|  24.7k|    return true;
  ------------------
  |  |   67|  24.7k|#define true ((cJSON_bool)1)
  ------------------
  756|  24.7k|}
cJSON.c:get_object_item:
 1501|   841k|static cJSON *get_object_item(const cJSON *const object, const char *const name, const cJSON_bool case_sensitive) {
 1502|   841k|    cJSON *current_element = NULL;
 1503|       |
 1504|   841k|    if ((object == NULL) || (name == NULL)) {
  ------------------
  |  Branch (1504:9): [True: 0, False: 841k]
  |  Branch (1504:29): [True: 0, False: 841k]
  ------------------
 1505|      0|        return NULL;
 1506|      0|    }
 1507|       |
 1508|   841k|    current_element = object->child;
 1509|   841k|    if (case_sensitive) {
  ------------------
  |  Branch (1509:9): [True: 0, False: 841k]
  ------------------
 1510|      0|        while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0)) {
  ------------------
  |  Branch (1510:16): [True: 0, False: 0]
  |  Branch (1510:45): [True: 0, False: 0]
  |  Branch (1510:82): [True: 0, False: 0]
  ------------------
 1511|      0|            current_element = current_element->next;
 1512|      0|        }
 1513|   841k|    } else {
 1514|  4.79M|        while ((current_element != NULL) &&
  ------------------
  |  Branch (1514:16): [True: 4.39M, False: 405k]
  ------------------
 1515|  4.39M|               (case_insensitive_strcmp((const unsigned char *)name, (const unsigned char *)(current_element->string)) != 0)) {
  ------------------
  |  Branch (1515:16): [True: 3.95M, False: 435k]
  ------------------
 1516|  3.95M|            current_element = current_element->next;
 1517|  3.95M|        }
 1518|   841k|    }
 1519|       |
 1520|   841k|    if ((current_element == NULL) || (current_element->string == NULL)) {
  ------------------
  |  Branch (1520:9): [True: 405k, False: 435k]
  |  Branch (1520:38): [True: 0, False: 435k]
  ------------------
 1521|   405k|        return NULL;
 1522|   405k|    }
 1523|       |
 1524|   435k|    return current_element;
 1525|   841k|}
cJSON.c:case_insensitive_strcmp:
  120|  4.39M|static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2) {
  121|  4.39M|    if ((string1 == NULL) || (string2 == NULL)) {
  ------------------
  |  Branch (121:9): [True: 0, False: 4.39M]
  |  Branch (121:30): [True: 42, False: 4.39M]
  ------------------
  122|     42|        return 1;
  123|     42|    }
  124|       |
  125|  4.39M|    if (string1 == string2) {
  ------------------
  |  Branch (125:9): [True: 0, False: 4.39M]
  ------------------
  126|      0|        return 0;
  127|      0|    }
  128|       |
  129|  9.10M|    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: 9.10M]
  |  Branch (129:12): [True: 5.15M, False: 3.95M]
  |  Branch (129:33): [True: 0, False: 0]
  |  Branch (129:33): [True: 0, False: 0]
  |  Branch (129:33): [Folded, False: 9.10M]
  ------------------
  130|  5.15M|        if (*string1 == '\0') {
  ------------------
  |  Branch (130:13): [True: 435k, False: 4.71M]
  ------------------
  131|   435k|            return 0;
  132|   435k|        }
  133|  5.15M|    }
  134|       |
  135|  3.95M|    return tolower(*string1) - tolower(*string2);
  ------------------
  |  Branch (135:12): [True: 0, False: 0]
  |  Branch (135:12): [True: 0, False: 0]
  |  Branch (135:12): [Folded, False: 3.95M]
  |  Branch (135:32): [True: 0, False: 0]
  |  Branch (135:32): [True: 0, False: 0]
  |  Branch (135:32): [Folded, False: 3.95M]
  ------------------
  136|  4.39M|}

loader_make_version:
  113|  27.4k|loader_api_version loader_make_version(uint32_t version) {
  114|  27.4k|    loader_api_version out_version;
  115|  27.4k|    out_version.major = VK_API_VERSION_MAJOR(version);
  116|       |    out_version.minor = VK_API_VERSION_MINOR(version);
  117|  27.4k|    out_version.patch = 0;
  118|  27.4k|    return out_version;
  119|  27.4k|}
loader_make_full_version:
  122|  6.04k|loader_api_version loader_make_full_version(uint32_t version) {
  123|  6.04k|    loader_api_version out_version;
  124|  6.04k|    out_version.major = VK_API_VERSION_MAJOR(version);
  125|  6.04k|    out_version.minor = VK_API_VERSION_MINOR(version);
  126|       |    out_version.patch = VK_API_VERSION_PATCH(version);
  127|  6.04k|    return out_version;
  128|  6.04k|}
loader_combine_version:
  131|  39.4k|loader_api_version loader_combine_version(uint32_t major, uint32_t minor, uint32_t patch) {
  132|  39.4k|    loader_api_version out_version;
  133|  39.4k|    out_version.major = (uint16_t)major;
  134|  39.4k|    out_version.minor = (uint16_t)minor;
  135|  39.4k|    out_version.patch = (uint16_t)patch;
  136|  39.4k|    return out_version;
  137|  39.4k|}
loader_check_version_meets_required:
  140|  42.2k|bool loader_check_version_meets_required(loader_api_version required, loader_api_version version) {
  141|       |    // major version is satisfied
  142|  42.2k|    return (version.major > required.major) ||
  ------------------
  |  Branch (142:12): [True: 14.4k, False: 27.8k]
  ------------------
  143|       |           // major version is equal, minor version is patch version is greater to minimum minor
  144|  27.8k|           (version.major == required.major && version.minor > required.minor) ||
  ------------------
  |  Branch (144:13): [True: 4.36k, False: 23.4k]
  |  Branch (144:48): [True: 1.15k, False: 3.20k]
  ------------------
  145|       |           // major and minor version are equal, patch version is greater or equal to minimum patch
  146|  26.6k|           (version.major == required.major && version.minor == required.minor && version.patch >= required.patch);
  ------------------
  |  Branch (146:13): [True: 3.20k, False: 23.4k]
  |  Branch (146:48): [True: 2.32k, False: 881]
  |  Branch (146:83): [True: 2.03k, False: 295]
  ------------------
  147|  42.2k|}
loader_opendir:
  172|   115k|DIR *loader_opendir(const struct loader_instance *instance, const char *name) {
  173|       |#if defined(_WIN32)
  174|       |    return opendir(instance ? &instance->alloc_callbacks : NULL, name);
  175|       |#elif COMMON_UNIX_PLATFORMS
  176|       |    (void)instance;
  177|   115k|    return opendir(name);
  178|       |#else
  179|       |#warning dirent.h - opendir not available on this platform
  180|       |#endif  // _WIN32
  181|   115k|}
loader_closedir:
  182|  10.8k|int loader_closedir(const struct loader_instance *instance, DIR *dir) {
  183|       |#if defined(_WIN32)
  184|       |    return closedir(instance ? &instance->alloc_callbacks : NULL, dir);
  185|       |#elif COMMON_UNIX_PLATFORMS
  186|       |    (void)instance;
  187|  10.8k|    return closedir(dir);
  188|       |#else
  189|       |#warning dirent.h - closedir not available on this platform
  190|       |#endif  // _WIN32
  191|  10.8k|}
is_json:
  193|   309k|bool is_json(const char *path, size_t len) {
  194|   309k|    if (len < 5) {
  ------------------
  |  Branch (194:9): [True: 40.8k, False: 268k]
  ------------------
  195|  40.8k|        return false;
  196|  40.8k|    }
  197|   268k|    return !strncmp(path + len - 5, ".json", 5);
  198|   309k|}
loader_free_layer_properties:
  248|   200k|void loader_free_layer_properties(const struct loader_instance *inst, struct loader_layer_properties *layer_properties) {
  249|   200k|    loader_instance_heap_free(inst, layer_properties->manifest_file_name);
  250|   200k|    loader_instance_heap_free(inst, layer_properties->lib_name);
  251|   200k|    loader_instance_heap_free(inst, layer_properties->functions.str_gipa);
  252|   200k|    loader_instance_heap_free(inst, layer_properties->functions.str_gdpa);
  253|   200k|    loader_instance_heap_free(inst, layer_properties->functions.str_negotiate_interface);
  254|   200k|    loader_destroy_generic_list(inst, (struct loader_generic_list *)&layer_properties->instance_extension_list);
  255|   200k|    if (layer_properties->device_extension_list.capacity > 0 && NULL != layer_properties->device_extension_list.list) {
  ------------------
  |  Branch (255:9): [True: 635, False: 199k]
  |  Branch (255:65): [True: 635, False: 0]
  ------------------
  256|  6.71k|        for (uint32_t i = 0; i < layer_properties->device_extension_list.count; i++) {
  ------------------
  |  Branch (256:30): [True: 6.08k, False: 635]
  ------------------
  257|  6.08k|            free_string_list(inst, &layer_properties->device_extension_list.list[i].entrypoints);
  258|  6.08k|        }
  259|    635|    }
  260|   200k|    loader_destroy_generic_list(inst, (struct loader_generic_list *)&layer_properties->device_extension_list);
  261|   200k|    loader_instance_heap_free(inst, layer_properties->disable_env_var.name);
  262|   200k|    loader_instance_heap_free(inst, layer_properties->disable_env_var.value);
  263|   200k|    loader_instance_heap_free(inst, layer_properties->enable_env_var.name);
  264|   200k|    loader_instance_heap_free(inst, layer_properties->enable_env_var.value);
  265|   200k|    free_string_list(inst, &layer_properties->component_layer_names);
  266|   200k|    loader_instance_heap_free(inst, layer_properties->pre_instance_functions.enumerate_instance_extension_properties);
  267|   200k|    loader_instance_heap_free(inst, layer_properties->pre_instance_functions.enumerate_instance_layer_properties);
  268|   200k|    loader_instance_heap_free(inst, layer_properties->pre_instance_functions.enumerate_instance_version);
  269|   200k|    free_string_list(inst, &layer_properties->override_paths);
  270|   200k|    free_string_list(inst, &layer_properties->blacklist_layer_names);
  271|   200k|    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|   200k|    memset(layer_properties, 0, sizeof(struct loader_layer_properties));
  275|   200k|}
is_string_in_string_list:
  288|   135k|bool is_string_in_string_list(struct loader_string_list *string_list, const char *str) {
  289|       |    // Remove duplicate paths, or it would result in duplicate extensions, duplicate devices, etc.
  290|  1.36M|    for (size_t i = 0; i < string_list->count; i++) {
  ------------------
  |  Branch (290:24): [True: 1.24M, False: 123k]
  ------------------
  291|  1.24M|        if (strcmp(string_list->list[i], str) == 0) {
  ------------------
  |  Branch (291:13): [True: 12.0k, False: 1.23M]
  ------------------
  292|  12.0k|            return true;
  293|  12.0k|        }
  294|  1.24M|    }
  295|   123k|    return false;
  296|   135k|}
loader_copy_to_new_str:
  298|   166k|VkResult loader_copy_to_new_str(const struct loader_instance *inst, const char *source_str, char **dest_str) {
  299|   166k|    assert(source_str && dest_str);
  300|   166k|    size_t str_len = strlen(source_str) + 1;
  301|   166k|    *dest_str = loader_instance_heap_calloc(inst, str_len, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  302|   166k|    if (NULL == *dest_str) return VK_ERROR_OUT_OF_HOST_MEMORY;
  ------------------
  |  Branch (302:9): [True: 0, False: 166k]
  ------------------
  303|   166k|    loader_strncpy(*dest_str, str_len, source_str, str_len);
  304|   166k|    (*dest_str)[str_len - 1] = 0;
  305|   166k|    return VK_SUCCESS;
  306|   166k|}
create_string_list:
  308|  11.2k|VkResult create_string_list(const struct loader_instance *inst, uint32_t allocated_count, struct loader_string_list *string_list) {
  309|  11.2k|    assert(string_list);
  310|  11.2k|    string_list->list =
  311|  11.2k|        (char **)loader_instance_heap_calloc(inst, sizeof(char *) * allocated_count, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  312|  11.2k|    if (NULL == string_list->list) {
  ------------------
  |  Branch (312:9): [True: 0, False: 11.2k]
  ------------------
  313|      0|        return VK_ERROR_OUT_OF_HOST_MEMORY;
  314|      0|    }
  315|  11.2k|    string_list->allocated_count = allocated_count;
  316|  11.2k|    string_list->count = 0;
  317|  11.2k|    return VK_SUCCESS;
  318|  11.2k|}
increase_str_capacity_by_at_least_one:
  320|   348k|VkResult increase_str_capacity_by_at_least_one(const struct loader_instance *inst, struct loader_string_list *string_list) {
  321|   348k|    assert(string_list);
  322|   348k|    if (string_list->allocated_count == 0) {
  ------------------
  |  Branch (322:9): [True: 24.0k, False: 324k]
  ------------------
  323|  24.0k|        string_list->allocated_count = 32;
  324|  24.0k|        string_list->list = (char **)loader_instance_heap_calloc(inst, sizeof(char *) * string_list->allocated_count,
  325|  24.0k|                                                                 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  326|  24.0k|        if (NULL == string_list->list) {
  ------------------
  |  Branch (326:13): [True: 0, False: 24.0k]
  ------------------
  327|      0|            return VK_ERROR_OUT_OF_HOST_MEMORY;
  328|      0|        }
  329|   324k|    } else if (string_list->count + 1 > string_list->allocated_count) {
  ------------------
  |  Branch (329:16): [True: 255, False: 324k]
  ------------------
  330|    255|        uint32_t new_allocated_count = string_list->allocated_count * 2;
  331|    255|        void *new_ptr = loader_instance_heap_realloc(inst, (void *)string_list->list, sizeof(char *) * string_list->allocated_count,
  332|    255|                                                     sizeof(char *) * new_allocated_count, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  333|    255|        if (NULL == new_ptr) {
  ------------------
  |  Branch (333:13): [True: 0, False: 255]
  ------------------
  334|      0|            return VK_ERROR_OUT_OF_HOST_MEMORY;
  335|      0|        }
  336|    255|        string_list->list = (char **)new_ptr;
  337|    255|        string_list->allocated_count *= 2;
  338|    255|    }
  339|   348k|    return VK_SUCCESS;
  340|   348k|}
append_str_to_string_list:
  342|   348k|VkResult append_str_to_string_list(const struct loader_instance *inst, struct loader_string_list *string_list, char *str) {
  343|   348k|    assert(string_list && str);
  344|   348k|    VkResult res = increase_str_capacity_by_at_least_one(inst, string_list);
  345|   348k|    if (res == VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (345:9): [True: 0, False: 348k]
  ------------------
  346|      0|        loader_instance_heap_free(inst, str);  // Must clean up in case of failure
  347|      0|        return res;
  348|      0|    }
  349|   348k|    string_list->list[string_list->count++] = str;
  350|   348k|    return VK_SUCCESS;
  351|   348k|}
append_str_to_string_list_if_unique:
  354|   135k|                                             char *str) {
  355|   135k|    if (is_string_in_string_list(string_list, str)) {
  ------------------
  |  Branch (355:9): [True: 12.0k, False: 123k]
  ------------------
  356|       |        // Since this string is a duplicate and this function takes ownership, we need to free it.
  357|  12.0k|        loader_instance_heap_free(inst, str);
  358|  12.0k|        return VK_SUCCESS;
  359|  12.0k|    }
  360|   123k|    return append_str_to_string_list(inst, string_list, str);
  361|   135k|}
copy_str_to_string_list:
  379|  15.5k|                                 size_t str_len) {
  380|  15.5k|    assert(string_list && str);
  381|  15.5k|    char *new_str = loader_instance_heap_calloc(inst, str_len + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  382|  15.5k|    if (NULL == new_str) {
  ------------------
  |  Branch (382:9): [True: 0, False: 15.5k]
  ------------------
  383|      0|        return VK_ERROR_OUT_OF_HOST_MEMORY;
  384|      0|    }
  385|  15.5k|    loader_strncpy(new_str, str_len + 1, str, str_len);
  386|  15.5k|    new_str[str_len] = '\0';
  387|  15.5k|    return append_str_to_string_list(inst, string_list, new_str);
  388|  15.5k|}
free_string_list:
  410|   870k|void free_string_list(const struct loader_instance *inst, struct loader_string_list *string_list) {
  411|   870k|    assert(string_list);
  412|   870k|    if (string_list->list) {
  ------------------
  |  Branch (412:9): [True: 35.3k, False: 834k]
  ------------------
  413|   384k|        for (uint32_t i = 0; i < string_list->count; i++) {
  ------------------
  |  Branch (413:30): [True: 348k, False: 35.3k]
  ------------------
  414|   348k|            loader_instance_heap_free(inst, string_list->list[i]);
  415|       |            string_list->list[i] = NULL;
  416|   348k|        }
  417|  35.3k|        loader_instance_heap_free(inst, (void *)string_list->list);
  418|  35.3k|    }
  419|   870k|    memset(string_list, 0, sizeof(struct loader_string_list));
  420|   870k|}
loader_parse_version_string:
  697|  47.4k|uint32_t loader_parse_version_string(char *vers_str) {
  698|  47.4k|    uint32_t variant = 0;
  699|  47.4k|    uint32_t major = 0;
  700|  47.4k|    uint32_t minor = 0;
  701|  47.4k|    uint32_t patch = 0;
  702|  47.4k|    char *vers_tok;
  703|  47.4k|    char *context = NULL;
  704|  47.4k|    if (!vers_str) {
  ------------------
  |  Branch (704:9): [True: 0, False: 47.4k]
  ------------------
  705|      0|        return 0;
  706|      0|    }
  707|       |
  708|  47.4k|    vers_tok = thread_safe_strtok(vers_str, ".\"\n\r", &context);
  709|  47.4k|    if (NULL != vers_tok) {
  ------------------
  |  Branch (709:9): [True: 35.1k, False: 12.2k]
  ------------------
  710|  35.1k|        major = (uint16_t)strtoul(vers_tok, NULL, 10);
  711|  35.1k|        vers_tok = thread_safe_strtok(NULL, ".\"\n\r", &context);
  712|  35.1k|        if (NULL != vers_tok) {
  ------------------
  |  Branch (712:13): [True: 4.74k, False: 30.4k]
  ------------------
  713|  4.74k|            minor = (uint16_t)strtoul(vers_tok, NULL, 10);
  714|  4.74k|            vers_tok = thread_safe_strtok(NULL, ".\"\n\r", &context);
  715|  4.74k|            if (NULL != vers_tok) {
  ------------------
  |  Branch (715:17): [True: 3.22k, False: 1.51k]
  ------------------
  716|  3.22k|                patch = (uint16_t)strtoul(vers_tok, NULL, 10);
  717|  3.22k|                vers_tok = thread_safe_strtok(NULL, ".\"\n\r", &context);
  718|       |                // check that we are using a 4 part version string
  719|  3.22k|                if (NULL != vers_tok) {
  ------------------
  |  Branch (719:21): [True: 128, False: 3.10k]
  ------------------
  720|       |                    // if we are, move the values over into the correct place
  721|    128|                    variant = major;
  722|    128|                    major = minor;
  723|    128|                    minor = patch;
  724|    128|                    patch = (uint16_t)strtoul(vers_tok, NULL, 10);
  725|    128|                }
  726|  3.22k|            }
  727|  4.74k|        }
  728|  35.1k|    }
  729|       |
  730|       |    return VK_MAKE_API_VERSION(variant, major, minor, patch);
  731|  47.4k|}
compare_vk_extension_properties:
  733|   610k|bool compare_vk_extension_properties(const VkExtensionProperties *op1, const VkExtensionProperties *op2) {
  734|   610k|    return strcmp(op1->extensionName, op2->extensionName) == 0 ? true : false;
  ------------------
  |  Branch (734:12): [True: 2.63k, False: 608k]
  ------------------
  735|   610k|}
has_vk_extension_property:
  747|  11.5k|bool has_vk_extension_property(const VkExtensionProperties *vk_ext_prop, const struct loader_extension_list *ext_list) {
  748|   366k|    for (uint32_t i = 0; i < ext_list->count; i++) {
  ------------------
  |  Branch (748:26): [True: 356k, False: 10.6k]
  ------------------
  749|   356k|        if (compare_vk_extension_properties(&ext_list->list[i], vk_ext_prop)) return true;
  ------------------
  |  Branch (749:13): [True: 912, False: 355k]
  ------------------
  750|   356k|    }
  751|  10.6k|    return false;
  752|  11.5k|}
has_vk_dev_ext_property:
  755|  10.7k|bool has_vk_dev_ext_property(const VkExtensionProperties *ext_prop, const struct loader_device_extension_list *ext_list) {
  756|   263k|    for (uint32_t i = 0; i < ext_list->count; i++) {
  ------------------
  |  Branch (756:26): [True: 254k, False: 9.05k]
  ------------------
  757|   254k|        if (compare_vk_extension_properties(&ext_list->list[i].props, ext_prop)) return true;
  ------------------
  |  Branch (757:13): [True: 1.72k, False: 252k]
  ------------------
  758|   254k|    }
  759|  9.05k|    return false;
  760|  10.7k|}
loader_append_layer_property:
  763|   142k|                                      struct loader_layer_properties *layer_property) {
  764|   142k|    VkResult res = VK_SUCCESS;
  765|   142k|    if (layer_list->capacity == 0) {
  ------------------
  |  Branch (765:9): [True: 4.54k, False: 137k]
  ------------------
  766|  4.54k|        res = loader_init_generic_list(inst, (struct loader_generic_list *)layer_list, sizeof(struct loader_layer_properties));
  767|  4.54k|        if (VK_SUCCESS != res) {
  ------------------
  |  Branch (767:13): [True: 0, False: 4.54k]
  ------------------
  768|      0|            goto out;
  769|      0|        }
  770|  4.54k|    }
  771|       |
  772|       |    // Ensure enough room to add an entry
  773|   142k|    if ((layer_list->count + 1) * sizeof(struct loader_layer_properties) > layer_list->capacity) {
  ------------------
  |  Branch (773:9): [True: 721, False: 141k]
  ------------------
  774|    721|        void *new_ptr = loader_instance_heap_realloc(inst, layer_list->list, layer_list->capacity, layer_list->capacity * 2,
  775|    721|                                                     VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  776|    721|        if (NULL == new_ptr) {
  ------------------
  |  Branch (776:13): [True: 0, False: 721]
  ------------------
  777|      0|            loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_append_layer_property: realloc failed for layer list");
  778|      0|            res = VK_ERROR_OUT_OF_HOST_MEMORY;
  779|      0|            goto out;
  780|      0|        }
  781|    721|        layer_list->list = new_ptr;
  782|    721|        layer_list->capacity *= 2;
  783|    721|    }
  784|   142k|    memcpy(&layer_list->list[layer_list->count], layer_property, sizeof(struct loader_layer_properties));
  785|   142k|    layer_list->count++;
  786|   142k|    memset(layer_property, 0, sizeof(struct loader_layer_properties));
  787|   142k|out:
  788|   142k|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (788:9): [True: 0, False: 142k]
  ------------------
  789|      0|        loader_free_layer_properties(inst, layer_property);
  790|      0|    }
  791|   142k|    return res;
  792|   142k|}
loader_find_layer_property:
  795|  5.85k|struct loader_layer_properties *loader_find_layer_property(const char *name, const struct loader_layer_list *layer_list) {
  796|   970k|    for (uint32_t i = 0; i < layer_list->count; i++) {
  ------------------
  |  Branch (796:26): [True: 968k, False: 1.79k]
  ------------------
  797|   968k|        const VkLayerProperties *item = &layer_list->list[i].info;
  798|   968k|        if (strcmp(name, item->layerName) == 0) return &layer_list->list[i];
  ------------------
  |  Branch (798:13): [True: 4.05k, False: 964k]
  ------------------
  799|   968k|    }
  800|  1.79k|    return NULL;
  801|  5.85k|}
loader_find_layer_name_in_blacklist:
  824|  2.88k|bool loader_find_layer_name_in_blacklist(const char *layer_name, struct loader_layer_properties *meta_layer_props) {
  825|  2.88k|    for (uint32_t black_layer = 0; black_layer < meta_layer_props->blacklist_layer_names.count; ++black_layer) {
  ------------------
  |  Branch (825:36): [True: 0, False: 2.88k]
  ------------------
  826|      0|        if (!strcmp(meta_layer_props->blacklist_layer_names.list[black_layer], layer_name)) {
  ------------------
  |  Branch (826:13): [True: 0, False: 0]
  ------------------
  827|      0|            return true;
  828|      0|        }
  829|      0|    }
  830|  2.88k|    return false;
  831|  2.88k|}
loader_delete_layer_list_and_properties:
  835|  35.7k|                                                                  struct loader_layer_list *layer_list) {
  836|  35.7k|    uint32_t i;
  837|  35.7k|    if (!layer_list) return;
  ------------------
  |  Branch (837:9): [True: 0, False: 35.7k]
  ------------------
  838|       |
  839|   106k|    for (i = 0; i < layer_list->count; i++) {
  ------------------
  |  Branch (839:17): [True: 70.5k, False: 35.7k]
  ------------------
  840|  70.5k|        if (layer_list->list[i].lib_handle) {
  ------------------
  |  Branch (840:13): [True: 0, False: 70.5k]
  ------------------
  841|      0|            loader_platform_close_library(layer_list->list[i].lib_handle);
  842|      0|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT | VULKAN_LOADER_LAYER_BIT, 0, "Unloading layer library %s",
  843|      0|                       layer_list->list[i].lib_name);
  844|      0|            layer_list->list[i].lib_handle = NULL;
  845|      0|        }
  846|  70.5k|        loader_free_layer_properties(inst, &(layer_list->list[i]));
  847|  70.5k|    }
  848|  35.7k|    layer_list->count = 0;
  849|       |
  850|  35.7k|    if (layer_list->capacity > 0) {
  ------------------
  |  Branch (850:9): [True: 4.79k, False: 30.9k]
  ------------------
  851|  4.79k|        layer_list->capacity = 0;
  852|  4.79k|        loader_instance_heap_free(inst, layer_list->list);
  853|  4.79k|    }
  854|  35.7k|    memset(layer_list, 0, sizeof(struct loader_layer_list));
  855|  35.7k|}
loader_remove_layer_in_list:
  858|  71.7k|                                 uint32_t layer_to_remove) {
  859|  71.7k|    if (layer_list == NULL || layer_to_remove >= layer_list->count) {
  ------------------
  |  Branch (859:9): [True: 0, False: 71.7k]
  |  Branch (859:31): [True: 0, False: 71.7k]
  ------------------
  860|      0|        return;
  861|      0|    }
  862|  71.7k|    loader_free_layer_properties(inst, &(layer_list->list[layer_to_remove]));
  863|       |
  864|       |    // Remove the current invalid meta-layer from the layer list.  Use memmove since we are
  865|       |    // overlapping the source and destination addresses.
  866|  71.7k|    if (layer_to_remove + 1 <= layer_list->count) {
  ------------------
  |  Branch (866:9): [True: 71.7k, False: 0]
  ------------------
  867|  71.7k|        memmove(&layer_list->list[layer_to_remove], &layer_list->list[layer_to_remove + 1],
  868|  71.7k|                sizeof(struct loader_layer_properties) * (layer_list->count - 1 - layer_to_remove));
  869|  71.7k|    }
  870|       |    // Decrement the count (because we now have one less) and decrement the loop index since we need to
  871|       |    // re-check this index.
  872|  71.7k|    layer_list->count--;
  873|  71.7k|}
loader_remove_layers_in_blacklist:
  877|    156|void loader_remove_layers_in_blacklist(const struct loader_instance *inst, struct loader_layer_list *layer_list) {
  878|    156|    struct loader_layer_properties *override_prop = loader_find_layer_property(VK_OVERRIDE_LAYER_NAME, layer_list);
  ------------------
  |  |  142|    156|#define VK_OVERRIDE_LAYER_NAME "VK_LAYER_LUNARG_override"
  ------------------
  879|    156|    if (NULL == override_prop) {
  ------------------
  |  Branch (879:9): [True: 0, False: 156]
  ------------------
  880|      0|        return;
  881|      0|    }
  882|       |
  883|  3.24k|    for (int32_t j = 0; j < (int32_t)(layer_list->count); j++) {
  ------------------
  |  Branch (883:25): [True: 3.09k, False: 156]
  ------------------
  884|  3.09k|        struct loader_layer_properties cur_layer_prop = layer_list->list[j];
  885|  3.09k|        const char *cur_layer_name = &cur_layer_prop.info.layerName[0];
  886|       |
  887|       |        // Skip the override layer itself.
  888|  3.09k|        if (!strcmp(VK_OVERRIDE_LAYER_NAME, cur_layer_name)) {
  ------------------
  |  |  142|  3.09k|#define VK_OVERRIDE_LAYER_NAME "VK_LAYER_LUNARG_override"
  ------------------
  |  Branch (888:13): [True: 209, False: 2.88k]
  ------------------
  889|    209|            continue;
  890|    209|        }
  891|       |
  892|       |        // If found in the override layer's blacklist, remove it
  893|  2.88k|        if (loader_find_layer_name_in_blacklist(cur_layer_name, override_prop)) {
  ------------------
  |  Branch (893:13): [True: 0, False: 2.88k]
  ------------------
  894|      0|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0,
  895|      0|                       "loader_remove_layers_in_blacklist: Override layer is active and layer %s is in the blacklist inside of it. "
  896|      0|                       "Removing that layer from current layer list.",
  897|      0|                       cur_layer_name);
  898|      0|            loader_remove_layer_in_list(inst, layer_list, j);
  899|      0|            j--;
  900|       |
  901|       |            // Re-do the query for the override layer
  902|      0|            override_prop = loader_find_layer_property(VK_OVERRIDE_LAYER_NAME, layer_list);
  ------------------
  |  |  142|      0|#define VK_OVERRIDE_LAYER_NAME "VK_LAYER_LUNARG_override"
  ------------------
  903|      0|        }
  904|  2.88k|    }
  905|    156|}
loader_remove_layers_not_in_implicit_meta_layers:
  908|  1.04k|void loader_remove_layers_not_in_implicit_meta_layers(const struct loader_instance *inst, struct loader_layer_list *layer_list) {
  909|  1.04k|    int32_t i;
  910|  1.04k|    int32_t j;
  911|  1.04k|    int32_t layer_count = (int32_t)(layer_list->count);
  912|       |
  913|  26.5k|    for (i = 0; i < layer_count; i++) {
  ------------------
  |  Branch (913:17): [True: 25.5k, False: 1.04k]
  ------------------
  914|  25.5k|        layer_list->list[i].keep = false;
  915|  25.5k|    }
  916|       |
  917|  26.5k|    for (i = 0; i < layer_count; i++) {
  ------------------
  |  Branch (917:17): [True: 25.5k, False: 1.04k]
  ------------------
  918|  25.5k|        struct loader_layer_properties *cur_layer_prop = &layer_list->list[i];
  919|       |
  920|  25.5k|        if (0 == (cur_layer_prop->type_flags & VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER)) {
  ------------------
  |  Branch (920:13): [True: 10.5k, False: 14.9k]
  ------------------
  921|  10.5k|            cur_layer_prop->keep = true;
  922|  10.5k|            continue;
  923|  10.5k|        }
  924|  13.7M|        for (j = 0; j < layer_count; j++) {
  ------------------
  |  Branch (924:21): [True: 13.7M, False: 14.9k]
  ------------------
  925|  13.7M|            struct loader_layer_properties *layer_to_check = &layer_list->list[j];
  926|       |
  927|  13.7M|            if (i == j) {
  ------------------
  |  Branch (927:17): [True: 14.9k, False: 13.7M]
  ------------------
  928|  14.9k|                continue;
  929|  14.9k|            }
  930|       |
  931|  13.7M|            if (layer_to_check->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER) {
  ------------------
  |  Branch (931:17): [True: 10.3M, False: 3.37M]
  ------------------
  932|       |                // For all layers found in this meta layer, we want to keep them as well.
  933|  10.4M|                for (uint32_t comp_layer = 0; comp_layer < layer_to_check->component_layer_names.count; comp_layer++) {
  ------------------
  |  Branch (933:47): [True: 70.3k, False: 10.3M]
  ------------------
  934|  70.3k|                    if (!strcmp(layer_to_check->component_layer_names.list[comp_layer], cur_layer_prop->info.layerName)) {
  ------------------
  |  Branch (934:25): [True: 15.1k, False: 55.1k]
  ------------------
  935|  15.1k|                        cur_layer_prop->keep = true;
  936|  15.1k|                    }
  937|  70.3k|                }
  938|  10.3M|            }
  939|  13.7M|        }
  940|  14.9k|    }
  941|       |
  942|       |    // Remove any layers we don't want to keep (Don't use layer_count here as we need it to be
  943|       |    // dynamically updated if we delete a layer property in the list).
  944|  26.5k|    for (i = 0; i < (int32_t)(layer_list->count); i++) {
  ------------------
  |  Branch (944:17): [True: 25.5k, False: 1.04k]
  ------------------
  945|  25.5k|        struct loader_layer_properties *cur_layer_prop = &layer_list->list[i];
  946|  25.5k|        if (!cur_layer_prop->keep) {
  ------------------
  |  Branch (946:13): [True: 13.1k, False: 12.3k]
  ------------------
  947|  13.1k|            loader_log(
  948|  13.1k|                inst, VULKAN_LOADER_DEBUG_BIT, 0,
  949|  13.1k|                "loader_remove_layers_not_in_implicit_meta_layers : Implicit meta-layers are active, and layer %s is not list "
  950|  13.1k|                "inside of any.  So removing layer from current layer list.",
  951|  13.1k|                cur_layer_prop->info.layerName);
  952|  13.1k|            loader_remove_layer_in_list(inst, layer_list, i);
  953|  13.1k|            i--;
  954|  13.1k|        }
  955|  25.5k|    }
  956|  1.04k|}
loader_init_generic_list:
 1062|  6.07k|VkResult loader_init_generic_list(const struct loader_instance *inst, struct loader_generic_list *list_info, size_t element_size) {
 1063|  6.07k|    size_t capacity = 32 * element_size;
 1064|  6.07k|    list_info->count = 0;
 1065|  6.07k|    list_info->capacity = 0;
 1066|  6.07k|    list_info->list = loader_instance_heap_calloc(inst, capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
 1067|  6.07k|    if (list_info->list == NULL) {
  ------------------
  |  Branch (1067:9): [True: 0, False: 6.07k]
  ------------------
 1068|      0|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_init_generic_list: Failed to allocate space for generic list");
 1069|      0|        return VK_ERROR_OUT_OF_HOST_MEMORY;
 1070|      0|    }
 1071|  6.07k|    list_info->capacity = capacity;
 1072|  6.07k|    return VK_SUCCESS;
 1073|  6.07k|}
loader_destroy_generic_list:
 1091|   412k|void loader_destroy_generic_list(const struct loader_instance *inst, struct loader_generic_list *list) {
 1092|   412k|    loader_instance_heap_free(inst, list->list);
 1093|   412k|    memset(list, 0, sizeof(struct loader_generic_list));
 1094|   412k|}
loader_add_to_ext_list:
 1147|  8.39k|                                uint32_t prop_list_count, const VkExtensionProperties *props) {
 1148|  8.39k|    if (ext_list->list == NULL || ext_list->capacity == 0) {
  ------------------
  |  Branch (1148:9): [True: 644, False: 7.75k]
  |  Branch (1148:35): [True: 0, False: 7.75k]
  ------------------
 1149|    644|        VkResult res = loader_init_generic_list(inst, (struct loader_generic_list *)ext_list, sizeof(VkExtensionProperties));
 1150|    644|        if (VK_SUCCESS != res) {
  ------------------
  |  Branch (1150:13): [True: 0, False: 644]
  ------------------
 1151|      0|            return res;
 1152|      0|        }
 1153|    644|    }
 1154|       |
 1155|  16.7k|    for (uint32_t i = 0; i < prop_list_count; i++) {
  ------------------
  |  Branch (1155:26): [True: 8.39k, False: 8.39k]
  ------------------
 1156|  8.39k|        const VkExtensionProperties *cur_ext = &props[i];
 1157|       |
 1158|       |        // look for duplicates
 1159|  8.39k|        if (has_vk_extension_property(cur_ext, ext_list)) {
  ------------------
  |  Branch (1159:13): [True: 684, False: 7.71k]
  ------------------
 1160|    684|            continue;
 1161|    684|        }
 1162|       |
 1163|       |        // add to list at end
 1164|       |        // check for enough capacity
 1165|  7.71k|        if (ext_list->count * sizeof(VkExtensionProperties) >= ext_list->capacity) {
  ------------------
  |  Branch (1165:13): [True: 146, False: 7.56k]
  ------------------
 1166|    146|            void *new_ptr = loader_instance_heap_realloc(inst, ext_list->list, ext_list->capacity, ext_list->capacity * 2,
 1167|    146|                                                         VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
 1168|    146|            if (new_ptr == NULL) {
  ------------------
  |  Branch (1168:17): [True: 0, False: 146]
  ------------------
 1169|      0|                loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
 1170|      0|                           "loader_add_to_ext_list: Failed to reallocate space for extension list");
 1171|      0|                return VK_ERROR_OUT_OF_HOST_MEMORY;
 1172|      0|            }
 1173|    146|            ext_list->list = new_ptr;
 1174|       |
 1175|       |            // double capacity
 1176|    146|            ext_list->capacity *= 2;
 1177|    146|        }
 1178|       |
 1179|       |        // every caller passes the address of an array element or on-stack struct, never NULL
 1180|       |        // NOLINTNEXTLINE(clang-analyzer-core.NonNullParamChecker)
 1181|  7.71k|        memcpy(&ext_list->list[ext_list->count], cur_ext, sizeof(VkExtensionProperties));
 1182|  7.71k|        ext_list->count++;
 1183|  7.71k|    }
 1184|  8.39k|    return VK_SUCCESS;
 1185|  8.39k|}
loader_add_to_dev_ext_list:
 1192|  6.38k|                                    const VkExtensionProperties *props, struct loader_string_list *entrys) {
 1193|  6.38k|    VkResult res = VK_SUCCESS;
 1194|  6.38k|    bool should_free_entrys = true;
 1195|  6.38k|    if (ext_list->list == NULL || ext_list->capacity == 0) {
  ------------------
  |  Branch (1195:9): [True: 635, False: 5.74k]
  |  Branch (1195:35): [True: 0, False: 5.74k]
  ------------------
 1196|    635|        res = loader_init_generic_list(inst, (struct loader_generic_list *)ext_list, sizeof(struct loader_dev_ext_props));
 1197|    635|        if (VK_SUCCESS != res) {
  ------------------
  |  Branch (1197:13): [True: 0, False: 635]
  ------------------
 1198|      0|            goto out;
 1199|      0|        }
 1200|    635|    }
 1201|       |
 1202|       |    // look for duplicates
 1203|  6.38k|    if (has_vk_dev_ext_property(props, ext_list)) {
  ------------------
  |  Branch (1203:9): [True: 301, False: 6.08k]
  ------------------
 1204|    301|        goto out;
 1205|    301|    }
 1206|       |
 1207|  6.08k|    uint32_t idx = ext_list->count;
 1208|       |    // add to list at end
 1209|       |    // check for enough capacity
 1210|  6.08k|    if (idx * sizeof(struct loader_dev_ext_props) >= ext_list->capacity) {
  ------------------
  |  Branch (1210:9): [True: 87, False: 5.99k]
  ------------------
 1211|     87|        void *new_ptr = loader_instance_heap_realloc(inst, ext_list->list, ext_list->capacity, ext_list->capacity * 2,
 1212|     87|                                                     VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
 1213|       |
 1214|     87|        if (NULL == new_ptr) {
  ------------------
  |  Branch (1214:13): [True: 0, False: 87]
  ------------------
 1215|      0|            loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
 1216|      0|                       "loader_add_to_dev_ext_list: Failed to reallocate space for device extension list");
 1217|      0|            res = VK_ERROR_OUT_OF_HOST_MEMORY;
 1218|      0|            goto out;
 1219|      0|        }
 1220|     87|        ext_list->list = new_ptr;
 1221|       |
 1222|       |        // double capacity
 1223|     87|        ext_list->capacity *= 2;
 1224|     87|    }
 1225|       |
 1226|       |    // every caller passes the address of an array element or on-stack struct, never NULL
 1227|       |    // NOLINTNEXTLINE(clang-analyzer-core.NonNullParamChecker)
 1228|  6.08k|    memcpy(&ext_list->list[idx].props, props, sizeof(*props));
 1229|  6.08k|    if (entrys) {
  ------------------
  |  Branch (1229:9): [True: 124, False: 5.95k]
  ------------------
 1230|    124|        ext_list->list[idx].entrypoints = *entrys;
 1231|    124|        should_free_entrys = false;
 1232|  5.95k|    } else {
 1233|  5.95k|        memset(&ext_list->list[idx].entrypoints, 0, sizeof(ext_list->list[idx].entrypoints));
 1234|  5.95k|    }
 1235|  6.08k|    ext_list->count++;
 1236|  6.38k|out:
 1237|  6.38k|    if (NULL != entrys && should_free_entrys) {
  ------------------
  |  Branch (1237:9): [True: 257, False: 6.12k]
  |  Branch (1237:27): [True: 133, False: 124]
  ------------------
 1238|    133|        free_string_list(inst, entrys);
 1239|    133|    }
 1240|  6.38k|    return res;
 1241|  6.08k|}
loader_layer_is_available:
 1300|  3.87k|                               const struct loader_layer_properties *prop) {
 1301|  3.87k|    bool available = true;
 1302|  3.87k|    bool is_implicit = (0 == (prop->type_flags & VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER));
 1303|  3.87k|    bool disabled_by_type =
 1304|  3.87k|        is_implicit ? filters->disable_filter.disable_all_implicit : filters->disable_filter.disable_all_explicit;
  ------------------
  |  Branch (1304:9): [True: 3.07k, False: 807]
  ------------------
 1305|  3.87k|    if ((filters->disable_filter.disable_all || disabled_by_type ||
  ------------------
  |  Branch (1305:10): [True: 0, False: 3.87k]
  |  Branch (1305:49): [True: 0, False: 3.87k]
  ------------------
 1306|  3.87k|         check_name_matches_filter_environment_var(prop->info.layerName, &filters->disable_filter.additional_filters)) &&
  ------------------
  |  Branch (1306:10): [True: 0, False: 3.87k]
  ------------------
 1307|      0|        !check_name_matches_filter_environment_var(prop->info.layerName, &filters->allow_filter)) {
  ------------------
  |  Branch (1307:9): [True: 0, False: 0]
  ------------------
 1308|      0|        available = false;
 1309|      0|    }
 1310|  3.87k|    if (check_name_matches_filter_environment_var(prop->info.layerName, &filters->enable_filter)) {
  ------------------
  |  Branch (1310:9): [True: 21, False: 3.85k]
  ------------------
 1311|     21|        available = true;
 1312|  3.85k|    } else if (!available) {
  ------------------
  |  Branch (1312:16): [True: 0, False: 3.85k]
  ------------------
 1313|      0|        loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 1314|      0|                   "Layer \"%s\" forced disabled because name matches filter of env var \'%s\'.", prop->info.layerName,
 1315|      0|                   VK_LAYERS_DISABLE_ENV_VAR);
  ------------------
  |  |  120|      0|#define VK_LAYERS_DISABLE_ENV_VAR "VK_LOADER_LAYERS_DISABLE"
  ------------------
 1316|      0|    }
 1317|       |
 1318|  3.87k|    return available;
 1319|  3.87k|}
loader_implicit_layer_is_enabled:
 1368|  15.1k|                                      const struct loader_layer_properties *prop) {
 1369|  15.1k|    bool enable = false;
 1370|  15.1k|    bool forced_disabled = false;
 1371|  15.1k|    bool forced_enabled = false;
 1372|       |
 1373|  15.1k|    if ((filters->disable_filter.disable_all || filters->disable_filter.disable_all_implicit ||
  ------------------
  |  Branch (1373:10): [True: 0, False: 15.1k]
  |  Branch (1373:49): [True: 0, False: 15.1k]
  ------------------
 1374|  15.1k|         check_name_matches_filter_environment_var(prop->info.layerName, &filters->disable_filter.additional_filters)) &&
  ------------------
  |  Branch (1374:10): [True: 0, False: 15.1k]
  ------------------
 1375|      0|        !check_name_matches_filter_environment_var(prop->info.layerName, &filters->allow_filter)) {
  ------------------
  |  Branch (1375:9): [True: 0, False: 0]
  ------------------
 1376|      0|        forced_disabled = true;
 1377|      0|    }
 1378|  15.1k|    if (check_name_matches_filter_environment_var(prop->info.layerName, &filters->enable_filter)) {
  ------------------
  |  Branch (1378:9): [True: 41, False: 15.1k]
  ------------------
 1379|     41|        forced_enabled = true;
 1380|     41|    }
 1381|       |
 1382|       |    // If no enable_environment variable is specified, this implicit layer is always be enabled by default.
 1383|  15.1k|    if (NULL == prop->enable_env_var.name) {
  ------------------
  |  Branch (1383:9): [True: 14.7k, False: 394]
  ------------------
 1384|  14.7k|        enable = true;
 1385|  14.7k|    } else {
 1386|    394|        char *env_value = loader_getenv(prop->enable_env_var.name, inst);
 1387|    394|        if (env_value && !strcmp(prop->enable_env_var.value, env_value)) {
  ------------------
  |  Branch (1387:13): [True: 218, False: 176]
  |  Branch (1387:26): [True: 0, False: 218]
  ------------------
 1388|      0|            enable = true;
 1389|      0|        }
 1390|       |
 1391|       |        // Otherwise, only enable this layer if the enable environment variable is defined
 1392|    394|        loader_free_getenv(env_value, inst);
 1393|    394|    }
 1394|       |
 1395|  15.1k|    if (forced_enabled) {
  ------------------
  |  Branch (1395:9): [True: 41, False: 15.1k]
  ------------------
 1396|       |        // Only report a message that we've forced on a layer if it wouldn't have been enabled
 1397|       |        // normally.
 1398|     41|        if (!enable) {
  ------------------
  |  Branch (1398:13): [True: 30, False: 11]
  ------------------
 1399|     30|            enable = true;
 1400|     30|            loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 1401|     30|                       "Implicit layer \"%s\" forced enabled due to env var \'%s\'.", prop->info.layerName,
 1402|     30|                       VK_LAYERS_ENABLE_ENV_VAR);
  ------------------
  |  |  119|     30|#define VK_LAYERS_ENABLE_ENV_VAR "VK_LOADER_LAYERS_ENABLE"
  ------------------
 1403|     30|        }
 1404|  15.1k|    } else if (enable && forced_disabled) {
  ------------------
  |  Branch (1404:16): [True: 14.7k, False: 364]
  |  Branch (1404:26): [True: 0, False: 14.7k]
  ------------------
 1405|      0|        enable = false;
 1406|       |        // Report a message that we've forced off a layer if it would have been enabled normally.
 1407|      0|        loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 1408|      0|                   "Implicit layer \"%s\" forced disabled because name matches filter of env var \'%s\'.", prop->info.layerName,
 1409|      0|                   VK_LAYERS_DISABLE_ENV_VAR);
  ------------------
  |  |  120|      0|#define VK_LAYERS_DISABLE_ENV_VAR "VK_LOADER_LAYERS_DISABLE"
  ------------------
 1410|      0|        return enable;
 1411|      0|    }
 1412|       |
 1413|       |    // The disable_environment has priority over everything else.  If it is defined, the layer is always
 1414|       |    // disabled.
 1415|  15.1k|    if (NULL != prop->disable_env_var.name) {
  ------------------
  |  Branch (1415:9): [True: 12.0k, False: 3.14k]
  ------------------
 1416|  12.0k|        char *env_value = loader_getenv(prop->disable_env_var.name, inst);
 1417|  12.0k|        if (NULL != env_value) {
  ------------------
  |  Branch (1417:13): [True: 58, False: 11.9k]
  ------------------
 1418|     58|            enable = false;
 1419|     58|        }
 1420|  12.0k|        loader_free_getenv(env_value, inst);
 1421|  12.0k|    } else if ((prop->type_flags & VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER) == 0) {
  ------------------
  |  Branch (1421:16): [True: 0, False: 3.14k]
  ------------------
 1422|      0|        loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 1423|      0|                   "Implicit layer \"%s\" missing disabled environment variable!", prop->info.layerName);
 1424|      0|    }
 1425|       |
 1426|       |    // Enable this layer if it is included in the override layer
 1427|  15.1k|    if (inst != NULL && inst->override_layer_present) {
  ------------------
  |  Branch (1427:9): [True: 0, False: 15.1k]
  |  Branch (1427:25): [True: 0, False: 0]
  ------------------
 1428|      0|        struct loader_layer_properties *override = NULL;
 1429|      0|        for (uint32_t i = 0; i < inst->instance_layer_list.count; ++i) {
  ------------------
  |  Branch (1429:30): [True: 0, False: 0]
  ------------------
 1430|      0|            if (strcmp(inst->instance_layer_list.list[i].info.layerName, VK_OVERRIDE_LAYER_NAME) == 0) {
  ------------------
  |  |  142|      0|#define VK_OVERRIDE_LAYER_NAME "VK_LAYER_LUNARG_override"
  ------------------
  |  Branch (1430:17): [True: 0, False: 0]
  ------------------
 1431|      0|                override = &inst->instance_layer_list.list[i];
 1432|      0|                break;
 1433|      0|            }
 1434|      0|        }
 1435|      0|        if (override != NULL) {
  ------------------
  |  Branch (1435:13): [True: 0, False: 0]
  ------------------
 1436|      0|            for (uint32_t i = 0; i < override->component_layer_names.count; ++i) {
  ------------------
  |  Branch (1436:34): [True: 0, False: 0]
  ------------------
 1437|      0|                if (strcmp(override->component_layer_names.list[i], prop->info.layerName) == 0) {
  ------------------
  |  Branch (1437:21): [True: 0, False: 0]
  ------------------
 1438|      0|                    enable = true;
 1439|      0|                    break;
 1440|      0|                }
 1441|      0|            }
 1442|      0|        }
 1443|      0|    }
 1444|       |
 1445|  15.1k|    return enable;
 1446|  15.1k|}
loader_initialize:
 2356|      2|void loader_initialize(void) {
 2357|      2|    loader_platform_thread_create_mutex(&loader_lock);
 2358|      2|    loader_platform_thread_create_mutex(&loader_preload_icd_lock);
 2359|      2|    init_global_loader_settings();
 2360|      2|#endif
 2361|       |
 2362|       |    // initialize logging
 2363|      2|    loader_init_global_debug_level();
 2364|       |#if defined(_WIN32)
 2365|       |    windows_initialization();
 2366|       |#endif
 2367|       |
 2368|      2|    loader_api_version version = loader_make_full_version(VK_HEADER_VERSION_COMPLETE);
 2369|      2|    loader_log(NULL, VULKAN_LOADER_INFO_BIT, 0, "Vulkan Loader Version %d.%d.%d", version.major, version.minor, version.patch);
 2370|       |
 2371|       |#if defined(GIT_BRANCH_NAME) && defined(GIT_TAG_INFO)
 2372|       |    loader_log(NULL, VULKAN_LOADER_INFO_BIT, 0, "[Vulkan Loader Git - Tag: " GIT_BRANCH_NAME ", Branch/Commit: " GIT_TAG_INFO "]");
 2373|       |#endif
 2374|       |
 2375|      2|    char *loader_disable_dynamic_library_unloading_env_var = loader_getenv("VK_LOADER_DISABLE_DYNAMIC_LIBRARY_UNLOADING", NULL);
 2376|      2|    if (loader_disable_dynamic_library_unloading_env_var &&
  ------------------
  |  Branch (2376:9): [True: 0, False: 2]
  ------------------
 2377|       |        // NOLINTNEXTLINE(bugprone-not-null-terminated-result) - n=2 intentionally excludes "1x" values like "10"
 2378|      0|        0 == strncmp(loader_disable_dynamic_library_unloading_env_var, "1", 2)) {
  ------------------
  |  Branch (2378:9): [True: 0, False: 0]
  ------------------
 2379|      0|        loader_disable_dynamic_library_unloading = true;
 2380|      0|        loader_log(NULL, VULKAN_LOADER_WARN_BIT, 0, "Vulkan Loader: library unloading is disabled");
 2381|      2|    } else {
 2382|      2|        loader_disable_dynamic_library_unloading = false;
 2383|      2|    }
 2384|      2|    loader_free_getenv(loader_disable_dynamic_library_unloading_env_var, NULL);
 2385|       |#if defined(LOADER_USE_UNSAFE_FILE_SEARCH)
 2386|       |    loader_log(NULL, VULKAN_LOADER_WARN_BIT, 0, "Vulkan Loader: unsafe searching is enabled");
 2387|       |#endif
 2388|       |#if defined(_WIN32)
 2389|       |    return TRUE;
 2390|       |#endif
 2391|      2|}
loader_init_library:
 2428|      2|__attribute__((constructor)) void loader_init_library(void) { loader_initialize(); }
loader_get_next_path:
 2439|   159k|char *loader_get_next_path(char *path) {
 2440|   159k|    uint32_t len;
 2441|   159k|    char *next;
 2442|       |
 2443|   159k|    if (path == NULL) return NULL;
  ------------------
  |  Branch (2443:9): [True: 0, False: 159k]
  ------------------
 2444|   159k|    next = strchr(path, PATH_SEPARATOR);
  ------------------
  |  |  154|   159k|#define PATH_SEPARATOR ':'
  ------------------
 2445|   159k|    if (next == NULL) {
  ------------------
  |  Branch (2445:9): [True: 159k, False: 0]
  ------------------
 2446|   159k|        len = (uint32_t)strlen(path);
 2447|   159k|        next = path + len;
 2448|   159k|    } else {
 2449|      0|        *next = '\0';
 2450|      0|        next++;
 2451|      0|    }
 2452|       |
 2453|   159k|    return next;
 2454|   159k|}
combine_manifest_directory_and_library_path:
 2464|  10.3k|                                                     const char *manifest_file_path, char **out_fullpath) {
 2465|  10.3k|    assert(library_path && manifest_file_path && out_fullpath);
 2466|  10.3k|    if (loader_platform_is_path_absolute(library_path)) {
  ------------------
  |  Branch (2466:9): [True: 169, False: 10.2k]
  ------------------
 2467|    169|        *out_fullpath = library_path;
 2468|    169|        return VK_SUCCESS;
 2469|    169|    }
 2470|  10.2k|    VkResult res = VK_SUCCESS;
 2471|       |
 2472|  10.2k|    size_t library_path_len = strlen(library_path);
 2473|  10.2k|    size_t manifest_file_path_str_len = strlen(manifest_file_path);
 2474|  10.2k|    bool library_path_contains_directory_symbol = false;
 2475|  1.83M|    for (size_t i = 0; i < library_path_len; i++) {
  ------------------
  |  Branch (2475:24): [True: 1.83M, False: 4.18k]
  ------------------
 2476|  1.83M|        if (library_path[i] == DIRECTORY_SYMBOL) {
  ------------------
  |  |  155|  1.83M|#define DIRECTORY_SYMBOL '/'
  ------------------
  |  Branch (2476:13): [True: 6.03k, False: 1.82M]
  ------------------
 2477|  6.03k|            library_path_contains_directory_symbol = true;
 2478|  6.03k|            break;
 2479|  6.03k|        }
 2480|  1.83M|    }
 2481|       |    // Means that the library_path is neither absolute nor relative - thus we should not modify it at all
 2482|  10.2k|    if (!library_path_contains_directory_symbol) {
  ------------------
  |  Branch (2482:9): [True: 4.18k, False: 6.03k]
  ------------------
 2483|  4.18k|        *out_fullpath = library_path;
 2484|  4.18k|        return VK_SUCCESS;
 2485|  4.18k|    }
 2486|       |    // must include both a directory symbol and the null terminator
 2487|  6.03k|    size_t new_str_len = library_path_len + manifest_file_path_str_len + 1 + 1;
 2488|       |
 2489|  6.03k|    *out_fullpath = loader_instance_heap_calloc(inst, new_str_len, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
 2490|  6.03k|    if (NULL == *out_fullpath) {
  ------------------
  |  Branch (2490:9): [True: 0, False: 6.03k]
  ------------------
 2491|      0|        res = VK_ERROR_OUT_OF_HOST_MEMORY;
 2492|      0|        goto out;
 2493|      0|    }
 2494|  6.03k|    size_t cur_loc_in_out_fullpath = 0;
 2495|       |    // look for the last occurrence of DIRECTORY_SYMBOL in manifest_file_path
 2496|  6.03k|    size_t last_directory_symbol = 0;
 2497|  6.03k|    bool found_directory_symbol = false;
 2498|   318k|    for (size_t i = 0; i < manifest_file_path_str_len; i++) {
  ------------------
  |  Branch (2498:24): [True: 312k, False: 6.03k]
  ------------------
 2499|   312k|        if (manifest_file_path[i] == DIRECTORY_SYMBOL) {
  ------------------
  |  |  155|   312k|#define DIRECTORY_SYMBOL '/'
  ------------------
  |  Branch (2499:13): [True: 16.2k, False: 296k]
  ------------------
 2500|  16.2k|            last_directory_symbol = i + 1;  // we want to include the symbol
 2501|  16.2k|            found_directory_symbol = true;
 2502|       |            // dont break because we want to find the last occurrence
 2503|  16.2k|        }
 2504|   312k|    }
 2505|       |    // Add manifest_file_path up to the last directory symbol
 2506|  6.03k|    if (found_directory_symbol) {
  ------------------
  |  Branch (2506:9): [True: 5.41k, False: 620]
  ------------------
 2507|  5.41k|        loader_strncpy(*out_fullpath, new_str_len, manifest_file_path, last_directory_symbol);
 2508|  5.41k|        cur_loc_in_out_fullpath += last_directory_symbol;
 2509|  5.41k|    }
 2510|  6.03k|    loader_strncpy(&(*out_fullpath)[cur_loc_in_out_fullpath], new_str_len - cur_loc_in_out_fullpath, library_path,
 2511|  6.03k|                   library_path_len);
 2512|  6.03k|    cur_loc_in_out_fullpath += library_path_len + 1;
 2513|  6.03k|    (*out_fullpath)[cur_loc_in_out_fullpath] = '\0';
 2514|       |
 2515|  6.03k|out:
 2516|  6.03k|    loader_instance_heap_free(inst, library_path);
 2517|       |
 2518|  6.03k|    return res;
 2519|  6.03k|}
loader_get_fullpath:
 2525|  41.6k|void loader_get_fullpath(const char *file, const char *in_dirs, size_t out_size, char *out_fullpath) {
 2526|  41.6k|    if (!loader_platform_is_path(file) && *in_dirs) {
  ------------------
  |  Branch (2526:9): [True: 41.4k, False: 132]
  |  Branch (2526:43): [True: 41.4k, False: 0]
  ------------------
 2527|  41.4k|        size_t dirs_copy_len = strlen(in_dirs) + 1;
 2528|  41.4k|        char *dirs_copy = loader_stack_alloc(dirs_copy_len);
  ------------------
  |  |   42|  41.4k|#define loader_stack_alloc(size) alloca(size)
  ------------------
 2529|  41.4k|        loader_strncpy(dirs_copy, dirs_copy_len, in_dirs, dirs_copy_len);
 2530|       |
 2531|       |        // find if file exists after prepending paths in given list
 2532|       |        // for (dir = dirs_copy; *dir && (next_dir = loader_get_next_path(dir)); dir = next_dir) {
 2533|  41.4k|        char *dir = dirs_copy;
 2534|  41.4k|        char *next_dir = loader_get_next_path(dir);
 2535|  42.7k|        while (*dir && next_dir) {
  ------------------
  |  Branch (2535:16): [True: 41.4k, False: 1.23k]
  |  Branch (2535:24): [True: 41.4k, False: 0]
  ------------------
 2536|  41.4k|            int path_concat_ret = snprintf(out_fullpath, out_size, "%s%c%s", dir, DIRECTORY_SYMBOL, file);
  ------------------
  |  |  155|  41.4k|#define DIRECTORY_SYMBOL '/'
  ------------------
 2537|  41.4k|            if (path_concat_ret < 0) {
  ------------------
  |  Branch (2537:17): [True: 0, False: 41.4k]
  ------------------
 2538|      0|                continue;
 2539|      0|            }
 2540|  41.4k|            if (loader_platform_file_exists(out_fullpath)) {
  ------------------
  |  Branch (2540:17): [True: 40.2k, False: 1.23k]
  ------------------
 2541|  40.2k|                return;
 2542|  40.2k|            }
 2543|  1.23k|            dir = next_dir;
 2544|  1.23k|            next_dir = loader_get_next_path(dir);
 2545|  1.23k|        }
 2546|  41.4k|    }
 2547|       |
 2548|  1.36k|    (void)snprintf(out_fullpath, out_size, "%s", file);
 2549|  1.36k|}
verify_meta_layer_component_layers:
 2556|  24.6k|                                        struct loader_layer_list *instance_layers, bool *already_checked_meta_layers) {
 2557|  24.6k|    struct loader_layer_properties *prop = &instance_layers->list[prop_index];
 2558|  24.6k|    loader_api_version meta_layer_version = loader_make_version(prop->info.specVersion);
 2559|       |
 2560|  24.6k|    if (NULL == already_checked_meta_layers) {
  ------------------
  |  Branch (2560:9): [True: 22.8k, False: 1.78k]
  ------------------
 2561|  22.8k|        already_checked_meta_layers = loader_stack_alloc(sizeof(bool) * instance_layers->count);
  ------------------
  |  |   42|  22.8k|#define loader_stack_alloc(size) alloca(size)
  ------------------
 2562|  22.8k|        if (already_checked_meta_layers == NULL) {
  ------------------
  |  Branch (2562:13): [True: 0, False: 22.8k]
  ------------------
 2563|      0|            return false;
 2564|      0|        }
 2565|  22.8k|        memset(already_checked_meta_layers, 0, sizeof(bool) * instance_layers->count);
 2566|  22.8k|    }
 2567|       |
 2568|       |    // Mark this meta layer as 'already checked', indicating which layers have already been recursed.
 2569|  24.6k|    already_checked_meta_layers[prop_index] = true;
 2570|       |
 2571|  26.0k|    for (uint32_t comp_layer = 0; comp_layer < prop->component_layer_names.count; comp_layer++) {
  ------------------
  |  Branch (2571:35): [True: 4.61k, False: 21.4k]
  ------------------
 2572|  4.61k|        struct loader_layer_properties *comp_prop =
 2573|  4.61k|            loader_find_layer_property(prop->component_layer_names.list[comp_layer], instance_layers);
 2574|  4.61k|        if (comp_prop == NULL) {
  ------------------
  |  Branch (2574:13): [True: 1.79k, False: 2.81k]
  ------------------
 2575|  1.79k|            loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2576|  1.79k|                       "verify_meta_layer_component_layers: Meta-layer %s can't find component layer %s at index %d."
 2577|  1.79k|                       "  Skipping this layer.",
 2578|  1.79k|                       prop->info.layerName, prop->component_layer_names.list[comp_layer], comp_layer);
 2579|       |
 2580|  1.79k|            return false;
 2581|  1.79k|        }
 2582|       |
 2583|       |        // Check the version of each layer, they need to be at least MAJOR and MINOR
 2584|  2.81k|        loader_api_version comp_prop_version = loader_make_version(comp_prop->info.specVersion);
 2585|  2.81k|        if (!loader_check_version_meets_required(meta_layer_version, comp_prop_version)) {
  ------------------
  |  Branch (2585:13): [True: 313, False: 2.50k]
  ------------------
 2586|    313|            loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2587|    313|                       "verify_meta_layer_component_layers: Meta-layer uses API version %d.%d, but component "
 2588|    313|                       "layer %d has API version %d.%d that is lower.  Skipping this layer.",
 2589|    313|                       meta_layer_version.major, meta_layer_version.minor, comp_layer, comp_prop_version.major,
 2590|    313|                       comp_prop_version.minor);
 2591|       |
 2592|    313|            return false;
 2593|    313|        }
 2594|       |
 2595|       |        // Make sure the layer isn't using it's own name
 2596|  2.50k|        if (!strcmp(prop->info.layerName, prop->component_layer_names.list[comp_layer])) {
  ------------------
  |  Branch (2596:13): [True: 151, False: 2.35k]
  ------------------
 2597|    151|            loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2598|    151|                       "verify_meta_layer_component_layers: Meta-layer %s lists itself in its component layer "
 2599|    151|                       "list at index %d.  Skipping this layer.",
 2600|    151|                       prop->info.layerName, comp_layer);
 2601|       |
 2602|    151|            return false;
 2603|    151|        }
 2604|  2.35k|        if (comp_prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER) {
  ------------------
  |  Branch (2604:13): [True: 1.99k, False: 353]
  ------------------
 2605|  1.99k|            size_t comp_prop_index = INT32_MAX;
 2606|       |            // Make sure we haven't verified this meta layer before
 2607|   698k|            for (uint32_t i = 0; i < instance_layers->count; i++) {
  ------------------
  |  Branch (2607:34): [True: 696k, False: 1.99k]
  ------------------
 2608|   696k|                if (strcmp(comp_prop->info.layerName, instance_layers->list[i].info.layerName) == 0) {
  ------------------
  |  Branch (2608:21): [True: 44.0k, False: 652k]
  ------------------
 2609|  44.0k|                    comp_prop_index = i;
 2610|  44.0k|                }
 2611|   696k|            }
 2612|  1.99k|            if (comp_prop_index != INT32_MAX && already_checked_meta_layers[comp_prop_index]) {
  ------------------
  |  Branch (2612:17): [True: 1.99k, False: 0]
  |  Branch (2612:49): [True: 214, False: 1.78k]
  ------------------
 2613|    214|                loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2614|    214|                           "verify_meta_layer_component_layers: Recursive dependency between Meta-layer %s and  Meta-layer %s.  "
 2615|    214|                           "Skipping this layer.",
 2616|    214|                           instance_layers->list[prop_index].info.layerName, comp_prop->info.layerName);
 2617|    214|                return false;
 2618|    214|            }
 2619|       |
 2620|  1.78k|            loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
 2621|  1.78k|                       "verify_meta_layer_component_layers: Adding meta-layer %s which also contains meta-layer %s",
 2622|  1.78k|                       prop->info.layerName, comp_prop->info.layerName);
 2623|       |
 2624|       |            // Make sure if the layer is using a meta-layer in its component list that we also verify that.
 2625|  1.78k|            if (!verify_meta_layer_component_layers(inst, comp_prop_index, instance_layers, already_checked_meta_layers)) {
  ------------------
  |  Branch (2625:17): [True: 728, False: 1.05k]
  ------------------
 2626|    728|                loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2627|    728|                           "Meta-layer %s component layer %s can not find all component layers."
 2628|    728|                           "  Skipping this layer.",
 2629|    728|                           prop->info.layerName, prop->component_layer_names.list[comp_layer]);
 2630|    728|                return false;
 2631|    728|            }
 2632|  1.78k|        }
 2633|  2.35k|    }
 2634|       |    // Didn't exit early so that means it passed all checks
 2635|  21.4k|    loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 2636|  21.4k|               "Meta-layer \"%s\" all %d component layers appear to be valid.", prop->info.layerName,
 2637|  21.4k|               prop->component_layer_names.count);
 2638|       |
 2639|       |    // If layer logging is on, list the internals included in the meta-layer
 2640|  22.6k|    for (uint32_t comp_layer = 0; comp_layer < prop->component_layer_names.count; comp_layer++) {
  ------------------
  |  Branch (2640:35): [True: 1.28k, False: 21.4k]
  ------------------
 2641|  1.28k|        loader_log(inst, VULKAN_LOADER_LAYER_BIT, 0, "  [%d] %s", comp_layer, prop->component_layer_names.list[comp_layer]);
 2642|  1.28k|    }
 2643|       |    return true;
 2644|  24.6k|}
update_meta_layer_extensions_from_component_layers:
 2650|  20.3k|                                                            struct loader_layer_list *instance_layers) {
 2651|  20.3k|    VkResult res = VK_SUCCESS;
 2652|  21.4k|    for (uint32_t comp_layer = 0; comp_layer < prop->component_layer_names.count; comp_layer++) {
  ------------------
  |  Branch (2652:35): [True: 1.08k, False: 20.3k]
  ------------------
 2653|  1.08k|        struct loader_layer_properties *comp_prop =
 2654|  1.08k|            loader_find_layer_property(prop->component_layer_names.list[comp_layer], instance_layers);
 2655|       |
 2656|  1.08k|        if (NULL != comp_prop->instance_extension_list.list) {
  ------------------
  |  Branch (2656:13): [True: 230, False: 853]
  ------------------
 2657|  3.35k|            for (uint32_t ext = 0; ext < comp_prop->instance_extension_list.count; ext++) {
  ------------------
  |  Branch (2657:36): [True: 3.12k, False: 230]
  ------------------
 2658|  3.12k|                loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Meta-layer %s component layer %s adding instance extension %s",
 2659|  3.12k|                           prop->info.layerName, prop->component_layer_names.list[comp_layer],
 2660|  3.12k|                           comp_prop->instance_extension_list.list[ext].extensionName);
 2661|       |
 2662|  3.12k|                if (!has_vk_extension_property(&comp_prop->instance_extension_list.list[ext], &prop->instance_extension_list)) {
  ------------------
  |  Branch (2662:21): [True: 2.89k, False: 228]
  ------------------
 2663|  2.89k|                    res = loader_add_to_ext_list(inst, &prop->instance_extension_list, 1,
 2664|  2.89k|                                                 &comp_prop->instance_extension_list.list[ext]);
 2665|  2.89k|                    if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
  ------------------
  |  Branch (2665:25): [True: 0, False: 2.89k]
  ------------------
 2666|      0|                        return res;
 2667|      0|                    }
 2668|  2.89k|                }
 2669|  3.12k|            }
 2670|    230|        }
 2671|  1.08k|        if (NULL != comp_prop->device_extension_list.list) {
  ------------------
  |  Branch (2671:13): [True: 321, False: 762]
  ------------------
 2672|  4.71k|            for (uint32_t ext = 0; ext < comp_prop->device_extension_list.count; ext++) {
  ------------------
  |  Branch (2672:36): [True: 4.39k, False: 321]
  ------------------
 2673|  4.39k|                loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Meta-layer %s component layer %s adding device extension %s",
 2674|  4.39k|                           prop->info.layerName, prop->component_layer_names.list[comp_layer],
 2675|  4.39k|                           comp_prop->device_extension_list.list[ext].props.extensionName);
 2676|       |
 2677|  4.39k|                if (!has_vk_dev_ext_property(&comp_prop->device_extension_list.list[ext].props, &prop->device_extension_list)) {
  ------------------
  |  Branch (2677:21): [True: 2.97k, False: 1.42k]
  ------------------
 2678|  2.97k|                    res = loader_add_to_dev_ext_list(inst, &prop->device_extension_list,
 2679|  2.97k|                                                     &comp_prop->device_extension_list.list[ext].props, NULL);
 2680|  2.97k|                    if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
  ------------------
  |  Branch (2680:25): [True: 0, False: 2.97k]
  ------------------
 2681|      0|                        return res;
 2682|      0|                    }
 2683|  2.97k|                }
 2684|  4.39k|            }
 2685|    321|        }
 2686|  1.08k|    }
 2687|  20.3k|    return res;
 2688|  20.3k|}
verify_all_meta_layers:
 2692|  10.0k|                                struct loader_layer_list *instance_layers, bool *override_layer_present) {
 2693|  10.0k|    VkResult res = VK_SUCCESS;
 2694|  10.0k|    *override_layer_present = false;
 2695|  42.1k|    for (int32_t i = 0; i < (int32_t)instance_layers->count; i++) {
  ------------------
  |  Branch (2695:25): [True: 32.1k, False: 10.0k]
  ------------------
 2696|  32.1k|        struct loader_layer_properties *prop = &instance_layers->list[i];
 2697|       |
 2698|       |        // If this is a meta-layer, make sure it is valid
 2699|  32.1k|        if (prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER) {
  ------------------
  |  Branch (2699:13): [True: 22.8k, False: 9.27k]
  ------------------
 2700|  22.8k|            if (verify_meta_layer_component_layers(inst, i, instance_layers, NULL)) {
  ------------------
  |  Branch (2700:17): [True: 20.3k, False: 2.47k]
  ------------------
 2701|       |                // If any meta layer is valid, update its extension list to include the extensions from its component layers.
 2702|  20.3k|                res = update_meta_layer_extensions_from_component_layers(inst, prop, instance_layers);
 2703|  20.3k|                if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
  ------------------
  |  Branch (2703:21): [True: 0, False: 20.3k]
  ------------------
 2704|      0|                    return res;
 2705|      0|                }
 2706|  20.3k|                if (prop->is_override && loader_implicit_layer_is_enabled(inst, filters, prop)) {
  ------------------
  |  Branch (2706:21): [True: 1.90k, False: 18.4k]
  |  Branch (2706:42): [True: 1.88k, False: 21]
  ------------------
 2707|  1.88k|                    *override_layer_present = true;
 2708|  1.88k|                }
 2709|  20.3k|            } else {
 2710|  2.47k|                loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0,
 2711|  2.47k|                           "Removing meta-layer %s from instance layer list since it appears invalid.", prop->info.layerName);
 2712|       |
 2713|  2.47k|                loader_remove_layer_in_list(inst, instance_layers, i);
 2714|  2.47k|                i--;
 2715|  2.47k|            }
 2716|  22.8k|        }
 2717|  32.1k|    }
 2718|  10.0k|    return res;
 2719|  10.0k|}
remove_all_non_valid_override_layers:
 2723|  10.0k|void remove_all_non_valid_override_layers(struct loader_instance *inst, struct loader_layer_list *instance_layers) {
 2724|  10.0k|    if (instance_layers == NULL) {
  ------------------
  |  Branch (2724:9): [True: 0, False: 10.0k]
  ------------------
 2725|      0|        return;
 2726|      0|    }
 2727|       |
 2728|  10.0k|    char cur_path[1024];
 2729|  10.0k|    char *ret = loader_platform_executable_path(cur_path, 1024);
 2730|  10.0k|    if (NULL == ret) {
  ------------------
  |  Branch (2730:9): [True: 0, False: 10.0k]
  ------------------
 2731|      0|        return;
 2732|      0|    }
 2733|       |    // Find out if there is an override layer with same the app_key_path as the path to the current executable.
 2734|       |    // If more than one is found, remove it and use the first layer
 2735|       |    // Remove any layers which aren't global and do not have the same app_key_path as the path to the current executable.
 2736|  10.0k|    bool found_active_override_layer = false;
 2737|  10.0k|    int global_layer_index = -1;
 2738|  26.8k|    for (uint32_t i = 0; i < instance_layers->count; i++) {
  ------------------
  |  Branch (2738:26): [True: 16.7k, False: 10.0k]
  ------------------
 2739|  16.7k|        struct loader_layer_properties *props = &instance_layers->list[i];
 2740|  16.7k|        if (strcmp(props->info.layerName, VK_OVERRIDE_LAYER_NAME) == 0) {
  ------------------
  |  |  142|  16.7k|#define VK_OVERRIDE_LAYER_NAME "VK_LAYER_LUNARG_override"
  ------------------
  |  Branch (2740:13): [True: 2.59k, False: 14.1k]
  ------------------
 2741|  2.59k|            if (props->app_key_paths.count > 0) {  // not the global layer
  ------------------
  |  Branch (2741:17): [True: 230, False: 2.36k]
  ------------------
 2742|  14.3k|                for (uint32_t j = 0; j < props->app_key_paths.count; j++) {
  ------------------
  |  Branch (2742:38): [True: 14.1k, False: 230]
  ------------------
 2743|  14.1k|                    if (strcmp(props->app_key_paths.list[j], cur_path) == 0) {
  ------------------
  |  Branch (2743:25): [True: 0, False: 14.1k]
  ------------------
 2744|      0|                        if (!found_active_override_layer) {
  ------------------
  |  Branch (2744:29): [True: 0, False: 0]
  ------------------
 2745|      0|                            found_active_override_layer = true;
 2746|      0|                        } else {
 2747|      0|                            loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 2748|      0|                                       "remove_all_non_valid_override_layers: Multiple override layers where the same path in "
 2749|      0|                                       "app_keys "
 2750|      0|                                       "was found. Using the first layer found");
 2751|       |
 2752|       |                            // Remove duplicate active override layers that have the same app_key_path
 2753|      0|                            loader_remove_layer_in_list(inst, instance_layers, i);
 2754|      0|                            i--;
 2755|      0|                        }
 2756|      0|                    }
 2757|  14.1k|                }
 2758|    230|                if (!found_active_override_layer) {
  ------------------
  |  Branch (2758:21): [True: 230, False: 0]
  ------------------
 2759|    230|                    loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 2760|    230|                               "--Override layer found but not used because app \'%s\' is not in \'app_keys\' list!", cur_path);
 2761|       |
 2762|       |                    // Remove non-global override layers that don't have an app_key that matches cur_path
 2763|    230|                    loader_remove_layer_in_list(inst, instance_layers, i);
 2764|    230|                    i--;
 2765|    230|                }
 2766|  2.36k|            } else {
 2767|  2.36k|                if (global_layer_index == -1) {
  ------------------
  |  Branch (2767:21): [True: 700, False: 1.66k]
  ------------------
 2768|    700|                    global_layer_index = (int)i;
 2769|  1.66k|                } else {
 2770|  1.66k|                    loader_log(
 2771|  1.66k|                        inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 2772|  1.66k|                        "remove_all_non_valid_override_layers: Multiple global override layers found. Using the first global "
 2773|  1.66k|                        "layer found");
 2774|  1.66k|                    loader_remove_layer_in_list(inst, instance_layers, i);
 2775|  1.66k|                    i--;
 2776|  1.66k|                }
 2777|  2.36k|            }
 2778|  2.59k|        }
 2779|  16.7k|    }
 2780|       |    // Remove global layer if layer with same the app_key_path as the path to the current executable is found
 2781|  10.0k|    if (found_active_override_layer && global_layer_index >= 0) {
  ------------------
  |  Branch (2781:9): [True: 0, False: 10.0k]
  |  Branch (2781:40): [True: 0, False: 0]
  ------------------
 2782|      0|        loader_remove_layer_in_list(inst, instance_layers, global_layer_index);
 2783|      0|    }
 2784|       |    // Should be at most 1 override layer in the list now.
 2785|  10.0k|    if (found_active_override_layer) {
  ------------------
  |  Branch (2785:9): [True: 0, False: 10.0k]
  ------------------
 2786|      0|        loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0, "Using the override layer for app key %s", cur_path);
 2787|  10.0k|    } else if (global_layer_index >= 0) {
  ------------------
  |  Branch (2787:16): [True: 700, False: 9.33k]
  ------------------
 2788|    700|        loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0, "Using the global override layer");
 2789|    700|    }
 2790|  10.0k|}
loader_read_layer_json:
 2804|  93.8k|                                cJSON *layer_node, loader_api_version version, bool is_implicit, char *filename) {
 2805|  93.8k|    assert(layer_instance_list);
 2806|  93.8k|    char *library_path = NULL;
 2807|  93.8k|    VkResult result = VK_SUCCESS;
 2808|  93.8k|    struct loader_layer_properties props = {0};
 2809|       |
 2810|  93.8k|    result = loader_copy_to_new_str(inst, filename, &props.manifest_file_name);
 2811|  93.8k|    if (result == VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (2811:9): [True: 0, False: 93.8k]
  ------------------
 2812|      0|        goto out;
 2813|      0|    }
 2814|       |
 2815|       |    // Parse name
 2816|       |
 2817|  93.8k|    result = loader_parse_json_string_to_existing_str(layer_node, "name", VK_MAX_EXTENSION_NAME_SIZE, props.info.layerName);
 2818|  93.8k|    if (VK_ERROR_INITIALIZATION_FAILED == result) {
  ------------------
  |  Branch (2818:9): [True: 9.32k, False: 84.5k]
  ------------------
 2819|  9.32k|        loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2820|  9.32k|                   "Layer located at %s didn't find required layer value \"name\" in manifest JSON file, skipping this layer",
 2821|  9.32k|                   filename);
 2822|  9.32k|        goto out;
 2823|  9.32k|    }
 2824|       |
 2825|       |    // Check if this layer's name matches the override layer name, set is_override to true if so.
 2826|  84.5k|    if (!strcmp(props.info.layerName, VK_OVERRIDE_LAYER_NAME)) {
  ------------------
  |  |  142|  84.5k|#define VK_OVERRIDE_LAYER_NAME "VK_LAYER_LUNARG_override"
  ------------------
  |  Branch (2826:9): [True: 4.33k, False: 80.1k]
  ------------------
 2827|  4.33k|        props.is_override = true;
 2828|  4.33k|    }
 2829|       |
 2830|  84.5k|    if (0 != strncmp(props.info.layerName, "VK_LAYER_", 9)) {
  ------------------
  |  Branch (2830:9): [True: 79.0k, False: 5.46k]
  ------------------
 2831|  79.0k|        loader_log(inst, VULKAN_LOADER_WARN_BIT, 0, "Layer name %s does not conform to naming standard (Policy #LLP_LAYER_3)",
 2832|  79.0k|                   props.info.layerName);
 2833|  79.0k|    }
 2834|       |
 2835|       |    // Parse type
 2836|  84.5k|    char *type = loader_cJSON_GetStringValue(loader_cJSON_GetObjectItem(layer_node, "type"));
 2837|  84.5k|    if (NULL == type) {
  ------------------
  |  Branch (2837:9): [True: 2.72k, False: 81.7k]
  ------------------
 2838|  2.72k|        loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2839|  2.72k|                   "Layer located at %s didn't find required layer value \"type\" in manifest JSON file, skipping this layer",
 2840|  2.72k|                   filename);
 2841|  2.72k|        result = VK_ERROR_INITIALIZATION_FAILED;
 2842|  2.72k|        goto out;
 2843|  2.72k|    }
 2844|       |
 2845|       |    // Add list entry
 2846|  81.7k|    if (!strcmp(type, "DEVICE")) {
  ------------------
  |  Branch (2846:9): [True: 57, False: 81.7k]
  ------------------
 2847|     57|        loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0, "Device layers are deprecated. Skipping layer %s",
 2848|     57|                   props.info.layerName);
 2849|     57|        result = VK_ERROR_INITIALIZATION_FAILED;
 2850|     57|        goto out;
 2851|     57|    }
 2852|       |
 2853|       |    // Allow either GLOBAL or INSTANCE type interchangeably to handle layers that must work with older loaders
 2854|  81.7k|    if (!strcmp(type, "INSTANCE") || !strcmp(type, "GLOBAL")) {
  ------------------
  |  Branch (2854:9): [True: 33.8k, False: 47.8k]
  |  Branch (2854:38): [True: 46.0k, False: 1.86k]
  ------------------
 2855|  79.8k|        props.type_flags = VK_LAYER_TYPE_FLAG_INSTANCE_LAYER;
 2856|  79.8k|        if (!is_implicit) {
  ------------------
  |  Branch (2856:13): [True: 30.7k, False: 49.0k]
  ------------------
 2857|  30.7k|            props.type_flags |= VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER;
 2858|  30.7k|        }
 2859|  79.8k|    } else {
 2860|  1.86k|        result = VK_ERROR_INITIALIZATION_FAILED;
 2861|  1.86k|        goto out;
 2862|  1.86k|    }
 2863|       |
 2864|       |    // Parse api_version
 2865|  79.8k|    char *api_version = loader_cJSON_GetStringValue(loader_cJSON_GetObjectItem(layer_node, "api_version"));
 2866|  79.8k|    if (NULL == api_version) {
  ------------------
  |  Branch (2866:9): [True: 38.4k, False: 41.3k]
  ------------------
 2867|  38.4k|        loader_log(
 2868|  38.4k|            inst, VULKAN_LOADER_WARN_BIT, 0,
 2869|  38.4k|            "Layer located at %s didn't find required layer value \"api_version\" in manifest JSON file, skipping this layer",
 2870|  38.4k|            filename);
 2871|  38.4k|        result = VK_ERROR_INITIALIZATION_FAILED;
 2872|  38.4k|        goto out;
 2873|  38.4k|    }
 2874|       |
 2875|  41.3k|    props.info.specVersion = loader_parse_version_string(api_version);
 2876|       |
 2877|       |    // Make sure the layer's manifest doesn't contain a non zero variant value
 2878|  41.3k|    if (VK_API_VERSION_VARIANT(props.info.specVersion) != 0) {
  ------------------
  |  Branch (2878:9): [True: 160, False: 41.2k]
  ------------------
 2879|    160|        loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 2880|    160|                   "Layer \"%s\" has an \'api_version\' field which contains a non-zero variant value of %d. "
 2881|    160|                   " Skipping Layer.",
 2882|    160|                   props.info.layerName, VK_API_VERSION_VARIANT(props.info.specVersion));
 2883|    160|        result = VK_ERROR_INITIALIZATION_FAILED;
 2884|    160|        goto out;
 2885|    160|    }
 2886|       |
 2887|       |    // Parse implementation_version
 2888|  41.2k|    char *implementation_version = loader_cJSON_GetStringValue(loader_cJSON_GetObjectItem(layer_node, "implementation_version"));
 2889|  41.2k|    if (NULL == implementation_version) {
  ------------------
  |  Branch (2889:9): [True: 1.28k, False: 39.9k]
  ------------------
 2890|  1.28k|        loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2891|  1.28k|                   "Layer located at %s didn't find required layer value \"implementation_version\" in manifest JSON file, "
 2892|  1.28k|                   "skipping this layer",
 2893|  1.28k|                   filename);
 2894|  1.28k|        result = VK_ERROR_INITIALIZATION_FAILED;
 2895|  1.28k|        goto out;
 2896|  1.28k|    }
 2897|  39.9k|    props.info.implementationVersion = (uint32_t)strtoul(implementation_version, NULL, 10);
 2898|       |
 2899|       |    // Parse description
 2900|       |
 2901|  39.9k|    result = loader_parse_json_string_to_existing_str(layer_node, "description", VK_MAX_DESCRIPTION_SIZE, props.info.description);
 2902|  39.9k|    if (VK_ERROR_INITIALIZATION_FAILED == result) {
  ------------------
  |  Branch (2902:9): [True: 630, False: 39.2k]
  ------------------
 2903|    630|        loader_log(
 2904|    630|            inst, VULKAN_LOADER_WARN_BIT, 0,
 2905|    630|            "Layer located at %s didn't find required layer value \"description\" in manifest JSON file, skipping this layer",
 2906|    630|            filename);
 2907|    630|        goto out;
 2908|    630|    }
 2909|       |
 2910|       |    // Parse library_path
 2911|       |
 2912|       |    // Library path no longer required unless component_layers is also not defined
 2913|  39.2k|    result = loader_parse_json_string(layer_node, "library_path", &library_path);
 2914|  39.2k|    if (result == VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (2914:9): [True: 0, False: 39.2k]
  ------------------
 2915|      0|        loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2916|      0|                   "Skipping layer \"%s\" due to problem accessing the library_path value in the manifest JSON file",
 2917|      0|                   props.info.layerName);
 2918|      0|        result = VK_ERROR_OUT_OF_HOST_MEMORY;
 2919|      0|        goto out;
 2920|      0|    }
 2921|  39.2k|    if (NULL != library_path) {
  ------------------
  |  Branch (2921:9): [True: 10.4k, False: 28.8k]
  ------------------
 2922|  10.4k|        if (NULL != loader_cJSON_GetObjectItem(layer_node, "component_layers")) {
  ------------------
  |  Branch (2922:13): [True: 28, False: 10.3k]
  ------------------
 2923|     28|            loader_log(
 2924|     28|                inst, VULKAN_LOADER_WARN_BIT, 0,
 2925|     28|                "Layer \"%s\" contains meta-layer-specific component_layers, but also defining layer library path.  Both are not "
 2926|     28|                "compatible, so skipping this layer",
 2927|     28|                props.info.layerName);
 2928|     28|            result = VK_ERROR_INITIALIZATION_FAILED;
 2929|     28|            loader_instance_heap_free(inst, library_path);
 2930|     28|            goto out;
 2931|     28|        }
 2932|       |
 2933|       |        // This function takes ownership of library_path_str - so we don't need to clean it up
 2934|  10.3k|        result = combine_manifest_directory_and_library_path(inst, library_path, filename, &props.lib_name);
 2935|  10.3k|        if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (2935:13): [True: 0, False: 10.3k]
  ------------------
 2936|  10.3k|    }
 2937|       |
 2938|       |    // Parse component_layers
 2939|       |
 2940|  39.2k|    if (NULL == library_path) {
  ------------------
  |  Branch (2940:9): [True: 28.8k, False: 10.3k]
  ------------------
 2941|  28.8k|        if (!loader_check_version_meets_required(LOADER_VERSION_1_1_0, version)) {
  ------------------
  |  |  271|  28.8k|#define LOADER_VERSION_1_1_0 loader_combine_version(1, 1, 0)
  ------------------
  |  Branch (2941:13): [True: 18.9k, False: 9.90k]
  ------------------
 2942|  18.9k|            loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2943|  18.9k|                       "Layer \"%s\" contains meta-layer-specific component_layers, but using older JSON file version.",
 2944|  18.9k|                       props.info.layerName);
 2945|  18.9k|        }
 2946|       |
 2947|  28.8k|        result = loader_parse_json_array_of_strings(inst, layer_node, "component_layers", &(props.component_layer_names));
 2948|  28.8k|        if (VK_ERROR_OUT_OF_HOST_MEMORY == result) {
  ------------------
  |  Branch (2948:13): [True: 0, False: 28.8k]
  ------------------
 2949|      0|            goto out;
 2950|      0|        }
 2951|  28.8k|        if (VK_ERROR_INITIALIZATION_FAILED == result) {
  ------------------
  |  Branch (2951:13): [True: 940, False: 27.9k]
  ------------------
 2952|    940|            loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2953|    940|                       "Layer \"%s\" is missing both library_path and component_layers fields.  One or the other MUST be defined.  "
 2954|    940|                       "Skipping this layer",
 2955|    940|                       props.info.layerName);
 2956|    940|            goto out;
 2957|    940|        }
 2958|       |        // This is now, officially, a meta-layer
 2959|  27.9k|        props.type_flags |= VK_LAYER_TYPE_FLAG_META_LAYER;
 2960|  27.9k|        loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0, "Encountered meta-layer \"%s\"",
 2961|  27.9k|                   props.info.layerName);
 2962|  27.9k|    }
 2963|       |
 2964|       |    // Parse blacklisted_layers
 2965|       |
 2966|  38.3k|    if (props.is_override) {
  ------------------
  |  Branch (2966:9): [True: 4.08k, False: 34.2k]
  ------------------
 2967|  4.08k|        result = loader_parse_json_array_of_strings(inst, layer_node, "blacklisted_layers", &(props.blacklist_layer_names));
 2968|  4.08k|        if (VK_ERROR_OUT_OF_HOST_MEMORY == result) {
  ------------------
  |  Branch (2968:13): [True: 0, False: 4.08k]
  ------------------
 2969|      0|            goto out;
 2970|      0|        }
 2971|  4.08k|    }
 2972|       |
 2973|       |    // Parse override_paths
 2974|       |
 2975|  38.3k|    result = loader_parse_json_array_of_strings(inst, layer_node, "override_paths", &(props.override_paths));
 2976|  38.3k|    if (VK_ERROR_OUT_OF_HOST_MEMORY == result) {
  ------------------
  |  Branch (2976:9): [True: 0, False: 38.3k]
  ------------------
 2977|      0|        goto out;
 2978|      0|    }
 2979|  38.3k|    if (NULL != props.override_paths.list && !loader_check_version_meets_required(loader_combine_version(1, 1, 0), version)) {
  ------------------
  |  Branch (2979:9): [True: 4.31k, False: 34.0k]
  |  Branch (2979:46): [True: 3.16k, False: 1.15k]
  ------------------
 2980|  3.16k|        loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2981|  3.16k|                   "Layer \"%s\" contains meta-layer-specific override paths, but using older JSON file version.",
 2982|  3.16k|                   props.info.layerName);
 2983|  3.16k|    }
 2984|       |
 2985|       |    // Parse disable_environment
 2986|       |
 2987|  38.3k|    if (is_implicit) {
  ------------------
  |  Branch (2987:9): [True: 19.0k, False: 19.2k]
  ------------------
 2988|  19.0k|        cJSON *disable_environment = loader_cJSON_GetObjectItem(layer_node, "disable_environment");
 2989|  19.0k|        if (disable_environment == NULL) {
  ------------------
  |  Branch (2989:13): [True: 2.16k, False: 16.8k]
  ------------------
 2990|  2.16k|            loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2991|  2.16k|                       "Layer \"%s\" doesn't contain required layer object disable_environment in the manifest JSON file, skipping "
 2992|  2.16k|                       "this layer",
 2993|  2.16k|                       props.info.layerName);
 2994|  2.16k|            result = VK_ERROR_INITIALIZATION_FAILED;
 2995|  2.16k|            goto out;
 2996|  2.16k|        }
 2997|       |
 2998|  16.8k|        if (!disable_environment->child || disable_environment->child->type != cJSON_String ||
  ------------------
  |  |  101|  33.7k|#define cJSON_String (1 << 4)
  ------------------
  |  Branch (2998:13): [True: 6, False: 16.8k]
  |  Branch (2998:44): [True: 14, False: 16.8k]
  ------------------
 2999|  16.8k|            !disable_environment->child->string || !disable_environment->child->valuestring) {
  ------------------
  |  Branch (2999:13): [True: 33, False: 16.8k]
  |  Branch (2999:52): [True: 0, False: 16.8k]
  ------------------
 3000|     53|            loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 3001|     53|                       "Layer \"%s\" doesn't contain required child value in object disable_environment in the manifest JSON file, "
 3002|     53|                       "skipping this layer (Policy #LLP_LAYER_9)",
 3003|     53|                       props.info.layerName);
 3004|     53|            result = VK_ERROR_INITIALIZATION_FAILED;
 3005|     53|            goto out;
 3006|     53|        }
 3007|  16.8k|        result = loader_copy_to_new_str(inst, disable_environment->child->string, &(props.disable_env_var.name));
 3008|  16.8k|        if (VK_SUCCESS != result) goto out;
  ------------------
  |  Branch (3008:13): [True: 0, False: 16.8k]
  ------------------
 3009|  16.8k|        result = loader_copy_to_new_str(inst, disable_environment->child->valuestring, &(props.disable_env_var.value));
 3010|  16.8k|        if (VK_SUCCESS != result) goto out;
  ------------------
  |  Branch (3010:13): [True: 0, False: 16.8k]
  ------------------
 3011|  16.8k|    }
 3012|       |
 3013|       |    // Now get all optional items and objects and put in list:
 3014|       |    // functions
 3015|       |    // instance_extensions
 3016|       |    // device_extensions
 3017|       |    // enable_environment (implicit layers only)
 3018|       |    // library_arch
 3019|       |
 3020|       |    // Layer interface functions
 3021|       |    //    vkGetInstanceProcAddr
 3022|       |    //    vkGetDeviceProcAddr
 3023|       |    //    vkNegotiateLoaderLayerInterfaceVersion (starting with JSON file 1.1.0)
 3024|  36.1k|    cJSON *functions = loader_cJSON_GetObjectItem(layer_node, "functions");
 3025|  36.1k|    if (functions != NULL) {
  ------------------
  |  Branch (3025:9): [True: 389, False: 35.7k]
  ------------------
 3026|    389|        if (loader_check_version_meets_required(loader_combine_version(1, 1, 0), version)) {
  ------------------
  |  Branch (3026:13): [True: 316, False: 73]
  ------------------
 3027|    316|            result = loader_parse_json_string(functions, "vkNegotiateLoaderLayerInterfaceVersion",
 3028|    316|                                              &props.functions.str_negotiate_interface);
 3029|    316|            if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (3029:17): [True: 0, False: 316]
  ------------------
 3030|    316|        }
 3031|    389|        result = loader_parse_json_string(functions, "vkGetInstanceProcAddr", &props.functions.str_gipa);
 3032|    389|        if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (3032:13): [True: 0, False: 389]
  ------------------
 3033|       |
 3034|    389|        if (NULL == props.functions.str_negotiate_interface && props.functions.str_gipa &&
  ------------------
  |  Branch (3034:13): [True: 389, False: 0]
  |  Branch (3034:64): [True: 0, False: 389]
  ------------------
 3035|      0|            loader_check_version_meets_required(loader_combine_version(1, 1, 0), version)) {
  ------------------
  |  Branch (3035:13): [True: 0, False: 0]
  ------------------
 3036|      0|            loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
 3037|      0|                       "Layer \"%s\" using deprecated \'vkGetInstanceProcAddr\' tag which was deprecated starting with JSON "
 3038|      0|                       "file version 1.1.0. The new vkNegotiateLoaderLayerInterfaceVersion function is preferred, though for "
 3039|      0|                       "compatibility reasons it may be desirable to continue using the deprecated tag.",
 3040|      0|                       props.info.layerName);
 3041|      0|        }
 3042|       |
 3043|    389|        result = loader_parse_json_string(functions, "vkGetDeviceProcAddr", &props.functions.str_gdpa);
 3044|    389|        if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (3044:13): [True: 0, False: 389]
  ------------------
 3045|       |
 3046|    389|        if (NULL == props.functions.str_negotiate_interface && props.functions.str_gdpa &&
  ------------------
  |  Branch (3046:13): [True: 389, False: 0]
  |  Branch (3046:64): [True: 0, False: 389]
  ------------------
 3047|      0|            loader_check_version_meets_required(loader_combine_version(1, 1, 0), version)) {
  ------------------
  |  Branch (3047:13): [True: 0, False: 0]
  ------------------
 3048|      0|            loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
 3049|      0|                       "Layer \"%s\" using deprecated \'vkGetDeviceProcAddr\' tag which was deprecated starting with JSON "
 3050|      0|                       "file version 1.1.0. The new vkNegotiateLoaderLayerInterfaceVersion function is preferred, though for "
 3051|      0|                       "compatibility reasons it may be desirable to continue using the deprecated tag.",
 3052|      0|                       props.info.layerName);
 3053|      0|        }
 3054|    389|    }
 3055|       |
 3056|       |    // instance_extensions
 3057|       |    //   array of {
 3058|       |    //     name
 3059|       |    //     spec_version
 3060|       |    //   }
 3061|       |
 3062|  36.1k|    cJSON *instance_extensions = loader_cJSON_GetObjectItem(layer_node, "instance_extensions");
 3063|  36.1k|    if (instance_extensions != NULL && instance_extensions->type == cJSON_Array) {
  ------------------
  |  |  102|    644|#define cJSON_Array (1 << 5)
  ------------------
  |  Branch (3063:9): [True: 644, False: 35.4k]
  |  Branch (3063:40): [True: 499, False: 145]
  ------------------
 3064|    499|        cJSON *ext_item = NULL;
 3065|  7.12k|        cJSON_ArrayForEach(ext_item, instance_extensions) {
  ------------------
  |  |  213|  7.62k|    for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
  |  |  ------------------
  |  |  |  Branch (213:20): [True: 499, False: 0]
  |  |  |  Branch (213:61): [True: 7.12k, False: 499]
  |  |  ------------------
  ------------------
 3066|  7.12k|            if (ext_item->type != cJSON_Object) {
  ------------------
  |  |  103|  7.12k|#define cJSON_Object (1 << 6)
  ------------------
  |  Branch (3066:17): [True: 547, False: 6.58k]
  ------------------
 3067|    547|                continue;
 3068|    547|            }
 3069|       |
 3070|  6.58k|            VkExtensionProperties ext_prop = {0};
 3071|  6.58k|            result = loader_parse_json_string_to_existing_str(ext_item, "name", VK_MAX_EXTENSION_NAME_SIZE, ext_prop.extensionName);
 3072|  6.58k|            if (result == VK_ERROR_INITIALIZATION_FAILED) {
  ------------------
  |  Branch (3072:17): [True: 1.04k, False: 5.53k]
  ------------------
 3073|  1.04k|                continue;
 3074|  1.04k|            }
 3075|  5.53k|            char *spec_version = NULL;
 3076|  5.53k|            result = loader_parse_json_string(ext_item, "spec_version", &spec_version);
 3077|  5.53k|            if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (3077:17): [True: 0, False: 5.53k]
  ------------------
 3078|  5.53k|            if (NULL != spec_version) {
  ------------------
  |  Branch (3078:17): [True: 5, False: 5.53k]
  ------------------
 3079|      5|                ext_prop.specVersion = (uint32_t)strtoul(spec_version, NULL, 10);
 3080|      5|            }
 3081|  5.53k|            loader_instance_heap_free(inst, spec_version);
 3082|  5.53k|            bool ext_unsupported = wsi_unsupported_instance_extension(&ext_prop);
 3083|  5.53k|            if (!ext_unsupported) {
  ------------------
  |  Branch (3083:17): [True: 5.49k, False: 39]
  ------------------
 3084|  5.49k|                result = loader_add_to_ext_list(inst, &props.instance_extension_list, 1, &ext_prop);
 3085|  5.49k|                if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (3085:21): [True: 0, False: 5.49k]
  ------------------
 3086|  5.49k|            }
 3087|  5.53k|        }
 3088|    499|    }
 3089|       |
 3090|       |    // device_extensions
 3091|       |    //   array of {
 3092|       |    //     name
 3093|       |    //     spec_version
 3094|       |    //     entrypoints
 3095|       |    //   }
 3096|  36.1k|    cJSON *device_extensions = loader_cJSON_GetObjectItem(layer_node, "device_extensions");
 3097|  36.1k|    if (device_extensions != NULL && device_extensions->type == cJSON_Array) {
  ------------------
  |  |  102|  1.77k|#define cJSON_Array (1 << 5)
  ------------------
  |  Branch (3097:9): [True: 1.77k, False: 34.3k]
  |  Branch (3097:38): [True: 1.45k, False: 322]
  ------------------
 3098|  1.45k|        cJSON *ext_item = NULL;
 3099|  4.44k|        cJSON_ArrayForEach(ext_item, device_extensions) {
  ------------------
  |  |  213|  5.90k|    for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
  |  |  ------------------
  |  |  |  Branch (213:20): [True: 1.45k, False: 0]
  |  |  |  Branch (213:61): [True: 4.44k, False: 1.45k]
  |  |  ------------------
  ------------------
 3100|  4.44k|            if (ext_item->type != cJSON_Object) {
  ------------------
  |  |  103|  4.44k|#define cJSON_Object (1 << 6)
  ------------------
  |  Branch (3100:17): [True: 102, False: 4.34k]
  ------------------
 3101|    102|                continue;
 3102|    102|            }
 3103|       |
 3104|  4.34k|            VkExtensionProperties ext_prop = {0};
 3105|  4.34k|            result = loader_parse_json_string_to_existing_str(ext_item, "name", VK_MAX_EXTENSION_NAME_SIZE, ext_prop.extensionName);
 3106|  4.34k|            if (result == VK_ERROR_INITIALIZATION_FAILED) {
  ------------------
  |  Branch (3106:17): [True: 938, False: 3.40k]
  ------------------
 3107|    938|                continue;
 3108|    938|            }
 3109|       |
 3110|  3.40k|            char *spec_version = NULL;
 3111|  3.40k|            result = loader_parse_json_string(ext_item, "spec_version", &spec_version);
 3112|  3.40k|            if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (3112:17): [True: 0, False: 3.40k]
  ------------------
 3113|  3.40k|            if (NULL != spec_version) {
  ------------------
  |  Branch (3113:17): [True: 67, False: 3.34k]
  ------------------
 3114|     67|                ext_prop.specVersion = (uint32_t)strtoul(spec_version, NULL, 10);
 3115|     67|            }
 3116|  3.40k|            loader_instance_heap_free(inst, spec_version);
 3117|       |
 3118|  3.40k|            cJSON *entrypoints = loader_cJSON_GetObjectItem(ext_item, "entrypoints");
 3119|  3.40k|            if (entrypoints == NULL) {
  ------------------
  |  Branch (3119:17): [True: 3.15k, False: 257]
  ------------------
 3120|  3.15k|                result = loader_add_to_dev_ext_list(inst, &props.device_extension_list, &ext_prop, NULL);
 3121|  3.15k|                if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (3121:21): [True: 0, False: 3.15k]
  ------------------
 3122|  3.15k|                continue;
 3123|  3.15k|            }
 3124|       |
 3125|    257|            struct loader_string_list entrys = {0};
 3126|    257|            result = loader_parse_json_array_of_strings(inst, ext_item, "entrypoints", &entrys);
 3127|    257|            if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (3127:17): [True: 0, False: 257]
  ------------------
 3128|    257|            result = loader_add_to_dev_ext_list(inst, &props.device_extension_list, &ext_prop, &entrys);
 3129|    257|            if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (3129:17): [True: 0, False: 257]
  ------------------
 3130|    257|        }
 3131|  1.45k|    }
 3132|  36.1k|    if (is_implicit) {
  ------------------
  |  Branch (3132:9): [True: 16.8k, False: 19.2k]
  ------------------
 3133|  16.8k|        cJSON *enable_environment = loader_cJSON_GetObjectItem(layer_node, "enable_environment");
 3134|       |
 3135|       |        // enable_environment is optional
 3136|  16.8k|        if (enable_environment && enable_environment->child && enable_environment->child->type == cJSON_String &&
  ------------------
  |  |  101|  17.2k|#define cJSON_String (1 << 4)
  ------------------
  |  Branch (3136:13): [True: 594, False: 16.2k]
  |  Branch (3136:35): [True: 477, False: 117]
  |  Branch (3136:64): [True: 477, False: 0]
  ------------------
 3137|    477|            enable_environment->child->string && enable_environment->child->valuestring) {
  ------------------
  |  Branch (3137:13): [True: 471, False: 6]
  |  Branch (3137:50): [True: 471, False: 0]
  ------------------
 3138|    471|            result = loader_copy_to_new_str(inst, enable_environment->child->string, &(props.enable_env_var.name));
 3139|    471|            if (VK_SUCCESS != result) goto out;
  ------------------
  |  Branch (3139:17): [True: 0, False: 471]
  ------------------
 3140|    471|            result = loader_copy_to_new_str(inst, enable_environment->child->valuestring, &(props.enable_env_var.value));
 3141|    471|            if (VK_SUCCESS != result) goto out;
  ------------------
  |  Branch (3141:17): [True: 0, False: 471]
  ------------------
 3142|    471|        }
 3143|  16.8k|    }
 3144|       |
 3145|       |    // Read in the pre-instance stuff
 3146|  36.1k|    cJSON *pre_instance = loader_cJSON_GetObjectItem(layer_node, "pre_instance_functions");
 3147|  36.1k|    if (NULL != pre_instance) {
  ------------------
  |  Branch (3147:9): [True: 355, False: 35.7k]
  ------------------
 3148|       |        // Supported versions started in 1.1.2, so anything newer
 3149|    355|        if (!loader_check_version_meets_required(loader_combine_version(1, 1, 2), version)) {
  ------------------
  |  Branch (3149:13): [True: 106, False: 249]
  ------------------
 3150|    106|            loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
 3151|    106|                       "Found pre_instance_functions section in layer from \"%s\". This section is only valid in manifest version "
 3152|    106|                       "1.1.2 or later. The section will be ignored",
 3153|    106|                       filename);
 3154|    249|        } else if (!is_implicit) {
  ------------------
  |  Branch (3154:20): [True: 96, False: 153]
  ------------------
 3155|     96|            loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 3156|     96|                       "Found pre_instance_functions section in explicit layer from \"%s\". This section is only valid in implicit "
 3157|     96|                       "layers. The section will be ignored",
 3158|     96|                       filename);
 3159|    153|        } else {
 3160|    153|            result = loader_parse_json_string(pre_instance, "vkEnumerateInstanceExtensionProperties",
 3161|    153|                                              &props.pre_instance_functions.enumerate_instance_extension_properties);
 3162|    153|            if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (3162:17): [True: 0, False: 153]
  ------------------
 3163|       |
 3164|    153|            result = loader_parse_json_string(pre_instance, "vkEnumerateInstanceLayerProperties",
 3165|    153|                                              &props.pre_instance_functions.enumerate_instance_layer_properties);
 3166|    153|            if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (3166:17): [True: 0, False: 153]
  ------------------
 3167|       |
 3168|    153|            result = loader_parse_json_string(pre_instance, "vkEnumerateInstanceVersion",
 3169|    153|                                              &props.pre_instance_functions.enumerate_instance_version);
 3170|    153|            if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (3170:17): [True: 0, False: 153]
  ------------------
 3171|    153|        }
 3172|    355|    }
 3173|       |
 3174|  36.1k|    if (loader_cJSON_GetObjectItem(layer_node, "app_keys")) {
  ------------------
  |  Branch (3174:9): [True: 560, False: 35.5k]
  ------------------
 3175|    560|        if (!props.is_override) {
  ------------------
  |  Branch (3175:13): [True: 275, False: 285]
  ------------------
 3176|    275|            loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 3177|    275|                       "Layer %s contains app_keys, but any app_keys can only be provided by the override meta layer. "
 3178|    275|                       "These will be ignored.",
 3179|    275|                       props.info.layerName);
 3180|    275|        }
 3181|       |
 3182|    560|        result = loader_parse_json_array_of_strings(inst, layer_node, "app_keys", &props.app_key_paths);
 3183|    560|        if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (3183:13): [True: 0, False: 560]
  ------------------
 3184|    560|    }
 3185|       |
 3186|  36.1k|    char *library_arch = loader_cJSON_GetStringValue(loader_cJSON_GetObjectItem(layer_node, "library_arch"));
 3187|  36.1k|    if (NULL != library_arch) {
  ------------------
  |  Branch (3187:9): [True: 163, False: 35.9k]
  ------------------
 3188|    163|        if ((strncmp(library_arch, "32", 2) == 0 && sizeof(void *) != 4) ||
  ------------------
  |  Branch (3188:14): [True: 72, False: 91]
  |  Branch (3188:53): [True: 0, Folded]
  ------------------
 3189|     91|            (strncmp(library_arch, "64", 2) == 0 && sizeof(void *) != 8)) {
  ------------------
  |  Branch (3189:14): [True: 0, False: 91]
  |  Branch (3189:53): [Folded, False: 0]
  ------------------
 3190|     72|            loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
 3191|     72|                       "The library architecture in layer %s doesn't match the current running architecture, skipping this layer",
 3192|     72|                       filename);
 3193|     72|            result = VK_ERROR_INITIALIZATION_FAILED;
 3194|     72|            goto out;
 3195|     72|        }
 3196|    163|    }
 3197|       |
 3198|  36.0k|    result = VK_SUCCESS;
 3199|       |
 3200|  93.8k|out:
 3201|       |    // Try to append the layer property
 3202|  93.8k|    if (VK_SUCCESS == result) {
  ------------------
  |  Branch (3202:9): [True: 36.0k, False: 57.8k]
  ------------------
 3203|  36.0k|        result = loader_append_layer_property(inst, layer_instance_list, &props);
 3204|  36.0k|    }
 3205|       |    // If appending fails - free all the memory allocated in it
 3206|  93.8k|    if (VK_SUCCESS != result) {
  ------------------
  |  Branch (3206:9): [True: 57.8k, False: 36.0k]
  ------------------
 3207|  57.8k|        loader_free_layer_properties(inst, &props);
 3208|  57.8k|    }
 3209|  93.8k|    return result;
 3210|  36.0k|}
is_valid_layer_json_version:
 3212|  6.04k|bool is_valid_layer_json_version(const loader_api_version *layer_json) {
 3213|       |    // Supported versions are: 1.0.0, 1.0.1, 1.1.0 - 1.1.2, and 1.2.0 - 1.2.1.
 3214|  6.04k|    if ((layer_json->major == 1 && layer_json->minor == 2 && layer_json->patch < 2) ||
  ------------------
  |  Branch (3214:10): [True: 641, False: 5.40k]
  |  Branch (3214:36): [True: 95, False: 546]
  |  Branch (3214:62): [True: 55, False: 40]
  ------------------
 3215|  5.98k|        (layer_json->major == 1 && layer_json->minor == 1 && layer_json->patch < 3) ||
  ------------------
  |  Branch (3215:10): [True: 586, False: 5.40k]
  |  Branch (3215:36): [True: 121, False: 465]
  |  Branch (3215:62): [True: 81, False: 40]
  ------------------
 3216|  5.90k|        (layer_json->major == 1 && layer_json->minor == 0 && layer_json->patch < 2)) {
  ------------------
  |  Branch (3216:10): [True: 505, False: 5.40k]
  |  Branch (3216:36): [True: 318, False: 187]
  |  Branch (3216:62): [True: 295, False: 23]
  ------------------
 3217|    431|        return true;
 3218|    431|    }
 3219|  5.61k|    return false;
 3220|  6.04k|}
loader_add_layer_properties:
 3232|  7.18k|                                     bool is_implicit, char *filename) {
 3233|       |    // The following Fields in layer manifest file that are required:
 3234|       |    //   - "file_format_version"
 3235|       |    //   - If more than one "layer" object are used, then the "layers" array is
 3236|       |    //     required
 3237|  7.18k|    VkResult result = VK_ERROR_INITIALIZATION_FAILED;
 3238|       |    // Make sure sure the top level json value is an object
 3239|  7.18k|    if (!json || json->type != cJSON_Object) {
  ------------------
  |  |  103|  7.18k|#define cJSON_Object (1 << 6)
  ------------------
  |  Branch (3239:9): [True: 0, False: 7.18k]
  |  Branch (3239:18): [True: 1.06k, False: 6.12k]
  ------------------
 3240|  1.06k|        goto out;
 3241|  1.06k|    }
 3242|  6.12k|    char *file_vers = loader_cJSON_GetStringValue(loader_cJSON_GetObjectItem(json, "file_format_version"));
 3243|  6.12k|    if (NULL == file_vers) {
  ------------------
  |  Branch (3243:9): [True: 79, False: 6.04k]
  ------------------
 3244|     79|        loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 3245|     79|                   "loader_add_layer_properties: Manifest %s missing required field file_format_version", filename);
 3246|     79|        goto out;
 3247|     79|    }
 3248|       |
 3249|  6.04k|    loader_log(inst, VULKAN_LOADER_INFO_BIT, 0, "Found manifest file %s (file version %s)", filename, file_vers);
 3250|       |    // Get the major/minor/and patch as integers for easier comparison
 3251|  6.04k|    loader_api_version json_version = loader_make_full_version(loader_parse_version_string(file_vers));
 3252|       |
 3253|  6.04k|    if (!is_valid_layer_json_version(&json_version)) {
  ------------------
  |  Branch (3253:9): [True: 5.61k, False: 431]
  ------------------
 3254|  5.61k|        loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 3255|  5.61k|                   "loader_add_layer_properties: %s has unknown layer manifest file version %d.%d.%d.  May cause errors.", filename,
 3256|  5.61k|                   json_version.major, json_version.minor, json_version.patch);
 3257|  5.61k|    }
 3258|       |
 3259|       |    // If "layers" is present, read in the array of layer objects
 3260|  6.04k|    cJSON *layers_node = loader_cJSON_GetObjectItem(json, "layers");
 3261|  6.04k|    if (layers_node != NULL) {
  ------------------
  |  Branch (3261:9): [True: 5.21k, False: 826]
  ------------------
 3262|       |        // Supported versions started in 1.0.1, so anything newer
 3263|  5.21k|        if (!loader_check_version_meets_required(loader_combine_version(1, 0, 1), json_version)) {
  ------------------
  |  Branch (3263:13): [True: 1.77k, False: 3.44k]
  ------------------
 3264|  1.77k|            loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 3265|  1.77k|                       "loader_add_layer_properties: \'layers\' tag not supported until file version 1.0.1, but %s is reporting "
 3266|  1.77k|                       "version %s",
 3267|  1.77k|                       filename, file_vers);
 3268|  1.77k|        }
 3269|  5.21k|        cJSON *layer_node = NULL;
 3270|  90.4k|        cJSON_ArrayForEach(layer_node, layers_node) {
  ------------------
  |  |  213|  95.5k|    for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
  |  |  ------------------
  |  |  |  Branch (213:20): [True: 5.21k, False: 0]
  |  |  |  Branch (213:61): [True: 90.4k, False: 5.08k]
  |  |  ------------------
  ------------------
 3271|  90.4k|            if (layer_node->type != cJSON_Object) {
  ------------------
  |  |  103|  90.4k|#define cJSON_Object (1 << 6)
  ------------------
  |  Branch (3271:17): [True: 134, False: 90.3k]
  ------------------
 3272|    134|                loader_log(
 3273|    134|                    inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 3274|    134|                    "loader_add_layer_properties: Array element in \"layers\" field in manifest JSON file %s is not an object.  "
 3275|    134|                    "Skipping this file",
 3276|    134|                    filename);
 3277|    134|                goto out;
 3278|    134|            }
 3279|  90.3k|            result = loader_read_layer_json(inst, layer_instance_list, layer_node, json_version, is_implicit, filename);
 3280|  90.3k|        }
 3281|  5.21k|    } else {
 3282|       |        // Otherwise, try to read in individual layers
 3283|    826|        cJSON *layer_node = loader_cJSON_GetObjectItem(json, "layer");
 3284|    826|        if (layer_node == NULL) {
  ------------------
  |  Branch (3284:13): [True: 468, False: 358]
  ------------------
 3285|       |            // Don't warn if this happens to be an ICD manifest
 3286|    468|            if (loader_cJSON_GetObjectItem(json, "ICD") == NULL) {
  ------------------
  |  Branch (3286:17): [True: 465, False: 3]
  ------------------
 3287|    465|                loader_log(
 3288|    465|                    inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 3289|    465|                    "loader_add_layer_properties: Can not find 'layer' object in manifest JSON file %s.  Skipping this file.",
 3290|    465|                    filename);
 3291|    465|            }
 3292|    468|            goto out;
 3293|    468|        }
 3294|       |        // Loop through all "layer" objects in the file to get a count of them
 3295|       |        // first.
 3296|    358|        uint16_t layer_count = 0;
 3297|    358|        cJSON *tempNode = layer_node;
 3298|  3.74k|        do {
 3299|  3.74k|            tempNode = tempNode->next;
 3300|  3.74k|            layer_count++;
 3301|  3.74k|        } while (tempNode != NULL);
  ------------------
  |  Branch (3301:18): [True: 3.38k, False: 358]
  ------------------
 3302|       |
 3303|       |        // Throw a warning if we encounter multiple "layer" objects in file
 3304|       |        // versions newer than 1.0.0.  Having multiple objects with the same
 3305|       |        // name at the same level is actually a JSON standard violation.
 3306|    358|        if (layer_count > 1 && loader_check_version_meets_required(loader_combine_version(1, 0, 1), json_version)) {
  ------------------
  |  Branch (3306:13): [True: 292, False: 66]
  |  Branch (3306:32): [True: 56, False: 236]
  ------------------
 3307|     56|            loader_log(inst, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 3308|     56|                       "loader_add_layer_properties: Multiple 'layer' nodes are deprecated starting in file version \"1.0.1\".  "
 3309|     56|                       "Please use 'layers' : [] array instead in %s.",
 3310|     56|                       filename);
 3311|    302|        } else {
 3312|  3.51k|            do {
 3313|  3.51k|                result = loader_read_layer_json(inst, layer_instance_list, layer_node, json_version, is_implicit, filename);
 3314|  3.51k|                layer_node = layer_node->next;
 3315|  3.51k|            } while (layer_node != NULL);
  ------------------
  |  Branch (3315:22): [True: 3.20k, False: 302]
  ------------------
 3316|    302|        }
 3317|    358|    }
 3318|       |
 3319|  7.18k|out:
 3320|       |
 3321|  7.18k|    return result;
 3322|  6.04k|}
copy_data_file_info:
 3326|   117k|                             size_t relative_path_size, struct loader_string_list *search_paths) {
 3327|   117k|    if (NULL != cur_path) {
  ------------------
  |  Branch (3327:9): [True: 117k, False: 0]
  ------------------
 3328|   117k|        uint32_t start = 0;
 3329|   117k|        uint32_t stop = 0;
 3330|       |
 3331|   252k|        while (cur_path[start] != '\0') {
  ------------------
  |  Branch (3331:16): [True: 135k, False: 117k]
  ------------------
 3332|   158k|            while (cur_path[start] == PATH_SEPARATOR && cur_path[start] != '\0') {
  ------------------
  |  |  154|   317k|#define PATH_SEPARATOR ':'
  ------------------
  |  Branch (3332:20): [True: 22.7k, False: 135k]
  |  Branch (3332:57): [True: 22.7k, False: 0]
  ------------------
 3333|  22.7k|                start++;
 3334|  22.7k|            }
 3335|   135k|            stop = start;
 3336|  37.2M|            while (cur_path[stop] != PATH_SEPARATOR && cur_path[stop] != '\0') {
  ------------------
  |  |  154|  74.4M|#define PATH_SEPARATOR ':'
  ------------------
  |  Branch (3336:20): [True: 37.1M, False: 19.2k]
  |  Branch (3336:56): [True: 37.0M, False: 116k]
  ------------------
 3337|  37.0M|                stop++;
 3338|  37.0M|            }
 3339|   135k|            const size_t s = stop - start;
 3340|   135k|            if (s) {
  ------------------
  |  Branch (3340:17): [True: 135k, False: 285]
  ------------------
 3341|       |                // space enough for base path, relative path, path separator, and null terminator
 3342|   135k|                size_t new_str_len = s + relative_path_size + 2;
 3343|       |
 3344|   135k|                char *new_str = loader_instance_heap_calloc(inst, new_str_len, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
 3345|   135k|                if (NULL == new_str) {
  ------------------
  |  Branch (3345:21): [True: 0, False: 135k]
  ------------------
 3346|      0|                    return VK_ERROR_OUT_OF_HOST_MEMORY;
 3347|      0|                }
 3348|   135k|                memcpy(new_str, &cur_path[start], s);
 3349|   135k|                new_str[s] = '\0';
 3350|       |
 3351|       |                // If this is a specific JSON file, just add it and don't add any
 3352|       |                // relative path or directory symbol to it.
 3353|   135k|                if (!is_json(new_str, s)) {
  ------------------
  |  Branch (3353:21): [True: 132k, False: 3.18k]
  ------------------
 3354|       |                    // Add the relative directory if present.
 3355|   132k|                    if (relative_path_size > 0) {
  ------------------
  |  Branch (3355:25): [True: 109k, False: 22.8k]
  ------------------
 3356|   109k|                        char *rel_start = new_str + s;
 3357|       |
 3358|       |                        // If last symbol written was not a directory symbol, add it.
 3359|   109k|                        if (*(rel_start - 1) != DIRECTORY_SYMBOL) {
  ------------------
  |  |  155|   109k|#define DIRECTORY_SYMBOL '/'
  ------------------
  |  Branch (3359:29): [True: 109k, False: 0]
  ------------------
 3360|   109k|                            *rel_start++ = DIRECTORY_SYMBOL;
  ------------------
  |  |  155|   109k|#define DIRECTORY_SYMBOL '/'
  ------------------
 3361|   109k|                        }
 3362|   109k|                        memcpy(rel_start, relative_path, relative_path_size);
 3363|   109k|                        rel_start[relative_path_size] = '\0';
 3364|   109k|                    }
 3365|   132k|                }
 3366|       |
 3367|   135k|                VkResult res = append_str_to_string_list_if_unique(inst, search_paths, new_str);
 3368|   135k|                if (VK_SUCCESS != res) {
  ------------------
  |  Branch (3368:21): [True: 0, False: 135k]
  ------------------
 3369|      0|                    return res;
 3370|      0|                }
 3371|   135k|                start = stop;
 3372|   135k|            }
 3373|   135k|        }
 3374|   117k|    }
 3375|   117k|    return VK_SUCCESS;
 3376|   117k|}
add_if_manifest_file:
 3379|  41.6k|VkResult add_if_manifest_file(const struct loader_instance *inst, const char *file_name, struct loader_string_list *out_files) {
 3380|  41.6k|    assert(NULL != file_name && "add_if_manifest_file: Received NULL pointer for file_name");
 3381|  41.6k|    assert(NULL != out_files && "add_if_manifest_file: Received NULL pointer for out_files");
 3382|       |
 3383|       |    // Look for files ending with ".json" suffix
 3384|  41.6k|    size_t name_len = strlen(file_name);
 3385|  41.6k|    if (!is_json(file_name, name_len)) {
  ------------------
  |  Branch (3385:9): [True: 26.0k, False: 15.5k]
  ------------------
 3386|       |        // Use incomplete to indicate invalid name, but to keep going.
 3387|  26.0k|        return VK_INCOMPLETE;
 3388|  26.0k|    }
 3389|       |
 3390|  15.5k|    return copy_str_to_string_list(inst, out_files, file_name, name_len);
 3391|  41.6k|}
add_data_files:
 3412|  16.1k|                        struct loader_string_list *out_files) {
 3413|  16.1k|    VkResult vk_result = VK_SUCCESS;
 3414|  16.1k|    char full_path[2048];
 3415|  16.1k|#if !defined(_WIN32)
 3416|  16.1k|    char temp_path[2048];
 3417|  16.1k|#endif
 3418|       |
 3419|   132k|    for (size_t i = 0; i < search_paths->count; i++) {
  ------------------
  |  Branch (3419:24): [True: 116k, False: 16.1k]
  ------------------
 3420|       |        // Now, parse the paths
 3421|   116k|        char *next_file = search_paths->list[i];
 3422|   232k|        while (NULL != next_file && *next_file != '\0') {
  ------------------
  |  Branch (3422:16): [True: 232k, False: 0]
  |  Branch (3422:37): [True: 116k, False: 116k]
  ------------------
 3423|   116k|            char *name = NULL;
 3424|   116k|            char *cur_file = next_file;
 3425|   116k|            next_file = loader_get_next_path(cur_file);
 3426|       |
 3427|       |            // Is this a JSON file, then try to open it.
 3428|   116k|            size_t len = strlen(cur_file);
 3429|   116k|            if (is_json(cur_file, len)) {
  ------------------
  |  Branch (3429:17): [True: 1.37k, False: 115k]
  ------------------
 3430|       |#if defined(_WIN32)
 3431|       |                name = cur_file;
 3432|       |#elif COMMON_UNIX_PLATFORMS
 3433|       |                // Only Linux has relative paths, make a copy of location so it isn't modified
 3434|  1.37k|                size_t str_len;
 3435|  1.37k|                if (NULL != next_file) {
  ------------------
  |  Branch (3435:21): [True: 1.37k, False: 0]
  ------------------
 3436|  1.37k|                    str_len = next_file - cur_file + 1;
 3437|  1.37k|                } else {
 3438|      0|                    str_len = strlen(cur_file) + 1;
 3439|      0|                }
 3440|  1.37k|                if (str_len > sizeof(temp_path)) {
  ------------------
  |  Branch (3440:21): [True: 25, False: 1.34k]
  ------------------
 3441|     25|                    loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "add_data_files: Path to %s too long", cur_file);
 3442|     25|                    continue;
 3443|     25|                }
 3444|  1.34k|                strncpy(temp_path, cur_file, str_len);
 3445|  1.34k|                name = temp_path;
 3446|       |#else
 3447|       |#warning add_data_files must define relative path copy for this platform
 3448|       |#endif
 3449|  1.34k|                loader_get_fullpath(cur_file, name, sizeof(full_path), full_path);
 3450|  1.34k|                name = full_path;
 3451|       |
 3452|  1.34k|                VkResult local_res;
 3453|  1.34k|                local_res = add_if_manifest_file(inst, name, out_files);
 3454|       |
 3455|       |                // Incomplete means this was not a valid data file.
 3456|  1.34k|                if (local_res == VK_INCOMPLETE) {
  ------------------
  |  Branch (3456:21): [True: 0, False: 1.34k]
  ------------------
 3457|      0|                    continue;
 3458|      0|                }
 3459|  1.34k|                if (local_res != VK_SUCCESS) {
  ------------------
  |  Branch (3459:21): [True: 0, False: 1.34k]
  ------------------
 3460|      0|                    vk_result = local_res;
 3461|      0|                    break;
 3462|      0|                }
 3463|   115k|            } else {  // Otherwise, treat it as a directory
 3464|   115k|                DIR *dir_stream = loader_opendir(inst, cur_file);
 3465|   115k|                if (NULL == dir_stream) {
  ------------------
  |  Branch (3465:21): [True: 104k, False: 10.8k]
  ------------------
 3466|   104k|                    continue;
 3467|   104k|                }
 3468|  51.1k|                while (1) {
  ------------------
  |  Branch (3468:24): [True: 51.1k, Folded]
  ------------------
 3469|  51.1k|                    errno = 0;
 3470|       |                    // NOLINTNEXTLINE(concurrency-mt-unsafe) - readdir is safe here since each thread uses its own dir_stream
 3471|  51.1k|                    struct dirent *dir_entry = readdir(dir_stream);
 3472|  51.1k|#if !defined(WIN32)  // Windows doesn't use readdir, don't check errors on functions which aren't called
 3473|  51.1k|                    if (errno != 0) {
  ------------------
  |  Branch (3473:25): [True: 0, False: 51.1k]
  ------------------
 3474|       |                        // NOLINTNEXTLINE(concurrency-mt-unsafe) - strerror's static buffer is used immediately and not retained
 3475|      0|                        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "readdir failed with %d: %s", errno, strerror(errno));
 3476|      0|                        break;
 3477|      0|                    }
 3478|  51.1k|#endif
 3479|  51.1k|                    if (NULL == dir_entry) {
  ------------------
  |  Branch (3479:25): [True: 10.8k, False: 40.2k]
  ------------------
 3480|  10.8k|                        break;
 3481|  10.8k|                    }
 3482|       |
 3483|  40.2k|                    name = &(dir_entry->d_name[0]);
 3484|       |                    // 'name' is the bare filename, 'cur_file' is the directory being scanned; the substring "file" in
 3485|       |                    // cur_file just confuses the naming heuristic below.
 3486|       |                    // NOLINTNEXTLINE(readability-suspicious-call-argument) - arguments are correctly ordered, not swapped
 3487|  40.2k|                    loader_get_fullpath(name, cur_file, sizeof(full_path), full_path);
 3488|  40.2k|                    name = full_path;
 3489|       |
 3490|  40.2k|                    VkResult local_res;
 3491|  40.2k|                    local_res = add_if_manifest_file(inst, name, out_files);
 3492|       |
 3493|       |                    // Incomplete means this was not a valid data file.
 3494|  40.2k|                    if (local_res == VK_INCOMPLETE) {
  ------------------
  |  Branch (3494:25): [True: 26.0k, False: 14.2k]
  ------------------
 3495|  26.0k|                        continue;
 3496|  26.0k|                    }
 3497|  14.2k|                    if (local_res != VK_SUCCESS) {
  ------------------
  |  Branch (3497:25): [True: 0, False: 14.2k]
  ------------------
 3498|      0|                        vk_result = local_res;
 3499|      0|                        break;
 3500|      0|                    }
 3501|  14.2k|                }
 3502|  10.8k|                loader_closedir(inst, dir_stream);
 3503|  10.8k|                if (vk_result != VK_SUCCESS) {
  ------------------
  |  Branch (3503:21): [True: 0, False: 10.8k]
  ------------------
 3504|      0|                    goto out;
 3505|      0|                }
 3506|  10.8k|            }
 3507|   116k|        }
 3508|   116k|    }
 3509|       |
 3510|  16.1k|out:
 3511|       |
 3512|  16.1k|    return vk_result;
 3513|  16.1k|}
read_data_files_in_search_paths:
 3519|  16.1k|                                         struct loader_string_list *out_files) {
 3520|  16.1k|    VkResult vk_result = VK_SUCCESS;
 3521|  16.1k|    char *override_env = NULL;
 3522|  16.1k|    char *additional_env = NULL;
 3523|  16.1k|    struct loader_string_list search_paths = {0};
 3524|       |
 3525|  16.1k|#if COMMON_UNIX_PLATFORMS
 3526|  16.1k|    const char *relative_location = NULL;  // Only used on unix platforms
 3527|  16.1k|    size_t rel_size = 0;                   // unused in windows, dont declare so no compiler warnings are generated
 3528|  16.1k|#endif
 3529|       |
 3530|       |#if defined(__APPLE__)
 3531|       |    char *bundle_path = NULL;
 3532|       |    char *search_only_in_bundle_env_var = loader_secure_getenv(VK_LOADER_SEARCH_ONLY_IN_BUNDLE_ENV_VAR, inst);
 3533|       |#endif
 3534|       |
 3535|       |#if defined(_WIN32)
 3536|       |    char *package_path = NULL;
 3537|       |#elif COMMON_UNIX_PLATFORMS
 3538|       |    // Determine how much space is needed to generate the full search path
 3539|       |    // for the current manifest files.
 3540|  16.1k|    char *xdg_config_home = loader_secure_getenv("XDG_CONFIG_HOME", inst);
 3541|  16.1k|    char *xdg_config_dirs = loader_secure_getenv("XDG_CONFIG_DIRS", inst);
 3542|       |
 3543|  16.1k|#if !defined(__Fuchsia__) && !defined(__QNX__)
 3544|  16.1k|    if (NULL == xdg_config_dirs || '\0' == xdg_config_dirs[0]) {
  ------------------
  |  Branch (3544:9): [True: 16.1k, False: 0]
  |  Branch (3544:36): [True: 0, False: 0]
  ------------------
 3545|  16.1k|        xdg_config_dirs = FALLBACK_CONFIG_DIRS;
 3546|  16.1k|    }
 3547|  16.1k|#endif
 3548|       |
 3549|  16.1k|    char *xdg_data_home = loader_secure_getenv("XDG_DATA_HOME", inst);
 3550|  16.1k|    char *xdg_data_dirs = loader_secure_getenv("XDG_DATA_DIRS", inst);
 3551|       |
 3552|  16.1k|#if !defined(__Fuchsia__) && !defined(__QNX__)
 3553|  16.1k|    if (NULL == xdg_data_dirs || '\0' == xdg_data_dirs[0]) {
  ------------------
  |  Branch (3553:9): [True: 16.1k, False: 0]
  |  Branch (3553:34): [True: 0, False: 0]
  ------------------
 3554|  16.1k|        xdg_data_dirs = FALLBACK_DATA_DIRS;
 3555|  16.1k|    }
 3556|  16.1k|#endif
 3557|       |
 3558|  16.1k|    char *home = NULL;
 3559|  16.1k|    char *default_data_home = NULL;
 3560|  16.1k|    char *default_config_home = NULL;
 3561|  16.1k|    char *home_data_dir = NULL;
 3562|  16.1k|    char *home_config_dir = NULL;
 3563|       |
 3564|       |    // Only use HOME if XDG_DATA_HOME is not present on the system
 3565|  16.1k|    home = loader_secure_getenv("HOME", inst);
 3566|  16.1k|    if (home != NULL) {
  ------------------
  |  Branch (3566:9): [True: 16.1k, False: 0]
  ------------------
 3567|  16.1k|        if (NULL == xdg_config_home || '\0' == xdg_config_home[0]) {
  ------------------
  |  Branch (3567:13): [True: 16.1k, False: 0]
  |  Branch (3567:40): [True: 0, False: 0]
  ------------------
 3568|  16.1k|            const char config_suffix[] = "/.config";
 3569|  16.1k|            size_t default_config_home_len = strlen(home) + sizeof(config_suffix) + 1;
 3570|  16.1k|            default_config_home = loader_instance_heap_calloc(inst, default_config_home_len, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
 3571|  16.1k|            if (default_config_home == NULL) {
  ------------------
  |  Branch (3571:17): [True: 0, False: 16.1k]
  ------------------
 3572|      0|                vk_result = VK_ERROR_OUT_OF_HOST_MEMORY;
 3573|      0|                goto out;
 3574|      0|            }
 3575|  16.1k|            strncpy(default_config_home, home, default_config_home_len);
 3576|  16.1k|            strncat(default_config_home, config_suffix, default_config_home_len);
 3577|  16.1k|        }
 3578|  16.1k|        if (NULL == xdg_data_home || '\0' == xdg_data_home[0]) {
  ------------------
  |  Branch (3578:13): [True: 16.1k, False: 0]
  |  Branch (3578:38): [True: 0, False: 0]
  ------------------
 3579|  16.1k|            const char data_suffix[] = "/.local/share";
 3580|  16.1k|            size_t default_data_home_len = strlen(home) + sizeof(data_suffix) + 1;
 3581|  16.1k|            default_data_home = loader_instance_heap_calloc(inst, default_data_home_len, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
 3582|  16.1k|            if (default_data_home == NULL) {
  ------------------
  |  Branch (3582:17): [True: 0, False: 16.1k]
  ------------------
 3583|      0|                vk_result = VK_ERROR_OUT_OF_HOST_MEMORY;
 3584|      0|                goto out;
 3585|      0|            }
 3586|  16.1k|            strncpy(default_data_home, home, default_data_home_len);
 3587|  16.1k|            strncat(default_data_home, data_suffix, default_data_home_len);
 3588|  16.1k|        }
 3589|  16.1k|    }
 3590|       |
 3591|  16.1k|    if (NULL != default_config_home) {
  ------------------
  |  Branch (3591:9): [True: 16.1k, False: 0]
  ------------------
 3592|  16.1k|        home_config_dir = default_config_home;
 3593|  16.1k|    } else {
 3594|      0|        home_config_dir = xdg_config_home;
 3595|      0|    }
 3596|  16.1k|    if (NULL != default_data_home) {
  ------------------
  |  Branch (3596:9): [True: 16.1k, False: 0]
  ------------------
 3597|  16.1k|        home_data_dir = default_data_home;
 3598|  16.1k|    } else {
 3599|      0|        home_data_dir = xdg_data_home;
 3600|      0|    }
 3601|       |#else
 3602|       |#warning read_data_files_in_search_paths unsupported platform
 3603|       |#endif
 3604|       |
 3605|  16.1k|    switch (manifest_type) {
 3606|      0|        case LOADER_DATA_FILE_MANIFEST_DRIVER:
  ------------------
  |  Branch (3606:9): [True: 0, False: 16.1k]
  ------------------
 3607|      0|            if (loader_settings_should_use_driver_environment_variables(inst)) {
  ------------------
  |  Branch (3607:17): [True: 0, False: 0]
  ------------------
 3608|      0|                override_env = loader_secure_getenv(VK_DRIVER_FILES_ENV_VAR, inst);
  ------------------
  |  |  113|      0|#define VK_DRIVER_FILES_ENV_VAR "VK_DRIVER_FILES"
  ------------------
 3609|      0|                if (NULL == override_env) {
  ------------------
  |  Branch (3609:21): [True: 0, False: 0]
  ------------------
 3610|       |                    // Not there, so fall back to the old name
 3611|      0|                    override_env = loader_secure_getenv(VK_ICD_FILENAMES_ENV_VAR, inst);
  ------------------
  |  |  112|      0|#define VK_ICD_FILENAMES_ENV_VAR "VK_ICD_FILENAMES"  // Deprecated in v1.3.207 loader
  ------------------
 3612|      0|                }
 3613|      0|                additional_env = loader_secure_getenv(VK_ADDITIONAL_DRIVER_FILES_ENV_VAR, inst);
  ------------------
  |  |  116|      0|#define VK_ADDITIONAL_DRIVER_FILES_ENV_VAR "VK_ADD_DRIVER_FILES"
  ------------------
 3614|      0|            }
 3615|      0|#if COMMON_UNIX_PLATFORMS
 3616|      0|            relative_location = VK_DRIVERS_INFO_RELATIVE_DIR;
  ------------------
  |  |  165|      0|#define VK_DRIVERS_INFO_RELATIVE_DIR VULKAN_DIR VULKAN_ICDCONF_DIR
  |  |  ------------------
  |  |  |  |  157|      0|#define VULKAN_DIR "vulkan/"
  |  |  ------------------
  |  |               #define VK_DRIVERS_INFO_RELATIVE_DIR VULKAN_DIR VULKAN_ICDCONF_DIR
  |  |  ------------------
  |  |  |  |  158|      0|#define VULKAN_ICDCONF_DIR "icd.d"
  |  |  ------------------
  ------------------
 3617|      0|#endif
 3618|       |#if defined(_WIN32)
 3619|       |            package_path = windows_get_app_package_manifest_path(inst);
 3620|       |#endif
 3621|      0|            break;
 3622|  10.0k|        case LOADER_DATA_FILE_MANIFEST_IMPLICIT_LAYER:
  ------------------
  |  Branch (3622:9): [True: 10.0k, False: 6.06k]
  ------------------
 3623|  10.0k|            override_env = loader_secure_getenv(VK_IMPLICIT_LAYER_PATH_ENV_VAR, inst);
  ------------------
  |  |  130|  10.0k|#define VK_IMPLICIT_LAYER_PATH_ENV_VAR "VK_IMPLICIT_LAYER_PATH"
  ------------------
 3624|  10.0k|            additional_env = loader_secure_getenv(VK_ADDITIONAL_IMPLICIT_LAYER_PATH_ENV_VAR, inst);
  ------------------
  |  |  131|  10.0k|#define VK_ADDITIONAL_IMPLICIT_LAYER_PATH_ENV_VAR "VK_ADD_IMPLICIT_LAYER_PATH"
  ------------------
 3625|  10.0k|#if COMMON_UNIX_PLATFORMS
 3626|  10.0k|            relative_location = VK_ILAYERS_INFO_RELATIVE_DIR;
  ------------------
  |  |  168|  10.0k|#define VK_ILAYERS_INFO_RELATIVE_DIR VULKAN_DIR VULKAN_ILAYERCONF_DIR
  |  |  ------------------
  |  |  |  |  157|  10.0k|#define VULKAN_DIR "vulkan/"
  |  |  ------------------
  |  |               #define VK_ILAYERS_INFO_RELATIVE_DIR VULKAN_DIR VULKAN_ILAYERCONF_DIR
  |  |  ------------------
  |  |  |  |  162|  10.0k|#define VULKAN_ILAYERCONF_DIR "implicit_layer.d"
  |  |  ------------------
  ------------------
 3627|  10.0k|#endif
 3628|       |#if defined(_WIN32)
 3629|       |            package_path = windows_get_app_package_manifest_path(inst);
 3630|       |#endif
 3631|  10.0k|            break;
 3632|  6.06k|        case LOADER_DATA_FILE_MANIFEST_EXPLICIT_LAYER:
  ------------------
  |  Branch (3632:9): [True: 6.06k, False: 10.0k]
  ------------------
 3633|  6.06k|            override_env = loader_secure_getenv(VK_EXPLICIT_LAYER_PATH_ENV_VAR, inst);
  ------------------
  |  |  114|  6.06k|#define VK_EXPLICIT_LAYER_PATH_ENV_VAR "VK_LAYER_PATH"
  ------------------
 3634|  6.06k|            additional_env = loader_secure_getenv(VK_ADDITIONAL_EXPLICIT_LAYER_PATH_ENV_VAR, inst);
  ------------------
  |  |  117|  6.06k|#define VK_ADDITIONAL_EXPLICIT_LAYER_PATH_ENV_VAR "VK_ADD_LAYER_PATH"
  ------------------
 3635|  6.06k|#if COMMON_UNIX_PLATFORMS
 3636|  6.06k|            relative_location = VK_ELAYERS_INFO_RELATIVE_DIR;
  ------------------
  |  |  167|  6.06k|#define VK_ELAYERS_INFO_RELATIVE_DIR VULKAN_DIR VULKAN_ELAYERCONF_DIR
  |  |  ------------------
  |  |  |  |  157|  6.06k|#define VULKAN_DIR "vulkan/"
  |  |  ------------------
  |  |               #define VK_ELAYERS_INFO_RELATIVE_DIR VULKAN_DIR VULKAN_ELAYERCONF_DIR
  |  |  ------------------
  |  |  |  |  161|  6.06k|#define VULKAN_ELAYERCONF_DIR "explicit_layer.d"
  |  |  ------------------
  ------------------
 3637|  6.06k|#endif
 3638|  6.06k|            break;
 3639|      0|        default:
  ------------------
  |  Branch (3639:9): [True: 0, False: 16.1k]
  ------------------
 3640|      0|            assert(false && "Shouldn't get here!");
 3641|      0|            break;
 3642|  16.1k|    }
 3643|       |
 3644|       |    // Log a message when VK_LAYER_PATH is set but the override layer paths take priority
 3645|  16.1k|    if (manifest_type == LOADER_DATA_FILE_MANIFEST_EXPLICIT_LAYER &&
  ------------------
  |  Branch (3645:9): [True: 6.06k, False: 10.0k]
  ------------------
 3646|  6.06k|        (NULL != override_env && NULL != path_overrides && path_overrides->count > 0)) {
  ------------------
  |  Branch (3646:10): [True: 0, False: 6.06k]
  |  Branch (3646:34): [True: 0, False: 0]
  |  Branch (3646:60): [True: 0, False: 0]
  ------------------
 3647|      0|        loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 3648|      0|                   "Ignoring VK_LAYER_PATH. The Override layer is active and has override paths set, which takes priority. "
 3649|      0|                   "VK_LAYER_PATH is set to %s",
 3650|      0|                   override_env);
 3651|      0|    }
 3652|       |
 3653|       |    // Add the remaining paths to the list
 3654|  16.1k|    if (NULL != path_overrides && path_overrides->count > 0) {
  ------------------
  |  Branch (3654:9): [True: 6.06k, False: 10.0k]
  |  Branch (3654:35): [True: 464, False: 5.60k]
  ------------------
 3655|  7.46k|        for (size_t i = 0; i < path_overrides->count; i++) {
  ------------------
  |  Branch (3655:28): [True: 6.99k, False: 464]
  ------------------
 3656|  6.99k|            if (NULL != path_overrides->list[i]) {
  ------------------
  |  Branch (3656:17): [True: 6.99k, False: 0]
  ------------------
 3657|  6.99k|                if (manifest_type == LOADER_DATA_FILE_MANIFEST_EXPLICIT_LAYER) {
  ------------------
  |  Branch (3657:21): [True: 6.99k, False: 0]
  ------------------
 3658|  6.99k|                    loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0, "%s", path_overrides->list[i]);
 3659|  6.99k|                }
 3660|  6.99k|                vk_result = copy_data_file_info(inst, path_overrides->list[i], NULL, 0, &search_paths);
 3661|  6.99k|                if (vk_result == VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (3661:21): [True: 0, False: 6.99k]
  ------------------
 3662|      0|                    goto out;
 3663|      0|                }
 3664|  6.99k|            }
 3665|  6.99k|        }
 3666|  15.6k|    } else if (override_env != NULL) {
  ------------------
  |  Branch (3666:16): [True: 0, False: 15.6k]
  ------------------
 3667|      0|        vk_result = copy_data_file_info(inst, override_env, NULL, 0, &search_paths);
 3668|      0|        if (vk_result == VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (3668:13): [True: 0, False: 0]
  ------------------
 3669|      0|            goto out;
 3670|      0|        }
 3671|  15.6k|    } else {
 3672|       |        // Add any additional search paths defined in the additive environment variable
 3673|  15.6k|        if (NULL != additional_env) {
  ------------------
  |  Branch (3673:13): [True: 0, False: 15.6k]
  ------------------
 3674|      0|            vk_result = copy_data_file_info(inst, additional_env, NULL, 0, &search_paths);
 3675|      0|            if (vk_result == VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (3675:17): [True: 0, False: 0]
  ------------------
 3676|      0|                goto out;
 3677|      0|            }
 3678|      0|        }
 3679|       |
 3680|       |#if defined(_WIN32)
 3681|       |        if (NULL != package_path) {
 3682|       |            vk_result = copy_data_file_info(inst, package_path, NULL, 0, &search_paths);
 3683|       |            if (vk_result == VK_ERROR_OUT_OF_HOST_MEMORY) {
 3684|       |                goto out;
 3685|       |            }
 3686|       |        }
 3687|       |#elif COMMON_UNIX_PLATFORMS
 3688|  15.6k|        bool search_outside_of_bundle = true;
 3689|       |
 3690|  15.6k|        rel_size = strlen(relative_location);
 3691|  15.6k|        if (rel_size > 0) {
  ------------------
  |  Branch (3691:13): [True: 15.6k, False: 0]
  ------------------
 3692|       |#if defined(__APPLE__)
 3693|       |            // Add the bundle's Resources dir to the beginning of the search path.
 3694|       |            // Looks for manifests in the bundle first, before any system directories.
 3695|       |            // This also appears to work unmodified for iOS, it finds the app bundle on the devices
 3696|       |            // file system. (RSW)
 3697|       |            CFBundleRef main_bundle = CFBundleGetMainBundle();
 3698|       |            if (NULL != main_bundle) {
 3699|       |                CFURLRef ref = CFBundleCopyResourcesDirectoryURL(main_bundle);
 3700|       |                if (NULL != ref) {
 3701|       |                    // Allocate large scratch buffer to hold the bundles path, the relative location inside the bundle, plus a path
 3702|       |                    // separator and null terminator. Since we are using a while loop, initialize length with half the intended size
 3703|       |                    size_t bundle_path_len = (MAXPATHLEN + rel_size + 2) / 2;
 3704|       |                    bool bundle_query_success = false;
 3705|       |                    uint32_t retry_count = 0;
 3706|       |                    while (!bundle_query_success && retry_count < 4) {
 3707|       |                        void *new_bundle_path = loader_instance_heap_realloc(
 3708|       |                            inst, bundle_path, bundle_path_len, bundle_path_len * 2, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
 3709|       |                        if (NULL == new_bundle_path) {
 3710|       |                            loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
 3711|       |                                       "read_data_files_in_search_paths: Failed to allocate space for bundle path of length %d",
 3712|       |                                       (uint32_t)bundle_path_len * 2);
 3713|       |                            vk_result = VK_ERROR_OUT_OF_HOST_MEMORY;
 3714|       |                            goto out;
 3715|       |                        }
 3716|       |                        bundle_path = new_bundle_path;
 3717|       |                        bundle_path_len = bundle_path_len * 2;
 3718|       |                        memset(bundle_path, 0, bundle_path_len);
 3719|       |                        bundle_query_success = CFURLGetFileSystemRepresentation(ref, TRUE, (UInt8 *)bundle_path, bundle_path_len);
 3720|       |                        retry_count++;
 3721|       |                    }
 3722|       |
 3723|       |                    if (bundle_query_success) {
 3724|       |                        size_t cur_bundle_len = strlen(bundle_path);
 3725|       |
 3726|       |                        if (cur_bundle_len + rel_size + 2 > bundle_path_len) {
 3727|       |                            loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
 3728|       |                                       "read_data_files_in_search_paths: bundle_path %s of size %d does not have enough space to "
 3729|       |                                       "append relative_path",
 3730|       |                                       bundle_path, (uint32_t)bundle_path_len);
 3731|       |                            vk_result = VK_ERROR_INITIALIZATION_FAILED;
 3732|       |                            goto out;
 3733|       |                        }
 3734|       |                        bundle_path[cur_bundle_len] = DIRECTORY_SYMBOL;
 3735|       |                        cur_bundle_len++;
 3736|       |                        memcpy(bundle_path + cur_bundle_len, relative_location, rel_size);
 3737|       |                        cur_bundle_len += rel_size;
 3738|       |                        bundle_path[cur_bundle_len] = '\0';
 3739|       |
 3740|       |                        vk_result = copy_data_file_info(inst, bundle_path, NULL, 0, &search_paths);
 3741|       |                        if (vk_result == VK_ERROR_OUT_OF_HOST_MEMORY) {
 3742|       |                            goto out;
 3743|       |                        }
 3744|       |                    }
 3745|       |                    CFRelease(ref);
 3746|       |                }
 3747|       |            }
 3748|       |
 3749|       |            if (NULL != search_only_in_bundle_env_var) {
 3750|       |                search_outside_of_bundle = false;
 3751|       |            }
 3752|       |#endif  // __APPLE__
 3753|  15.6k|            if (search_outside_of_bundle) {
  ------------------
  |  Branch (3753:17): [True: 15.6k, False: 0]
  ------------------
 3754|       |                // Only add the home folders if not NULL
 3755|  15.6k|                if (NULL != home_config_dir) {
  ------------------
  |  Branch (3755:21): [True: 15.6k, False: 0]
  ------------------
 3756|  15.6k|                    vk_result = copy_data_file_info(inst, home_config_dir, relative_location, rel_size, &search_paths);
 3757|  15.6k|                    if (VK_SUCCESS != vk_result) {
  ------------------
  |  Branch (3757:25): [True: 0, False: 15.6k]
  ------------------
 3758|      0|                        goto out;
 3759|      0|                    }
 3760|  15.6k|                }
 3761|  15.6k|                vk_result = copy_data_file_info(inst, xdg_config_dirs, relative_location, rel_size, &search_paths);
 3762|  15.6k|                if (VK_SUCCESS != vk_result) {
  ------------------
  |  Branch (3762:21): [True: 0, False: 15.6k]
  ------------------
 3763|      0|                    goto out;
 3764|      0|                }
 3765|  15.6k|                vk_result = copy_data_file_info(inst, SYSCONFDIR, relative_location, rel_size, &search_paths);
 3766|  15.6k|                if (VK_SUCCESS != vk_result) {
  ------------------
  |  Branch (3766:21): [True: 0, False: 15.6k]
  ------------------
 3767|      0|                    goto out;
 3768|      0|                }
 3769|  15.6k|#if defined(EXTRASYSCONFDIR)
 3770|  15.6k|                vk_result = copy_data_file_info(inst, EXTRASYSCONFDIR, relative_location, rel_size, &search_paths);
 3771|  15.6k|                if (VK_SUCCESS != vk_result) {
  ------------------
  |  Branch (3771:21): [True: 0, False: 15.6k]
  ------------------
 3772|      0|                    goto out;
 3773|      0|                }
 3774|  15.6k|#endif
 3775|       |
 3776|       |                // Only add the home folders if not NULL
 3777|  15.6k|                if (NULL != home_data_dir) {
  ------------------
  |  Branch (3777:21): [True: 15.6k, False: 0]
  ------------------
 3778|  15.6k|                    vk_result = copy_data_file_info(inst, home_data_dir, relative_location, rel_size, &search_paths);
 3779|  15.6k|                    if (VK_SUCCESS != vk_result) {
  ------------------
  |  Branch (3779:25): [True: 0, False: 15.6k]
  ------------------
 3780|      0|                        goto out;
 3781|      0|                    }
 3782|  15.6k|                }
 3783|  15.6k|                vk_result = copy_data_file_info(inst, xdg_data_dirs, relative_location, rel_size, &search_paths);
 3784|  15.6k|                if (VK_SUCCESS != vk_result) {
  ------------------
  |  Branch (3784:21): [True: 0, False: 15.6k]
  ------------------
 3785|      0|                    goto out;
 3786|      0|                }
 3787|  15.6k|            }
 3788|  15.6k|        }
 3789|       |#else
 3790|       |#warning read_data_files_in_search_paths unsupported platform
 3791|       |#endif
 3792|  15.6k|    }
 3793|       |
 3794|       |    // Print out the paths being searched if debugging is enabled
 3795|  16.1k|    uint32_t log_flags = 0;
 3796|       |
 3797|  16.1k|    if (manifest_type == LOADER_DATA_FILE_MANIFEST_DRIVER) {
  ------------------
  |  Branch (3797:9): [True: 0, False: 16.1k]
  ------------------
 3798|      0|        log_flags = VULKAN_LOADER_DRIVER_BIT;
 3799|      0|        loader_log(inst, VULKAN_LOADER_DRIVER_BIT, 0, "Searching for driver manifest files");
 3800|  16.1k|    } else {
 3801|  16.1k|        log_flags = VULKAN_LOADER_LAYER_BIT;
 3802|  16.1k|        loader_log(inst, VULKAN_LOADER_LAYER_BIT, 0, "Searching for %s layer manifest files",
 3803|  16.1k|                   manifest_type == LOADER_DATA_FILE_MANIFEST_EXPLICIT_LAYER ? "explicit" : "implicit");
  ------------------
  |  Branch (3803:20): [True: 6.06k, False: 10.0k]
  ------------------
 3804|  16.1k|    }
 3805|  16.1k|    loader_log(inst, log_flags, 0, "   In following locations:");
 3806|       |
 3807|   132k|    for (size_t i = 0; i < search_paths.count; i++) {
  ------------------
  |  Branch (3807:24): [True: 116k, False: 16.1k]
  ------------------
 3808|   116k|        loader_log(inst, log_flags, 0, "      %s", search_paths.list[i]);
 3809|   116k|    }
 3810|       |
 3811|       |    // Now, parse the paths and add any manifest files found in them.
 3812|  16.1k|    vk_result = add_data_files(inst, &search_paths, out_files);
 3813|       |
 3814|  16.1k|    if (log_flags != 0 && out_files->count > 0) {
  ------------------
  |  Branch (3814:9): [True: 16.1k, False: 0]
  |  Branch (3814:27): [True: 7.44k, False: 8.66k]
  ------------------
 3815|  7.44k|        loader_log(inst, log_flags, 0, "   Found the following files:");
 3816|  23.0k|        for (uint32_t cur_file = 0; cur_file < out_files->count; ++cur_file) {
  ------------------
  |  Branch (3816:37): [True: 15.5k, False: 7.44k]
  ------------------
 3817|  15.5k|            loader_log(inst, log_flags, 0, "      %s", out_files->list[cur_file]);
 3818|  15.5k|        }
 3819|  8.66k|    } else {
 3820|  8.66k|        loader_log(inst, log_flags, 0, "   Found no files");
 3821|  8.66k|    }
 3822|       |
 3823|  16.1k|    if ((NULL != path_overrides && path_overrides->count > 0) || NULL != override_env) {
  ------------------
  |  Branch (3823:10): [True: 6.06k, False: 10.0k]
  |  Branch (3823:36): [True: 464, False: 5.60k]
  |  Branch (3823:66): [True: 0, False: 15.6k]
  ------------------
 3824|    464|        *override_active = true;
 3825|  15.6k|    } else {
 3826|  15.6k|        *override_active = false;
 3827|  15.6k|    }
 3828|       |
 3829|  16.1k|out:
 3830|       |
 3831|  16.1k|    loader_free_getenv(additional_env, inst);
 3832|  16.1k|    loader_free_getenv(override_env, inst);
 3833|       |#if defined(_WIN32)
 3834|       |    loader_instance_heap_free(inst, package_path);
 3835|       |#elif COMMON_UNIX_PLATFORMS
 3836|       |#if defined(__APPLE__)
 3837|       |    loader_instance_heap_free(inst, bundle_path);
 3838|       |    loader_free_getenv(search_only_in_bundle_env_var, inst);
 3839|       |#endif
 3840|  16.1k|    loader_free_getenv(xdg_config_home, inst);
 3841|  16.1k|    loader_free_getenv(xdg_config_dirs, inst);
 3842|  16.1k|    loader_free_getenv(xdg_data_home, inst);
 3843|  16.1k|    loader_free_getenv(xdg_data_dirs, inst);
 3844|  16.1k|    loader_free_getenv(xdg_data_home, inst);
 3845|  16.1k|    loader_free_getenv(home, inst);
 3846|  16.1k|    loader_instance_heap_free(inst, default_data_home);
 3847|  16.1k|    loader_instance_heap_free(inst, default_config_home);
 3848|       |#else
 3849|       |#warning read_data_files_in_search_paths unsupported platform
 3850|       |#endif
 3851|       |
 3852|  16.1k|    free_string_list(inst, &search_paths);
 3853|       |
 3854|  16.1k|    return vk_result;
 3855|  16.1k|}
loader_get_data_files:
 3881|  16.1k|                               const struct loader_string_list *path_overrides, struct loader_string_list *out_files) {
 3882|  16.1k|    VkResult res = VK_SUCCESS;
 3883|  16.1k|    bool override_active = false;
 3884|       |
 3885|       |    // Free and init the out_files information so there's no false data left from uninitialized variables.
 3886|  16.1k|    free_string_list(inst, out_files);
 3887|       |
 3888|  16.1k|    res = read_data_files_in_search_paths(inst, manifest_type, path_overrides, &override_active, out_files);
 3889|  16.1k|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (3889:9): [True: 0, False: 16.1k]
  ------------------
 3890|      0|        goto out;
 3891|      0|    }
 3892|       |
 3893|       |#if defined(_WIN32)
 3894|       |    // Read the registry if the override wasn't active.
 3895|       |    if (!override_active) {
 3896|       |        bool warn_if_not_present = false;
 3897|       |        char *registry_location = NULL;
 3898|       |
 3899|       |        switch (manifest_type) {
 3900|       |            default:
 3901|       |                goto out;
 3902|       |            case LOADER_DATA_FILE_MANIFEST_DRIVER:
 3903|       |                warn_if_not_present = true;
 3904|       |                registry_location = VK_DRIVERS_INFO_REGISTRY_LOC;
 3905|       |                break;
 3906|       |            case LOADER_DATA_FILE_MANIFEST_IMPLICIT_LAYER:
 3907|       |                registry_location = VK_ILAYERS_INFO_REGISTRY_LOC;
 3908|       |                break;
 3909|       |            case LOADER_DATA_FILE_MANIFEST_EXPLICIT_LAYER:
 3910|       |                warn_if_not_present = true;
 3911|       |                registry_location = VK_ELAYERS_INFO_REGISTRY_LOC;
 3912|       |                break;
 3913|       |        }
 3914|       |        VkResult tmp_res =
 3915|       |            windows_read_data_files_in_registry(inst, manifest_type, warn_if_not_present, registry_location, out_files);
 3916|       |        // Only return an error if there was an error this time, and no manifest files from before.
 3917|       |        if (VK_SUCCESS != tmp_res && out_files->count == 0) {
 3918|       |            res = tmp_res;
 3919|       |            goto out;
 3920|       |        }
 3921|       |    }
 3922|       |#endif
 3923|       |
 3924|  16.1k|out:
 3925|       |
 3926|  16.1k|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (3926:9): [True: 0, False: 16.1k]
  ------------------
 3927|      0|        free_string_list(inst, out_files);
 3928|      0|    }
 3929|       |
 3930|  16.1k|    return res;
 3931|  16.1k|}
loader_parse_instance_layers:
 4240|  16.1k|                                      const struct loader_string_list *path_overrides, struct loader_layer_list *instance_layers) {
 4241|  16.1k|    assert(manifest_type == LOADER_DATA_FILE_MANIFEST_IMPLICIT_LAYER || manifest_type == LOADER_DATA_FILE_MANIFEST_EXPLICIT_LAYER);
 4242|  16.1k|    VkResult res = VK_SUCCESS;
 4243|  16.1k|    struct loader_string_list manifest_files = {0};
 4244|       |
 4245|  16.1k|    res = loader_get_data_files(inst, manifest_type, path_overrides, &manifest_files);
 4246|  16.1k|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (4246:9): [True: 0, False: 16.1k]
  ------------------
 4247|      0|        goto out;
 4248|      0|    }
 4249|       |
 4250|  31.6k|    for (uint32_t i = 0; i < manifest_files.count; i++) {
  ------------------
  |  Branch (4250:26): [True: 15.5k, False: 16.1k]
  ------------------
 4251|  15.5k|        char *file_str = manifest_files.list[i];
 4252|  15.5k|        if (file_str == NULL) {
  ------------------
  |  Branch (4252:13): [True: 0, False: 15.5k]
  ------------------
 4253|      0|            continue;
 4254|      0|        }
 4255|       |
 4256|       |        // Parse file into JSON struct
 4257|  15.5k|        cJSON *json = NULL;
 4258|  15.5k|        VkResult local_res = loader_get_json(inst, file_str, &json);
 4259|  15.5k|        if (VK_ERROR_OUT_OF_HOST_MEMORY == local_res) {
  ------------------
  |  Branch (4259:13): [True: 0, False: 15.5k]
  ------------------
 4260|      0|            res = VK_ERROR_OUT_OF_HOST_MEMORY;
 4261|      0|            goto out;
 4262|  15.5k|        } else if (VK_SUCCESS != local_res || NULL == json) {
  ------------------
  |  Branch (4262:20): [True: 1.24k, False: 14.3k]
  |  Branch (4262:47): [True: 7.41k, False: 6.92k]
  ------------------
 4263|  8.66k|            continue;
 4264|  8.66k|        }
 4265|       |
 4266|  6.92k|        local_res = loader_add_layer_properties(inst, instance_layers, json,
 4267|  6.92k|                                                manifest_type == LOADER_DATA_FILE_MANIFEST_IMPLICIT_LAYER, file_str);
 4268|  6.92k|        loader_cJSON_Delete(json);
 4269|       |
 4270|       |        // If the error is anything other than out of memory we still want to try to load the other layers
 4271|  6.92k|        if (VK_ERROR_OUT_OF_HOST_MEMORY == local_res) {
  ------------------
  |  Branch (4271:13): [True: 0, False: 6.92k]
  ------------------
 4272|      0|            res = VK_ERROR_OUT_OF_HOST_MEMORY;
 4273|      0|            goto out;
 4274|      0|        }
 4275|  6.92k|    }
 4276|  16.1k|out:
 4277|  16.1k|    free_string_list(inst, &manifest_files);
 4278|       |
 4279|  16.1k|    return res;
 4280|  16.1k|}
get_override_layer_override_paths:
 4285|    534|                                           struct loader_string_list *override_paths) {
 4286|    534|    if (prop->override_paths.count > 0) {
  ------------------
  |  Branch (4286:9): [True: 464, False: 70]
  ------------------
 4287|  16.7k|        for (uint32_t j = 0; j < prop->override_paths.count; j++) {
  ------------------
  |  Branch (4287:30): [True: 16.2k, False: 464]
  ------------------
 4288|  16.2k|            VkResult result = copy_data_file_info(inst, prop->override_paths.list[j], NULL, 0, override_paths);
 4289|  16.2k|            if (VK_SUCCESS != result) {
  ------------------
  |  Branch (4289:17): [True: 0, False: 16.2k]
  ------------------
 4290|      0|                return result;
 4291|      0|            }
 4292|  16.2k|            loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0, "Override layer has override path %s",
 4293|  16.2k|                       prop->override_paths.list[j]);
 4294|  16.2k|        }
 4295|    464|    }
 4296|    534|    return VK_SUCCESS;
 4297|    534|}
loader_remove_duplicate_layers:
 4299|  10.0k|void loader_remove_duplicate_layers(struct loader_instance *inst, struct loader_layer_list *layers) {
 4300|       |    // Remove duplicate layers (that share the same layerName)
 4301|  19.3k|    for (uint32_t i = 0; i < layers->count; ++i) {
  ------------------
  |  Branch (4301:26): [True: 9.34k, False: 10.0k]
  ------------------
 4302|  9.34k|        bool has_duplicate = false;
 4303|  9.34k|        uint32_t duplicate_index = 0;
 4304|  43.4k|        for (uint32_t j = i + 1; j < layers->count; ++j) {
  ------------------
  |  Branch (4304:34): [True: 40.9k, False: 2.53k]
  ------------------
 4305|  40.9k|            if (strcmp(layers->list[i].info.layerName, layers->list[j].info.layerName) == 0) {
  ------------------
  |  Branch (4305:17): [True: 6.81k, False: 34.0k]
  ------------------
 4306|  6.81k|                has_duplicate = true;
 4307|  6.81k|                duplicate_index = j;
 4308|  6.81k|                break;
 4309|  6.81k|            }
 4310|  40.9k|        }
 4311|  9.34k|        if (has_duplicate) {
  ------------------
  |  Branch (4311:13): [True: 6.81k, False: 2.53k]
  ------------------
 4312|  6.81k|            loader_log(inst, VULKAN_LOADER_WARN_BIT, 0, "Removing layer %s (%s) because it is a duplicate of %s (%s)",
 4313|  6.81k|                       layers->list[duplicate_index].info.layerName, layers->list[duplicate_index].manifest_file_name,
 4314|  6.81k|                       layers->list[i].info.layerName, layers->list[i].manifest_file_name);
 4315|  6.81k|            loader_remove_layer_in_list(inst, layers, duplicate_index);
 4316|  6.81k|        }
 4317|  9.34k|    }
 4318|  10.0k|}
loader_scan_for_layers:
 4321|  5.96k|                                const struct loader_envvar_all_filters *filters) {
 4322|  5.96k|    VkResult res = VK_SUCCESS;
 4323|  5.96k|    struct loader_layer_list settings_layers = {0};
 4324|  5.96k|    struct loader_layer_list regular_instance_layers = {0};
 4325|  5.96k|    bool override_layer_valid = false;
 4326|  5.96k|    struct loader_string_list override_paths = {0};
 4327|       |
 4328|  5.96k|    bool should_search_for_other_layers = true;
 4329|  5.96k|    res = get_settings_layers(inst, &settings_layers, &should_search_for_other_layers);
 4330|  5.96k|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (4330:9): [True: 0, False: 5.96k]
  ------------------
 4331|      0|        goto out;
 4332|      0|    }
 4333|       |
 4334|       |    // If we should not look for layers using other mechanisms, assign settings_layers to instance_layers and jump to the
 4335|       |    // output
 4336|  5.96k|    if (!should_search_for_other_layers) {
  ------------------
  |  Branch (4336:9): [True: 941, False: 5.01k]
  ------------------
 4337|    941|        *instance_layers = settings_layers;
 4338|    941|        memset(&settings_layers, 0, sizeof(struct loader_layer_list));
 4339|    941|        goto out;
 4340|    941|    }
 4341|       |
 4342|  5.01k|    res = loader_parse_instance_layers(inst, LOADER_DATA_FILE_MANIFEST_IMPLICIT_LAYER, NULL, &regular_instance_layers);
 4343|  5.01k|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (4343:9): [True: 0, False: 5.01k]
  ------------------
 4344|      0|        goto out;
 4345|      0|    }
 4346|       |
 4347|       |    // Remove any extraneous override layers.
 4348|  5.01k|    remove_all_non_valid_override_layers(inst, &regular_instance_layers);
 4349|       |
 4350|       |    // Check to see if the override layer is present, and use it's override paths.
 4351|  6.25k|    for (uint32_t i = 0; i < regular_instance_layers.count; i++) {
  ------------------
  |  Branch (4351:26): [True: 1.34k, False: 4.91k]
  ------------------
 4352|  1.34k|        struct loader_layer_properties *prop = &regular_instance_layers.list[i];
 4353|  1.34k|        if (prop->is_override && loader_implicit_layer_is_enabled(inst, filters, prop) && prop->override_paths.count > 0) {
  ------------------
  |  Branch (4353:13): [True: 221, False: 1.12k]
  |  Branch (4353:34): [True: 165, False: 56]
  |  Branch (4353:91): [True: 101, False: 64]
  ------------------
 4354|    101|            res = get_override_layer_override_paths(inst, prop, &override_paths);
 4355|    101|            if (VK_SUCCESS != res) {
  ------------------
  |  Branch (4355:17): [True: 0, False: 101]
  ------------------
 4356|      0|                goto out;
 4357|      0|            }
 4358|    101|            break;
 4359|    101|        }
 4360|  1.34k|    }
 4361|       |
 4362|       |    // Get a list of manifest files for explicit layers
 4363|  5.01k|    res = loader_parse_instance_layers(inst, LOADER_DATA_FILE_MANIFEST_EXPLICIT_LAYER, &override_paths, &regular_instance_layers);
 4364|  5.01k|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (4364:9): [True: 0, False: 5.01k]
  ------------------
 4365|      0|        goto out;
 4366|      0|    }
 4367|       |
 4368|       |    // Verify any meta-layers in the list are valid and all the component layers are
 4369|       |    // actually present in the available layer list
 4370|  5.01k|    res = verify_all_meta_layers(inst, filters, &regular_instance_layers, &override_layer_valid);
 4371|  5.01k|    if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
  ------------------
  |  Branch (4371:9): [True: 0, False: 5.01k]
  ------------------
 4372|      0|        return res;
 4373|      0|    }
 4374|       |
 4375|  5.01k|    if (override_layer_valid) {
  ------------------
  |  Branch (4375:9): [True: 156, False: 4.86k]
  ------------------
 4376|    156|        loader_remove_layers_in_blacklist(inst, &regular_instance_layers);
 4377|    156|        if (NULL != inst) {
  ------------------
  |  Branch (4377:13): [True: 0, False: 156]
  ------------------
 4378|      0|            inst->override_layer_present = true;
 4379|      0|        }
 4380|    156|    }
 4381|       |
 4382|       |    // Remove disabled layers
 4383|  8.89k|    for (uint32_t i = 0; i < regular_instance_layers.count; ++i) {
  ------------------
  |  Branch (4383:26): [True: 3.87k, False: 5.01k]
  ------------------
 4384|  3.87k|        if (!loader_layer_is_available(inst, filters, &regular_instance_layers.list[i])) {
  ------------------
  |  Branch (4384:13): [True: 0, False: 3.87k]
  ------------------
 4385|      0|            loader_remove_layer_in_list(inst, &regular_instance_layers, i);
 4386|      0|            i--;
 4387|      0|        }
 4388|  3.87k|    }
 4389|       |
 4390|       |    // Make sure no layers have the same layerName
 4391|  5.01k|    loader_remove_duplicate_layers(inst, &regular_instance_layers);
 4392|       |
 4393|  5.01k|    res = combine_settings_layers_with_regular_layers(inst, &settings_layers, &regular_instance_layers, instance_layers);
 4394|       |
 4395|  5.96k|out:
 4396|  5.96k|    loader_delete_layer_list_and_properties(inst, &settings_layers);
 4397|  5.96k|    loader_delete_layer_list_and_properties(inst, &regular_instance_layers);
 4398|       |
 4399|  5.96k|    free_string_list(inst, &override_paths);
 4400|  5.96k|    return res;
 4401|  5.01k|}
loader_scan_for_implicit_layers:
 4404|  5.96k|                                         const struct loader_envvar_all_filters *layer_filters) {
 4405|  5.96k|    VkResult res = VK_SUCCESS;
 4406|  5.96k|    struct loader_layer_list settings_layers = {0};
 4407|  5.96k|    struct loader_layer_list regular_instance_layers = {0};
 4408|  5.96k|    bool override_layer_valid = false;
 4409|  5.96k|    struct loader_string_list override_paths = {0};
 4410|  5.96k|    bool implicit_metalayer_present = false;
 4411|       |
 4412|  5.96k|    bool should_search_for_other_layers = true;
 4413|  5.96k|    res = get_settings_layers(inst, &settings_layers, &should_search_for_other_layers);
 4414|  5.96k|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (4414:9): [True: 0, False: 5.96k]
  ------------------
 4415|      0|        goto out;
 4416|      0|    }
 4417|       |
 4418|       |    // Remove layers from settings file that are off, are explicit, or are implicit layers that aren't active
 4419|  52.5k|    for (uint32_t i = 0; i < settings_layers.count; ++i) {
  ------------------
  |  Branch (4419:26): [True: 46.6k, False: 5.96k]
  ------------------
 4420|  46.6k|        if (settings_layers.list[i].settings_control_value == LOADER_SETTINGS_LAYER_CONTROL_OFF ||
  ------------------
  |  Branch (4420:13): [True: 19.0k, False: 27.5k]
  ------------------
 4421|  27.5k|            settings_layers.list[i].settings_control_value == LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION ||
  ------------------
  |  Branch (4421:13): [True: 27.5k, False: 60]
  ------------------
 4422|     60|            (settings_layers.list[i].type_flags & VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER) == VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER ||
  ------------------
  |  Branch (4422:13): [True: 60, False: 0]
  ------------------
 4423|  46.6k|            !loader_implicit_layer_is_enabled(inst, layer_filters, &settings_layers.list[i])) {
  ------------------
  |  Branch (4423:13): [True: 0, False: 0]
  ------------------
 4424|  46.6k|            loader_remove_layer_in_list(inst, &settings_layers, i);
 4425|  46.6k|            i--;
 4426|  46.6k|        }
 4427|  46.6k|    }
 4428|       |
 4429|       |    // If we should not look for layers using other mechanisms, assign settings_layers to instance_layers and jump to the
 4430|       |    // output
 4431|  5.96k|    if (!should_search_for_other_layers) {
  ------------------
  |  Branch (4431:9): [True: 941, False: 5.01k]
  ------------------
 4432|    941|        *instance_layers = settings_layers;
 4433|    941|        memset(&settings_layers, 0, sizeof(struct loader_layer_list));
 4434|    941|        goto out;
 4435|    941|    }
 4436|       |
 4437|  5.01k|    res = loader_parse_instance_layers(inst, LOADER_DATA_FILE_MANIFEST_IMPLICIT_LAYER, NULL, &regular_instance_layers);
 4438|  5.01k|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (4438:9): [True: 0, False: 5.01k]
  ------------------
 4439|      0|        goto out;
 4440|      0|    }
 4441|       |
 4442|       |    // Remove any extraneous override layers.
 4443|  5.01k|    remove_all_non_valid_override_layers(inst, &regular_instance_layers);
 4444|       |
 4445|       |    // Check to see if either the override layer is present, or another implicit meta-layer.
 4446|       |    // Each of these may require explicit layers to be enabled at this time.
 4447|  16.5k|    for (uint32_t i = 0; i < regular_instance_layers.count; i++) {
  ------------------
  |  Branch (4447:26): [True: 11.5k, False: 5.01k]
  ------------------
 4448|  11.5k|        struct loader_layer_properties *prop = &regular_instance_layers.list[i];
 4449|  11.5k|        if (prop->is_override && loader_implicit_layer_is_enabled(inst, layer_filters, prop)) {
  ------------------
  |  Branch (4449:13): [True: 479, False: 11.0k]
  |  Branch (4449:34): [True: 433, False: 46]
  ------------------
 4450|    433|            override_layer_valid = true;
 4451|    433|            res = get_override_layer_override_paths(inst, prop, &override_paths);
 4452|    433|            if (VK_SUCCESS != res) {
  ------------------
  |  Branch (4452:17): [True: 0, False: 433]
  ------------------
 4453|      0|                goto out;
 4454|      0|            }
 4455|  11.0k|        } else if (!prop->is_override && prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER) {
  ------------------
  |  Branch (4455:20): [True: 11.0k, False: 46]
  |  Branch (4455:42): [True: 10.2k, False: 741]
  ------------------
 4456|  10.2k|            implicit_metalayer_present = true;
 4457|  10.2k|        }
 4458|  11.5k|    }
 4459|       |
 4460|       |    // If either the override layer or an implicit meta-layer are present, we need to add
 4461|       |    // explicit layer info as well.  Not to worry, though, all explicit layers not included
 4462|       |    // in the override layer will be removed below in loader_remove_layers_in_blacklist().
 4463|  5.01k|    if (override_layer_valid || implicit_metalayer_present) {
  ------------------
  |  Branch (4463:9): [True: 433, False: 4.58k]
  |  Branch (4463:33): [True: 616, False: 3.97k]
  ------------------
 4464|  1.04k|        res =
 4465|  1.04k|            loader_parse_instance_layers(inst, LOADER_DATA_FILE_MANIFEST_EXPLICIT_LAYER, &override_paths, &regular_instance_layers);
 4466|  1.04k|        if (VK_SUCCESS != res) {
  ------------------
  |  Branch (4466:13): [True: 0, False: 1.04k]
  ------------------
 4467|      0|            goto out;
 4468|      0|        }
 4469|  1.04k|    }
 4470|       |
 4471|       |    // Verify any meta-layers in the list are valid and all the component layers are
 4472|       |    // actually present in the available layer list
 4473|  5.01k|    res = verify_all_meta_layers(inst, layer_filters, &regular_instance_layers, &override_layer_valid);
 4474|  5.01k|    if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
  ------------------
  |  Branch (4474:9): [True: 0, False: 5.01k]
  ------------------
 4475|      0|        return res;
 4476|      0|    }
 4477|       |
 4478|  5.01k|    if (override_layer_valid || implicit_metalayer_present) {
  ------------------
  |  Branch (4478:9): [True: 416, False: 4.60k]
  |  Branch (4478:33): [True: 627, False: 3.97k]
  ------------------
 4479|  1.04k|        loader_remove_layers_not_in_implicit_meta_layers(inst, &regular_instance_layers);
 4480|  1.04k|        if (override_layer_valid && inst != NULL) {
  ------------------
  |  Branch (4480:13): [True: 416, False: 627]
  |  Branch (4480:37): [True: 0, False: 416]
  ------------------
 4481|      0|            inst->override_layer_present = true;
 4482|      0|        }
 4483|  1.04k|    }
 4484|       |
 4485|       |    // Remove disabled layers
 4486|  17.6k|    for (uint32_t i = 0; i < regular_instance_layers.count; ++i) {
  ------------------
  |  Branch (4486:26): [True: 12.5k, False: 5.01k]
  ------------------
 4487|  12.5k|        if (!loader_implicit_layer_is_enabled(inst, layer_filters, &regular_instance_layers.list[i])) {
  ------------------
  |  Branch (4487:13): [True: 299, False: 12.2k]
  ------------------
 4488|    299|            loader_remove_layer_in_list(inst, &regular_instance_layers, i);
 4489|    299|            i--;
 4490|    299|        }
 4491|  12.5k|    }
 4492|       |
 4493|       |    // Make sure no layers have the same layerName
 4494|  5.01k|    loader_remove_duplicate_layers(inst, &regular_instance_layers);
 4495|       |
 4496|  5.01k|    res = combine_settings_layers_with_regular_layers(inst, &settings_layers, &regular_instance_layers, instance_layers);
 4497|       |
 4498|  5.96k|out:
 4499|  5.96k|    loader_delete_layer_list_and_properties(inst, &settings_layers);
 4500|  5.96k|    loader_delete_layer_list_and_properties(inst, &regular_instance_layers);
 4501|       |
 4502|  5.96k|    free_string_list(inst, &override_paths);
 4503|  5.96k|    return res;
 4504|  5.01k|}
vk_string_validate:
 7542|  5.96k|TEST_FUNCTION_EXPORT VkStringErrorFlags vk_string_validate(const int max_length, const char *utf8) {
 7543|  5.96k|    VkStringErrorFlags result = VK_STRING_ERROR_NONE;
 7544|  5.96k|    int num_char_bytes = 0;
 7545|  5.96k|    int i;
 7546|  5.96k|    int j;
 7547|       |
 7548|  5.96k|    if (utf8 == NULL) {
  ------------------
  |  Branch (7548:9): [True: 0, False: 5.96k]
  ------------------
 7549|      0|        return VK_STRING_ERROR_NULL_PTR;
 7550|      0|    }
 7551|       |
 7552|  59.6k|    for (i = 0; i <= max_length; i++) {
  ------------------
  |  Branch (7552:17): [True: 59.6k, False: 0]
  ------------------
 7553|  59.6k|        if (utf8[i] == 0) {
  ------------------
  |  Branch (7553:13): [True: 5.96k, False: 53.6k]
  ------------------
 7554|  5.96k|            break;
 7555|  5.96k|        }
 7556|  53.6k|        if (i == max_length) {
  ------------------
  |  Branch (7556:13): [True: 0, False: 53.6k]
  ------------------
 7557|      0|            result |= VK_STRING_ERROR_LENGTH;
 7558|      0|            break;
 7559|      0|        }
 7560|  53.6k|        if ((utf8[i] >= 0x20) && (utf8[i] < 0x7f)) {
  ------------------
  |  Branch (7560:13): [True: 53.6k, False: 0]
  |  Branch (7560:34): [True: 53.6k, False: 0]
  ------------------
 7561|  53.6k|            num_char_bytes = 0;
 7562|  53.6k|        } else if ((utf8[i] & UTF8_ONE_BYTE_MASK) == UTF8_ONE_BYTE_CODE) {
  ------------------
  |  Branch (7562:20): [True: 0, False: 0]
  ------------------
 7563|      0|            num_char_bytes = 1;
 7564|      0|        } else if ((utf8[i] & UTF8_TWO_BYTE_MASK) == UTF8_TWO_BYTE_CODE) {
  ------------------
  |  Branch (7564:20): [True: 0, False: 0]
  ------------------
 7565|      0|            num_char_bytes = 2;
 7566|      0|        } else if ((utf8[i] & UTF8_THREE_BYTE_MASK) == UTF8_THREE_BYTE_CODE) {
  ------------------
  |  Branch (7566:20): [True: 0, False: 0]
  ------------------
 7567|      0|            num_char_bytes = 3;
 7568|      0|        } else {
 7569|      0|            result = VK_STRING_ERROR_BAD_DATA;
 7570|      0|        }
 7571|       |
 7572|       |        // Validate the following num_char_bytes of data
 7573|  53.6k|        for (j = 0; (j < num_char_bytes) && (i < max_length); j++) {
  ------------------
  |  Branch (7573:21): [True: 0, False: 53.6k]
  |  Branch (7573:45): [True: 0, False: 0]
  ------------------
 7574|      0|            if (++i == max_length) {
  ------------------
  |  Branch (7574:17): [True: 0, False: 0]
  ------------------
 7575|      0|                result |= VK_STRING_ERROR_LENGTH;
 7576|      0|                break;
 7577|      0|            }
 7578|      0|            if (utf8[i] == 0) {
  ------------------
  |  Branch (7578:17): [True: 0, False: 0]
  ------------------
 7579|       |                // The string terminated in the middle of a multi-byte character. Stop here so the
 7580|       |                // continuation-byte scan doesn't read past the terminator.
 7581|      0|                result |= VK_STRING_ERROR_BAD_DATA;
 7582|      0|                return result;
 7583|      0|            }
 7584|      0|            if ((utf8[i] & UTF8_DATA_BYTE_MASK) != UTF8_DATA_BYTE_CODE) {
  ------------------
  |  Branch (7584:17): [True: 0, False: 0]
  ------------------
 7585|      0|                result |= VK_STRING_ERROR_BAD_DATA;
 7586|      0|            }
 7587|      0|        }
 7588|  53.6k|    }
 7589|  5.96k|    return result;
 7590|  5.96k|}
terminator_EnumerateInstanceExtensionProperties:
 7606|  5.96k|                                                                               VkExtensionProperties *pProperties) {
 7607|  5.96k|    struct loader_extension_list *global_ext_list = NULL;
 7608|  5.96k|    struct loader_layer_list instance_layers;
 7609|  5.96k|    struct loader_extension_list local_ext_list;
 7610|  5.96k|    struct loader_icd_tramp_list icd_tramp_list;
 7611|  5.96k|    uint32_t copy_size;
 7612|  5.96k|    VkResult res = VK_SUCCESS;
 7613|  5.96k|    struct loader_envvar_all_filters layer_filters = {0};
 7614|       |
 7615|  5.96k|    memset(&local_ext_list, 0, sizeof(local_ext_list));
 7616|  5.96k|    memset(&instance_layers, 0, sizeof(instance_layers));
 7617|  5.96k|    memset(&icd_tramp_list, 0, sizeof(icd_tramp_list));
 7618|       |
 7619|  5.96k|    res = parse_layer_environment_var_filters(NULL, &layer_filters);
 7620|  5.96k|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (7620:9): [True: 0, False: 5.96k]
  ------------------
 7621|      0|        goto out;
 7622|      0|    }
 7623|       |
 7624|       |    // Get layer libraries if needed
 7625|  5.96k|    if (pLayerName && strlen(pLayerName) != 0) {
  ------------------
  |  Branch (7625:9): [True: 5.96k, False: 0]
  |  Branch (7625:23): [True: 5.96k, False: 0]
  ------------------
 7626|  5.96k|        if (vk_string_validate(MaxLoaderStringLength, pLayerName) != VK_STRING_ERROR_NONE) {
  ------------------
  |  Branch (7626:13): [True: 0, False: 5.96k]
  ------------------
 7627|      0|            assert(VK_FALSE && "vkEnumerateInstanceExtensionProperties: pLayerName is too long or is badly formed");
 7628|      0|            res = VK_ERROR_EXTENSION_NOT_PRESENT;
 7629|      0|            goto out;
 7630|      0|        }
 7631|       |
 7632|  5.96k|        res = loader_scan_for_layers(NULL, &instance_layers, &layer_filters);
 7633|  5.96k|        if (VK_SUCCESS != res) {
  ------------------
  |  Branch (7633:13): [True: 0, False: 5.96k]
  ------------------
 7634|      0|            goto out;
 7635|      0|        }
 7636|  46.9k|        for (uint32_t i = 0; i < instance_layers.count; i++) {
  ------------------
  |  Branch (7636:30): [True: 41.4k, False: 5.52k]
  ------------------
 7637|  41.4k|            struct loader_layer_properties *props = &instance_layers.list[i];
 7638|  41.4k|            if (strcmp(props->info.layerName, pLayerName) == 0) {
  ------------------
  |  Branch (7638:17): [True: 431, False: 40.9k]
  ------------------
 7639|    431|                global_ext_list = &props->instance_extension_list;
 7640|    431|                break;
 7641|    431|            }
 7642|  41.4k|        }
 7643|  5.96k|    } else {
 7644|       |        // Preload ICD libraries so subsequent calls to EnumerateInstanceExtensionProperties don't have to load them
 7645|      0|        loader_preload_icds();
 7646|       |
 7647|       |        // Scan/discover all ICD libraries
 7648|      0|        res = loader_icd_scan(NULL, &icd_tramp_list, NULL, NULL);
 7649|       |        // EnumerateInstanceExtensionProperties can't return anything other than OOM or VK_ERROR_LAYER_NOT_PRESENT
 7650|      0|        if ((VK_SUCCESS != res && icd_tramp_list.count > 0) || res == VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (7650:14): [True: 0, False: 0]
  |  Branch (7650:35): [True: 0, False: 0]
  |  Branch (7650:64): [True: 0, False: 0]
  ------------------
 7651|      0|            goto out;
 7652|      0|        }
 7653|       |        // Get extensions from all ICD's, merge so no duplicates
 7654|      0|        res = loader_get_icd_loader_instance_extensions(NULL, &icd_tramp_list, &local_ext_list);
 7655|      0|        if (VK_SUCCESS != res) {
  ------------------
  |  Branch (7655:13): [True: 0, False: 0]
  ------------------
 7656|      0|            goto out;
 7657|      0|        }
 7658|      0|        loader_clear_scanned_icd_list(NULL, &icd_tramp_list);
 7659|       |
 7660|       |        // Append enabled implicit layers.
 7661|      0|        res = loader_scan_for_implicit_layers(NULL, &instance_layers, &layer_filters);
 7662|      0|        if (VK_SUCCESS != res) {
  ------------------
  |  Branch (7662:13): [True: 0, False: 0]
  ------------------
 7663|      0|            goto out;
 7664|      0|        }
 7665|      0|        for (uint32_t i = 0; i < instance_layers.count; i++) {
  ------------------
  |  Branch (7665:30): [True: 0, False: 0]
  ------------------
 7666|      0|            struct loader_extension_list *ext_list = &instance_layers.list[i].instance_extension_list;
 7667|      0|            res = loader_add_to_ext_list(NULL, &local_ext_list, ext_list->count, ext_list->list);
 7668|      0|            if (VK_SUCCESS != res) {
  ------------------
  |  Branch (7668:17): [True: 0, False: 0]
  ------------------
 7669|      0|                goto out;
 7670|      0|            }
 7671|      0|        }
 7672|       |
 7673|      0|        global_ext_list = &local_ext_list;
 7674|      0|    }
 7675|       |
 7676|  5.96k|    if (global_ext_list == NULL) {
  ------------------
  |  Branch (7676:9): [True: 5.52k, False: 431]
  ------------------
 7677|  5.52k|        res = VK_ERROR_LAYER_NOT_PRESENT;
 7678|  5.52k|        goto out;
 7679|  5.52k|    }
 7680|       |
 7681|    431|    if (pProperties == NULL) {
  ------------------
  |  Branch (7681:9): [True: 277, False: 154]
  ------------------
 7682|    277|        *pPropertyCount = global_ext_list->count;
 7683|    277|        goto out;
 7684|    277|    }
 7685|       |
 7686|    154|    copy_size = *pPropertyCount < global_ext_list->count ? *pPropertyCount : global_ext_list->count;
  ------------------
  |  Branch (7686:17): [True: 0, False: 154]
  ------------------
 7687|    238|    for (uint32_t i = 0; i < copy_size; i++) {
  ------------------
  |  Branch (7687:26): [True: 84, False: 154]
  ------------------
 7688|     84|        memcpy(&pProperties[i], &global_ext_list->list[i], sizeof(VkExtensionProperties));
 7689|     84|    }
 7690|    154|    *pPropertyCount = copy_size;
 7691|       |
 7692|    154|    if (copy_size < global_ext_list->count) {
  ------------------
  |  Branch (7692:9): [True: 0, False: 154]
  ------------------
 7693|      0|        res = VK_INCOMPLETE;
 7694|      0|        goto out;
 7695|      0|    }
 7696|       |
 7697|  5.96k|out:
 7698|  5.96k|    loader_destroy_generic_list(NULL, (struct loader_generic_list *)&icd_tramp_list);
 7699|  5.96k|    loader_destroy_generic_list(NULL, (struct loader_generic_list *)&local_ext_list);
 7700|       |    loader_delete_layer_list_and_properties(NULL, &instance_layers);
 7701|  5.96k|    return res;
 7702|    154|}
terminator_pre_instance_EnumerateInstanceExtensionProperties:
 7706|  5.96k|    VkExtensionProperties *pProperties) {
 7707|  5.96k|    (void)chain;
 7708|  5.96k|    return terminator_EnumerateInstanceExtensionProperties(pLayerName, pPropertyCount, pProperties);
 7709|  5.96k|}

loader_getenv:
   43|  12.4k|char *loader_getenv(const char *name, const struct loader_instance *inst) {
   44|  12.4k|    if (NULL == name) return NULL;
  ------------------
  |  Branch (44:9): [True: 0, False: 12.4k]
  ------------------
   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|  12.4k|    (void)inst;
   48|       |    // NOLINTNEXTLINE(concurrency-mt-unsafe) - there is no portable reentrant getenv; the loader never calls setenv concurrently
   49|  12.4k|    return getenv(name);
   50|  12.4k|}
loader_secure_getenv:
   52|   178k|char *loader_secure_getenv(const char *name, const struct loader_instance *inst) {
   53|       |#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__)
   54|       |    // Apple does not appear to have a secure getenv implementation.
   55|       |    // The main difference between secure getenv and getenv is that secure getenv
   56|       |    // returns NULL if the process is being run with elevated privileges by a normal user.
   57|       |    // The idea is to prevent the reading of malicious environment variables by a process
   58|       |    // that can do damage.
   59|       |    // This algorithm is derived from glibc code that sets an internal
   60|       |    // variable (__libc_enable_secure) if the process is running under setuid or setgid.
   61|       |    return is_high_integrity() ? NULL : loader_getenv(name, inst);
   62|       |#elif defined(__Fuchsia__)
   63|       |    return loader_getenv(name, inst);
   64|       |#else
   65|       |    // Linux
   66|   178k|    char *out;
   67|   178k|#if defined(HAVE_SECURE_GETENV) && !defined(LOADER_USE_UNSAFE_FILE_SEARCH)
   68|   178k|    (void)inst;
   69|   178k|    out = secure_getenv(name);
   70|       |#elif defined(HAVE___SECURE_GETENV) && !defined(LOADER_USE_UNSAFE_FILE_SEARCH)
   71|       |    (void)inst;
   72|       |    out = __secure_getenv(name);
   73|       |#else
   74|       |    out = loader_getenv(name, inst);
   75|       |#if !defined(LOADER_USE_UNSAFE_FILE_SEARCH)
   76|       |    loader_log(inst, VULKAN_LOADER_INFO_BIT, 0, "Loader is using non-secure environment variable lookup for %s", name);
   77|       |#endif
   78|       |#endif
   79|   178k|    return out;
   80|   178k|#endif
   81|   178k|}
loader_free_getenv:
   83|   165k|void loader_free_getenv(const char *val, const struct loader_instance *inst) {
   84|       |    // No freeing of memory necessary for Linux, but we should at least touch
   85|       |    // the val and inst pointers to get rid of compiler warnings.
   86|   165k|    (void)val;
   87|   165k|    (void)inst;
   88|   165k|}
determine_filter_type:
  193|  11.9k|                           size_t *new_length) {
  194|  11.9k|    size_t filter_length = strlen(filter_string);
  195|  11.9k|    bool star_begin = false;
  196|  11.9k|    bool star_end = false;
  197|  11.9k|    if ('~' == filter_string[0]) {
  ------------------
  |  Branch (197:9): [True: 0, False: 11.9k]
  ------------------
  198|       |        // One of the special identifiers like: ~all~, ~implicit~, or ~explicit~
  199|      0|        *filter_type = FILTER_STRING_SPECIAL;
  200|      0|        *new_start = filter_string;
  201|      0|        *new_length = filter_length;
  202|  11.9k|    } else {
  203|  11.9k|        if ('*' == filter_string[0]) {
  ------------------
  |  Branch (203:13): [True: 0, False: 11.9k]
  ------------------
  204|       |            // Only the * means everything
  205|      0|            if (filter_length == 1) {
  ------------------
  |  Branch (205:17): [True: 0, False: 0]
  ------------------
  206|      0|                *filter_type = FILTER_STRING_SPECIAL;
  207|      0|                *new_start = filter_string;
  208|      0|                *new_length = filter_length;
  209|      0|                return;
  210|      0|            }
  211|      0|            star_begin = true;
  212|      0|        }
  213|  11.9k|        if ('*' == filter_string[filter_length - 1]) {
  ------------------
  |  Branch (213:13): [True: 0, False: 11.9k]
  ------------------
  214|       |            // Not really valid, but just catch this case so if someone accidentally types "**" it will also mean everything
  215|      0|            if (star_begin && filter_length == 2) {
  ------------------
  |  Branch (215:17): [True: 0, False: 0]
  |  Branch (215:31): [True: 0, False: 0]
  ------------------
  216|      0|                *filter_type = FILTER_STRING_SPECIAL;
  217|      0|                *new_start = filter_string;
  218|      0|                *new_length = filter_length;
  219|      0|                return;
  220|      0|            }
  221|      0|            star_end = true;
  222|      0|        }
  223|  11.9k|        if (star_begin && star_end) {
  ------------------
  |  Branch (223:13): [True: 0, False: 11.9k]
  |  Branch (223:27): [True: 0, False: 0]
  ------------------
  224|      0|            *filter_type = FILTER_STRING_SUBSTRING;
  225|      0|            *new_start = &filter_string[1];
  226|      0|            *new_length = filter_length - 2;
  227|  11.9k|        } else if (star_begin) {
  ------------------
  |  Branch (227:20): [True: 0, False: 11.9k]
  ------------------
  228|      0|            *new_start = &filter_string[1];
  229|      0|            *new_length = filter_length - 1;
  230|      0|            *filter_type = FILTER_STRING_SUFFIX;
  231|  11.9k|        } else if (star_end) {
  ------------------
  |  Branch (231:20): [True: 0, False: 11.9k]
  ------------------
  232|      0|            *filter_type = FILTER_STRING_PREFIX;
  233|      0|            *new_start = filter_string;
  234|      0|            *new_length = filter_length - 1;
  235|  11.9k|        } else {
  236|  11.9k|            *filter_type = FILTER_STRING_FULLNAME;
  237|  11.9k|            *new_start = filter_string;
  238|  11.9k|            *new_length = filter_length;
  239|  11.9k|        }
  240|  11.9k|    }
  241|  11.9k|}
parse_generic_filter_environment_var:
  246|  23.8k|                                              struct loader_envvar_filter *filter_struct) {
  247|  23.8k|    VkResult result = VK_SUCCESS;
  248|  23.8k|    memset(filter_struct, 0, sizeof(struct loader_envvar_filter));
  249|  23.8k|    char *parsing_string = NULL;
  250|  23.8k|    char *env_var_value = loader_secure_getenv(env_var_name, inst);
  251|  23.8k|    if (NULL == env_var_value) {
  ------------------
  |  Branch (251:9): [True: 11.9k, False: 11.9k]
  ------------------
  252|  11.9k|        return result;
  253|  11.9k|    }
  254|  11.9k|    const size_t env_var_len = strlen(env_var_value);
  255|  11.9k|    if (env_var_len == 0) {
  ------------------
  |  Branch (255:9): [True: 0, False: 11.9k]
  ------------------
  256|      0|        goto out;
  257|      0|    }
  258|       |    // Allocate a separate string since scan_for_next_comma modifies the original string
  259|  11.9k|    parsing_string = loader_instance_heap_calloc(inst, env_var_len + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  260|  11.9k|    if (NULL == parsing_string) {
  ------------------
  |  Branch (260:9): [True: 0, False: 11.9k]
  ------------------
  261|      0|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
  262|      0|                   "parse_generic_filter_environment_var: Failed to allocate space for parsing env var \'%s\'", env_var_name);
  263|      0|        result = VK_ERROR_OUT_OF_HOST_MEMORY;
  264|      0|        goto out;
  265|      0|    }
  266|       |
  267|  47.6k|    for (uint32_t iii = 0; iii < env_var_len; ++iii) {
  ------------------
  |  Branch (267:28): [True: 35.7k, False: 11.9k]
  ------------------
  268|  35.7k|        parsing_string[iii] = (char)tolower((unsigned char)env_var_value[iii]);
  ------------------
  |  Branch (268:37): [True: 0, False: 0]
  |  Branch (268:37): [True: 0, False: 0]
  |  Branch (268:37): [Folded, False: 35.7k]
  ------------------
  269|  35.7k|    }
  270|  11.9k|    parsing_string[env_var_len] = '\0';
  271|       |
  272|  11.9k|    char *context = NULL;
  273|  11.9k|    char *token = thread_safe_strtok(parsing_string, ",", &context);
  274|  23.8k|    while (NULL != token) {
  ------------------
  |  Branch (274:12): [True: 11.9k, False: 11.9k]
  ------------------
  275|  11.9k|        enum loader_filter_string_type cur_filter_type;
  276|  11.9k|        const char *actual_start;
  277|  11.9k|        size_t actual_len;
  278|  11.9k|        determine_filter_type(token, &cur_filter_type, &actual_start, &actual_len);
  279|       |        // value holds at most VK_MAX_EXTENSION_NAME_SIZE - 1 chars plus the null terminator. Keep the stored length in sync
  280|       |        // with what actually fits so the matcher never walks past the buffer, and make sure it stays null terminated.
  281|  11.9k|        size_t stored_len = actual_len < VK_MAX_EXTENSION_NAME_SIZE - 1 ? actual_len : VK_MAX_EXTENSION_NAME_SIZE - 1;
  ------------------
  |  Branch (281:29): [True: 11.9k, False: 0]
  ------------------
  282|  11.9k|        loader_strncpy(filter_struct->filters[filter_struct->count].value, VK_MAX_EXTENSION_NAME_SIZE, actual_start, stored_len);
  283|  11.9k|        filter_struct->filters[filter_struct->count].value[stored_len] = '\0';
  284|  11.9k|        filter_struct->filters[filter_struct->count].length = stored_len;
  285|  11.9k|        filter_struct->filters[filter_struct->count++].type = cur_filter_type;
  286|  11.9k|        if (filter_struct->count >= MAX_ADDITIONAL_FILTERS) {
  ------------------
  |  |  531|  11.9k|#define MAX_ADDITIONAL_FILTERS 16
  ------------------
  |  Branch (286:13): [True: 0, False: 11.9k]
  ------------------
  287|      0|            break;
  288|      0|        }
  289|  11.9k|        token = thread_safe_strtok(NULL, ",", &context);
  290|  11.9k|    }
  291|       |
  292|  11.9k|out:
  293|       |
  294|  11.9k|    loader_instance_heap_free(inst, parsing_string);
  295|  11.9k|    loader_free_getenv(env_var_value, inst);
  296|  11.9k|    return result;
  297|  11.9k|}
parse_layers_disable_filter_environment_var:
  303|  11.9k|                                                     struct loader_envvar_disable_layers_filter *disable_struct) {
  304|  11.9k|    VkResult result = VK_SUCCESS;
  305|  11.9k|    memset(disable_struct, 0, sizeof(struct loader_envvar_disable_layers_filter));
  306|  11.9k|    char *parsing_string = NULL;
  307|  11.9k|    char *env_var_value = loader_secure_getenv(VK_LAYERS_DISABLE_ENV_VAR, inst);
  ------------------
  |  |  120|  11.9k|#define VK_LAYERS_DISABLE_ENV_VAR "VK_LOADER_LAYERS_DISABLE"
  ------------------
  308|  11.9k|    if (NULL == env_var_value) {
  ------------------
  |  Branch (308:9): [True: 11.9k, False: 0]
  ------------------
  309|  11.9k|        goto out;
  310|  11.9k|    }
  311|      0|    const size_t env_var_len = strlen(env_var_value);
  312|      0|    if (env_var_len == 0) {
  ------------------
  |  Branch (312:9): [True: 0, False: 0]
  ------------------
  313|      0|        goto out;
  314|      0|    }
  315|       |    // Allocate a separate string since scan_for_next_comma modifies the original string
  316|      0|    parsing_string = loader_instance_heap_calloc(inst, env_var_len + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  317|      0|    if (NULL == parsing_string) {
  ------------------
  |  Branch (317:9): [True: 0, False: 0]
  ------------------
  318|      0|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
  319|      0|                   "parse_layers_disable_filter_environment_var: Failed to allocate space for parsing env var "
  320|      0|                   "\'VK_LAYERS_DISABLE_ENV_VAR\'");
  321|      0|        result = VK_ERROR_OUT_OF_HOST_MEMORY;
  322|      0|        goto out;
  323|      0|    }
  324|       |
  325|      0|    for (uint32_t iii = 0; iii < env_var_len; ++iii) {
  ------------------
  |  Branch (325:28): [True: 0, False: 0]
  ------------------
  326|      0|        parsing_string[iii] = (char)tolower((unsigned char)env_var_value[iii]);
  ------------------
  |  Branch (326:37): [True: 0, False: 0]
  |  Branch (326:37): [True: 0, False: 0]
  |  Branch (326:37): [Folded, False: 0]
  ------------------
  327|      0|    }
  328|      0|    parsing_string[env_var_len] = '\0';
  329|       |
  330|      0|    char *context = NULL;
  331|      0|    char *token = thread_safe_strtok(parsing_string, ",", &context);
  332|      0|    while (NULL != token) {
  ------------------
  |  Branch (332:12): [True: 0, False: 0]
  ------------------
  333|      0|        uint32_t cur_count = disable_struct->additional_filters.count;
  334|      0|        enum loader_filter_string_type cur_filter_type;
  335|      0|        const char *actual_start;
  336|      0|        size_t actual_len;
  337|      0|        determine_filter_type(token, &cur_filter_type, &actual_start, &actual_len);
  338|      0|        if (cur_filter_type == FILTER_STRING_SPECIAL) {
  ------------------
  |  Branch (338:13): [True: 0, False: 0]
  ------------------
  339|      0|            if (!strcmp(VK_LOADER_DISABLE_ALL_LAYERS_VAR_1, token) || !strcmp(VK_LOADER_DISABLE_ALL_LAYERS_VAR_2, token) ||
  ------------------
  |  |  124|      0|#define VK_LOADER_DISABLE_ALL_LAYERS_VAR_1 "~all~"
  ------------------
                          if (!strcmp(VK_LOADER_DISABLE_ALL_LAYERS_VAR_1, token) || !strcmp(VK_LOADER_DISABLE_ALL_LAYERS_VAR_2, token) ||
  ------------------
  |  |  125|      0|#define VK_LOADER_DISABLE_ALL_LAYERS_VAR_2 "*"
  ------------------
  |  Branch (339:17): [True: 0, False: 0]
  |  Branch (339:71): [True: 0, False: 0]
  ------------------
  340|      0|                !strcmp(VK_LOADER_DISABLE_ALL_LAYERS_VAR_3, token)) {
  ------------------
  |  |  126|      0|#define VK_LOADER_DISABLE_ALL_LAYERS_VAR_3 "**"
  ------------------
  |  Branch (340:17): [True: 0, False: 0]
  ------------------
  341|      0|                disable_struct->disable_all = true;
  342|      0|            } else if (!strcmp(VK_LOADER_DISABLE_IMPLICIT_LAYERS_VAR, token)) {
  ------------------
  |  |  127|      0|#define VK_LOADER_DISABLE_IMPLICIT_LAYERS_VAR "~implicit~"
  ------------------
  |  Branch (342:24): [True: 0, False: 0]
  ------------------
  343|      0|                disable_struct->disable_all_implicit = true;
  344|      0|            } else if (!strcmp(VK_LOADER_DISABLE_EXPLICIT_LAYERS_VAR, token)) {
  ------------------
  |  |  128|      0|#define VK_LOADER_DISABLE_EXPLICIT_LAYERS_VAR "~explicit~"
  ------------------
  |  Branch (344:24): [True: 0, False: 0]
  ------------------
  345|      0|                disable_struct->disable_all_explicit = true;
  346|      0|            }
  347|      0|        } else {
  348|       |            // Keep the stored length in sync with what actually fits (value is VK_MAX_EXTENSION_NAME_SIZE bytes including
  349|       |            // the null terminator) so the matcher never reads past the buffer.
  350|      0|            size_t stored_len = actual_len < VK_MAX_EXTENSION_NAME_SIZE - 1 ? actual_len : VK_MAX_EXTENSION_NAME_SIZE - 1;
  ------------------
  |  Branch (350:33): [True: 0, False: 0]
  ------------------
  351|      0|            loader_strncpy(disable_struct->additional_filters.filters[cur_count].value, VK_MAX_EXTENSION_NAME_SIZE, actual_start,
  352|      0|                           stored_len);
  353|      0|            disable_struct->additional_filters.filters[cur_count].value[stored_len] = '\0';
  354|      0|            disable_struct->additional_filters.filters[cur_count].length = stored_len;
  355|      0|            disable_struct->additional_filters.filters[cur_count].type = cur_filter_type;
  356|      0|            disable_struct->additional_filters.count++;
  357|      0|            if (disable_struct->additional_filters.count >= MAX_ADDITIONAL_FILTERS) {
  ------------------
  |  |  531|      0|#define MAX_ADDITIONAL_FILTERS 16
  ------------------
  |  Branch (357:17): [True: 0, False: 0]
  ------------------
  358|      0|                break;
  359|      0|            }
  360|      0|        }
  361|      0|        token = thread_safe_strtok(NULL, ",", &context);
  362|      0|    }
  363|  11.9k|out:
  364|  11.9k|    loader_instance_heap_free(inst, parsing_string);
  365|  11.9k|    loader_free_getenv(env_var_value, inst);
  366|  11.9k|    return result;
  367|      0|}
parse_layer_environment_var_filters:
  370|  11.9k|VkResult parse_layer_environment_var_filters(const struct loader_instance *inst, struct loader_envvar_all_filters *layer_filters) {
  371|  11.9k|    VkResult res = parse_generic_filter_environment_var(inst, VK_LAYERS_ENABLE_ENV_VAR, &layer_filters->enable_filter);
  ------------------
  |  |  119|  11.9k|#define VK_LAYERS_ENABLE_ENV_VAR "VK_LOADER_LAYERS_ENABLE"
  ------------------
  372|  11.9k|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (372:9): [True: 0, False: 11.9k]
  ------------------
  373|      0|        return res;
  374|      0|    }
  375|  11.9k|    res = parse_layers_disable_filter_environment_var(inst, &layer_filters->disable_filter);
  376|  11.9k|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (376:9): [True: 0, False: 11.9k]
  ------------------
  377|      0|        return res;
  378|      0|    }
  379|  11.9k|    res = parse_generic_filter_environment_var(inst, VK_LAYERS_ALLOW_ENV_VAR, &layer_filters->allow_filter);
  ------------------
  |  |  121|  11.9k|#define VK_LAYERS_ALLOW_ENV_VAR "VK_LOADER_LAYERS_ALLOW"
  ------------------
  380|  11.9k|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (380:9): [True: 0, False: 11.9k]
  ------------------
  381|      0|        return res;
  382|      0|    }
  383|  11.9k|    return res;
  384|  11.9k|}
check_name_matches_filter_environment_var:
  405|  38.1k|bool check_name_matches_filter_environment_var(const char *name, const struct loader_envvar_filter *filter_struct) {
  406|  38.1k|    bool ret_value = false;
  407|  38.1k|    size_t name_len = strlen(name);
  408|       |    // Compare each filter against `name` directly. name_segment_matches_filter_value does a case-insensitive compare
  409|       |    // (filter values are already lowercased at parse time), so there's no need to make a lowercased copy of name first
  410|       |    // and no limit on how long name can be.
  411|  57.1k|    for (uint32_t filt = 0; filt < filter_struct->count; ++filt) {
  ------------------
  |  Branch (411:29): [True: 19.0k, False: 38.0k]
  ------------------
  412|  19.0k|        const struct loader_envvar_filter_value *filter = &filter_struct->filters[filt];
  413|       |        // The filter (with its wildcards stripped) is longer than the name, so it can't possibly match.
  414|  19.0k|        if (filter->length > name_len) {
  ------------------
  |  Branch (414:13): [True: 3.30k, False: 15.7k]
  ------------------
  415|  3.30k|            continue;
  416|  3.30k|        }
  417|  15.7k|        switch (filter->type) {
  ------------------
  |  Branch (417:17): [True: 15.7k, False: 0]
  ------------------
  418|      0|            case FILTER_STRING_SPECIAL:
  ------------------
  |  Branch (418:13): [True: 0, False: 15.7k]
  ------------------
  419|      0|                if (!strcmp(VK_LOADER_DISABLE_ALL_LAYERS_VAR_1, filter->value) ||
  ------------------
  |  |  124|      0|#define VK_LOADER_DISABLE_ALL_LAYERS_VAR_1 "~all~"
  ------------------
  |  Branch (419:21): [True: 0, False: 0]
  ------------------
  420|      0|                    !strcmp(VK_LOADER_DISABLE_ALL_LAYERS_VAR_2, filter->value) ||
  ------------------
  |  |  125|      0|#define VK_LOADER_DISABLE_ALL_LAYERS_VAR_2 "*"
  ------------------
  |  Branch (420:21): [True: 0, False: 0]
  ------------------
  421|      0|                    !strcmp(VK_LOADER_DISABLE_ALL_LAYERS_VAR_3, filter->value)) {
  ------------------
  |  |  126|      0|#define VK_LOADER_DISABLE_ALL_LAYERS_VAR_3 "**"
  ------------------
  |  Branch (421:21): [True: 0, False: 0]
  ------------------
  422|      0|                    ret_value = true;
  423|      0|                }
  424|      0|                break;
  425|       |
  426|      0|            case FILTER_STRING_SUBSTRING:
  ------------------
  |  Branch (426:13): [True: 0, False: 15.7k]
  ------------------
  427|       |                // Slide the filter along the name looking for a match, stopping as soon as one is found.
  428|      0|                for (size_t start = 0; start + filter->length <= name_len; ++start) {
  ------------------
  |  Branch (428:40): [True: 0, False: 0]
  ------------------
  429|      0|                    if (name_segment_matches_filter_value(name + start, filter->value, filter->length)) {
  ------------------
  |  Branch (429:25): [True: 0, False: 0]
  ------------------
  430|      0|                        ret_value = true;
  431|      0|                        break;
  432|      0|                    }
  433|      0|                }
  434|      0|                break;
  435|       |
  436|      0|            case FILTER_STRING_SUFFIX:
  ------------------
  |  Branch (436:13): [True: 0, False: 15.7k]
  ------------------
  437|      0|                ret_value = name_segment_matches_filter_value(name + name_len - filter->length, filter->value, filter->length);
  438|      0|                break;
  439|       |
  440|      0|            case FILTER_STRING_PREFIX:
  ------------------
  |  Branch (440:13): [True: 0, False: 15.7k]
  ------------------
  441|      0|                ret_value = name_segment_matches_filter_value(name, filter->value, filter->length);
  442|      0|                break;
  443|       |
  444|  15.7k|            case FILTER_STRING_FULLNAME:
  ------------------
  |  Branch (444:13): [True: 15.7k, False: 0]
  ------------------
  445|  15.7k|                ret_value = (name_len == filter->length) && name_segment_matches_filter_value(name, filter->value, filter->length);
  ------------------
  |  Branch (445:29): [True: 198, False: 15.5k]
  |  Branch (445:61): [True: 62, False: 136]
  ------------------
  446|  15.7k|                break;
  447|  15.7k|        }
  448|  15.7k|        if (ret_value) {
  ------------------
  |  Branch (448:13): [True: 62, False: 15.7k]
  ------------------
  449|     62|            break;
  450|     62|        }
  451|  15.7k|    }
  452|  38.1k|    return ret_value;
  453|  38.1k|}
loader_environment.c:name_segment_matches_filter_value:
  390|    198|static bool name_segment_matches_filter_value(const char *name_segment, const char *lowercase_filter_value, size_t count) {
  391|    429|    for (size_t iii = 0; iii < count; ++iii) {
  ------------------
  |  Branch (391:26): [True: 367, False: 62]
  ------------------
  392|    367|        if ((char)tolower((unsigned char)name_segment[iii]) != lowercase_filter_value[iii]) {
  ------------------
  |  Branch (392:13): [True: 136, False: 231]
  |  Branch (392:19): [True: 0, False: 0]
  |  Branch (392:19): [True: 0, False: 0]
  |  Branch (392:19): [Folded, False: 367]
  ------------------
  393|    136|            return false;
  394|    136|        }
  395|    367|    }
  396|     62|    return true;
  397|    198|}

loader_get_json:
  164|  23.4k|TEST_FUNCTION_EXPORT VkResult loader_get_json(const struct loader_instance *inst, const char *filename, cJSON **json) {
  165|  23.4k|    char *json_buf = NULL;
  166|  23.4k|    VkResult res = VK_SUCCESS;
  167|       |
  168|  23.4k|    assert(json != NULL);
  169|       |
  170|  23.4k|    size_t json_len = 0;
  171|  23.4k|    *json = NULL;
  172|  23.4k|    res = loader_read_entire_file(inst, filename, &json_len, &json_buf);
  173|  23.4k|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (173:9): [True: 3.31k, False: 20.1k]
  ------------------
  174|  3.31k|        goto out;
  175|  3.31k|    }
  176|  23.4k|    bool out_of_memory = false;
  177|       |    // Parse text from file
  178|  20.1k|    *json = loader_cJSON_ParseWithLength(inst ? &inst->alloc_callbacks : NULL, json_buf, json_len, &out_of_memory);
  ------------------
  |  Branch (178:42): [True: 0, False: 20.1k]
  ------------------
  179|  20.1k|    if (out_of_memory) {
  ------------------
  |  Branch (179:9): [True: 0, False: 20.1k]
  ------------------
  180|      0|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Out of Memory error occurred while parsing JSON file %s.",
  181|      0|                   filename);
  182|      0|        res = VK_ERROR_OUT_OF_HOST_MEMORY;
  183|      0|        goto out;
  184|  20.1k|    } else if (*json == NULL) {
  ------------------
  |  Branch (184:16): [True: 8.73k, False: 11.4k]
  ------------------
  185|  8.73k|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Invalid JSON file %s.", filename);
  186|  8.73k|        goto out;
  187|  8.73k|    }
  188|       |
  189|  23.4k|out:
  190|  23.4k|    loader_instance_heap_free(inst, json_buf);
  191|  23.4k|    if (res != VK_SUCCESS && *json != NULL) {
  ------------------
  |  Branch (191:9): [True: 3.31k, False: 20.1k]
  |  Branch (191:30): [True: 0, False: 3.31k]
  ------------------
  192|      0|        loader_cJSON_Delete(*json);
  193|      0|        *json = NULL;
  194|      0|    }
  195|       |
  196|  23.4k|    return res;
  197|  20.1k|}
loader_parse_json_string_to_existing_str:
  199|   144k|VkResult loader_parse_json_string_to_existing_str(cJSON *object, const char *key, size_t out_str_len, char *out_string) {
  200|   144k|    if (NULL == key) {
  ------------------
  |  Branch (200:9): [True: 0, False: 144k]
  ------------------
  201|      0|        return VK_ERROR_INITIALIZATION_FAILED;
  202|      0|    }
  203|   144k|    cJSON *item = loader_cJSON_GetObjectItem(object, key);
  204|   144k|    if (NULL == item) {
  ------------------
  |  Branch (204:9): [True: 11.7k, False: 132k]
  ------------------
  205|  11.7k|        return VK_ERROR_INITIALIZATION_FAILED;
  206|  11.7k|    }
  207|       |
  208|   132k|    if (item->type != cJSON_String || item->valuestring == NULL) {
  ------------------
  |  |  101|   265k|#define cJSON_String (1 << 4)
  ------------------
  |  Branch (208:9): [True: 113, False: 132k]
  |  Branch (208:39): [True: 0, False: 132k]
  ------------------
  209|    113|        return VK_ERROR_INITIALIZATION_FAILED;
  210|    113|    }
  211|   132k|    bool out_of_memory = false;
  212|   132k|    bool success = loader_cJSON_PrintPreallocated(item, out_string, (int)out_str_len, cJSON_False);
  ------------------
  |  |   97|   132k|#define cJSON_False (1 << 0)
  ------------------
  213|   132k|    if (out_of_memory) {
  ------------------
  |  Branch (213:9): [True: 0, False: 132k]
  ------------------
  214|      0|        return VK_ERROR_OUT_OF_HOST_MEMORY;
  215|      0|    }
  216|   132k|    if (!success) {
  ------------------
  |  Branch (216:9): [True: 43, False: 132k]
  ------------------
  217|     43|        return VK_ERROR_INITIALIZATION_FAILED;
  218|     43|    }
  219|   132k|    return VK_SUCCESS;
  220|   132k|}
loader_parse_json_string:
  222|   108k|VkResult loader_parse_json_string(cJSON *object, const char *key, char **out_string) {
  223|   108k|    if (NULL == key) {
  ------------------
  |  Branch (223:9): [True: 0, False: 108k]
  ------------------
  224|      0|        return VK_ERROR_INITIALIZATION_FAILED;
  225|      0|    }
  226|       |
  227|   108k|    cJSON *item = loader_cJSON_GetObjectItem(object, key);
  228|   108k|    if (NULL == item || NULL == item->valuestring) {
  ------------------
  |  Branch (228:9): [True: 39.3k, False: 69.2k]
  |  Branch (228:25): [True: 145, False: 69.0k]
  ------------------
  229|  39.4k|        return VK_ERROR_INITIALIZATION_FAILED;
  230|  39.4k|    }
  231|       |
  232|   108k|    bool out_of_memory = false;
  233|  69.0k|    char *str = loader_cJSON_Print(item, &out_of_memory);
  234|  69.0k|    if (out_of_memory || NULL == str) {
  ------------------
  |  Branch (234:9): [True: 0, False: 69.0k]
  |  Branch (234:26): [True: 0, False: 69.0k]
  ------------------
  235|      0|        return VK_ERROR_OUT_OF_HOST_MEMORY;
  236|      0|    }
  237|  69.0k|    if (NULL != out_string) {
  ------------------
  |  Branch (237:9): [True: 69.0k, False: 0]
  ------------------
  238|  69.0k|        *out_string = str;
  239|  69.0k|    }
  240|  69.0k|    return VK_SUCCESS;
  241|  69.0k|}
loader_parse_json_array_of_strings:
  243|  73.7k|                                            struct loader_string_list *string_list) {
  244|  73.7k|    if (NULL == key) {
  ------------------
  |  Branch (244:9): [True: 0, False: 73.7k]
  ------------------
  245|      0|        return VK_ERROR_INITIALIZATION_FAILED;
  246|      0|    }
  247|  73.7k|    cJSON *item = loader_cJSON_GetObjectItem(object, key);
  248|  73.7k|    if (NULL == item) {
  ------------------
  |  Branch (248:9): [True: 39.9k, False: 33.8k]
  ------------------
  249|  39.9k|        return VK_ERROR_INITIALIZATION_FAILED;
  250|  39.9k|    }
  251|       |
  252|  33.8k|    uint32_t count = loader_cJSON_GetArraySize(item);
  253|  33.8k|    if (count == 0) {
  ------------------
  |  Branch (253:9): [True: 22.5k, False: 11.2k]
  ------------------
  254|  22.5k|        return VK_SUCCESS;
  255|  22.5k|    }
  256|       |
  257|  11.2k|    VkResult res = create_string_list(inst, count, string_list);
  258|  11.2k|    if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
  ------------------
  |  Branch (258:9): [True: 0, False: 11.2k]
  ------------------
  259|      0|        goto out;
  260|      0|    }
  261|  11.2k|    cJSON *element = NULL;
  262|   210k|    cJSON_ArrayForEach(element, item) {
  ------------------
  |  |  213|   221k|    for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
  |  |  ------------------
  |  |  |  Branch (213:20): [True: 11.2k, False: 0]
  |  |  |  Branch (213:61): [True: 210k, False: 10.9k]
  |  |  ------------------
  ------------------
  263|   210k|        if (element->type != cJSON_String) {
  ------------------
  |  |  101|   210k|#define cJSON_String (1 << 4)
  ------------------
  |  Branch (263:13): [True: 316, False: 209k]
  ------------------
  264|    316|            return VK_ERROR_INITIALIZATION_FAILED;
  265|    316|        }
  266|   210k|        bool out_of_memory = false;
  267|   209k|        char *out_data = loader_cJSON_Print(element, &out_of_memory);
  268|   209k|        if (out_of_memory) {
  ------------------
  |  Branch (268:13): [True: 0, False: 209k]
  ------------------
  269|      0|            res = VK_ERROR_OUT_OF_HOST_MEMORY;
  270|      0|            goto out;
  271|      0|        }
  272|   209k|        res = append_str_to_string_list(inst, string_list, out_data);
  273|   209k|        if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
  ------------------
  |  Branch (273:13): [True: 0, False: 209k]
  ------------------
  274|      0|            goto out;
  275|      0|        }
  276|   209k|    }
  277|  10.9k|out:
  278|  10.9k|    if (res == VK_ERROR_OUT_OF_HOST_MEMORY && NULL != string_list->list) {
  ------------------
  |  Branch (278:9): [True: 0, False: 10.9k]
  |  Branch (278:47): [True: 0, False: 0]
  ------------------
  279|      0|        free_string_list(inst, string_list);
  280|      0|    }
  281|       |
  282|  10.9k|    return res;
  283|  11.2k|}
loader_json.c:loader_read_entire_file:
  110|  23.4k|                                        char **out_buff) {
  111|  23.4k|    FILE *file = NULL;
  112|  23.4k|    struct stat stats = {0};
  113|  23.4k|    VkResult res = VK_SUCCESS;
  114|       |
  115|       |    // fprintf(stderr, "loader_get_json: Reading JSON file %s\n", filename);
  116|  23.4k|    file = fopen(filename, "rb");
  117|  23.4k|#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
  118|  23.4k|    if (file == NULL) {
  ------------------
  |  Branch (118:9): [True: 3.26k, False: 20.2k]
  ------------------
  119|  3.26k|        create_callback_file(filename);
  120|  3.26k|        file = fopen(filename, "rb");
  121|  3.26k|    }
  122|  23.4k|#endif
  123|  23.4k|    if (NULL == file) {
  ------------------
  |  Branch (123:9): [True: 3.26k, False: 20.2k]
  ------------------
  124|  3.26k|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Failed to open JSON file %s", filename);
  125|  3.26k|        res = VK_ERROR_INITIALIZATION_FAILED;
  126|  3.26k|        goto out;
  127|  3.26k|    }
  128|  20.2k|    if (-1 == fstat(fileno(file), &stats)) {
  ------------------
  |  Branch (128:9): [True: 0, False: 20.2k]
  ------------------
  129|      0|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Failed to read file size of JSON file %s", filename);
  130|      0|        res = VK_ERROR_INITIALIZATION_FAILED;
  131|      0|        goto out;
  132|      0|    }
  133|  20.2k|    *out_buff = (char *)loader_instance_heap_calloc(inst, stats.st_size + 1, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
  134|  20.2k|    if (NULL == *out_buff) {
  ------------------
  |  Branch (134:9): [True: 0, False: 20.2k]
  ------------------
  135|      0|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Failed to allocate memory to read JSON file %s", filename);
  136|      0|        res = VK_ERROR_OUT_OF_HOST_MEMORY;
  137|      0|        goto out;
  138|      0|    }
  139|  20.2k|    if (stats.st_size != (long int)fread(*out_buff, sizeof(char), stats.st_size, file)) {
  ------------------
  |  Branch (139:9): [True: 55, False: 20.1k]
  ------------------
  140|     55|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Failed to read entire JSON file %s", filename);
  141|     55|        res = VK_ERROR_INITIALIZATION_FAILED;
  142|     55|        goto out;
  143|     55|    }
  144|  20.1k|    *out_len = stats.st_size + 1;
  145|       |    // out_buff was allocated with stats.st_size + 1 bytes above, and the fread check already verified the file's
  146|       |    // contents did not change size out from under us; this is the last valid byte.
  147|       |    // NOLINTNEXTLINE(clang-analyzer-security.ArrayBound)
  148|  20.1k|    (*out_buff)[stats.st_size] = '\0';
  149|       |
  150|  23.4k|out:
  151|  23.4k|    if (NULL != file) {
  ------------------
  |  Branch (151:9): [True: 20.2k, False: 3.26k]
  ------------------
  152|       |        // NOLINTNEXTLINE(cert-err33-c) - file was only opened for reading, nothing to flush; res already reflects any read failure
  153|  20.2k|        fclose(file);
  154|  20.2k|    }
  155|  23.4k|    return res;
  156|  20.1k|}

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

free_layer_configuration:
   41|  32.5k|void free_layer_configuration(const struct loader_instance* inst, loader_settings_layer_configuration* layer_configuration) {
   42|  32.5k|    loader_instance_heap_free(inst, layer_configuration->name);
   43|  32.5k|    loader_instance_heap_free(inst, layer_configuration->path);
   44|  32.5k|    memset(layer_configuration, 0, sizeof(loader_settings_layer_configuration));
   45|  32.5k|}
free_loader_settings:
   57|  2.85k|void free_loader_settings(const struct loader_instance* inst, loader_settings* settings) {
   58|  2.85k|    if (NULL != settings->layer_configurations) {
  ------------------
  |  Branch (58:9): [True: 686, False: 2.17k]
  ------------------
   59|  29.6k|        for (uint32_t i = 0; i < settings->layer_configuration_count; i++) {
  ------------------
  |  Branch (59:30): [True: 29.0k, False: 686]
  ------------------
   60|  29.0k|            free_layer_configuration(inst, &settings->layer_configurations[i]);
   61|  29.0k|        }
   62|    686|        loader_instance_heap_free(inst, settings->layer_configurations);
   63|    686|    }
   64|  2.85k|    if (NULL != settings->additional_drivers) {
  ------------------
  |  Branch (64:9): [True: 0, False: 2.85k]
  ------------------
   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|  2.85k|    if (NULL != settings->device_configurations) {
  ------------------
  |  Branch (70:9): [True: 0, False: 2.85k]
  ------------------
   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|  2.85k|    loader_instance_heap_free(inst, settings->settings_file_path);
   77|  2.85k|    memset(settings, 0, sizeof(loader_settings));
   78|  2.85k|}
parse_control_string:
   80|  29.6k|loader_settings_layer_control parse_control_string(char* control_string) {
   81|  29.6k|    loader_settings_layer_control layer_control = LOADER_SETTINGS_LAYER_CONTROL_DEFAULT;
   82|  29.6k|    if (strcmp(control_string, "auto") == 0)
  ------------------
  |  Branch (82:9): [True: 469, False: 29.1k]
  ------------------
   83|    469|        layer_control = LOADER_SETTINGS_LAYER_CONTROL_DEFAULT;
   84|  29.1k|    else if (strcmp(control_string, "on") == 0)
  ------------------
  |  Branch (84:14): [True: 602, False: 28.5k]
  ------------------
   85|    602|        layer_control = LOADER_SETTINGS_LAYER_CONTROL_ON;
   86|  28.5k|    else if (strcmp(control_string, "off") == 0)
  ------------------
  |  Branch (86:14): [True: 7.41k, False: 21.1k]
  ------------------
   87|  7.41k|        layer_control = LOADER_SETTINGS_LAYER_CONTROL_OFF;
   88|  21.1k|    else if (strcmp(control_string, "unordered_layer_location") == 0)
  ------------------
  |  Branch (88:14): [True: 16.9k, False: 4.19k]
  ------------------
   89|  16.9k|        layer_control = LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION;
   90|  29.6k|    return layer_control;
   91|  29.6k|}
loader_settings_layer_control_to_string:
   93|  28.3k|const char* loader_settings_layer_control_to_string(loader_settings_layer_control control) {
   94|  28.3k|    switch (control) {
   95|  3.59k|        case LOADER_SETTINGS_LAYER_CONTROL_DEFAULT:
  ------------------
  |  Branch (95:9): [True: 3.59k, False: 24.7k]
  ------------------
   96|  3.59k|            return "auto";
   97|    585|        case LOADER_SETTINGS_LAYER_CONTROL_ON:
  ------------------
  |  Branch (97:9): [True: 585, False: 27.7k]
  ------------------
   98|    585|            return "on";
   99|  7.35k|        case LOADER_SETTINGS_LAYER_CONTROL_OFF:
  ------------------
  |  Branch (99:9): [True: 7.35k, False: 20.9k]
  ------------------
  100|  7.35k|            return "off";
  101|  16.8k|        case LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION:
  ------------------
  |  Branch (101:9): [True: 16.8k, False: 11.5k]
  ------------------
  102|  16.8k|            return "unordered_layer_location";
  103|      0|        default:
  ------------------
  |  Branch (103:9): [True: 0, False: 28.3k]
  ------------------
  104|      0|            return "UNKNOWN_LAYER_CONTROl";
  105|  28.3k|    }
  106|  28.3k|}
parse_log_filters_from_strings:
  108|    295|uint32_t parse_log_filters_from_strings(struct loader_string_list* log_filters) {
  109|    295|    uint32_t filters = 0;
  110|   160k|    for (uint32_t i = 0; i < log_filters->count; i++) {
  ------------------
  |  Branch (110:26): [True: 160k, False: 295]
  ------------------
  111|   160k|        if (strcmp(log_filters->list[i], "all") == 0)
  ------------------
  |  Branch (111:13): [True: 1.91k, False: 158k]
  ------------------
  112|  1.91k|            filters |= VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_PERF_BIT | VULKAN_LOADER_ERROR_BIT |
  113|  1.91k|                       VULKAN_LOADER_DEBUG_BIT | VULKAN_LOADER_LAYER_BIT | VULKAN_LOADER_DRIVER_BIT | VULKAN_LOADER_VALIDATION_BIT;
  114|   158k|        else if (strcmp(log_filters->list[i], "info") == 0)
  ------------------
  |  Branch (114:18): [True: 798, False: 157k]
  ------------------
  115|    798|            filters |= VULKAN_LOADER_INFO_BIT;
  116|   157k|        else if (strcmp(log_filters->list[i], "warn") == 0)
  ------------------
  |  Branch (116:18): [True: 599, False: 157k]
  ------------------
  117|    599|            filters |= VULKAN_LOADER_WARN_BIT;
  118|   157k|        else if (strcmp(log_filters->list[i], "perf") == 0)
  ------------------
  |  Branch (118:18): [True: 767, False: 156k]
  ------------------
  119|    767|            filters |= VULKAN_LOADER_PERF_BIT;
  120|   156k|        else if (strcmp(log_filters->list[i], "error") == 0)
  ------------------
  |  Branch (120:18): [True: 546, False: 155k]
  ------------------
  121|    546|            filters |= VULKAN_LOADER_ERROR_BIT;
  122|   155k|        else if (strcmp(log_filters->list[i], "debug") == 0)
  ------------------
  |  Branch (122:18): [True: 546, False: 155k]
  ------------------
  123|    546|            filters |= VULKAN_LOADER_DEBUG_BIT;
  124|   155k|        else if (strcmp(log_filters->list[i], "layer") == 0)
  ------------------
  |  Branch (124:18): [True: 793, False: 154k]
  ------------------
  125|    793|            filters |= VULKAN_LOADER_LAYER_BIT;
  126|   154k|        else if (strcmp(log_filters->list[i], "driver") == 0)
  ------------------
  |  Branch (126:18): [True: 1.51k, False: 153k]
  ------------------
  127|  1.51k|            filters |= VULKAN_LOADER_DRIVER_BIT;
  128|   153k|        else if (strcmp(log_filters->list[i], "validation") == 0)
  ------------------
  |  Branch (128:18): [True: 269, False: 152k]
  ------------------
  129|    269|            filters |= VULKAN_LOADER_VALIDATION_BIT;
  130|   160k|    }
  131|    295|    return filters;
  132|    295|}
parse_layer_configuration:
  147|  29.6k|                                   loader_settings_layer_configuration* layer_configuration) {
  148|  29.6k|    char* control_string = NULL;
  149|  29.6k|    VkResult res = loader_parse_json_string(layer_configuration_json, "control", &control_string);
  150|  29.6k|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (150:9): [True: 14, False: 29.6k]
  ------------------
  151|     14|        goto out;
  152|     14|    }
  153|  29.6k|    layer_configuration->control = parse_control_string(control_string);
  154|  29.6k|    loader_instance_heap_free(inst, control_string);
  155|       |
  156|       |    // If that is the only value - do no further parsing
  157|  29.6k|    if (layer_configuration->control == LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION) {
  ------------------
  |  Branch (157:9): [True: 16.9k, False: 12.6k]
  ------------------
  158|  16.9k|        goto out;
  159|  16.9k|    }
  160|       |
  161|  12.6k|    res = loader_parse_json_string(layer_configuration_json, "name", &(layer_configuration->name));
  162|  12.6k|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (162:9): [True: 101, False: 12.5k]
  ------------------
  163|    101|        goto out;
  164|    101|    }
  165|       |
  166|  12.5k|    res = loader_parse_json_string(layer_configuration_json, "path", &(layer_configuration->path));
  167|  12.5k|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (167:9): [True: 5, False: 12.5k]
  ------------------
  168|      5|        goto out;
  169|      5|    }
  170|       |
  171|  12.5k|    cJSON* treat_as_implicit_manifest = loader_cJSON_GetObjectItem(layer_configuration_json, "treat_as_implicit_manifest");
  172|  12.5k|    if (treat_as_implicit_manifest && treat_as_implicit_manifest->type == cJSON_True) {
  ------------------
  |  |   98|    629|#define cJSON_True (1 << 1)
  ------------------
  |  Branch (172:9): [True: 629, False: 11.9k]
  |  Branch (172:39): [True: 295, False: 334]
  ------------------
  173|    295|        layer_configuration->treat_as_implicit_manifest = true;
  174|    295|    }
  175|  29.6k|out:
  176|  29.6k|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (176:9): [True: 120, False: 29.5k]
  ------------------
  177|    120|        free_layer_configuration(inst, layer_configuration);
  178|    120|    }
  179|  29.6k|    return res;
  180|  12.5k|}
parse_layer_configurations:
  182|  1.17k|VkResult parse_layer_configurations(const struct loader_instance* inst, cJSON* settings_object, loader_settings* loader_settings) {
  183|  1.17k|    VkResult res = VK_SUCCESS;
  184|       |
  185|  1.17k|    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|  1.17k|    if (NULL == layer_configurations) {
  ------------------
  |  Branch (187:9): [True: 305, False: 869]
  ------------------
  188|    305|        return VK_SUCCESS;
  189|    305|    }
  190|       |
  191|    869|    uint32_t layer_configurations_count = loader_cJSON_GetArraySize(layer_configurations);
  192|    869|    if (layer_configurations_count == 0) {
  ------------------
  |  Branch (192:9): [True: 50, False: 819]
  ------------------
  193|     50|        loader_settings->layer_configurations_active = true;
  194|     50|        return VK_SUCCESS;
  195|     50|    }
  196|       |
  197|    819|    loader_settings->layer_configuration_count = layer_configurations_count;
  198|       |
  199|    819|    loader_settings->layer_configurations = loader_instance_heap_calloc(
  200|    819|        inst, sizeof(loader_settings_layer_configuration) * layer_configurations_count, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  201|    819|    if (NULL == loader_settings->layer_configurations) {
  ------------------
  |  Branch (201:9): [True: 0, False: 819]
  ------------------
  202|      0|        res = VK_ERROR_OUT_OF_HOST_MEMORY;
  203|      0|        goto out;
  204|      0|    }
  205|       |
  206|    819|    cJSON* layer = NULL;
  207|    819|    size_t i = 0;
  208|  29.6k|    cJSON_ArrayForEach(layer, layer_configurations) {
  ------------------
  |  |  213|  30.3k|    for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
  |  |  ------------------
  |  |  |  Branch (213:20): [True: 819, False: 0]
  |  |  |  Branch (213:61): [True: 29.6k, False: 686]
  |  |  ------------------
  ------------------
  209|  29.6k|        if (layer->type != cJSON_Object) {
  ------------------
  |  |  103|  29.6k|#define cJSON_Object (1 << 6)
  ------------------
  |  Branch (209:13): [True: 13, False: 29.6k]
  ------------------
  210|     13|            res = VK_ERROR_INITIALIZATION_FAILED;
  211|     13|            goto out;
  212|     13|        }
  213|  29.6k|        res = parse_layer_configuration(inst, layer, &(loader_settings->layer_configurations[i++]));
  214|  29.6k|        if (VK_SUCCESS != res) {
  ------------------
  |  Branch (214:13): [True: 120, False: 29.5k]
  ------------------
  215|    120|            goto out;
  216|    120|        }
  217|  29.6k|    }
  218|    686|    loader_settings->layer_configurations_active = true;
  219|    819|out:
  220|    819|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (220:9): [True: 133, False: 686]
  ------------------
  221|    133|        if (loader_settings->layer_configurations) {
  ------------------
  |  Branch (221:13): [True: 133, False: 0]
  ------------------
  222|  3.59k|            for (size_t index = 0; index < loader_settings->layer_configuration_count; index++) {
  ------------------
  |  Branch (222:36): [True: 3.46k, False: 133]
  ------------------
  223|  3.46k|                free_layer_configuration(inst, &(loader_settings->layer_configurations[index]));
  224|  3.46k|            }
  225|    133|            loader_settings->layer_configuration_count = 0;
  226|    133|            loader_instance_heap_free(inst, loader_settings->layer_configurations);
  227|    133|            loader_settings->layer_configurations = NULL;
  228|    133|        }
  229|    133|    }
  230|       |
  231|    819|    return res;
  232|    686|}
parse_additional_drivers:
  248|  1.17k|VkResult parse_additional_drivers(const struct loader_instance* inst, cJSON* settings_object, loader_settings* loader_settings) {
  249|  1.17k|    VkResult res = VK_SUCCESS;
  250|       |
  251|  1.17k|    cJSON* additional_drivers_use_exclusively_json =
  252|  1.17k|        loader_cJSON_GetObjectItem(settings_object, "additional_drivers_use_exclusively");
  253|  1.17k|    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: 1.17k]
  |  Branch (253:52): [True: 0, False: 0]
  ------------------
  254|      0|        loader_settings->additional_drivers_use_exclusively = true;
  255|      0|    }
  256|       |
  257|  1.17k|    cJSON* additional_drivers_json = loader_cJSON_GetObjectItem(settings_object, "additional_drivers");
  258|  1.17k|    if (NULL == additional_drivers_json) {
  ------------------
  |  Branch (258:9): [True: 1.17k, False: 0]
  ------------------
  259|  1.17k|        return VK_SUCCESS;
  260|  1.17k|    }
  261|       |
  262|      0|    uint32_t additional_driver_count = loader_cJSON_GetArraySize(additional_drivers_json);
  263|      0|    if (additional_driver_count == 0) {
  ------------------
  |  Branch (263:9): [True: 0, False: 0]
  ------------------
  264|      0|        return VK_SUCCESS;
  265|      0|    }
  266|       |
  267|      0|    loader_settings->additional_driver_count = additional_driver_count;
  268|       |
  269|      0|    loader_settings->additional_drivers = loader_instance_heap_calloc(
  270|      0|        inst, sizeof(loader_settings_driver_configuration) * additional_driver_count, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  271|      0|    if (NULL == loader_settings->additional_drivers) {
  ------------------
  |  Branch (271:9): [True: 0, False: 0]
  ------------------
  272|      0|        res = VK_ERROR_OUT_OF_HOST_MEMORY;
  273|      0|        goto out;
  274|      0|    }
  275|       |
  276|      0|    cJSON* driver = NULL;
  277|      0|    size_t i = 0;
  278|      0|    cJSON_ArrayForEach(driver, additional_drivers_json) {
  ------------------
  |  |  213|      0|    for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
  |  |  ------------------
  |  |  |  Branch (213:20): [True: 0, False: 0]
  |  |  |  Branch (213:61): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  279|      0|        if (driver->type != cJSON_Object) {
  ------------------
  |  |  103|      0|#define cJSON_Object (1 << 6)
  ------------------
  |  Branch (279:13): [True: 0, False: 0]
  ------------------
  280|      0|            res = VK_ERROR_INITIALIZATION_FAILED;
  281|      0|            goto out;
  282|      0|        }
  283|      0|        res = parse_additional_driver(inst, driver, &(loader_settings->additional_drivers[i++]));
  284|      0|        if (VK_SUCCESS != res) {
  ------------------
  |  Branch (284:13): [True: 0, False: 0]
  ------------------
  285|      0|            goto out;
  286|      0|        }
  287|      0|    }
  288|      0|out:
  289|      0|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (289:9): [True: 0, False: 0]
  ------------------
  290|      0|        if (loader_settings->additional_drivers) {
  ------------------
  |  Branch (290:13): [True: 0, False: 0]
  ------------------
  291|      0|            for (size_t index = 0; index < loader_settings->additional_driver_count; index++) {
  ------------------
  |  Branch (291:36): [True: 0, False: 0]
  ------------------
  292|      0|                free_driver_configuration(inst, &(loader_settings->additional_drivers[index]));
  293|      0|            }
  294|      0|            loader_settings->additional_driver_count = 0;
  295|      0|            loader_instance_heap_free(inst, loader_settings->additional_drivers);
  296|       |            loader_settings->additional_drivers = NULL;
  297|      0|        }
  298|      0|    }
  299|      0|    return res;
  300|      0|}
parse_device_configurations:
  375|  1.17k|VkResult parse_device_configurations(const struct loader_instance* inst, cJSON* settings_object, loader_settings* loader_settings) {
  376|  1.17k|    VkResult res = VK_SUCCESS;
  377|       |
  378|  1.17k|    cJSON* device_configurations = loader_cJSON_GetObjectItem(settings_object, "device_configurations");
  379|  1.17k|    if (NULL == device_configurations) {
  ------------------
  |  Branch (379:9): [True: 1.17k, False: 0]
  ------------------
  380|  1.17k|        return VK_SUCCESS;
  381|  1.17k|    }
  382|       |
  383|      0|    uint32_t device_configuration_count = loader_cJSON_GetArraySize(device_configurations);
  384|      0|    if (device_configuration_count == 0) {
  ------------------
  |  Branch (384:9): [True: 0, False: 0]
  ------------------
  385|      0|        loader_settings->device_configurations_active = true;
  386|      0|        return VK_SUCCESS;
  387|      0|    }
  388|       |
  389|      0|    loader_settings->device_configuration_count = device_configuration_count;
  390|       |
  391|      0|    loader_settings->device_configurations = loader_instance_heap_calloc(
  392|      0|        inst, sizeof(loader_settings_device_configuration) * device_configuration_count, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  393|      0|    if (NULL == loader_settings->device_configurations) {
  ------------------
  |  Branch (393:9): [True: 0, False: 0]
  ------------------
  394|      0|        res = VK_ERROR_OUT_OF_HOST_MEMORY;
  395|      0|        goto out;
  396|      0|    }
  397|       |
  398|      0|    cJSON* device = NULL;
  399|      0|    size_t i = 0;
  400|      0|    cJSON_ArrayForEach(device, device_configurations) {
  ------------------
  |  |  213|      0|    for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
  |  |  ------------------
  |  |  |  Branch (213:20): [True: 0, False: 0]
  |  |  |  Branch (213:61): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  401|      0|        if (device->type != cJSON_Object) {
  ------------------
  |  |  103|      0|#define cJSON_Object (1 << 6)
  ------------------
  |  Branch (401:13): [True: 0, False: 0]
  ------------------
  402|      0|            res = VK_ERROR_INITIALIZATION_FAILED;
  403|      0|            goto out;
  404|      0|        }
  405|      0|        res = parse_device_configuration(inst, device, &(loader_settings->device_configurations[i]));
  406|      0|        if (res == VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (406:13): [True: 0, False: 0]
  ------------------
  407|      0|            goto out;
  408|      0|        } else if (res != VK_SUCCESS) {
  ------------------
  |  Branch (408:20): [True: 0, False: 0]
  ------------------
  409|       |            // Skip a malformed entry rather than discarding every device configuration in the file
  410|      0|            res = VK_SUCCESS;
  411|      0|            continue;
  412|      0|        }
  413|      0|        i++;
  414|      0|    }
  415|       |    // Only the first i entries were successfully parsed; the trailing entries are unpopulated
  416|      0|    loader_settings->device_configuration_count = (uint32_t)i;
  417|      0|    loader_settings->device_configurations_active = true;
  418|      0|out:
  419|      0|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (419:9): [True: 0, False: 0]
  ------------------
  420|      0|        if (loader_settings->device_configurations) {
  ------------------
  |  Branch (420:13): [True: 0, False: 0]
  ------------------
  421|      0|            for (size_t index = 0; index < loader_settings->device_configuration_count; index++) {
  ------------------
  |  Branch (421:36): [True: 0, False: 0]
  ------------------
  422|      0|                free_device_configuration(inst, &(loader_settings->device_configurations[index]));
  423|      0|            }
  424|      0|            loader_settings->device_configuration_count = 0;
  425|      0|            loader_instance_heap_free(inst, loader_settings->device_configurations);
  426|       |            loader_settings->device_configurations = NULL;
  427|      0|        }
  428|      0|    }
  429|      0|    return res;
  430|      0|}
check_if_settings_path_exists:
  437|  25.5k|                                       char** settings_file_path) {
  438|  25.5k|    if (NULL == base || NULL == suffix) {
  ------------------
  |  Branch (438:9): [True: 11.9k, False: 13.6k]
  |  Branch (438:25): [True: 0, False: 13.6k]
  ------------------
  439|  11.9k|        return VK_ERROR_INITIALIZATION_FAILED;
  440|  11.9k|    }
  441|       |
  442|  13.6k|    size_t base_len = strlen(base);
  443|  13.6k|    size_t suffix_len = strlen(suffix);
  444|       |
  445|  13.6k|    uint32_t start = 0;
  446|  13.6k|    uint32_t stop = 0;
  447|  22.0k|    while (base[start] != '\0' && start < base_len && stop < base_len) {
  ------------------
  |  Branch (447:12): [True: 22.0k, False: 0]
  |  Branch (447:35): [True: 22.0k, False: 0]
  |  Branch (447:55): [True: 14.0k, False: 8.06k]
  ------------------
  448|  14.0k|        start = stop;
  449|  14.0k|        stop = start + 1;
  450|  69.9k|        while (base[stop] != PATH_SEPARATOR && base[stop] != '\0' && stop < base_len) {
  ------------------
  |  |  154|   139k|#define PATH_SEPARATOR ':'
  ------------------
  |  Branch (450:16): [True: 69.5k, False: 420]
  |  Branch (450:48): [True: 55.9k, False: 13.6k]
  |  Branch (450:70): [True: 55.9k, False: 0]
  ------------------
  451|  55.9k|            stop++;
  452|  55.9k|        }
  453|       |
  454|  14.0k|        size_t segment_len = (stop - start);
  455|  14.0k|        if (segment_len <= 1) {
  ------------------
  |  Branch (455:13): [True: 0, False: 14.0k]
  ------------------
  456|       |            // segment is *just* a PATH_SEPARATOR, skip it
  457|      0|            continue;
  458|      0|        }
  459|  14.0k|        size_t path_len = segment_len + suffix_len + 1;
  460|  14.0k|        *settings_file_path = loader_instance_heap_calloc(inst, path_len, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
  461|  14.0k|        if (NULL == *settings_file_path) {
  ------------------
  |  Branch (461:13): [True: 0, False: 14.0k]
  ------------------
  462|      0|            return VK_ERROR_OUT_OF_HOST_MEMORY;
  463|      0|        }
  464|  14.0k|        loader_strncpy(*settings_file_path, path_len, base + start, segment_len);
  465|  14.0k|        loader_strncat(*settings_file_path, path_len, suffix, suffix_len);
  466|       |
  467|  14.0k|        if (loader_platform_file_exists(*settings_file_path)) {
  ------------------
  |  Branch (467:13): [True: 5.54k, False: 8.48k]
  ------------------
  468|  5.54k|            return VK_SUCCESS;
  469|  5.54k|        }
  470|  8.48k|        loader_instance_heap_free(inst, *settings_file_path);
  471|  8.48k|        *settings_file_path = NULL;
  472|  8.48k|    }
  473|       |
  474|  8.06k|    return VK_ERROR_INITIALIZATION_FAILED;
  475|  13.6k|}
get_unix_settings_path:
  478|  5.96k|VkResult get_unix_settings_path(const struct loader_instance* inst, char** settings_file_path) {
  479|       |    // First, get XDG env-vars we use. Don't need to worry about free'ing because on linux getenv is non-allocating
  480|  5.96k|    char* xdg_config_home = loader_secure_getenv("XDG_CONFIG_HOME", inst);
  481|  5.96k|    char* xdg_config_dirs = loader_secure_getenv("XDG_CONFIG_DIRS", inst);
  482|  5.96k|    char* xdg_data_home = loader_secure_getenv("XDG_DATA_HOME", inst);
  483|  5.96k|    char* xdg_data_dirs = loader_secure_getenv("XDG_DATA_DIRS", inst);
  484|       |
  485|       |    // Use fallback directories for xdg_config_dirs and xdg_data_dirs if they are NULL.
  486|  5.96k|#if !defined(__Fuchsia__) && !defined(__QNX__)
  487|  5.96k|    if (NULL == xdg_config_dirs || '\0' == xdg_config_dirs[0]) {
  ------------------
  |  Branch (487:9): [True: 5.96k, False: 0]
  |  Branch (487:36): [True: 0, False: 0]
  ------------------
  488|  5.96k|        xdg_config_dirs = FALLBACK_CONFIG_DIRS;
  489|  5.96k|    }
  490|  5.96k|#endif
  491|       |
  492|  5.96k|#if !defined(__Fuchsia__) && !defined(__QNX__)
  493|  5.96k|    if (NULL == xdg_data_dirs || '\0' == xdg_data_dirs[0]) {
  ------------------
  |  Branch (493:9): [True: 5.96k, False: 0]
  |  Branch (493:34): [True: 0, False: 0]
  ------------------
  494|  5.96k|        xdg_data_dirs = FALLBACK_DATA_DIRS;
  495|  5.96k|    }
  496|  5.96k|#endif
  497|       |
  498|  5.96k|    VkResult res = check_if_settings_path_exists(
  499|  5.96k|        inst, xdg_config_home, "/" VULKAN_DIR "/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME, settings_file_path);
  ------------------
  |  |  145|  5.96k|#define VK_LOADER_SETTINGS_FILENAME "vk_loader_settings.json"
  ------------------
  500|  5.96k|    if (res == VK_SUCCESS) {
  ------------------
  |  Branch (500:9): [True: 0, False: 5.96k]
  ------------------
  501|      0|        return res;
  502|      0|    }
  503|       |
  504|  5.96k|    res = check_if_settings_path_exists(inst, xdg_data_home, "/" VULKAN_DIR "/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME,
  ------------------
  |  |  145|  5.96k|#define VK_LOADER_SETTINGS_FILENAME "vk_loader_settings.json"
  ------------------
  505|  5.96k|                                        settings_file_path);
  506|  5.96k|    if (res == VK_SUCCESS) {
  ------------------
  |  Branch (506:9): [True: 0, False: 5.96k]
  ------------------
  507|      0|        return res;
  508|      0|    }
  509|       |
  510|       |    // Check home if either xdg_config_home or xdg_data_home wasn't set
  511|  5.96k|    char* home = loader_secure_getenv("HOME", inst);
  512|  5.96k|    if (home != NULL) {
  ------------------
  |  Branch (512:9): [True: 5.96k, False: 0]
  ------------------
  513|  5.96k|        if (NULL == xdg_config_home || '\0' == xdg_config_home[0]) {
  ------------------
  |  Branch (513:13): [True: 5.96k, False: 0]
  |  Branch (513:40): [True: 0, False: 0]
  ------------------
  514|  5.96k|            res = check_if_settings_path_exists(
  515|  5.96k|                inst, home, "/.config/" VULKAN_DIR "/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME, settings_file_path);
  ------------------
  |  |  145|  5.96k|#define VK_LOADER_SETTINGS_FILENAME "vk_loader_settings.json"
  ------------------
  516|  5.96k|            if (res == VK_SUCCESS) {
  ------------------
  |  Branch (516:17): [True: 0, False: 5.96k]
  ------------------
  517|      0|                return res;
  518|      0|            }
  519|  5.96k|        }
  520|  5.96k|        if (NULL == xdg_data_home || '\0' == xdg_data_home[0]) {
  ------------------
  |  Branch (520:13): [True: 5.96k, False: 0]
  |  Branch (520:38): [True: 0, False: 0]
  ------------------
  521|  5.96k|            res = check_if_settings_path_exists(
  522|  5.96k|                inst, home, "/.local/share/" VULKAN_DIR "/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME, settings_file_path);
  ------------------
  |  |  145|  5.96k|#define VK_LOADER_SETTINGS_FILENAME "vk_loader_settings.json"
  ------------------
  523|  5.96k|            if (res == VK_SUCCESS) {
  ------------------
  |  Branch (523:17): [True: 5.54k, False: 420]
  ------------------
  524|  5.54k|                return res;
  525|  5.54k|            }
  526|  5.96k|        }
  527|  5.96k|    }
  528|       |
  529|    420|    res = check_if_settings_path_exists(inst, xdg_config_dirs, "/" VULKAN_DIR "/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME,
  ------------------
  |  |  145|    420|#define VK_LOADER_SETTINGS_FILENAME "vk_loader_settings.json"
  ------------------
  530|    420|                                        settings_file_path);
  531|    420|    if (res == VK_SUCCESS) {
  ------------------
  |  Branch (531:9): [True: 0, False: 420]
  ------------------
  532|      0|        return res;
  533|      0|    }
  534|       |
  535|    420|    res = check_if_settings_path_exists(inst, SYSCONFDIR, "/" VULKAN_DIR "/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME,
  ------------------
  |  |  145|    420|#define VK_LOADER_SETTINGS_FILENAME "vk_loader_settings.json"
  ------------------
  536|    420|                                        settings_file_path);
  537|    420|    if (res == VK_SUCCESS) {
  ------------------
  |  Branch (537:9): [True: 0, False: 420]
  ------------------
  538|      0|        return res;
  539|      0|    }
  540|    420|#if defined(EXTRASYSCONFDIR)
  541|       |
  542|    420|    res = check_if_settings_path_exists(inst, EXTRASYSCONFDIR, "/" VULKAN_DIR "/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME,
  ------------------
  |  |  145|    420|#define VK_LOADER_SETTINGS_FILENAME "vk_loader_settings.json"
  ------------------
  543|    420|                                        settings_file_path);
  544|    420|    if (res == VK_SUCCESS) {
  ------------------
  |  Branch (544:9): [True: 0, False: 420]
  ------------------
  545|      0|        return res;
  546|      0|    }
  547|    420|#endif
  548|    420|    res = check_if_settings_path_exists(inst, xdg_data_dirs, "/" VULKAN_DIR "/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME,
  ------------------
  |  |  145|    420|#define VK_LOADER_SETTINGS_FILENAME "vk_loader_settings.json"
  ------------------
  549|    420|                                        settings_file_path);
  550|    420|    if (res == VK_SUCCESS) {
  ------------------
  |  Branch (550:9): [True: 0, False: 420]
  ------------------
  551|      0|        return res;
  552|      0|    }
  553|       |
  554|    420|    return VK_ERROR_INITIALIZATION_FAILED;
  555|    420|}
check_if_layer_configurations_are_equal:
  558|  2.06k|bool check_if_layer_configurations_are_equal(loader_settings_layer_configuration* a, loader_settings_layer_configuration* b) {
  559|  2.06k|    if (!a->name || !b->name || 0 != strcmp(a->name, b->name)) {
  ------------------
  |  Branch (559:9): [True: 115, False: 1.94k]
  |  Branch (559:21): [True: 7, False: 1.94k]
  |  Branch (559:33): [True: 259, False: 1.68k]
  ------------------
  560|    381|        return false;
  561|    381|    }
  562|  1.68k|    if (!a->path || !b->path || 0 != strcmp(a->path, b->path)) {
  ------------------
  |  Branch (562:9): [True: 0, False: 1.68k]
  |  Branch (562:21): [True: 0, False: 1.68k]
  |  Branch (562:33): [True: 43, False: 1.63k]
  ------------------
  563|     43|        return false;
  564|     43|    }
  565|  1.63k|    return a->control == b->control && a->treat_as_implicit_manifest == b->treat_as_implicit_manifest;
  ------------------
  |  Branch (565:12): [True: 1.62k, False: 9]
  |  Branch (565:40): [True: 1.62k, False: 0]
  ------------------
  566|  1.68k|}
check_if_settings_are_equal:
  588|  2.85k|bool check_if_settings_are_equal(loader_settings* a, loader_settings* b) {
  589|       |    // If either pointer is null, return true
  590|  2.85k|    if (NULL == a || NULL == b) return false;
  ------------------
  |  Branch (590:9): [True: 0, False: 2.85k]
  |  Branch (590:22): [True: 0, False: 2.85k]
  ------------------
  591|  2.85k|    bool are_equal = true;
  592|  2.85k|    are_equal &= a->settings_active == b->settings_active;
  593|  2.85k|    are_equal &= a->has_unordered_layer_location == b->has_unordered_layer_location;
  594|  2.85k|    are_equal &= a->debug_level == b->debug_level;
  595|  2.85k|    are_equal &= a->layer_configurations_active == b->layer_configurations_active;
  596|  2.85k|    are_equal &= a->layer_configuration_count == b->layer_configuration_count;
  597|  2.85k|    are_equal &= a->additional_drivers_use_exclusively == b->additional_drivers_use_exclusively;
  598|  2.85k|    are_equal &= a->additional_driver_count == b->additional_driver_count;
  599|  2.85k|    are_equal &= a->device_configurations_active == b->device_configurations_active;
  600|  2.85k|    are_equal &= a->device_configuration_count == b->device_configuration_count;
  601|  2.85k|    if (!are_equal) return false;
  ------------------
  |  Branch (601:9): [True: 1.01k, False: 1.84k]
  ------------------
  602|  3.90k|    for (uint32_t i = 0; i < a->layer_configuration_count && i < b->layer_configuration_count; i++) {
  ------------------
  |  Branch (602:26): [True: 2.06k, False: 1.84k]
  |  Branch (602:62): [True: 2.06k, False: 0]
  ------------------
  603|  2.06k|        are_equal &= check_if_layer_configurations_are_equal(&a->layer_configurations[i], &b->layer_configurations[i]);
  604|  2.06k|    }
  605|  1.84k|    for (uint32_t i = 0; i < a->additional_driver_count && i < b->additional_driver_count; i++) {
  ------------------
  |  Branch (605:26): [True: 0, False: 1.84k]
  |  Branch (605:60): [True: 0, False: 0]
  ------------------
  606|      0|        are_equal &= check_if_driver_configurations_are_equal(&a->additional_drivers[i], &b->additional_drivers[i]);
  607|      0|    }
  608|  1.84k|    for (uint32_t i = 0; i < a->device_configuration_count && i < b->device_configuration_count; i++) {
  ------------------
  |  Branch (608:26): [True: 0, False: 1.84k]
  |  Branch (608:63): [True: 0, False: 0]
  ------------------
  609|      0|        are_equal &= check_if_device_configurations_are_equal(&a->device_configurations[i], &b->device_configurations[i]);
  610|      0|    }
  611|  1.84k|    return are_equal;
  612|  2.85k|}
log_settings:
  614|  1.13k|void log_settings(const struct loader_instance* inst, loader_settings* settings) {
  615|  1.13k|    if (settings == NULL) {
  ------------------
  |  Branch (615:9): [True: 0, False: 1.13k]
  ------------------
  616|      0|        return;
  617|      0|    }
  618|  1.13k|    loader_log(inst, VULKAN_LOADER_INFO_BIT, 0, "Using layer configurations found in loader settings from %s",
  619|  1.13k|               settings->settings_file_path);
  620|       |
  621|  1.13k|    char cmd_line_msg[64] = {0};
  622|  1.13k|    size_t cmd_line_size = sizeof(cmd_line_msg);
  623|       |
  624|  1.13k|    cmd_line_msg[0] = '\0';
  625|       |
  626|  1.13k|    generate_debug_flag_str(settings->debug_level, cmd_line_size, cmd_line_msg);
  627|  1.13k|    if (strlen(cmd_line_msg)) {
  ------------------
  |  Branch (627:9): [True: 121, False: 1.01k]
  ------------------
  628|    121|        loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Loader Settings Filters for Logging to Standard Error: %s", cmd_line_msg);
  629|    121|    }
  630|  1.13k|    if (settings->layer_configurations_active) {
  ------------------
  |  Branch (630:9): [True: 700, False: 432]
  ------------------
  631|    700|        loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Layer Configurations count = %d", settings->layer_configuration_count);
  632|  29.0k|        for (uint32_t i = 0; i < settings->layer_configuration_count; i++) {
  ------------------
  |  Branch (632:30): [True: 28.3k, False: 700]
  ------------------
  633|  28.3k|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "---- Layer Configuration [%d] ----", i);
  634|  28.3k|            if (settings->layer_configurations[i].control != LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION) {
  ------------------
  |  Branch (634:17): [True: 11.5k, False: 16.8k]
  ------------------
  635|  11.5k|                loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Name: %s", settings->layer_configurations[i].name);
  636|  11.5k|                loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Path: %s", settings->layer_configurations[i].path);
  637|  11.5k|                loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Layer Type: %s",
  638|  11.5k|                           settings->layer_configurations[i].treat_as_implicit_manifest ? "Implicit" : "Explicit");
  ------------------
  |  Branch (638:28): [True: 241, False: 11.2k]
  ------------------
  639|  11.5k|            }
  640|  28.3k|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Control: %s",
  641|  28.3k|                       loader_settings_layer_control_to_string(settings->layer_configurations[i].control));
  642|  28.3k|        }
  643|    700|    }
  644|  1.13k|    if (settings->additional_driver_count > 0) {
  ------------------
  |  Branch (644:9): [True: 0, False: 1.13k]
  ------------------
  645|      0|        loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "----");
  646|      0|        loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Use Additional Drivers Exclusively = %s",
  647|      0|                   settings->additional_drivers_use_exclusively ? "true" : "false");
  ------------------
  |  Branch (647:20): [True: 0, False: 0]
  ------------------
  648|      0|        loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Additional Driver Configurations count = %d",
  649|      0|                   settings->additional_driver_count);
  650|      0|        for (uint32_t i = 0; i < settings->additional_driver_count; i++) {
  ------------------
  |  Branch (650:30): [True: 0, False: 0]
  ------------------
  651|      0|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "---- Driver Configuration [%d] ----", i);
  652|      0|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Path: %s", settings->additional_drivers[i].path);
  653|      0|        }
  654|      0|    }
  655|  1.13k|    if (settings->device_configurations_active) {
  ------------------
  |  Branch (655:9): [True: 0, False: 1.13k]
  ------------------
  656|      0|        loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "----");
  657|      0|        loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Device Configurations count = %d", settings->device_configuration_count);
  658|      0|        for (uint32_t i = 0; i < settings->device_configuration_count; i++) {
  ------------------
  |  Branch (658:30): [True: 0, False: 0]
  ------------------
  659|      0|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "---- Device Configuration [%d] ----", i);
  660|      0|            char device_uuid_str[UUID_STR_LEN] = {0};
  661|      0|            loader_log_generate_uuid_string(settings->device_configurations[i].deviceUUID, device_uuid_str);
  662|      0|            char driver_uuid_str[UUID_STR_LEN] = {0};
  663|      0|            loader_log_generate_uuid_string(settings->device_configurations[i].driverUUID, driver_uuid_str);
  664|      0|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "deviceUUID: %s", device_uuid_str);
  665|      0|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "driverUUID: %s", driver_uuid_str);
  666|      0|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "driverVersion: %d", settings->device_configurations[i].driverVersion);
  667|      0|            if ('\0' != settings->device_configurations[i].deviceName[0]) {
  ------------------
  |  Branch (667:17): [True: 0, False: 0]
  ------------------
  668|      0|                loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "deviceName: %s", settings->device_configurations[i].deviceName);
  669|      0|            }
  670|      0|            if ('\0' != settings->device_configurations[i].driverName[0]) {
  ------------------
  |  Branch (670:17): [True: 0, False: 0]
  ------------------
  671|      0|                loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "driverName: %s", settings->device_configurations[i].driverName);
  672|      0|            }
  673|      0|        }
  674|      0|    }
  675|  1.13k|    loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "---------------------------------");
  676|  1.13k|}
get_loader_settings:
  681|  5.96k|VkResult get_loader_settings(const struct loader_instance* inst, loader_settings* loader_settings) {
  682|  5.96k|    VkResult res = VK_SUCCESS;
  683|  5.96k|    cJSON* json = NULL;
  684|  5.96k|    char* file_format_version_string = NULL;
  685|  5.96k|    char* settings_file_path = NULL;
  686|       |#if defined(WIN32)
  687|       |    res = windows_get_loader_settings_file_path(inst, &settings_file_path);
  688|       |    if (res != VK_SUCCESS) {
  689|       |        loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
  690|       |                   "No valid vk_loader_settings.json file found, no loader settings will be active");
  691|       |        goto out;
  692|       |    }
  693|       |
  694|       |#elif COMMON_UNIX_PLATFORMS
  695|       |    res = get_unix_settings_path(inst, &settings_file_path);
  696|  5.96k|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (696:9): [True: 420, False: 5.54k]
  ------------------
  697|    420|        loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
  698|    420|                   "No valid vk_loader_settings.json file found, no loader settings will be active");
  699|    420|        goto out;
  700|    420|    }
  701|       |#else
  702|       |#warning "Unsupported platform - must specify platform specific location for vk_loader_settings.json"
  703|       |#endif
  704|       |
  705|  5.54k|    res = loader_get_json(inst, settings_file_path, &json);
  706|       |    // Make sure sure the top level json value is an object
  707|  5.54k|    if (res != VK_SUCCESS || NULL == json || json->type != cJSON_Object) {
  ------------------
  |  |  103|  4.25k|#define cJSON_Object (1 << 6)
  ------------------
  |  Branch (707:9): [True: 106, False: 5.43k]
  |  Branch (707:30): [True: 1.17k, False: 4.25k]
  |  Branch (707:46): [True: 383, False: 3.87k]
  ------------------
  708|  1.66k|        goto out;
  709|  1.66k|    }
  710|       |
  711|  3.87k|    res = loader_parse_json_string(json, "file_format_version", &file_format_version_string);
  712|  3.87k|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (712:9): [True: 47, False: 3.82k]
  ------------------
  713|     47|        if (res != VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (713:13): [True: 47, False: 0]
  ------------------
  714|     47|            loader_log(
  715|     47|                inst, VULKAN_LOADER_DEBUG_BIT, 0,
  716|     47|                "Loader settings file from %s missing required field file_format_version - no loader settings will be active",
  717|     47|                settings_file_path);
  718|     47|        }
  719|     47|        goto out;
  720|     47|    }
  721|       |
  722|       |    // Because the file may contain either a "settings_array" or a single "settings" object, we need to create a cJSON so that we
  723|       |    // can iterate on both cases with common code
  724|  3.82k|    cJSON settings_iter_parent = {0};
  725|       |
  726|  3.82k|    cJSON* settings_array = loader_cJSON_GetObjectItem(json, "settings_array");
  727|  3.82k|    cJSON* single_settings_object = loader_cJSON_GetObjectItem(json, "settings");
  728|  3.82k|    if (NULL != settings_array) {
  ------------------
  |  Branch (728:9): [True: 1.12k, False: 2.70k]
  ------------------
  729|  1.12k|        memcpy(&settings_iter_parent, settings_array, sizeof(cJSON));
  730|  2.70k|    } else if (NULL != single_settings_object) {
  ------------------
  |  Branch (730:16): [True: 170, False: 2.53k]
  ------------------
  731|    170|        settings_iter_parent.child = single_settings_object;
  732|  2.53k|    } else {
  733|  2.53k|        loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0,
  734|  2.53k|                   "Loader settings file from %s missing required settings objects: Either one of the \"settings\" or "
  735|  2.53k|                   "\"settings_array\" objects must be present - no loader settings will be active",
  736|  2.53k|                   settings_file_path);
  737|  2.53k|        res = VK_ERROR_INITIALIZATION_FAILED;
  738|  2.53k|        goto out;
  739|  2.53k|    }
  740|       |
  741|       |    // Corresponds to the settings object that has no app keys
  742|  1.29k|    cJSON* global_settings = NULL;
  743|       |    // Corresponds to the settings object which has a matching app key
  744|  1.29k|    cJSON* settings_to_use = NULL;
  745|       |
  746|  1.29k|    char current_process_path[1024];
  747|  1.29k|    bool valid_exe_path = NULL != loader_platform_executable_path(current_process_path, 1024);
  748|       |
  749|  1.29k|    cJSON* settings_object_iter = NULL;
  750|  1.90k|    cJSON_ArrayForEach(settings_object_iter, &settings_iter_parent) {
  ------------------
  |  |  213|  3.16k|    for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
  |  |  ------------------
  |  |  |  Branch (213:20): [True: 1.29k, Folded]
  |  |  |  Branch (213:61): [True: 1.90k, False: 1.25k]
  |  |  ------------------
  ------------------
  751|  1.90k|        if (settings_object_iter->type != cJSON_Object) {
  ------------------
  |  |  103|  1.90k|#define cJSON_Object (1 << 6)
  ------------------
  |  Branch (751:13): [True: 36, False: 1.87k]
  ------------------
  752|     36|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0,
  753|     36|                       "Loader settings file from %s has a settings element that is not an object", settings_file_path);
  754|     36|            break;
  755|     36|        }
  756|       |
  757|  1.87k|        cJSON* app_keys = loader_cJSON_GetObjectItem(settings_object_iter, "app_keys");
  758|  1.87k|        if (NULL == app_keys) {
  ------------------
  |  Branch (758:13): [True: 1.40k, False: 466]
  ------------------
  759|       |            // use the first 'global' settings that has no app keys as the global one
  760|  1.40k|            if (global_settings == NULL) {
  ------------------
  |  Branch (760:17): [True: 1.17k, False: 231]
  ------------------
  761|  1.17k|                global_settings = settings_object_iter;
  762|  1.17k|            }
  763|  1.40k|            continue;
  764|  1.40k|        }
  765|       |        // No sense iterating if we couldn't get the executable path
  766|    466|        if (!valid_exe_path) {
  ------------------
  |  Branch (766:13): [True: 0, False: 466]
  ------------------
  767|      0|            break;
  768|      0|        }
  769|    466|        cJSON* app_key = NULL;
  770|    944|        cJSON_ArrayForEach(app_key, app_keys) {
  ------------------
  |  |  213|  1.41k|    for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
  |  |  ------------------
  |  |  |  Branch (213:20): [True: 466, False: 0]
  |  |  |  Branch (213:61): [True: 944, False: 466]
  |  |  ------------------
  ------------------
  771|    944|            char* app_key_str = loader_cJSON_GetStringValue(app_key);
  772|    944|            if (app_key_str && strcmp(current_process_path, app_key_str) == 0) {
  ------------------
  |  Branch (772:17): [True: 379, False: 565]
  |  Branch (772:32): [True: 0, False: 379]
  ------------------
  773|      0|                settings_to_use = settings_object_iter;
  774|      0|                break;
  775|      0|            }
  776|    944|        }
  777|       |
  778|       |        // Break if we have found a matching current_process_path
  779|    466|        if (NULL != settings_to_use) {
  ------------------
  |  Branch (779:13): [True: 0, False: 466]
  ------------------
  780|      0|            break;
  781|      0|        }
  782|    466|    }
  783|       |
  784|       |    // No app specific settings match - either use global settings or exit
  785|  1.29k|    if (settings_to_use == NULL) {
  ------------------
  |  Branch (785:9): [True: 1.29k, False: 0]
  ------------------
  786|  1.29k|        if (global_settings == NULL) {
  ------------------
  |  Branch (786:13): [True: 120, False: 1.17k]
  ------------------
  787|    120|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0,
  788|    120|                       "Loader settings file from %s missing global settings and none of the app specific settings matched the "
  789|    120|                       "current application - no loader settings will be active",
  790|    120|                       settings_file_path);
  791|    120|            goto out;  // No global settings were found - exit
  792|  1.17k|        } else {
  793|  1.17k|            settings_to_use = global_settings;  // Global settings are present - use it
  794|  1.17k|        }
  795|  1.29k|    }
  796|       |
  797|       |    // optional
  798|  1.17k|    cJSON* stderr_filter = loader_cJSON_GetObjectItem(settings_to_use, "stderr_log");
  799|  1.17k|    if (NULL != stderr_filter) {
  ------------------
  |  Branch (799:9): [True: 295, False: 879]
  ------------------
  800|    295|        struct loader_string_list stderr_log = {0};
  801|    295|        VkResult stderr_log_result = VK_SUCCESS;
  802|    295|        stderr_log_result = loader_parse_json_array_of_strings(inst, settings_to_use, "stderr_log", &stderr_log);
  803|    295|        if (VK_ERROR_OUT_OF_HOST_MEMORY == stderr_log_result) {
  ------------------
  |  Branch (803:13): [True: 0, False: 295]
  ------------------
  804|      0|            res = VK_ERROR_OUT_OF_HOST_MEMORY;
  805|      0|            goto out;
  806|      0|        }
  807|       |        // NOLINTNEXTLINE(clang-analyzer-optin.core.EnumCastOutOfRange) - 0xFF is a valid bitwise-OR of all flags (the "all" filter)
  808|    295|        loader_settings->debug_level = parse_log_filters_from_strings(&stderr_log);
  809|    295|        free_string_list(inst, &stderr_log);
  810|    295|    }
  811|       |
  812|       |    // optional
  813|  1.17k|    cJSON* logs_to_use = loader_cJSON_GetObjectItem(settings_to_use, "log_locations");
  814|  1.17k|    if (NULL != logs_to_use) {
  ------------------
  |  Branch (814:9): [True: 44, False: 1.13k]
  ------------------
  815|     44|        cJSON* log_element = NULL;
  816|    663|        cJSON_ArrayForEach(log_element, logs_to_use) {
  ------------------
  |  |  213|    707|    for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
  |  |  ------------------
  |  |  |  Branch (213:20): [True: 44, False: 0]
  |  |  |  Branch (213:61): [True: 663, False: 44]
  |  |  ------------------
  ------------------
  817|       |            // bool is_valid = true;
  818|    663|            struct loader_string_list log_destinations = {0};
  819|    663|            VkResult parse_dest_res = loader_parse_json_array_of_strings(inst, log_element, "destinations", &log_destinations);
  820|    663|            if (parse_dest_res != VK_SUCCESS) {
  ------------------
  |  Branch (820:17): [True: 657, False: 6]
  ------------------
  821|       |                // is_valid = false;
  822|    657|            }
  823|    663|            free_string_list(inst, &log_destinations);
  824|    663|            struct loader_string_list log_filters = {0};
  825|    663|            VkResult parse_filters_res = loader_parse_json_array_of_strings(inst, log_element, "filters", &log_filters);
  826|    663|            if (parse_filters_res != VK_SUCCESS) {
  ------------------
  |  Branch (826:17): [True: 463, False: 200]
  ------------------
  827|       |                // is_valid = false;
  828|    463|            }
  829|    663|            free_string_list(inst, &log_filters);
  830|    663|        }
  831|     44|    }
  832|       |
  833|  1.17k|    VkResult layer_configurations_res = parse_layer_configurations(inst, settings_to_use, loader_settings);
  834|  1.17k|    if (VK_ERROR_OUT_OF_HOST_MEMORY == layer_configurations_res) {
  ------------------
  |  Branch (834:9): [True: 0, False: 1.17k]
  ------------------
  835|      0|        res = layer_configurations_res;
  836|      0|        goto out;
  837|      0|    }
  838|       |
  839|       |    // Determine if there exists a layer configuration indicating where to put layers not contained in the settings file
  840|       |    // LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION
  841|  6.90k|    for (uint32_t i = 0; i < loader_settings->layer_configuration_count; i++) {
  ------------------
  |  Branch (841:26): [True: 6.14k, False: 760]
  ------------------
  842|  6.14k|        if (loader_settings->layer_configurations[i].control == LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION) {
  ------------------
  |  Branch (842:13): [True: 414, False: 5.73k]
  ------------------
  843|    414|            loader_settings->has_unordered_layer_location = true;
  844|    414|            break;
  845|    414|        }
  846|  6.14k|    }
  847|       |
  848|  1.17k|    VkResult additional_drivers_res = parse_additional_drivers(inst, settings_to_use, loader_settings);
  849|  1.17k|    if (VK_ERROR_OUT_OF_HOST_MEMORY == additional_drivers_res) {
  ------------------
  |  Branch (849:9): [True: 0, False: 1.17k]
  ------------------
  850|      0|        res = additional_drivers_res;
  851|      0|        goto out;
  852|      0|    }
  853|       |
  854|  1.17k|    VkResult device_configurations_res = parse_device_configurations(inst, settings_to_use, loader_settings);
  855|  1.17k|    if (VK_ERROR_OUT_OF_HOST_MEMORY == device_configurations_res) {
  ------------------
  |  Branch (855:9): [True: 0, False: 1.17k]
  ------------------
  856|      0|        res = device_configurations_res;
  857|      0|        goto out;
  858|      0|    }
  859|       |
  860|       |    // Only consider the settings active if there is at least one "setting" active.
  861|       |    // Those are either logging, layers, additional_drivers, or device_configurations.
  862|  1.17k|    if (loader_settings->debug_level != 0 || loader_settings->layer_configurations_active ||
  ------------------
  |  Branch (862:9): [True: 126, False: 1.04k]
  |  Branch (862:46): [True: 708, False: 340]
  ------------------
  863|    834|        loader_settings->additional_driver_count != 0 || loader_settings->device_configurations_active) {
  ------------------
  |  Branch (863:9): [True: 0, False: 340]
  |  Branch (863:58): [True: 0, False: 340]
  ------------------
  864|    834|        loader_settings->settings_file_path = settings_file_path;
  865|    834|        settings_file_path = NULL;
  866|    834|        loader_settings->settings_active = true;
  867|    834|    } else {
  868|    340|        loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
  869|    340|                   "vk_loader_settings.json file found at \"%s\" but did not contain any valid settings.", settings_file_path);
  870|    340|    }
  871|  5.96k|out:
  872|  5.96k|    if (NULL != json) {
  ------------------
  |  Branch (872:9): [True: 4.25k, False: 1.70k]
  ------------------
  873|  4.25k|        loader_cJSON_Delete(json);
  874|  4.25k|    }
  875|       |
  876|  5.96k|    loader_instance_heap_free(inst, settings_file_path);
  877|       |
  878|  5.96k|    loader_instance_heap_free(inst, file_format_version_string);
  879|  5.96k|    return res;
  880|  1.17k|}
update_global_loader_settings:
  882|  5.96k|TEST_FUNCTION_EXPORT VkResult update_global_loader_settings(void) {
  883|  5.96k|    loader_settings settings = {0};
  884|  5.96k|    VkResult res = get_loader_settings(NULL, &settings);
  885|  5.96k|    loader_platform_thread_lock_mutex(&global_loader_settings_lock);
  886|       |
  887|  5.96k|    if (res == VK_SUCCESS) {
  ------------------
  |  Branch (887:9): [True: 2.85k, False: 3.10k]
  ------------------
  888|  2.85k|        if (!check_if_settings_are_equal(&settings, &global_loader_settings)) {
  ------------------
  |  Branch (888:13): [True: 1.13k, False: 1.72k]
  ------------------
  889|  1.13k|            log_settings(NULL, &settings);
  890|  1.13k|        }
  891|  2.85k|        free_loader_settings(NULL, &global_loader_settings);
  892|  2.85k|        memcpy(&global_loader_settings, &settings, sizeof(loader_settings));
  893|  2.85k|        if (global_loader_settings.settings_active && global_loader_settings.debug_level > 0) {
  ------------------
  |  Branch (893:13): [True: 834, False: 2.02k]
  |  Branch (893:55): [True: 126, False: 708]
  ------------------
  894|    126|            loader_set_global_debug_level(global_loader_settings.debug_level);
  895|    126|        }
  896|  2.85k|    }
  897|  5.96k|    loader_platform_thread_unlock_mutex(&global_loader_settings_lock);
  898|  5.96k|    return res;
  899|  5.96k|}
init_global_loader_settings:
  901|      2|void init_global_loader_settings(void) {
  902|      2|    loader_platform_thread_create_mutex(&global_loader_settings_lock);
  903|       |    // Free out the global settings in case the process was loaded & unloaded
  904|       |    free_loader_settings(NULL, &global_loader_settings);
  905|      2|}
get_current_settings_and_lock:
  921|  11.9k|const loader_settings* get_current_settings_and_lock(const struct loader_instance* inst) {
  922|  11.9k|    if (inst) {
  ------------------
  |  Branch (922:9): [True: 0, False: 11.9k]
  ------------------
  923|      0|        return &inst->settings;
  924|      0|    }
  925|  11.9k|    loader_platform_thread_lock_mutex(&global_loader_settings_lock);
  926|  11.9k|    return &global_loader_settings;
  927|  11.9k|}
release_current_settings_lock:
  929|  11.9k|void release_current_settings_lock(const struct loader_instance* inst) {
  930|  11.9k|    if (inst == NULL) {
  ------------------
  |  Branch (930:9): [True: 11.9k, False: 0]
  ------------------
  931|  11.9k|        loader_platform_thread_unlock_mutex(&global_loader_settings_lock);
  932|  11.9k|    }
  933|  11.9k|}
get_settings_layers:
  936|  11.9k|                                                  bool* should_search_for_other_layers) {
  937|  11.9k|    VkResult res = VK_SUCCESS;
  938|  11.9k|    *should_search_for_other_layers = true;  // default to true
  939|       |
  940|  11.9k|    const loader_settings* settings = get_current_settings_and_lock(inst);
  941|       |
  942|  11.9k|    if (NULL == settings || !settings->settings_active || !settings->layer_configurations_active) {
  ------------------
  |  Branch (942:9): [True: 0, False: 11.9k]
  |  Branch (942:29): [True: 7.57k, False: 4.34k]
  |  Branch (942:59): [True: 512, False: 3.83k]
  ------------------
  943|  8.08k|        goto out;
  944|  8.08k|    }
  945|       |
  946|       |    // Assume the list doesn't contain LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION at first
  947|  3.83k|    *should_search_for_other_layers = false;
  948|       |
  949|   112k|    for (uint32_t i = 0; i < settings->layer_configuration_count; i++) {
  ------------------
  |  Branch (949:26): [True: 109k, False: 3.83k]
  ------------------
  950|   109k|        loader_settings_layer_configuration* layer_config = &settings->layer_configurations[i];
  951|       |
  952|       |        // If we encountered a layer that should be forced off, we add it to the settings_layers list but only
  953|       |        // with the data required to compare it with layers not in the settings file (aka name and manifest path)
  954|   109k|        if (layer_config->control == LOADER_SETTINGS_LAYER_CONTROL_OFF) {
  ------------------
  |  Branch (954:13): [True: 38.0k, False: 71.0k]
  ------------------
  955|  38.0k|            struct loader_layer_properties props = {0};
  956|  38.0k|            props.settings_control_value = LOADER_SETTINGS_LAYER_CONTROL_OFF;
  957|  38.0k|            loader_strncpy(props.info.layerName, VK_MAX_EXTENSION_NAME_SIZE, layer_config->name, VK_MAX_EXTENSION_NAME_SIZE);
  958|  38.0k|            props.info.layerName[VK_MAX_EXTENSION_NAME_SIZE - 1] = '\0';
  959|  38.0k|            res = loader_copy_to_new_str(inst, layer_config->path, &props.manifest_file_name);
  960|  38.0k|            if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
  ------------------
  |  Branch (960:17): [True: 0, False: 38.0k]
  ------------------
  961|      0|                goto out;
  962|      0|            }
  963|  38.0k|            res = loader_append_layer_property(inst, settings_layers, &props);
  964|  38.0k|            if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
  ------------------
  |  Branch (964:17): [True: 0, False: 38.0k]
  ------------------
  965|      0|                loader_free_layer_properties(inst, &props);
  966|      0|                goto out;
  967|      0|            }
  968|  38.0k|            continue;
  969|  38.0k|        }
  970|       |
  971|       |        // The special layer location that indicates where unordered layers should go only should have the
  972|       |        // settings_control_value set - everything else should be NULL
  973|  71.0k|        if (layer_config->control == LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION) {
  ------------------
  |  Branch (973:13): [True: 55.0k, False: 16.0k]
  ------------------
  974|  55.0k|            struct loader_layer_properties props = {0};
  975|  55.0k|            props.settings_control_value = LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION;
  976|  55.0k|            res = loader_append_layer_property(inst, settings_layers, &props);
  977|  55.0k|            if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
  ------------------
  |  Branch (977:17): [True: 0, False: 55.0k]
  ------------------
  978|      0|                loader_free_layer_properties(inst, &props);
  979|      0|                goto out;
  980|      0|            }
  981|  55.0k|            *should_search_for_other_layers = true;
  982|  55.0k|            continue;
  983|  55.0k|        }
  984|       |
  985|  16.0k|        if (layer_config->path == NULL) {
  ------------------
  |  Branch (985:13): [True: 0, False: 16.0k]
  ------------------
  986|      0|            continue;
  987|      0|        }
  988|       |
  989|  16.0k|        if (!is_json(layer_config->path, strlen(layer_config->path))) {
  ------------------
  |  Branch (989:13): [True: 13.6k, False: 2.36k]
  ------------------
  990|  13.6k|            continue;
  991|  13.6k|        }
  992|       |
  993|  2.36k|        cJSON* json = NULL;
  994|  2.36k|        VkResult local_res = loader_get_json(inst, layer_config->path, &json);
  995|  2.36k|        if (VK_ERROR_OUT_OF_HOST_MEMORY == local_res) {
  ------------------
  |  Branch (995:13): [True: 0, False: 2.36k]
  ------------------
  996|      0|            res = VK_ERROR_OUT_OF_HOST_MEMORY;
  997|      0|            goto out;
  998|  2.36k|        } else if (VK_SUCCESS != local_res || NULL == json) {
  ------------------
  |  Branch (998:20): [True: 1.96k, False: 402]
  |  Branch (998:47): [True: 136, False: 266]
  ------------------
  999|  2.10k|            continue;
 1000|  2.10k|        }
 1001|       |
 1002|       |        // Makes it possible to know if a new layer was added or not, since the only return value is VkResult
 1003|    266|        uint32_t count_before_adding = settings_layers->count;
 1004|       |
 1005|    266|        local_res =
 1006|    266|            loader_add_layer_properties(inst, settings_layers, json, layer_config->treat_as_implicit_manifest, layer_config->path);
 1007|    266|        loader_cJSON_Delete(json);
 1008|       |
 1009|       |        // If the error is anything other than out of memory we still want to try to load the other layers
 1010|    266|        if (VK_ERROR_OUT_OF_HOST_MEMORY == local_res) {
  ------------------
  |  Branch (1010:13): [True: 0, False: 266]
  ------------------
 1011|      0|            res = VK_ERROR_OUT_OF_HOST_MEMORY;
 1012|      0|            goto out;
 1013|    266|        } else if (local_res != VK_SUCCESS || count_before_adding == settings_layers->count) {
  ------------------
  |  Branch (1013:20): [True: 200, False: 66]
  |  Branch (1013:47): [True: 0, False: 66]
  ------------------
 1014|       |            // Indicates something was wrong with the layer, can't add it to the list
 1015|    200|            continue;
 1016|    200|        }
 1017|       |
 1018|  1.99k|        for (uint32_t j = count_before_adding; j < settings_layers->count; j++) {
  ------------------
  |  Branch (1018:48): [True: 1.92k, False: 66]
  ------------------
 1019|  1.92k|            struct loader_layer_properties* newly_added_layer = &settings_layers->list[j];
 1020|  1.92k|            newly_added_layer->settings_control_value = layer_config->control;
 1021|       |            // If the manifest file found has a name that differs from the one in the settings, remove this layer from
 1022|       |            // consideration
 1023|  1.92k|            if (strncmp(newly_added_layer->info.layerName, layer_config->name, VK_MAX_EXTENSION_NAME_SIZE) != 0) {
  ------------------
  |  Branch (1023:17): [True: 483, False: 1.44k]
  ------------------
 1024|    483|                loader_remove_layer_in_list(inst, settings_layers, j);
 1025|    483|                j--;
 1026|    483|                continue;
 1027|    483|            }
 1028|  1.92k|            bool should_remove = false;
 1029|       |            // Make sure the layer isn't already in the list
 1030|   963k|            for (uint32_t k = 0; k < j; k++) {
  ------------------
  |  Branch (1030:34): [True: 961k, False: 1.43k]
  ------------------
 1031|   961k|                if (0 == strncmp(settings_layers->list[k].info.layerName, newly_added_layer->info.layerName,
  ------------------
  |  Branch (1031:21): [True: 959k, False: 1.95k]
  ------------------
 1032|   961k|                                 VK_MAX_EXTENSION_NAME_SIZE)) {
 1033|   959k|                    if (0 == (newly_added_layer->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER) &&
  ------------------
  |  Branch (1033:25): [True: 2.31k, False: 957k]
  ------------------
 1034|  2.31k|                        settings_layers->list[k].lib_name != NULL && newly_added_layer->lib_name != NULL &&
  ------------------
  |  Branch (1034:25): [True: 109, False: 2.20k]
  |  Branch (1034:70): [True: 109, False: 0]
  ------------------
 1035|    109|                        strcmp(settings_layers->list[k].lib_name, newly_added_layer->lib_name) == 0) {
  ------------------
  |  Branch (1035:25): [True: 13, False: 96]
  ------------------
 1036|     13|                        should_remove = true;
 1037|     13|                        break;
 1038|     13|                    }
 1039|   959k|                }
 1040|   961k|            }
 1041|  1.44k|            if (should_remove) {
  ------------------
  |  Branch (1041:17): [True: 13, False: 1.43k]
  ------------------
 1042|     13|                loader_remove_layer_in_list(inst, settings_layers, j);
 1043|     13|                j--;
 1044|     13|            }
 1045|  1.44k|        }
 1046|     66|    }
 1047|       |
 1048|  11.9k|out:
 1049|  11.9k|    release_current_settings_lock(inst);
 1050|  11.9k|    return res;
 1051|  3.83k|}
check_if_layer_is_in_list:
 1062|  16.8k|                               bool consider_lib_path) {
 1063|       |    // If the layer is a meta layer, just check against the name
 1064|  19.0M|    for (uint32_t i = 0; i < layer_list->count; i++) {
  ------------------
  |  Branch (1064:26): [True: 19.0M, False: 13.9k]
  ------------------
 1065|  19.0M|        if (0 == strncmp(layer_list->list[i].info.layerName, layer_property->info.layerName, VK_MAX_EXTENSION_NAME_SIZE)) {
  ------------------
  |  Branch (1065:13): [True: 19.0M, False: 54.7k]
  ------------------
 1066|  19.0M|            if (layer_list->list[i].settings_control_value == LOADER_SETTINGS_LAYER_CONTROL_OFF) {
  ------------------
  |  Branch (1066:17): [True: 2.49k, False: 19.0M]
  ------------------
 1067|  2.49k|                return true;
 1068|  2.49k|            }
 1069|  19.0M|            if (VK_LAYER_TYPE_FLAG_META_LAYER == (layer_property->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER)) {
  ------------------
  |  Branch (1069:17): [True: 109, False: 19.0M]
  ------------------
 1070|    109|                return true;
 1071|    109|            }
 1072|  19.0M|            if (!consider_lib_path) {
  ------------------
  |  Branch (1072:17): [True: 328, False: 19.0M]
  ------------------
 1073|    328|                return true;
 1074|    328|            }
 1075|  19.0M|            if (layer_list->list[i].lib_name && layer_property->lib_name) {
  ------------------
  |  Branch (1075:17): [True: 24, False: 19.0M]
  |  Branch (1075:49): [True: 18, False: 6]
  ------------------
 1076|     18|                return strcmp(layer_list->list[i].lib_name, layer_property->lib_name) == 0;
 1077|     18|            }
 1078|  19.0M|        }
 1079|  19.0M|    }
 1080|  13.9k|    return false;
 1081|  16.8k|}
combine_settings_layers_with_regular_layers:
 1085|  10.0k|                                                     struct loader_layer_list* output_layers) {
 1086|  10.0k|    VkResult res = VK_SUCCESS;
 1087|  10.0k|    bool has_unordered_layer_location = false;
 1088|  10.0k|    uint32_t unordered_layer_location_index = 0;
 1089|       |    // Location to put layers that aren't known to the settings file
 1090|       |    // Find it here so we dont have to pass in a loader_settings struct
 1091|  15.7k|    for (uint32_t i = 0; i < settings_layers->count; i++) {
  ------------------
  |  Branch (1091:26): [True: 6.65k, False: 9.06k]
  ------------------
 1092|  6.65k|        if (settings_layers->list[i].settings_control_value == LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION) {
  ------------------
  |  Branch (1092:13): [True: 975, False: 5.67k]
  ------------------
 1093|    975|            has_unordered_layer_location = true;
 1094|    975|            unordered_layer_location_index = i;
 1095|    975|            break;
 1096|    975|        }
 1097|  6.65k|    }
 1098|       |
 1099|  10.0k|    if (settings_layers->count == 0 && regular_layers->count == 0) {
  ------------------
  |  Branch (1099:9): [True: 9.06k, False: 975]
  |  Branch (1099:40): [True: 7.74k, False: 1.32k]
  ------------------
 1100|       |        // No layers to combine
 1101|  7.74k|        goto out;
 1102|  7.74k|    } else if (settings_layers->count == 0) {
  ------------------
  |  Branch (1102:16): [True: 1.32k, False: 975]
  ------------------
 1103|       |        // No settings layers - just copy regular to output_layers - memset regular layers to prevent double frees
 1104|  1.32k|        *output_layers = *regular_layers;
 1105|  1.32k|        memset(regular_layers, 0, sizeof(struct loader_layer_list));
 1106|  1.32k|        goto out;
 1107|  1.32k|    } else if (regular_layers->count == 0 || !has_unordered_layer_location) {
  ------------------
  |  Branch (1107:16): [True: 727, False: 248]
  |  Branch (1107:46): [True: 0, False: 248]
  ------------------
 1108|       |        // No regular layers or has_unordered_layer_location is false - just copy settings to output_layers -
 1109|       |        // memset settings layers to prevent double frees
 1110|    727|        *output_layers = *settings_layers;
 1111|    727|        memset(settings_layers, 0, sizeof(struct loader_layer_list));
 1112|    727|        goto out;
 1113|    727|    }
 1114|       |
 1115|    248|    res = loader_init_generic_list(inst, (struct loader_generic_list*)output_layers,
 1116|    248|                                   (settings_layers->count + regular_layers->count) * sizeof(struct loader_layer_properties));
 1117|    248|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (1117:9): [True: 0, False: 248]
  ------------------
 1118|      0|        goto out;
 1119|      0|    }
 1120|       |
 1121|       |    // Insert the settings layers into output_layers up to unordered_layer_index
 1122|  1.86k|    for (uint32_t i = 0; i < unordered_layer_location_index; i++) {
  ------------------
  |  Branch (1122:26): [True: 1.61k, False: 248]
  ------------------
 1123|  1.61k|        if (!check_if_layer_is_in_list(output_layers, &settings_layers->list[i], true)) {
  ------------------
  |  Branch (1123:13): [True: 357, False: 1.26k]
  ------------------
 1124|    357|            res = loader_append_layer_property(inst, output_layers, &settings_layers->list[i]);
 1125|    357|            if (VK_SUCCESS != res) {
  ------------------
  |  Branch (1125:17): [True: 0, False: 357]
  ------------------
 1126|      0|                goto out;
 1127|      0|            }
 1128|    357|        }
 1129|  1.61k|    }
 1130|       |
 1131|  1.12k|    for (uint32_t i = 0; i < regular_layers->count; i++) {
  ------------------
  |  Branch (1131:26): [True: 872, False: 248]
  ------------------
 1132|       |        // Check if its already been put in the output_layers list as well as the remaining settings_layers
 1133|    872|        bool regular_layer_is_ordered = check_if_layer_is_in_list(output_layers, &regular_layers->list[i], false) ||
  ------------------
  |  Branch (1133:41): [True: 133, False: 739]
  ------------------
 1134|    739|                                        check_if_layer_is_in_list(settings_layers, &regular_layers->list[i], false);
  ------------------
  |  Branch (1134:41): [True: 302, False: 437]
  ------------------
 1135|       |        // If it isn't found, add it
 1136|    872|        if (!regular_layer_is_ordered) {
  ------------------
  |  Branch (1136:13): [True: 437, False: 435]
  ------------------
 1137|    437|            res = loader_append_layer_property(inst, output_layers, &regular_layers->list[i]);
 1138|    437|            if (VK_SUCCESS != res) {
  ------------------
  |  Branch (1138:17): [True: 0, False: 437]
  ------------------
 1139|      0|                goto out;
 1140|      0|            }
 1141|    437|        } else {
 1142|       |            // layer is already ordered and can be safely freed
 1143|    435|            loader_free_layer_properties(inst, &regular_layers->list[i]);
 1144|    435|        }
 1145|    872|    }
 1146|       |
 1147|       |    // Insert the rest of the settings layers into combined_layers from  unordered_layer_index to the end
 1148|       |    // start at one after the unordered_layer_index
 1149|  13.8k|    for (uint32_t i = unordered_layer_location_index + 1; i < settings_layers->count; i++) {
  ------------------
  |  Branch (1149:59): [True: 13.6k, False: 248]
  ------------------
 1150|  13.6k|        if (!check_if_layer_is_in_list(output_layers, &settings_layers->list[i], true)) {
  ------------------
  |  Branch (1150:13): [True: 12.3k, False: 1.23k]
  ------------------
 1151|  12.3k|            res = loader_append_layer_property(inst, output_layers, &settings_layers->list[i]);
 1152|  12.3k|            if (VK_SUCCESS != res) {
  ------------------
  |  Branch (1152:17): [True: 0, False: 12.3k]
  ------------------
 1153|      0|                goto out;
 1154|      0|            }
 1155|  12.3k|        }
 1156|  13.6k|    }
 1157|       |
 1158|  10.0k|out:
 1159|  10.0k|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (1159:9): [True: 0, False: 10.0k]
  ------------------
 1160|      0|        loader_delete_layer_list_and_properties(inst, output_layers);
 1161|      0|    }
 1162|       |
 1163|  10.0k|    return res;
 1164|    248|}

vkEnumerateInstanceExtensionProperties:
  164|  5.96k|                                                                                    VkExtensionProperties *pProperties) {
  165|  5.96k|    LOADER_PLATFORM_THREAD_ONCE(&once_init, loader_initialize);
  166|       |
  167|  5.96k|    update_global_loader_settings();
  168|       |
  169|       |    // We know we need to call at least the terminator
  170|  5.96k|    VkResult res = VK_SUCCESS;
  171|  5.96k|    VkEnumerateInstanceExtensionPropertiesChain chain_tail = {
  172|  5.96k|        .header =
  173|  5.96k|            {
  174|  5.96k|                .type = VK_CHAIN_TYPE_ENUMERATE_INSTANCE_EXTENSION_PROPERTIES,
  175|  5.96k|                .version = VK_CURRENT_CHAIN_VERSION,
  176|  5.96k|                .size = sizeof(chain_tail),
  177|  5.96k|            },
  178|  5.96k|        .pfnNextLayer = &terminator_pre_instance_EnumerateInstanceExtensionProperties,
  179|  5.96k|        .pNextLink = NULL,
  180|  5.96k|    };
  181|  5.96k|    VkEnumerateInstanceExtensionPropertiesChain *chain_head = &chain_tail;
  182|       |
  183|       |    // Get the implicit layers
  184|  5.96k|    struct loader_layer_list layers = {0};
  185|  5.96k|    memset(&layers, 0, sizeof(layers));
  186|  5.96k|    struct loader_envvar_all_filters layer_filters = {0};
  187|       |
  188|  5.96k|    res = parse_layer_environment_var_filters(NULL, &layer_filters);
  189|  5.96k|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (189:9): [True: 0, False: 5.96k]
  ------------------
  190|      0|        return res;
  191|      0|    }
  192|       |
  193|  5.96k|    res = loader_scan_for_implicit_layers(NULL, &layers, &layer_filters);
  194|  5.96k|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (194:9): [True: 0, False: 5.96k]
  ------------------
  195|      0|        return res;
  196|      0|    }
  197|       |
  198|       |    // Prepend layers onto the chain if they implement this entry point
  199|  12.9k|    for (uint32_t i = 0; i < layers.count; ++i) {
  ------------------
  |  Branch (199:26): [True: 6.94k, False: 5.96k]
  ------------------
  200|       |        // Skip this layer if it doesn't expose the entry-point
  201|  6.94k|        if (NULL == layers.list[i].pre_instance_functions.enumerate_instance_extension_properties) {
  ------------------
  |  Branch (201:13): [True: 6.94k, False: 0]
  ------------------
  202|  6.94k|            continue;
  203|  6.94k|        }
  204|       |
  205|      0|        loader_open_layer_file(NULL, &layers.list[i]);
  206|      0|        if (layers.list[i].lib_handle == NULL) {
  ------------------
  |  Branch (206:13): [True: 0, False: 0]
  ------------------
  207|      0|            continue;
  208|      0|        }
  209|       |
  210|      0|        void *pfn = loader_platform_get_proc_address(layers.list[i].lib_handle,
  211|      0|                                                     layers.list[i].pre_instance_functions.enumerate_instance_extension_properties);
  212|      0|        if (pfn == NULL) {
  ------------------
  |  Branch (212:13): [True: 0, False: 0]
  ------------------
  213|      0|            loader_log(NULL, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
  214|      0|                       "%s: Unable to resolve symbol \"%s\" in implicit layer library \"%s\"", __FUNCTION__,
  215|      0|                       layers.list[i].pre_instance_functions.enumerate_instance_extension_properties, layers.list[i].lib_name);
  216|      0|            continue;
  217|      0|        }
  218|       |
  219|      0|        VkEnumerateInstanceExtensionPropertiesChain *chain_link =
  220|      0|            loader_alloc(NULL, sizeof(VkEnumerateInstanceExtensionPropertiesChain), VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
  221|      0|        if (chain_link == NULL) {
  ------------------
  |  Branch (221:13): [True: 0, False: 0]
  ------------------
  222|      0|            res = VK_ERROR_OUT_OF_HOST_MEMORY;
  223|      0|            break;
  224|      0|        }
  225|      0|        memset(chain_link, 0, sizeof(VkEnumerateInstanceLayerPropertiesChain));
  226|      0|        chain_link->header.type = VK_CHAIN_TYPE_ENUMERATE_INSTANCE_EXTENSION_PROPERTIES;
  227|      0|        chain_link->header.version = VK_CURRENT_CHAIN_VERSION;
  228|      0|        chain_link->header.size = sizeof(*chain_link);
  229|      0|        chain_link->pfnNextLayer = pfn;
  230|      0|        chain_link->pNextLink = chain_head;
  231|       |
  232|      0|        chain_head = chain_link;
  233|      0|    }
  234|       |
  235|       |    // Call down the chain
  236|  5.96k|    if (res == VK_SUCCESS) {
  ------------------
  |  Branch (236:9): [True: 5.96k, False: 0]
  ------------------
  237|  5.96k|        res = chain_head->pfnNextLayer(chain_head->pNextLink, pLayerName, pPropertyCount, pProperties);
  238|  5.96k|    }
  239|       |
  240|       |    // Free up the layers
  241|  5.96k|    loader_delete_layer_list_and_properties(NULL, &layers);
  242|       |
  243|       |    // Tear down the chain
  244|  5.96k|    while (chain_head != &chain_tail) {
  ------------------
  |  Branch (244:12): [True: 0, False: 5.96k]
  ------------------
  245|      0|        VkEnumerateInstanceExtensionPropertiesChain *holder = chain_head;
  246|      0|        chain_head = (VkEnumerateInstanceExtensionPropertiesChain *)chain_head->pNextLink;
  247|      0|        loader_free(NULL, holder);
  248|      0|    }
  249|       |
  250|  5.96k|    return res;
  251|  5.96k|}

loader.c:loader_strncpy:
  467|   234k|static inline char *loader_strncpy(char *dest, size_t dest_sz, const char *src, size_t count) {
  468|   234k|    (void)dest_sz;
  469|   234k|    return strncpy(dest, src, count);
  470|   234k|}
loader.c:thread_safe_strtok:
  460|  90.5k|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:
  450|      4|static inline void loader_platform_thread_create_mutex(loader_platform_thread_mutex *pMutex) {
  451|      4|    pthread_mutexattr_t attr;
  452|      4|    pthread_mutexattr_init(&attr);
  453|      4|    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
  454|      4|    pthread_mutex_init(pMutex, &attr);
  455|      4|}
loader.c:loader_platform_is_path_absolute:
  296|  10.3k|static inline bool loader_platform_is_path_absolute(const char *path) {
  297|  10.3k|    if (path[0] == '/') return true;
  ------------------
  |  Branch (297:9): [True: 169, False: 10.2k]
  ------------------
  298|  10.2k|    return false;
  299|  10.3k|}
loader.c:loader_platform_is_path:
  252|  41.6k|static inline bool loader_platform_is_path(const char *path) { return strchr(path, DIRECTORY_SYMBOL) != NULL; }
  ------------------
  |  |  155|  41.6k|#define DIRECTORY_SYMBOL '/'
  ------------------
loader.c:loader_platform_file_exists:
  289|  41.4k|static inline bool loader_platform_file_exists(const char *path) {
  290|  41.4k|    if (access(path, F_OK)) return false;
  ------------------
  |  Branch (290:9): [True: 1.23k, False: 40.2k]
  ------------------
  291|  40.2k|    return true;
  292|  41.4k|}
loader.c:loader_platform_executable_path:
  307|  10.0k|static inline char *loader_platform_executable_path(char *buffer, size_t size) {
  308|  10.0k|    ssize_t count = readlink("/proc/self/exe", buffer, size);
  309|  10.0k|    if (count == -1) return NULL;
  ------------------
  |  Branch (309:9): [True: 0, False: 10.0k]
  ------------------
  310|  10.0k|    if (count == 0) return NULL;
  ------------------
  |  Branch (310:9): [True: 0, False: 10.0k]
  ------------------
  311|       |    // readlink does not append a null terminator and returns up to size bytes, so a target of size or more
  312|       |    // would leave no room for the terminator and buffer[count] would write past the end.
  313|  10.0k|    if ((size_t)count >= size) return NULL;
  ------------------
  |  Branch (313:9): [True: 0, False: 10.0k]
  ------------------
  314|  10.0k|    buffer[count] = '\0';
  315|  10.0k|    return buffer;
  316|  10.0k|}
loader_environment.c:thread_safe_strtok:
  460|  23.8k|static inline void *thread_safe_strtok(char *str, const char *delim, char **saveptr) { return strtok_r(str, delim, saveptr); }
loader_environment.c:loader_strncpy:
  467|  11.9k|static inline char *loader_strncpy(char *dest, size_t dest_sz, const char *src, size_t count) {
  468|  11.9k|    (void)dest_sz;
  469|  11.9k|    return strncpy(dest, src, count);
  470|  11.9k|}
log.c:loader_strncat:
  463|  1.14M|static inline char *loader_strncat(char *dest, size_t dest_sz, const char *src, size_t count) {
  464|  1.14M|    (void)dest_sz;
  465|  1.14M|    return strncat(dest, src, count);
  466|  1.14M|}
settings.c:loader_strncpy:
  467|  52.0k|static inline char *loader_strncpy(char *dest, size_t dest_sz, const char *src, size_t count) {
  468|  52.0k|    (void)dest_sz;
  469|  52.0k|    return strncpy(dest, src, count);
  470|  52.0k|}
settings.c:loader_strncat:
  463|  14.0k|static inline char *loader_strncat(char *dest, size_t dest_sz, const char *src, size_t count) {
  464|  14.0k|    (void)dest_sz;
  465|  14.0k|    return strncat(dest, src, count);
  466|  14.0k|}
settings.c:loader_platform_file_exists:
  289|  14.0k|static inline bool loader_platform_file_exists(const char *path) {
  290|  14.0k|    if (access(path, F_OK)) return false;
  ------------------
  |  Branch (290:9): [True: 8.48k, False: 5.54k]
  ------------------
  291|  5.54k|    return true;
  292|  14.0k|}
settings.c:loader_platform_executable_path:
  307|  1.29k|static inline char *loader_platform_executable_path(char *buffer, size_t size) {
  308|  1.29k|    ssize_t count = readlink("/proc/self/exe", buffer, size);
  309|  1.29k|    if (count == -1) return NULL;
  ------------------
  |  Branch (309:9): [True: 0, False: 1.29k]
  ------------------
  310|  1.29k|    if (count == 0) return NULL;
  ------------------
  |  Branch (310:9): [True: 0, False: 1.29k]
  ------------------
  311|       |    // readlink does not append a null terminator and returns up to size bytes, so a target of size or more
  312|       |    // would leave no room for the terminator and buffer[count] would write past the end.
  313|  1.29k|    if ((size_t)count >= size) return NULL;
  ------------------
  |  Branch (313:9): [True: 0, False: 1.29k]
  ------------------
  314|  1.29k|    buffer[count] = '\0';
  315|  1.29k|    return buffer;
  316|  1.29k|}
settings.c:loader_platform_thread_lock_mutex:
  456|  17.8k|static inline void loader_platform_thread_lock_mutex(loader_platform_thread_mutex *pMutex) { pthread_mutex_lock(pMutex); }
settings.c:loader_platform_thread_unlock_mutex:
  457|  17.8k|static inline void loader_platform_thread_unlock_mutex(loader_platform_thread_mutex *pMutex) { pthread_mutex_unlock(pMutex); }
settings.c:loader_platform_thread_create_mutex:
  450|      2|static inline void loader_platform_thread_create_mutex(loader_platform_thread_mutex *pMutex) {
  451|      2|    pthread_mutexattr_t attr;
  452|      2|    pthread_mutexattr_init(&attr);
  453|      2|    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
  454|      2|    pthread_mutex_init(pMutex, &attr);
  455|      2|}

wsi_unsupported_instance_extension:
  280|  5.53k|bool wsi_unsupported_instance_extension(const VkExtensionProperties *ext_prop) {
  281|       |#if !defined(VK_USE_PLATFORM_WAYLAND_KHR)
  282|       |    if (!strcmp(ext_prop->extensionName, "VK_KHR_wayland_surface")) return true;
  283|       |#endif  // VK_USE_PLATFORM_WAYLAND_KHR
  284|       |#if !defined(VK_USE_PLATFORM_XCB_KHR)
  285|       |    if (!strcmp(ext_prop->extensionName, "VK_KHR_xcb_surface")) return true;
  286|       |#endif  // VK_USE_PLATFORM_XCB_KHR
  287|       |#if !defined(VK_USE_PLATFORM_XLIB_KHR)
  288|       |    if (!strcmp(ext_prop->extensionName, "VK_KHR_xlib_surface")) return true;
  289|       |#endif  // VK_USE_PLATFORM_XLIB_KHR
  290|  5.53k|#if !defined(VK_USE_PLATFORM_DIRECTFB_EXT)
  291|  5.53k|    if (!strcmp(ext_prop->extensionName, "VK_EXT_directfb_surface")) return true;
  ------------------
  |  Branch (291:9): [True: 35, False: 5.50k]
  ------------------
  292|  5.50k|#endif  // VK_USE_PLATFORM_DIRECTFB_EXT
  293|  5.50k|#if !defined(VK_USE_PLATFORM_SCREEN_QNX)
  294|  5.50k|    if (!strcmp(ext_prop->extensionName, "VK_QNX_screen_surface")) return true;
  ------------------
  |  Branch (294:9): [True: 4, False: 5.49k]
  ------------------
  295|  5.49k|#endif  // VK_USE_PLATFORM_SCREEN_QNX
  296|       |
  297|  5.49k|    return false;
  298|  5.50k|}

