mirror of
https://github.com/google/pebble.git
synced 2025-03-22 11:42:19 +00:00
197 lines
6.1 KiB
C
197 lines
6.1 KiB
C
/*
|
|
* Copyright 2024 Google LLC
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "services/normal/settings/settings_file.h"
|
|
#include "system/status_codes.h"
|
|
#include "util/crc8.h"
|
|
|
|
#include <string.h>
|
|
#include <stdint.h>
|
|
|
|
#include "clar_asserts.h"
|
|
|
|
struct {
|
|
bool open;
|
|
void *values[UINT8_MAX];
|
|
void *keys[UINT8_MAX];
|
|
uint32_t val_lens[UINT8_MAX];
|
|
uint32_t key_lens[UINT8_MAX];
|
|
bool dirty[UINT8_MAX];
|
|
} s_settings_file;
|
|
|
|
void fake_settings_file_reset(void) {
|
|
for (unsigned i = 0; i < UINT8_MAX; ++i) {
|
|
free(s_settings_file.values[i]);
|
|
s_settings_file.values[i] = NULL;
|
|
free(s_settings_file.keys[i]);
|
|
s_settings_file.keys[i] = NULL;
|
|
s_settings_file.val_lens[i] = 0;
|
|
s_settings_file.key_lens[i] = 0;
|
|
s_settings_file.dirty[i] = false;
|
|
}
|
|
s_settings_file.open = false;
|
|
}
|
|
|
|
status_t settings_file_get(SettingsFile *file, const void *key, size_t key_len,
|
|
void *val_out, size_t val_out_len) {
|
|
if (settings_file_exists(file, key, key_len)) {
|
|
const uint8_t key_crc8 = crc8_calculate_bytes(key, key_len, false);
|
|
memcpy(val_out, s_settings_file.values[key_crc8], val_out_len);
|
|
return S_SUCCESS;
|
|
}
|
|
|
|
memset(val_out, 0, val_out_len);
|
|
return E_DOES_NOT_EXIST;
|
|
}
|
|
|
|
status_t settings_file_set(SettingsFile *file, const void *key, size_t key_len,
|
|
const void *val, size_t val_len) {
|
|
void *val_copy = malloc(val_len);
|
|
void *key_copy = malloc(key_len);
|
|
cl_assert(val_copy && key_copy);
|
|
memcpy(val_copy, val, val_len);
|
|
memcpy(key_copy, key, key_len);
|
|
const uint8_t key_crc8 = crc8_calculate_bytes(key, key_len, false);
|
|
if (s_settings_file.values[key_crc8] != NULL) {
|
|
cl_assert(memcmp(key, s_settings_file.keys[key_crc8], key_len) == 0);
|
|
}
|
|
|
|
free(s_settings_file.values[key_crc8]);
|
|
free(s_settings_file.keys[key_crc8]);
|
|
s_settings_file.values[key_crc8] = val_copy;
|
|
s_settings_file.keys[key_crc8] = key_copy;
|
|
s_settings_file.val_lens[key_crc8] = val_len;
|
|
s_settings_file.key_lens[key_crc8] = key_len;
|
|
s_settings_file.dirty[key_crc8] = true;
|
|
return S_SUCCESS;
|
|
}
|
|
|
|
int settings_file_get_len(SettingsFile *file, const void *key, size_t key_len) {
|
|
if (settings_file_exists(file, key, key_len)) {
|
|
const uint8_t key_crc8 = crc8_calculate_bytes(key, key_len, false);
|
|
return s_settings_file.val_lens[key_crc8];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
status_t settings_file_delete(SettingsFile *file,
|
|
const void *key, size_t key_len) {
|
|
if (settings_file_exists(file, key, key_len)) {
|
|
const uint8_t key_crc8 = crc8_calculate_bytes(key, key_len, false);
|
|
free(s_settings_file.values[key_crc8]);
|
|
free(s_settings_file.keys[key_crc8]);
|
|
s_settings_file.values[key_crc8] = NULL;
|
|
s_settings_file.keys[key_crc8] = NULL;
|
|
s_settings_file.val_lens[key_crc8] = 0;
|
|
s_settings_file.key_lens[key_crc8] = 0;
|
|
s_settings_file.dirty[key_crc8] = false;
|
|
return S_SUCCESS;
|
|
} else {
|
|
return E_DOES_NOT_EXIST;
|
|
}
|
|
}
|
|
|
|
status_t settings_file_open(SettingsFile *file, const char *name,
|
|
int max_used_space) {
|
|
if (s_settings_file.open) {
|
|
return E_BUSY;
|
|
} else {
|
|
*file = (SettingsFile){};
|
|
s_settings_file.open = true;
|
|
return S_SUCCESS;
|
|
}
|
|
}
|
|
|
|
void settings_file_close(SettingsFile *file) {
|
|
cl_assert(s_settings_file.open);
|
|
s_settings_file.open = false;
|
|
}
|
|
|
|
bool settings_file_exists(SettingsFile *file, const void *key, size_t key_len) {
|
|
const uint8_t key_crc8 = crc8_calculate_bytes(key, key_len, false);
|
|
return (s_settings_file.values[key_crc8] != NULL &&
|
|
memcmp(s_settings_file.keys[key_crc8], key, key_len) == 0);
|
|
}
|
|
|
|
status_t settings_file_mark_synced(SettingsFile *file, const void *key, size_t key_len) {
|
|
if (settings_file_exists(file, key, key_len)) {
|
|
const uint8_t key_crc8 = crc8_calculate_bytes(key, key_len, false);
|
|
s_settings_file.dirty[key_crc8] = false;
|
|
return S_SUCCESS;
|
|
}
|
|
return E_DOES_NOT_EXIST;
|
|
}
|
|
|
|
status_t settings_file_set_byte(SettingsFile *file, const void *key, size_t key_len, size_t offset,
|
|
uint8_t byte) {
|
|
if (settings_file_exists(file, key, key_len)) {
|
|
const uint8_t key_crc8 = crc8_calculate_bytes(key, key_len, false);
|
|
uint8_t *val_bytes = s_settings_file.values[key_crc8];
|
|
val_bytes[offset] &= byte;
|
|
return S_SUCCESS;
|
|
} else {
|
|
return E_DOES_NOT_EXIST;
|
|
}
|
|
}
|
|
|
|
uint8_t s_cur_itr;
|
|
|
|
static void prv_get_key(SettingsFile *file, void *key, size_t key_len) {
|
|
memcpy(key, s_settings_file.keys[s_cur_itr], key_len);
|
|
}
|
|
|
|
static void prv_get_val(SettingsFile *file, void *val, size_t val_len) {
|
|
memcpy(val, s_settings_file.values[s_cur_itr], val_len);
|
|
}
|
|
|
|
status_t settings_file_each(SettingsFile *file, SettingsFileEachCallback cb,
|
|
void *context) {
|
|
for (unsigned i = 0; i < UINT8_MAX; ++i) {
|
|
if (s_settings_file.keys[i] != NULL &&
|
|
s_settings_file.values[i] != NULL) {
|
|
s_cur_itr = i;
|
|
|
|
SettingsRecordInfo info = {
|
|
.get_key = prv_get_key,
|
|
.get_val = prv_get_val,
|
|
.key_len = s_settings_file.key_lens[i],
|
|
.val_len = s_settings_file.val_lens[i],
|
|
.dirty = s_settings_file.dirty[i],
|
|
};
|
|
if (!cb(file, &info, context)) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return S_SUCCESS;
|
|
}
|
|
|
|
status_t settings_file_rewrite(SettingsFile *file,
|
|
SettingsFileRewriteCallback cb,
|
|
void *context) {
|
|
// TODO
|
|
fake_settings_file_reset();
|
|
return S_SUCCESS;
|
|
}
|
|
|
|
status_t settings_file_rewrite_filtered(SettingsFile *file,
|
|
SettingsFileRewriteFilterCallback filter_cb,
|
|
void *context) {
|
|
// TODO
|
|
fake_settings_file_reset();
|
|
return S_SUCCESS;
|
|
}
|