Search code examples
c++stringparsingchars

Read Syntax from configuration file


I'm trying to write a configuration reader in C/C++ (using Low-Level I/O). The configuration contains directions like:

App example.com {
      use: python vauejs sass;
      root: www/html;
      ssl: Enabled;
}

How could i read the content into a std::map or struct? Google did not give me the results i'm looking for yet. I hope SO got some ideas...

What i got so far:

// File Descriptor
int fd;
// Open File
const errno_t ferr = _sopen_s(&fd, _file, _O_RDONLY, _SH_DENYWR, _S_IREAD);
// Handle returned value
switch (ferr) {
    // The given path is a directory, or the file is read-only, but an open-for-writing operation was attempted.
    case EACCES:
        perror("[Error] Following error occurred while reading configuration");
        return false;
    break;
    // Invalid oflag, shflag, or pmode argument, or pfh or filename was a null pointer.
    case EINVAL:
        perror("[Error] Following error occurred while reading configuration");
        return false;
    break;
    // No more file descriptors available.
    case EMFILE:
        perror("[Error] Following error occurred while reading configuration");
        return false;
    break;
    // File or path not found.
    case ENOENT:
        perror("[Error] Following error occured while reading configuration");
        return false;
    break;
}

// Notify Screen
if (pDevMode)
    std::printf("[Configuration]: '_sopen_s' were able to open file \"%s\".\n", _file);

// Allocate memory for buffer
buffer = new (std::nothrow) char[4098 * 4];
// Did the allocation succeed?
if (buffer == nullptr) {
    _close(fd);
    std::perror("[Error] Following error occurred while reading configuration");
    return false;
}

// Notify Screen
if (pDevMode)
    std::printf("[Configuration]: Buffer Allocation succeed.\n");

// Reading content from file
const std::size_t size = _read(fd, buffer, (4098 * 4)); 

Solution

  • If you put your buffer into a std::string you can piece together a solution from various answers about splitting strings on SO.

    The essential structure seems to be "stuff { key:value \n key:value \n }" with varying amounts of whitespace. Many questions have been asked about trimming a string. Splitting a string can happen in several ways, e.g.

    std::string config = "App example.com {\n"
        "   use: python vauejs sass;\n"
        "   root: www / html; \n"
        "   ssl: Enabled;"
        "}";
    std::istringstream ss(config);
    std::string token;
    std::getline(ss, token, '{');
    std::cout << token << "... ";
    
    std::getline(ss, token, ':');
    //use handy trim function - loads of e.g.s on SO
    std::cout << token << " = ";
    std::getline(ss, token, '\n');
    // trim function required...
    std::cout << token << "...\n\n";
    
    //as many times or in a loop.. 
    //then check for closing }
    

    If you have more complicated parsing consider a full-on parser.