inline std::vector ConfigBase::from_config()

in fboss/cli/fboss2/CLI11/Config.hpp [165:257]


inline std::vector<ConfigItem> ConfigBase::from_config(std::istream &input) const {
    std::string line;
    std::string section = "default";

    std::vector<ConfigItem> output;
    bool defaultArray = (arrayStart == '\0' || arrayStart == ' ') && arrayStart == arrayEnd;
    char aStart = (defaultArray) ? '[' : arrayStart;
    char aEnd = (defaultArray) ? ']' : arrayEnd;
    char aSep = (defaultArray && arraySeparator == ' ') ? ',' : arraySeparator;

    while(getline(input, line)) {
        std::vector<std::string> items_buffer;
        std::string name;

        detail::trim(line);
        std::size_t len = line.length();
        if(len > 1 && line.front() == '[' && line.back() == ']') {
            if(section != "default") {
                // insert a section end which is just an empty items_buffer
                output.emplace_back();
                output.back().parents = detail::generate_parents(section, name);
                output.back().name = "--";
            }
            section = line.substr(1, len - 2);
            // deal with double brackets for TOML
            if(section.size() > 1 && section.front() == '[' && section.back() == ']') {
                section = section.substr(1, section.size() - 2);
            }
            if(detail::to_lower(section) == "default") {
                section = "default";
            } else {
                detail::checkParentSegments(output, section);
            }
            continue;
        }
        if(len == 0) {
            continue;
        }
        // comment lines
        if(line.front() == ';' || line.front() == '#' || line.front() == commentChar) {
            continue;
        }

        // Find = in string, split and recombine
        auto pos = line.find(valueDelimiter);
        if(pos != std::string::npos) {
            name = detail::trim_copy(line.substr(0, pos));
            std::string item = detail::trim_copy(line.substr(pos + 1));
            if(item.size() > 1 && item.front() == aStart && item.back() == aEnd) {
                items_buffer = detail::split_up(item.substr(1, item.length() - 2), aSep);
            } else if(defaultArray && item.find_first_of(aSep) != std::string::npos) {
                items_buffer = detail::split_up(item, aSep);
            } else if(defaultArray && item.find_first_of(' ') != std::string::npos) {
                items_buffer = detail::split_up(item);
            } else {
                items_buffer = {item};
            }
        } else {
            name = detail::trim_copy(line);
            items_buffer = {"true"};
        }
        if(name.find('.') == std::string::npos) {
            detail::remove_quotes(name);
        }
        // clean up quotes on the items
        for(auto &it : items_buffer) {
            detail::remove_quotes(it);
        }

        std::vector<std::string> parents = detail::generate_parents(section, name);

        if(!output.empty() && name == output.back().name && parents == output.back().parents) {
            output.back().inputs.insert(output.back().inputs.end(), items_buffer.begin(), items_buffer.end());
        } else {
            output.emplace_back();
            output.back().parents = std::move(parents);
            output.back().name = std::move(name);
            output.back().inputs = std::move(items_buffer);
        }
    }
    if(section != "default") {
        // insert a section end which is just an empty items_buffer
        std::string ename;
        output.emplace_back();
        output.back().parents = detail::generate_parents(section, ename);
        output.back().name = "--";
        while(output.back().parents.size() > 1) {
            output.push_back(output.back());
            output.back().parents.pop_back();
        }
    }
    return output;
}