Game Storage

Source: src/game_storage.c · 103 lines · 4 functions.

Module entry points

These functions are exposed to the rest of the project. Open one to follow its decisions and the helpers it calls.

How to read these diagrams

Each function has its own expandable diagram using the actual expressions and statements from this file. Decisions split into True and False; loop bodies are indented. Returns end the function immediately; break and continue follow their C meanings. Arrows between statements show their order when execution reaches them.

These are structural source diagrams before preprocessing, not runtime traces. Conditional compilation and macros remain source expressions. Ternary choices remain inside their statement. Calls are linked separately; callback execution and task scheduling are not inferred.

Functions in this file

game_storage_initialize() · source line 9
bool game_storage_initialize(void)
  1. Decisionready
    True
      1. Exit this functionreturn true;
    False

    Continue after this decision.

  2. Executeconst esp_err_t result = nvs_flash_init();
  3. Executeready = result == ESP_OK;
  4. Decision!ready
    True
      1. ExecuteESP_LOGE(TAG, "NVS unavailable: %s; stored data left intact", esp_err_to_name(result));
    False

    Continue after this decision.

  5. Exit this functionreturn ready;
Read original function source
bool game_storage_initialize(void)
{
    if (ready) {
        return true;
    }
    const esp_err_t result = nvs_flash_init();
    ready = result == ESP_OK;
    if (!ready) {
        // Never erase existing settings as an automatic recovery action.
        ESP_LOGE(TAG, "NVS unavailable: %s; stored data left intact",
                 esp_err_to_name(result));
    }
    return ready;
}
game_storage_read_sized() · source line 24
bool game_storage_read_sized(const char *name_space, const char *key, void *record,
                             size_t capacity, size_t *record_size, bool *found)
  1. Decisionfound == NULL || record_size == NULL
    True
      1. Exit this functionreturn false;
    False

    Continue after this decision.

  2. Execute*found = false;
  3. Execute*record_size = 0;
  4. Decision!ready || record == NULL || capacity == 0
    True
      1. Exit this functionreturn false;
    False

    Continue after this decision.

  5. Executenvs_handle_t handle;
  6. Executeesp_err_t result = nvs_open(name_space, NVS_READONLY, &handle);
  7. Decisionresult == ESP_ERR_NVS_NOT_FOUND
    True
      1. Exit this functionreturn true;
    False

    Continue after this decision.

  8. Decisionresult != ESP_OK
    True
      1. ExecuteESP_LOGE(TAG, "Cannot open %s: %s", name_space, esp_err_to_name(result));
      2. Exit this functionreturn false;
    False

    Continue after this decision.

  9. Executesize_t length = 0;
  10. Executeresult = nvs_get_blob(handle, key, NULL, &length);
  11. Decisionresult == ESP_ERR_NVS_NOT_FOUND
    True
      1. Executenvs_close(handle);
      2. Exit this functionreturn true;
    False

    Continue after this decision.

  12. Decisionresult == ESP_OK && length <= capacity
    True
      1. Executeresult = nvs_get_blob(handle, key, record, &length);
      2. Execute*found = result == ESP_OK;
      3. Decision*found
        True
          1. Execute*record_size = length;
        False

        Continue after this decision.

    False
    1. Decisionresult == ESP_OK
      True
        1. Executeresult = ESP_ERR_NVS_INVALID_LENGTH;
      False

      Continue after this decision.

  13. Executenvs_close(handle);
  14. Decisionresult != ESP_OK
    True
      1. ExecuteESP_LOGE(TAG, "Cannot read %s/%s: %s", name_space, key, esp_err_to_name(result));
    False

    Continue after this decision.

  15. Exit this functionreturn result == ESP_OK;
Read original function source
bool game_storage_read_sized(const char *name_space, const char *key, void *record,
                             size_t capacity, size_t *record_size, bool *found)
{
    if (found == NULL || record_size == NULL) {
        return false;
    }
    *found = false;
    *record_size = 0;
    if (!ready || record == NULL || capacity == 0) {
        return false;
    }
    nvs_handle_t handle;
    esp_err_t result = nvs_open(name_space, NVS_READONLY, &handle);
    if (result == ESP_ERR_NVS_NOT_FOUND) {
        return true;
    }
    if (result != ESP_OK) {
        ESP_LOGE(TAG, "Cannot open %s: %s", name_space, esp_err_to_name(result));
        return false;
    }
    size_t length = 0;
    result = nvs_get_blob(handle, key, NULL, &length);
    if (result == ESP_ERR_NVS_NOT_FOUND) {
        nvs_close(handle);
        return true;
    }
    if (result == ESP_OK && length <= capacity) {
        result = nvs_get_blob(handle, key, record, &length);
        *found = result == ESP_OK;
        if (*found) {
            *record_size = length;
        }
    } else if (result == ESP_OK) {
        result = ESP_ERR_NVS_INVALID_LENGTH;
    }
    nvs_close(handle);
    if (result != ESP_OK) {
        ESP_LOGE(TAG, "Cannot read %s/%s: %s", name_space, key, esp_err_to_name(result));
    }
    return result == ESP_OK;
}
game_storage_read() · source line 66
bool game_storage_read(const char *name_space, const char *key, void *record,
                       size_t size, bool *found)

Calls into this documentation:

  1. Executesize_t record_size = 0;
  2. Decision!game_storage_read_sized(name_space, key, record, size, &record_size, found)
    True
      1. Exit this functionreturn false;
    False

    Continue after this decision.

  3. Decision*found && record_size != size
    True
      1. ExecuteESP_LOGE(TAG, "Cannot read %s/%s: unexpected record size %u", name_space, key, (unsigned)record_size);
      2. Execute*found = false;
      3. Exit this functionreturn false;
    False

    Continue after this decision.

  4. Exit this functionreturn true;
Read original function source
bool game_storage_read(const char *name_space, const char *key, void *record,
                       size_t size, bool *found)
{
    size_t record_size = 0;
    if (!game_storage_read_sized(name_space, key, record, size, &record_size, found)) {
        return false;
    }
    if (*found && record_size != size) {
        ESP_LOGE(TAG, "Cannot read %s/%s: unexpected record size %u", name_space, key,
                 (unsigned)record_size);
        *found = false;
        return false;
    }
    return true;
}
game_storage_write() · source line 82
bool game_storage_write(const char *name_space, const char *key,
                        const void *record, size_t size)
  1. Decision!ready || record == NULL || size == 0
    True
      1. Exit this functionreturn false;
    False

    Continue after this decision.

  2. Executenvs_handle_t handle;
  3. Executeesp_err_t result = nvs_open(name_space, NVS_READWRITE, &handle);
  4. Decisionresult != ESP_OK
    True
      1. ExecuteESP_LOGE(TAG, "Cannot open %s: %s", name_space, esp_err_to_name(result));
      2. Exit this functionreturn false;
    False

    Continue after this decision.

  5. Executeresult = nvs_set_blob(handle, key, record, size);
  6. Decisionresult == ESP_OK
    True
      1. Executeresult = nvs_commit(handle);
    False

    Continue after this decision.

  7. Executenvs_close(handle);
  8. Decisionresult != ESP_OK
    True
      1. ExecuteESP_LOGE(TAG, "Cannot save %s/%s: %s", name_space, key, esp_err_to_name(result));
    False

    Continue after this decision.

  9. Exit this functionreturn result == ESP_OK;
Read original function source
bool game_storage_write(const char *name_space, const char *key,
                        const void *record, size_t size)
{
    if (!ready || record == NULL || size == 0) {
        return false;
    }
    nvs_handle_t handle;
    esp_err_t result = nvs_open(name_space, NVS_READWRITE, &handle);
    if (result != ESP_OK) {
        ESP_LOGE(TAG, "Cannot open %s: %s", name_space, esp_err_to_name(result));
        return false;
    }
    result = nvs_set_blob(handle, key, record, size);
    if (result == ESP_OK) {
        result = nvs_commit(handle);
    }
    nvs_close(handle);
    if (result != ESP_OK) {
        ESP_LOGE(TAG, "Cannot save %s/%s: %s", name_space, key, esp_err_to_name(result));
    }
    return result == ESP_OK;
}
Complete original file, including constants and data
/* Coded By JD(2026) */
#error "Reference listing only — not provided as build-ready source."
#include "game_storage.h"
#include "esp_log.h"
#include "nvs.h"
#include "nvs_flash.h"

static const char *TAG = "game_storage";
static bool ready = false;

bool game_storage_initialize(void)
{
    if (ready) {
        return true;
    }
    const esp_err_t result = nvs_flash_init();
    ready = result == ESP_OK;
    if (!ready) {
        // Never erase existing settings as an automatic recovery action.
        ESP_LOGE(TAG, "NVS unavailable: %s; stored data left intact",
                 esp_err_to_name(result));
    }
    return ready;
}

bool game_storage_read_sized(const char *name_space, const char *key, void *record,
                             size_t capacity, size_t *record_size, bool *found)
{
    if (found == NULL || record_size == NULL) {
        return false;
    }
    *found = false;
    *record_size = 0;
    if (!ready || record == NULL || capacity == 0) {
        return false;
    }
    nvs_handle_t handle;
    esp_err_t result = nvs_open(name_space, NVS_READONLY, &handle);
    if (result == ESP_ERR_NVS_NOT_FOUND) {
        return true;
    }
    if (result != ESP_OK) {
        ESP_LOGE(TAG, "Cannot open %s: %s", name_space, esp_err_to_name(result));
        return false;
    }
    size_t length = 0;
    result = nvs_get_blob(handle, key, NULL, &length);
    if (result == ESP_ERR_NVS_NOT_FOUND) {
        nvs_close(handle);
        return true;
    }
    if (result == ESP_OK && length <= capacity) {
        result = nvs_get_blob(handle, key, record, &length);
        *found = result == ESP_OK;
        if (*found) {
            *record_size = length;
        }
    } else if (result == ESP_OK) {
        result = ESP_ERR_NVS_INVALID_LENGTH;
    }
    nvs_close(handle);
    if (result != ESP_OK) {
        ESP_LOGE(TAG, "Cannot read %s/%s: %s", name_space, key, esp_err_to_name(result));
    }
    return result == ESP_OK;
}

bool game_storage_read(const char *name_space, const char *key, void *record,
                       size_t size, bool *found)
{
    size_t record_size = 0;
    if (!game_storage_read_sized(name_space, key, record, size, &record_size, found)) {
        return false;
    }
    if (*found && record_size != size) {
        ESP_LOGE(TAG, "Cannot read %s/%s: unexpected record size %u", name_space, key,
                 (unsigned)record_size);
        *found = false;
        return false;
    }
    return true;
}

bool game_storage_write(const char *name_space, const char *key,
                        const void *record, size_t size)
{
    if (!ready || record == NULL || size == 0) {
        return false;
    }
    nvs_handle_t handle;
    esp_err_t result = nvs_open(name_space, NVS_READWRITE, &handle);
    if (result != ESP_OK) {
        ESP_LOGE(TAG, "Cannot open %s: %s", name_space, esp_err_to_name(result));
        return false;
    }
    result = nvs_set_blob(handle, key, record, size);
    if (result == ESP_OK) {
        result = nvs_commit(handle);
    }
    nvs_close(handle);
    if (result != ESP_OK) {
        ESP_LOGE(TAG, "Cannot save %s/%s: %s", name_space, key, esp_err_to_name(result));
    }
    return result == ESP_OK;
}