C/C++ 解析ini文件

C/C++ 解析ini文件

c++版本

/*
 * inicpp.h
 *
 * Created on: 26 Dec 2015
 *     Author: Fabian Meyer
 *    License: MIT
 */

#ifndef INICPP_H_
#define INICPP_H_

#include <algorithm>
#include <fstream>
#include <istream>
#include <map>
#include <sstream>
#include <stdexcept>

namespace ini
{
    class IniField
    {
    private:
        std::string value_;

    public:
        IniField() : value_()
        {}

        IniField(const std::string &value) : value_(value)
        {}
        IniField(const IniField &field) : value_(field.value_)
        {}

        ~IniField()
        {}

        template<typename T>
        T as() const
        {
            return static_cast<T>(*this);
        }

        /**********************************************************************
         * Assignment Operators
         *********************************************************************/

        IniField &operator=(const char *value)
        {
            value_ = std::string(value);
            return *this;
        }

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

        IniField &operator=(const IniField &field)
        {
            value_ = field.value_;
            return *this;
        }

        IniField &operator=(const int value)
        {
            std::stringstream ss;
            ss << value;
            value_ = ss.str();
            return *this;
        }

        IniField &operator=(const unsigned int value)
        {
            std::stringstream ss;
            ss << value;
            value_ = ss.str();
            return *this;
        }

        IniField &operator=(const double value)
        {
            std::stringstream ss;
            ss << value;
            value_ = ss.str();
            return *this;
        }

        IniField &operator=(const float value)
        {
            std::stringstream ss;
            ss << value;
            value_ = ss.str();
            return *this;
        }

        IniField &operator=(const bool value)
        {
            if(value)
                value_ = "true";
            else
                value_ = "false";
            return *this;
        }

        /**********************************************************************
         * Cast Operators
         *********************************************************************/

        explicit operator const char *() const
        {
            return value_.c_str();
        }

        explicit operator std::string() const
        {
            return value_;
        }

        explicit operator int() const
        {
            char *endptr;
            // check if decimal
            int result = std::strtol(value_.c_str(), &endptr, 10);
            if(*endptr == '\0')
                return result;
            // check if octal
            result = std::strtol(value_.c_str(), &endptr, 8);
            if(*endptr == '\0')
                return result;
            // check if hex
            result = std::strtol(value_.c_str(), &endptr, 16);
            if(*endptr == '\0')
                return result;

            throw std::invalid_argument("field is not an int");
        }

        explicit operator unsigned int() const
        {
            char *endptr;
            // check if decimal
            int result = std::strtoul(value_.c_str(), &endptr, 10);
            if(*endptr == '\0')
                return result;
            // check if octal
            result = std::strtoul(value_.c_str(), &endptr, 8);
            if(*endptr == '\0')
                return result;
            // check if hex
            result = std::strtoul(value_.c_str(), &endptr, 16);
            if(*endptr == '\0')
                return result;

            throw std::invalid_argument("field is not an unsigned int");
        }

        explicit operator float() const
        {
            return std::stof(value_);
        }

        explicit operator double() const
        {
            return std::stod(value_);
        }

        explicit operator bool() const
        {
            std::string str(value_);
            std::transform(str.begin(), str.end(), str.begin(), ::toupper);

            if(str == "TRUE")
                return true;
            else if(str == "FALSE")
                return false;
            else
                throw std::invalid_argument("field is not a bool");
        }
    };

    class IniSection : public std::map<std::string, IniField>
    {
    public:
        IniSection()
        {}
        ~IniSection()
        {}
    };

    class IniFile : public std::map<std::string, IniSection>
    {
    private:
        char fieldSep_;
        char comment_;

    public:
        IniFile() : IniFile('=', '#')
        {}

        IniFile(const char fieldSep, const char comment)
            : fieldSep_(fieldSep), comment_(comment)
        {}

        IniFile(const std::string &filename,
            const char fieldSep = '=',
            const char comment = '#')
            : IniFile(fieldSep, comment)
        {
            load(filename);
        }

        IniFile(std::istream &is,
            const char fieldSep = '=',
            const char comment = '#')
            : IniFile(fieldSep, comment)
        {
            decode(is);
        }

        ~IniFile()
        {}

        void setFieldSep(const char sep)
        {
            fieldSep_ = sep;
        }

        void setCommentChar(const char comment)
        {
            comment_ = comment;
        }

        void decode(std::istream &is)
        {
            clear();
            int lineNo = 0;
            IniSection *currentSection = NULL;
            // iterate file by line
            while(!is.eof() && !is.fail())
            {
                std::string line;
                std::getline(is, line, '\n');
                ++lineNo;

                // skip if line is empty
                if(line.size() == 0)
                    continue;
                // skip if line is a comment
                if(line[0] == comment_)
                    continue;
                if(line[0] == '[')
                {
                    // line is a section
                    // check if the section is also closed on same line
                    std::size_t pos = line.find("]");
                    if(pos == std::string::npos)
                    {
                        std::stringstream ss;
                        ss << "l" << lineNo
                           << ": ini parsing failed, section not closed";
                        throw std::logic_error(ss.str());
                    }
                    // check if the section name is empty
                    if(pos == 1)
                    {
                        std::stringstream ss;
                        ss << "l" << lineNo
                           << ": ini parsing failed, section is empty";
                        throw std::logic_error(ss.str());
                    }
                    // check if there is a newline following closing bracket
                    if(pos + 1 != line.length())
                    {
                        std::stringstream ss;
                        ss << "l" << lineNo
                           << ": ini parsing failed, no end of line after "
                              "section";
                        throw std::logic_error(ss.str());
                    }

                    // retrieve section name
                    std::string secName = line.substr(1, pos - 1);
                    currentSection = &((*this)[secName]);
                }
                else
                {
                    // line is a field definition
                    // check if section was already opened
                    if(currentSection == NULL)
                    {
                        std::stringstream ss;
                        ss << "l" << lineNo
                           << ": ini parsing failed, field has no section";
                        throw std::logic_error(ss.str());
                    }

                    // find key value separator
                    std::size_t pos = line.find(fieldSep_);
                    if(pos == std::string::npos)
                    {
                        std::stringstream ss;
                        ss << "l" << lineNo
                           << ": ini parsing failed, no '=' found";
                        throw std::logic_error(ss.str());
                    }
                    // retrieve field name and value
                    std::string name = line.substr(0, pos);
                    std::string value = line.substr(pos + 1, std::string::npos);
                    (*currentSection)[name] = value;
                }
            }
        }

        void decode(const std::string &content)
        {
            std::istringstream ss(content);
            decode(ss);
        }

        void load(const std::string &fileName)
        {
            std::ifstream is(fileName.c_str());
            decode(is);
        }

        void encode(std::ostream &os) const
        {
            // iterate through all sections in this file
            for(const auto &filePair : *this)
            {
                os << "[" << filePair.first << "]" << std::endl;
                // iterate through all fields in the section
                for(const auto &secPair : filePair.second)
                    os << secPair.first << fieldSep_
                       << secPair.second.as<std::string>() << std::endl;
            }
        }

        std::string encode() const
        {
            std::ostringstream ss;
            encode(ss);
            return ss.str();
        }

        void save(const std::string &fileName) const
        {
            std::ofstream os(fileName.c_str());
            encode(os);
        }
    };
}

#endif
#include "inicpp.h"

void main()
{
#if 1//read
        ini::IniFile myIni;
        myIni.load("sysconfig.ini");
        float min = myIni["Frequecy"]["min"].as<float>();
        float max = myIni["Frequecy"]["max"].as<float>();
        float def = myIni["Frequecy"]["default"].as<float>();
        float step = myIni["Frequecy"]["step"].as<float>();
        std::string unit = myIni["Frequecy"]["unit"].as<std::string>();
        qDebug() << "******************";
        qDebug() << "min:"<<min;
        qDebug() << "max:"<<max;
        qDebug() << "def:"<<def;
        qDebug() << "step:"<<step;
        //qDebug() << unit;
#endif

#if 1//write
        ini::IniFile sysIni;
        sysIni["Frequecy"]["min"] = 1.0;
        sysIni["Frequecy"]["max"] = 18.0;
        sysIni["Frequecy"]["default"] = 1.0;
        sysIni["Frequecy"]["step"] = 0.5;
        sysIni["Frequecy"]["unit"] = "MHz";

        sysIni.save("sysconfig.ini");
#endif
}

ini文件解析

C语言版本

csdn下载

猜你喜欢

转载自blog.csdn.net/al86866365/article/details/81743708
今日推荐