| // 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_ |