blob: e3c43e5eacb00653afe27a2042a1ba71918f02ce [file] [log] [blame] [edit]
// Copyright 2021 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef RMAD_UTILS_JSON_STORE_H_
#define RMAD_UTILS_JSON_STORE_H_
#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include <base/files/file_path.h>
#include <base/memory/ref_counted.h>
#include <base/values.h>
#include "rmad/utils/type_conversions.h"
namespace rmad {
// A class to store a JSON dictionary and keep in sync with a file.
class JsonStore : public base::RefCounted<JsonStore> {
public:
enum ReadError {
READ_ERROR_NONE = 0,
READ_ERROR_JSON_PARSE = 1,
READ_ERROR_JSON_TYPE = 2,
READ_ERROR_FILE_ACCESS_DENIED = 3,
READ_ERROR_FILE_OTHER = 4,
READ_ERROR_FILE_LOCKED = 5,
READ_ERROR_NO_SUCH_FILE = 6,
READ_ERROR_MAX_ENUM
};
explicit JsonStore(const base::FilePath& file_path, bool read_only);
// Initialize from the file.
bool InitFromFile(bool read_only);
// Set a (key, value) pair to the dictionary. Return true if there's no
// update or the updated data is successfully written to the file, false if
// the update cannot be written to the file.
bool SetValue(const std::string& key, base::Value&& value);
// Set a (key, value) pair to the dictionary for types supported by
// base::Value (bool, int, double, string), or nested vector of these types.
// Return true if there's no update or the updated data is successfully
// written to the file, false if the update cannot be written to the file.
template <typename T>
bool SetValue(const std::string& key, const T& value) {
return SetValue(key, ConvertToValue(value));
}
// Get the value associated to the key, and copy to `value` for types
// supported by base::Value.
// If value is null then just the existence and type of the key value is
// checked.
// If the key is not found, `value` is not modified by the function. Return
// true if the key is found in the dictionary, false if the key is not found.
template <typename T>
bool GetValue(const std::string& key, T* result) const {
return ConvertFromValue(data_.Find(key), result);
}
// Get the value associated to the key, and assign its const pointer to
// `result`. If the key is not found, `result` is not modified by the
// function. Return true if the key is found in the dictionary, false if the
// key is not found.
bool GetValue(const std::string& key, const base::Value** result) const;
// Get the value associated to the key, and copy to `result`. If the key is
// not found, `result` is not modified by the function. Return true if the key
// is found in the dictionary, false if the key is not found.
bool GetValue(const std::string& key, base::Value* result) const;
// Get the complete copy of the dictionary.
base::Value::Dict GetValues() const;
// Remove a key in the dictionary. Return true if the key is removed, return
// false otherwise.
bool RemoveKey(const std::string& key);
// Clear the dictionary. Return true on success, false if failed to write to
// the file.
bool Clear();
// Clear the dictionary and delete the file that stores the data in storage.
// Return true on success, false if failed to clear or delete the file.
bool ClearAndDeleteFile();
// Get read status of the file.
ReadError GetReadError() const { return read_error_; }
// Return true if the file existed when read was attempted.
bool Exists() const { return read_error_ != READ_ERROR_NO_SUCH_FILE; }
// Return true if the file exists and contains a valid JSON string.
bool Initialized() const { return initialized_; }
// Return true if the file cannot be written, such as access denied, or the
// file already exists but contains invalid JSON format.
bool ReadOnly() const { return !initialized_ || read_only_; }
private:
// Hide the destructor so we don't accidentally delete this while there are
// references to it.
friend class base::RefCounted<JsonStore>;
~JsonStore() = default;
// Read result returned from internal read tasks.
struct ReadResult;
std::unique_ptr<JsonStore::ReadResult> ReadFromFile();
// This function is guarded by |read_only_|, but can be overridden by |force|
// argument.
bool WriteToFile(bool force = false);
const base::FilePath file_path_;
base::Value::Dict data_;
ReadError read_error_;
bool read_only_;
bool initialized_;
};
} // namespace rmad
#endif // RMAD_UTILS_JSON_STORE_H_