CLion实现ini 解析器设计与实现

INI格式:

cpp 复制代码
[server]
ip = 127.0.0.1
port = 80

[profile]
name = jack
gender = male
age = 30

IniFile.h

cpp 复制代码
#pragma once
#include <string>
#include <map>
class Value {
public:
    Value();
    explicit Value(bool value);
    explicit Value(int value);
    explicit Value(double value);
    explicit Value(const char * value);
    explicit Value(const std::string & value);

    Value& operator = (bool value);
    Value& operator = (int value);
    Value& operator = (double value);
    Value& operator = (const char * value);
    Value& operator = (const std::string & value);

    explicit operator bool();
    explicit  operator int();
    explicit operator double();
    explicit operator std::string();
private:
    std::string m_value;
};

typedef std::map<std::string, Value> Section;
class IniFile {
public:
    IniFile();
    bool load(const std::string & filename);
    Value & get(const std::string & section, const std::string & key);
    void set(const std::string & section, const std::string & key,const Value & value);
    bool has(const std::string & section,const std::string & key);
    bool has(const std::string & secton);
    void remove(const std::string & section,const std::string & key);
    void remove(const std::string & section);
    void clear();
    bool save(const std::string& filename);
    Section & operator [] (const std::string & section) {
        return m_sections[section];
    }
private:
    std::string trim(std::string & str);
private:
    std::string m_filename;
    std::map<std::string,Section> m_sections;
};

IniFile.cpp

cpp 复制代码
#include "IniFile.h"
#include <fstream>
#include <iostream>
Value::Value() {
    m_value = "";
}
Value::Value(bool value) {
    *this = value;
}
Value::Value(int value) {
    *this = value;
}
Value::Value(double value) {
    *this = value;
}
Value::Value(const char * value) {
    *this = value;
}
Value::Value(const std::string & value) {
    *this = value;
}

Value& Value::operator=(bool value) {
    m_value = value ? "true" : "false";
    return *this;
}

Value& Value::operator=(int value) {
    m_value = std::to_string(value);
    return *this;
}

Value& Value::operator=(double value) {
    m_value = std::to_string(value);
    return *this;
}

Value& Value::operator=(const char* value) {
    m_value = value;
    return *this;
}

Value& Value::operator=(const std::string& value) {
    m_value = value;
    return *this;
}

Value::operator bool() {
    return m_value == "true";
}
Value::operator int() {
    return std::stoi(m_value);
}
Value::operator double() {
    return std::stod(m_value);
}
Value::operator std::string() {
    return m_value;
}

IniFile::IniFile() = default;

bool IniFile::load(const std::string & filename) {
    m_filename = filename;
    std::ifstream fin( filename);
    if(fin.fail()) {
        std::cout << "Failed to open file: " <<std::endl;
        return false;
    }
    std::string line;
    std::string section;
    while(std::getline(fin, line)) {
        line = trim(line);
        if(line.empty()) {
            continue;
        }
        int pos = line.find_first_of(']');
        if(pos != std::string::npos) {
            section = line.substr(1, pos - 1);
            section = trim(section);
            m_sections[section] = Section();
        }else {
            int pos = line.find_first_of('=');
            if(pos != std::string::npos) {
                std::string key = line.substr(0, pos);
                key = trim(key);
                std::string value = line.substr(pos + 1);
                value = trim(value);
                m_sections[section][key] = value;
            }
        }
    }
    fin.close();
    return true;
}

std::string IniFile::trim(std::string &str) {
    if(str.empty()) {
        return str;
    }
    str.erase(0, str.find_first_not_of(" \n\r"));
    str.erase(str.find_last_not_of(" \n\r") + 1);
    return str;
}

Value & IniFile::get(const std::string & section, const std::string & key) {
    return m_sections[section][key];
}

void IniFile::set(const std::string & section, const std::string & key,const Value & value) {
    m_sections[section][key] = value;
}

bool IniFile::has(const std::string & section,const std::string & key) {
    std::map<std::string,Section>::const_iterator it = m_sections.find(section);
    if(it != m_sections.end()) {
        return it->second.find(key) != it->second.end();
    }
    return false;
}

// 在 IniFile 类中添加保存方法
bool IniFile::save(const std::string& filename) {
    std::ofstream fout(filename );
    if (fout.fail()) {
        return false;
    }

    for ( auto& section_pair : m_sections) {
        fout << "[" << section_pair.first << "]\n";
        for ( auto& key_value : section_pair.second) {
            fout << key_value.first << "=" << static_cast<std::string>(key_value.second) << "\n";
        }
        fout << "\n";
    }

    fout.close();
    return true;
}

bool IniFile::has(const std::string & section) {
    return m_sections.find(section) != m_sections.end();
}

void IniFile::remove(const std::string & section,const std::string & key) {
    std::map<std::string,Section>::iterator it = m_sections.find(section);
    if(it != m_sections.end()) {
        it->second.erase(key);
    }
}
void IniFile::remove(const std::string & section) {
    m_sections.erase(section);
}
void IniFile::clear() {
    m_sections.clear();
}

main.cpp

cpp 复制代码
#include <iostream>
#include "IniFile.h"

int main() {
    IniFile ini;
    ini.load("test.ini");
    const std::string & ip = static_cast<std::string>(ini.get("server", "ip"));
    int port = static_cast< int>(ini.get("server", "port"));
    std::cout<<"ip:"<<ip<<" port:"<<port<<std::endl;

    const std::string ipp = static_cast<std::string>(ini["server"]["ip"]);
    std::cout<<"ipp:"<<ipp<<std::endl;

    //ini.set("server", "ip", "192.168.1.1");
    //std::cout<<"ip:"<<ip<<" port:"<<port<<std::endl;
    ini.set("server","timeout",Value(1000));

    std::cout<<"timeout:"<<static_cast<int>(ini.get("server","timeout"))<<std::endl;

    bool b = ini.has("server","timeout");
    std::cout<<"has timeout:"<<b<<std::endl;

    b = ini.has("server");
    std::cout<<"has server:"<<b<<std::endl;
    ini.remove("server","timeout");
    ini.save("test.ini");
    return 0;
}
相关推荐
程序员飞哥3 小时前
如何设计多级缓存架构并解决一致性问题?
java·后端·面试
前端小马4 小时前
前后端Long类型ID精度丢失问题
java·前端·javascript·后端
Lisonseekpan4 小时前
Java Caffeine 高性能缓存库详解与使用案例
java·后端·spring·缓存
柳贯一(逆流河版)4 小时前
Spring Boot Actuator+Micrometer:高并发下 JVM 监控体系的轻量化实践
jvm·spring boot·后端
AA陈超4 小时前
虚幻引擎5 GAS开发俯视角RPG游戏 P05-05 游戏效果委托
c++·游戏·ue5·游戏引擎·虚幻
杨小码不BUG4 小时前
Davor的北极探险资金筹集:数学建模与算法优化(洛谷P4956)
c++·算法·数学建模·信奥赛·csp-j/s
SXJR4 小时前
Spring前置准备(七)——DefaultListableBeanFactory
java·spring boot·后端·spring·源码·spring源码·java开发
mit6.8244 小时前
10.5 数位dp
c++·算法
初圣魔门首席弟子4 小时前
C++ STL 向量(vector)学习笔记:从基础到实战
c++·笔记·学习