383 lines
16 KiB
C++
Executable File
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));
|
|
}
|
|
|