device_manager_4_linux/lib/libsources/ini.cpp

383 lines
16 KiB
C++
Executable File

//-----------------------------------------------------------------------------------------//
// Distributed under the MIT License - https://opensource.org/licenses/MIT
//-----------------------------------------------------------------------------------------//
//
// Copyright © 2019 Sasko Usinov
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
// OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//-----------------------------------------------------------------------------------------//
// Distributed under the MIT License - https://opensource.org/licenses/MIT
//-----------------------------------------------------------------------------------------//
#include "api.h"
#include "liblogman/log_manager.h"
#include <iostream>
#include <string>
#include <sstream>
#include <sys/klog.h>
#include <sys/stat.h>
#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <sstream>
#include <fstream>
#include <algorithm>
api::log_manager api::ini::g_out, api::ini::g_err(api::log_manager::level_err);
//-------------------------------------------------------------------------------//
// WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
//-------------------------------------------------------------------------------/
//
// This code assumes the file is formatted with new line chars after each
// section and key.
//
// If the section and key are joined into one line, this code will ***not*** work
//
// I needed something quickly without using third party code so I wrote this
// for my own projects and in my projects I always format things properly
//
//-------------------------------------------------------------------------------//
// WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
//-------------------------------------------------------------------------------//
//-------------------------------------------------------------------------------//
// namespace
//-------------------------------------------------------------------------------//
//
// ToDo: n/a
//
// Notes: Obtains an INI value
//
// Returns: A string containing the INI value
//
//------------------------------------------------------------------------------//
std::string api::ini::get_ini_value(const std::string & file, const std::string & section, const std::string & key)
{
std::string out {};
std::vector<std::string> ini_content {api::vct::to_vector_string_list(api::fs::load_from_file(file), std::vector<char> () = {10,13})};
std::string ini_section {(section[0] != '[' && section[section.size() - 1] != ']') ? "[" + section + "]" : section};
std::string ini_key {key + "="};
//----------------------------------------------------------------------------
// Iterate through each line of the current file
//----------------------------------------------------------------------------
for (size_t i = 0; i < ini_content.size(); i++)
{
//----------------------------------------------------------------------------
// we found the section we are searching for
//----------------------------------------------------------------------------
if (api::str::left_string_compare(ini_content[i], ini_section))
{
for (; i < ini_content.size(); ++i)
{
if (api::str::left_string_compare(ini_content[i], ini_key))
return api::str::trim(api::str::range_copy(api::str::get_char_index('=', 1, ini_content[i]) + 1, ini_content[i].size() - 1, ini_content[i]));
}
}
}
return out;
}
//-------------------------------------------------------------------------------//
// namespace
//-------------------------------------------------------------------------------//
//
// ToDo: n/a
//
// Notes: Obtains an INI value
//
// Returns: A string containing the INI value
//
//------------------------------------------------------------------------------//
std::string api::ini::get_ini_value(const std::vector<std::string> & ini_content, const std::string & section, const std::string & key)
{
std::string out {};
std::string ini_section {(section[0] != '[' && section[section.size() - 1] != ']') ? "[" + section + "]" : section};
std::string ini_key {key + "="};
//----------------------------------------------------------------------------
// Iterate through each line of the current file
//----------------------------------------------------------------------------
for (size_t i = 0; i < ini_content.size(); i++)
{
//----------------------------------------------------------------------------
// we found the section we are searching for
//----------------------------------------------------------------------------
if (api::str::left_string_compare(ini_content[i], ini_section))
{
for (; i < ini_content.size(); ++i)
{
if (api::str::left_string_compare(ini_content[i], ini_key))
return api::str::trim(api::str::range_copy(api::str::get_char_index('=', 1, ini_content[i]) + 1, ini_content[i].size() - 1, ini_content[i]));
}
}
}
return out;
}
//-------------------------------------------------------------------------------//
// namespace
//-------------------------------------------------------------------------------//
//
// ToDo: n/a
//
// Notes: Obtains the line index relative to the file of key in section
//
// This is for internal use but feel free to use it as you wish
//
// Returns: The line index
//
//------------------------------------------------------------------------------//
size_t api::ini::get_ini_index_of_key(const std::string & file, const std::string & section, const std::string & key)
{
std::string out {};
std::vector<std::string> ini_content {api::vct::to_vector_string_list(api::fs::load_from_file(file), std::vector<char> () = {10,13})};
std::string ini_section {(section[0] != '[' && section[section.size() - 1] != ']') ? "[" + section + "]" : section};
std::string ini_key {key + "="};
//----------------------------------------------------------------------------
// Iterate through each line of the current file
//----------------------------------------------------------------------------
for (size_t i = 0; i < ini_content.size(); i++)
{
//----------------------------------------------------------------------------
// we found the section we are searching for
//----------------------------------------------------------------------------
if (api::str::left_string_compare(ini_content[i], ini_section))
{
for (; i < ini_content.size(); ++i)
{
if (api::str::left_string_compare(ini_content[i], ini_key))
return i;
}
}
}
return API_ERROR_IDX_NOT_FOUND;
}
//-------------------------------------------------------------------------------//
// namespace
//-------------------------------------------------------------------------------//
//
// ToDo: n/a
//
// Notes: Obtains the line index relative to the ini_content of key in section
//
// This is for internal use but feel free to use it as you wish
//
// Returns: The line index
//
//------------------------------------------------------------------------------//
size_t api::ini::get_ini_index_of_key(const std::vector<std::string> & ini_content, const std::string & section, const std::string & key)
{
std::string out {};
std::string ini_section {(section[0] != '[' && section[section.size() - 1] != ']') ? "[" + section + "]" : section};
std::string ini_key {key + "="};
//----------------------------------------------------------------------------
// Iterate through each line of the current file
//----------------------------------------------------------------------------
for (size_t i = 0; i < ini_content.size(); i++)
{
//----------------------------------------------------------------------------
// we found the section we are searching for
//----------------------------------------------------------------------------
if (api::str::left_string_compare(ini_content[i], ini_section))
{
for (; i < ini_content.size(); ++i)
{
if (api::str::left_string_compare(ini_content[i], ini_key))
return i;
}
}
}
return API_ERROR_IDX_NOT_FOUND;
}
//-------------------------------------------------------------------------------//
// namespace
//-------------------------------------------------------------------------------//
//
// ToDo: n/a
//
// Notes: Returns the index relative to file of the section
//
// Returns: The line index
//
//------------------------------------------------------------------------------//
size_t api::ini::get_ini_index_of_section(const std::string & file, const std::string & section)
{
std::string out {};
std::vector<std::string> ini_content {api::vct::to_vector_string_list(api::fs::load_from_file(file), std::vector<char> () = {10,13})};
std::string ini_section {(section[0] != '[' && section[section.size() - 1] != ']') ? "[" + section + "]" : section};
//----------------------------------------------------------------------------
// Iterate through each line of the current file
//----------------------------------------------------------------------------
for (size_t i = 0; i < ini_content.size(); i++)
{
//----------------------------------------------------------------------------
// we found the section we are searching for
//----------------------------------------------------------------------------
if (api::str::left_string_compare(ini_content[i], ini_section))
return i;
}
return API_ERROR_IDX_NOT_FOUND;
}
//-------------------------------------------------------------------------------//
// namespace
//-------------------------------------------------------------------------------//
//
// ToDo: n/a
//
// Notes: Returns the index relative to ini_content of the section
//
// Returns: The line index
//
//------------------------------------------------------------------------------//
size_t api::ini::get_ini_index_of_section(const std::vector<std::string> & ini_content, const std::string & section)
{
std::string out {};
std::string ini_section {(section[0] != '[' && section[section.size() - 1] != ']') ? "[" + section + "]" : section};
//----------------------------------------------------------------------------
// Iterate through each line of the current file
//----------------------------------------------------------------------------
for (size_t i = 0; i < ini_content.size(); i++)
{
//----------------------------------------------------------------------------
// we found the section we are searching for
//----------------------------------------------------------------------------
if (api::str::left_string_compare(ini_content[i], ini_section))
return i;
}
return API_ERROR_IDX_NOT_FOUND;
}
//-------------------------------------------------------------------------------//
// namespace
//-------------------------------------------------------------------------------//
//
// ToDo: n/a
//
// Notes: Writes to an INI file
//
// Returns: true on success otherwise false
//
//------------------------------------------------------------------------------//
bool api::ini::write_to_ini(const std::string & file, const std::string & section, const std::string & key, const std::string & value)
{
std::string new_value {key + "=" + value + "\n"};
std::vector<std::string> ini_content {api::vct::to_vector_string_list(api::str::load_from_file(file), std::vector<char> () = {10,13})};
size_t idx_key {api::ini::get_ini_index_of_key(file, section, key)};
ini_content = {api::vct::to_vector_string_list(api::str::load_from_file(file), std::vector<char> () = {10,13})};
//-------------------------------------------------------------------------------//
// If the INI key is not found
//-------------------------------------------------------------------------------//
if (idx_key == API_ERROR_IDX_NOT_FOUND)
{
size_t section_idx {api::ini::get_ini_index_of_section(ini_content, section)};
//-------------------------------------------------------------------------------//
// If the section does not exist in the INI file create a new one and
// then add the specified key along with its value
//-------------------------------------------------------------------------------//
if (section_idx == API_ERROR_IDX_NOT_FOUND)
{
if (api::str::trim(ini_content[ini_content.size() - 1]).size())
ini_content.push_back("\n\n");
ini_content.push_back("[" + section + "]\n");
ini_content.push_back(new_value);
ini_content.push_back("\n");
}
//-------------------------------------------------------------------------------//
// The section exists but the specified key does not exist so just
// create the new key right after the section
//-------------------------------------------------------------------------------//
else
ini_content.insert(ini_content.begin() + static_cast<long>(section_idx + 1), new_value);
return api::fs::save_to_file(file, api::vct::to_string(ini_content));
}
//-------------------------------------------------------------------------------//
// Just update the INI file
//-------------------------------------------------------------------------------//
ini_content[idx_key] = new_value;
return api::fs::save_to_file(file, api::vct::to_string(ini_content));
}
//-------------------------------------------------------------------------------//
// namespace
//-------------------------------------------------------------------------------//
//
// ToDo: n/a
//
// Notes: Deletes entire "section" in the INI file
//
// Returns: true on success otherwise false
//
//------------------------------------------------------------------------------//
bool api::ini::remove_ini_section(const std::string & file, const std::string & section)
{
std::string ini_section {(section[0] != '[' && section[section.size() - 1] != ']') ? "[" + section + "]" : section};
std::vector<std::string> ini_content {api::vct::to_vector_string_list(api::fs::load_from_file(file), std::vector<char> () = {10,13})};
for (size_t i = 0; i < ini_content.size(); i++)
{
if (api::str::left_string_compare(api::str::trim(ini_content[i]), ini_section))
{
ini_content.erase(ini_content.begin() + static_cast<int>(i));
for (; i < ini_content.size(); i++)
{
if (ini_content[i][0] == '[')
return api::fs::save_to_file(file, api::vct::to_string(ini_content));
ini_content.erase(ini_content.begin() + static_cast<int>(i));
i--;
}
}
}
return api::fs::save_to_file(file, api::vct::to_string(ini_content));
}