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;
}
相关推荐
Victor35614 小时前
Redis(99)Redis的高可用性如何实现?
后端
小-黯14 小时前
OpenGL使用C++实现相机模块功能
c++·3d·opengl
Victor35614 小时前
Redis(98) Redis的安全更新如何进行?
后端
_dindong15 小时前
牛客101:二叉树
数据结构·c++·笔记·学习·算法
计算机学姐16 小时前
基于SpringBoot的动漫推荐系统【协同过滤推荐算法+词云图+排行榜】
java·vue.js·spring boot·后端·mysql·intellij-idea·推荐算法
人邮异步社区16 小时前
推荐几本学习计算机语言的书
java·c语言·c++·python·学习·golang
韩立学长18 小时前
基于Springboot的影视评论网站的设计与实现58py6238(程序、源码、数据库、调试部署方案及开发环境)系统界面展示及获取方式置于文档末尾,可供参考。
数据库·spring boot·后端
ha204289419419 小时前
Linux操作系统学习之---线程池
linux·c++·学习
A-code19 小时前
C/C++ 中 void* 深度解析:从概念到实战
c语言·开发语言·c++·经验分享·嵌入式
JavaTree201721 小时前
SpringMVC基础入门
后端