| // Copyright 2015 The Android Open Source Project |
| // |
| // This software is licensed under the terms of the GNU General Public |
| // License version 2, as published by the Free Software Foundation, and |
| // may be copied, distributed, and modified under those terms. |
| // |
| // This program is distributed in the hope that it will be useful, |
| // but WITHOUT ANY WARRANTY; without even the implied warranty of |
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| // GNU General Public License for more details. |
| |
| #pragma once |
| |
| #include "android/base/Compiler.h" |
| #include "android/base/StringView.h" |
| |
| #include <iosfwd> |
| #include <string> |
| #include <unordered_map> |
| #include <utility> |
| #include <vector> |
| |
| #include <inttypes.h> |
| |
| namespace android { |
| namespace base { |
| |
| class IniFile { |
| public: |
| typedef int64_t DiskSize; |
| typedef std::unordered_map<std::string, std::string> MapType; |
| typedef std::vector<std::string> KeyListType; |
| |
| // Note that the constructor _does not_ read data from the backing file. |
| // Call |Read| to read the data. |
| IniFile(const std::string& backingFilePath) |
| : mDirty(true), mBackingFilePath(backingFilePath) {} |
| // When created without a backing file, all |read|/|write*| operations will |
| // fail unless |setBackingFile| is called to point to a valid file path. |
| IniFile() : mDirty(true) {} |
| |
| // Set a new backing file. This does not read data from the file. Call |
| // |read| |
| // to refresh data from the new backing file. |
| void setBackingFile(const std::string& filePath); |
| const std::string& getBackingFile() const { return mBackingFilePath; } |
| |
| // Reads data into IniFile from the the backing file, overwriting any |
| // existing data. |
| bool read(); |
| |
| // Write the current IniFile to the backing file. |
| bool write(); |
| // Write the current IniFile to backing file. Discard any keys that have |
| // empty values. |
| bool writeDiscardingEmpty(); |
| // An optimized write. |
| // - Advantage: We don't write if there have been no updates since last |
| // write. |
| // - Disadvantage: Not safe if something else might be changing the ini |
| // file -- your view of the file is no longer consistent. Actually, this |
| // "bug" can be considered a "feature", if the ini file changed unbeknown |
| // to you, you're probably doing wrong in overwriting the changes without |
| // any update on your side. |
| bool writeIfChanged(); |
| |
| // Gets the number of (key,value) pairs in the file. |
| int size() const; |
| // Check if a certain key exists in the file. |
| bool hasKey(const std::string& key) const; |
| |
| // Make sure the string can be used as a valid key |
| static std::string makeValidKey(StringView str); |
| |
| // ///////////////////// Value Getters |
| // ////////////////////////////////////// |
| // The IniFile has no knowledge about the type of the values. |
| // |defaultValue| is returned if the key doesn't exist or the value is badly |
| // formatted for the requested type. |
| // |
| // For some value types where the disk format is significantly more useful |
| // for human-parsing, overloads are provided that accept default values as |
| // strings to be parsed just like the backing ini file. |
| // - This has the benefit that default values can be stored in a separate |
| // file in human friendly form, and used directly. |
| // - The disadvantage is that behaviour is undefined if we fail to parse the |
| // default value. |
| std::string getString(const std::string& key, |
| const std::string& defaultValue) const; |
| int getInt(const std::string& key, int defaultValue) const; |
| int64_t getInt64(const std::string& key, int64_t defaultValue) const; |
| double getDouble(const std::string& key, double defaultValue) const; |
| // The serialized format for a bool acceepts the following values: |
| // True: "1", "yes", "YES". |
| // False: "0", "no", "NO". |
| bool getBool(const std::string& key, bool defaultValue) const; |
| bool getBoolStr(const std::string& kye, |
| const std::string& defaultValueStr) const; |
| // Parses a string as disk size. The serialized format is [0-9]+[kKmMgG]. |
| // The |
| // suffixes correspond to KiB, MiB and GiB multipliers. |
| // Note: We consider 1K = 1024, not 1000. |
| DiskSize getDiskSize(const std::string& key, DiskSize defaultValue) const; |
| DiskSize getDiskSizeStr(const std::string& key, |
| const std::string& defaultValueStr) const; |
| |
| // ///////////////////// Value Setters |
| // ////////////////////////////////////// |
| void setString(const std::string& key, const std::string& value); |
| void setInt(const std::string& key, int value); |
| void setInt64(const std::string& key, int64_t value); |
| void setDouble(const std::string& key, double value); |
| void setBool(const std::string& key, bool value); |
| void setDiskSize(const std::string& key, DiskSize value); |
| |
| // //////////////////// Iterators |
| // /////////////////////////////////////////// |
| // You can iterate through (string) keys in this IniFile, and then use the |
| // correct |get*| function to obtain the corresponding value. |
| // The order of keys is guaranteed to be an extension of the order in the |
| // backing file: |
| // - For keys that exist in the backing file, order is maintained. |
| // - Rest of the keys are appended in the end, in the order they were |
| // first added. |
| // Only const_iterator is provided. Use |set*| functions to modify the |
| // IniFile. |
| typedef KeyListType::const_iterator const_iterator; |
| const_iterator begin() const { return std::begin(mKeys); } |
| const_iterator end() const { return std::end(mKeys); } |
| |
| protected: |
| // Helper functions. |
| void parseFile(std::istream* inFile); |
| void updateData(const std::string& key, const std::string& value); |
| bool writeCommon(bool discardEmpty); |
| |
| private: |
| bool mDirty; |
| MapType mData; |
| KeyListType mKeys; |
| std::vector<std::pair<int, std::string>> mComments; |
| std::string mBackingFilePath; |
| |
| DISALLOW_COPY_AND_ASSIGN(IniFile); |
| }; |
| |
| } // namespace base |
| } // namespace android |