jtilly/inih

How implementing custom or string-based I/O

fananchong opened this issue · 2 comments

    /* Same as ini_parse(), but takes an ini_reader function pointer instead of
   filename. Used for implementing custom or string-based I/O. */
    int ini_parse_stream(ini_reader reader, void *stream, ini_handler handler,
                         void *user);

How I use ini_parse_stream , implementing custom or string-based I/O

I want init with string

#pragma once

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include "INIReader.h"

class INIReaderEx final : public INIReader
{
public:
    INIReaderEx(const std::string &ini_string)
    {
        _error = ini_parse_string(ini_string.c_str(), ValueHandler, this);
    }

private:
    /**
     * 代码摘自 https://github.com/benhoyt/inih
     */

    /* Used by ini_parse_string() to keep track of string parsing state. */
    typedef struct
    {
        const char *ptr;
        size_t num_left;
    } ini_parse_string_ctx;

    /* An ini_reader function to read the next line from a string buffer. This
   is the fgets() equivalent used by ini_parse_string(). */
    static char *ini_reader_string(char *str, int num, void *stream)
    {
        ini_parse_string_ctx *ctx = (ini_parse_string_ctx *)stream;
        const char *ctx_ptr = ctx->ptr;
        size_t ctx_num_left = ctx->num_left;
        char *strp = str;
        char c;

        if (ctx_num_left == 0 || num < 2)
            return NULL;

        while (num > 1 && ctx_num_left != 0)
        {
            c = *ctx_ptr++;
            ctx_num_left--;
            *strp++ = c;
            if (c == '\n')
                break;
            num--;
        }

        *strp = '\0';
        ctx->ptr = ctx_ptr;
        ctx->num_left = ctx_num_left;
        return str;
    }

    /* See documentation in header file. */
    int ini_parse_string(const char *string, ini_handler handler, void *user)
    {
        ini_parse_string_ctx ctx;

        ctx.ptr = string;
        ctx.num_left = strlen(string);
        return ini_parse_stream((ini_reader)ini_reader_string, &ctx, handler,
                                user);
    }
};