Skip to content

Commit

Permalink
Finish v0.2.1
Browse files Browse the repository at this point in the history
This fixes incorrect usage of the C API in the unit tests ultimately leading to a crash
  • Loading branch information
Master92 committed Nov 14, 2024
2 parents 2f5bff0 + abec693 commit 9363545
Show file tree
Hide file tree
Showing 9 changed files with 153 additions and 84 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.24)
project(cppIni LANGUAGES CXX VERSION 0.2.0)
project(cppIni LANGUAGES CXX VERSION 0.2.1)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
Expand Down
18 changes: 16 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,29 @@ On every write, the file is completely rewritten.

## Usage

### C++:

``` cpp
#include <cppIni/cppIni.hpp>

File ini("test.ini");
const auto intValue = init.get<int>("section", "key");
const auto intValue = ini.get<int>("section", "key");
const auto newValue = 42;
ini.set("section", "key", newValue);
```
### C:
``` c
#include <cppIni/cppIni_c.h>
void* ini = cppIni_open("test.ini");
const int intValue = cppIni_geti(ini, "section", "key");
const int newValue = 42;
cppIni_set(ini, "section", "key", newValue);
cppIni_close(&ini);
```

## License

cppIni is licensed under the MIT license. See [COPYING](https://github.com/Master92/cppIni/COPYING) for more information.
cppIni is licensed under the GPLv3. See [COPYING](https://github.com/Master92/cppIni/blob/master/COPYING) for more information.
15 changes: 14 additions & 1 deletion conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,19 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.

from conan import ConanFile
from conan.tools.build import check_min_cppstd
Expand All @@ -34,7 +47,7 @@

class cppiniRecipe(ConanFile):
name = "cppini"
version = "0.2.0"
version = "0.2.1"
package_type = "library"

# Optional metadata
Expand Down
15 changes: 8 additions & 7 deletions include/cppIni/cppIni_c.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
extern "C" {
#endif

typedef void* pFile;
/// \file cppIni_c.h
/// \brief The C API for cppIni
///
Expand All @@ -32,12 +31,14 @@ typedef void* pFile;
/// the C++ API. It is intended for use with languages that do not support
/// C++.

CPPINI_EXPORT pFile cppIni_open(const char* filename); ///< Opens a file
CPPINI_EXPORT void cppIni_close(pFile* file); ///< Closes a file
CPPINI_EXPORT void cppIni_set(pFile file, const char* section, const char* key, const char* value); ///< Sets a value
CPPINI_EXPORT const char* cppIni_gets(pFile file, const char* section, const char* key, char* out, size_t outSize); ///< Gets a string
CPPINI_EXPORT int cppIni_geti(pFile file, const char* section, const char* key); ///< Gets an integer
CPPINI_EXPORT float cppIni_getf(pFile file, const char* section, const char* key); ///< Gets a float
CPPINI_EXPORT void* cppIni_open(const char* filename); ///< Opens a file
CPPINI_EXPORT void cppIni_close(void** file); ///< Closes a file

CPPINI_EXPORT void cppIni_set(void* file, const char* section, const char* key, const char* value); ///< Sets a value

CPPINI_EXPORT const char* cppIni_gets(const void* file, const char* section, const char* key, char* out, size_t outSize); ///< Gets a string
CPPINI_EXPORT int cppIni_geti(const void* file, const char* section, const char* key); ///< Gets an integer
CPPINI_EXPORT float cppIni_getf(const void* file, const char* section, const char* key); ///< Gets a float

#ifdef __cplusplus
}
Expand Down
18 changes: 9 additions & 9 deletions src/CInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@
///
/// \param[in] filename The name of the file to open
/// \return A pointer to a File object
pFile cppIni_open(const char* filename)
void* cppIni_open(const char* filename)
{
return new File(filename);
}

/// Closes a file that was opened with cppIni_open().
/// \param[in] file A pointer to a File object
void cppIni_close(pFile* file)
void cppIni_close(void** const file)
{
delete static_cast<File*>(*file);
}
Expand All @@ -40,7 +40,7 @@ void cppIni_close(pFile* file)
/// \param[in] section The name of the section to add
/// \param[in] key The name of the key to add
/// \param[in] value The value to add
void cppIni_set(pFile file, const char* section, const char* key, const char* value)
void cppIni_set(void* const file, const char* const section, const char* const key, const char* value)
{
static_cast<File*>(file)->set(section, key, value);
}
Expand All @@ -51,9 +51,9 @@ void cppIni_set(pFile file, const char* section, const char* key, const char* va
/// \param[out] out A buffer to store the value in
/// \param[in] outSize The size of the buffer
/// \return A pointer to the buffer
const char* cppIni_gets(pFile file, const char* section, const char* key, char* out, size_t outSize)
const char* cppIni_gets(const void* const file, const char* const section, const char* const key, char* out, size_t outSize)
{
const auto value = static_cast<File*>(file)->get<std::string>(section, key);
const auto value = static_cast<const File*>(file)->get<std::string>(section, key);

if (value.empty()) {
return out;
Expand All @@ -68,17 +68,17 @@ const char* cppIni_gets(pFile file, const char* section, const char* key, char*
/// \param[in] section The name of the section to get
/// \param[in] key The name of the key to get
/// \return The value of the key
int cppIni_geti(pFile file, const char* section, const char* key)
int cppIni_geti(const void* const file, const char* const section, const char* const key)
{
return static_cast<File*>(file)->get<int>(section, key);
return static_cast<const File*>(file)->get<int>(section, key);
}

/// \see cppIni_gets
/// \param[in] file A pointer to a File object
/// \param[in] section The name of the section to get
/// \param[in] key The name of the key to get
/// \return The value of the key
float cppIni_getf(pFile file, const char* section, const char* key)
float cppIni_getf(const void* const file, const char* const section, const char* const key)
{
return static_cast<File*>(file)->get<float>(section, key);
return static_cast<const File*>(file)->get<float>(section, key);
}
80 changes: 33 additions & 47 deletions tests/CInterfaceTest.cpp
Original file line number Diff line number Diff line change
@@ -1,25 +1,28 @@
// cppIni - A C++20 library for reading and writing INI files
// Copyright (C) 2023-2024 Nils Hofmann <[email protected]>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
/*
* cppIni - A C++20 library for reading and writing INI files
* Copyright (C) 2023-2024 Nils Hofmann <[email protected]>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

#include <array>
#include <filesystem>
#include <format>

#include <cppIni/cppIni_c.h>
#include <doctest/doctest.h>
#include "utils.h"

static const std::string fileName = std::format("{}{}", WORKING_DIR, "/res/test.ini");;

Expand All @@ -33,67 +36,50 @@ TEST_CASE("Construction of File object")
CHECK_NOTHROW(cppIni_close(&file));
}

struct ScopeGuard
{
ScopeGuard(pFile file) : file(file){};
~ScopeGuard(){ cppIni_close(&file); };
pFile file;
};

TEST_CASE("Read a string entry")
{
void* file = cppIni_open(fileName.c_str());
ScopeGuard guard{file};
auto file = utils::ScopeGuard<void*, cppIni_close>(cppIni_open(fileName.c_str()));

std::array<char, 64> buffer{0};
cppIni_gets(file, "Section1", "Entry1", buffer.data(), buffer.size());
cppIni_gets(*file, "Section1", "Entry1", buffer.data(), buffer.size());

CHECK_EQ(std::string_view{buffer.data()}, "Value1");
}

TEST_CASE("Try to read a non-existing entry")
{
void* file = cppIni_open(fileName.c_str());
ScopeGuard guard{file};
auto file = utils::ScopeGuard<void*, cppIni_close>(cppIni_open(fileName.c_str()));

std::array<char, 64> buffer{0};
CHECK_EQ(cppIni_gets(file, "Section1", "NonExistingEntry", buffer.data(), buffer.size()), buffer.data());
CHECK_EQ(cppIni_gets(*file, "Section1", "NonExistingEntry", buffer.data(), buffer.size()), buffer.data());
CHECK_EQ(buffer[0], '\0');
}

TEST_CASE("Change a value")
{
constexpr auto tempFileName = "tmp.ini";
std::filesystem::copy_file(fileName, tempFileName);

{
constexpr auto newValue = 1337;
void* file = cppIni_open(tempFileName);
ScopeGuard guard{file};
constexpr auto newValue = 1337;

const auto previousValue = cppIni_geti(file, "Section1", "IntEntry");
CHECK_NE(previousValue, newValue);
cppIni_set(file, "Section1", "IntEntry", std::to_string(newValue).c_str());
CHECK_EQ(cppIni_geti(file, "Section1", "IntEntry"), newValue);
}
utils::TempFile tmpFile(fileName);
auto file = utils::ScopeGuard<void*, cppIni_close>(cppIni_open(tmpFile.filename().data()));

std::filesystem::remove(tempFileName);
const auto previousValue = cppIni_geti(*file, "Section1", "IntEntry");
CHECK_NE(previousValue, newValue);
cppIni_set(*file, "Section1", "IntEntry", std::to_string(newValue).c_str());
CHECK_EQ(cppIni_geti(*file, "Section1", "IntEntry"), newValue);
}

TEST_CASE("Read an integer entry")
{
void* file = cppIni_open(fileName.c_str());
ScopeGuard guard{file};
auto file = utils::ScopeGuard<void*, cppIni_close>(cppIni_open(fileName.c_str()));

CHECK_EQ(cppIni_geti(file, "Section1", "IntEntry"), 42);
CHECK_EQ(cppIni_geti(*file, "Section1", "IntEntry"), 42);
}

TEST_CASE("Read a floating point value entry")
{
void* file = cppIni_open(fileName.c_str());
ScopeGuard guard{file};
auto file = utils::ScopeGuard<void*, cppIni_close>(cppIni_open(fileName.c_str()));

CHECK_LT(std::abs(cppIni_getf(file, "Section1.Subsection1", "DoubleEntry") - 3.1415), 0.001);
CHECK_LT(std::abs(cppIni_getf(*file, "Section1.Subsection1", "DoubleEntry") - 3.1415), 0.001);
}

TEST_SUITE_END();
1 change: 1 addition & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ set(TEST_SOURCES
FileTest.cpp
SectionTest.cpp
CInterfaceTest.cpp
utils.h
)

add_executable(${PROJECT_NAME}_tests ${TEST_SOURCES})
Expand Down
23 changes: 6 additions & 17 deletions tests/FileTest.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* cppIni - A C++20 library for reading and writing INI files
* Copyright (C) 2023 Nils Hofmann <[email protected]>
* Copyright (C) 2023-2024 Nils Hofmann <[email protected]>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand All @@ -21,26 +21,14 @@
#include <doctest/doctest.h>

#include <cppIni/File.h>
#include "utils.h"

using namespace std::literals;

static const std::string fileName = std::format("{}{}", WORKING_DIR, "/res/test.ini");

TEST_SUITE_BEGIN("File");

class FileFixture
{
public:
FileFixture() {
std::filesystem::copy_file(::fileName, fileName);
}
~FileFixture() {
std::filesystem::remove(fileName);
}
protected:
const std::string fileName = std::format("{}{}", WORKING_DIR, "/res/tmp.ini");
};

TEST_CASE("Failing construction of an empty File object")
{
CHECK_THROWS(File{""});
Expand Down Expand Up @@ -145,15 +133,16 @@ TEST_CASE("Equality operator")
CHECK_EQ(f, f2);
}

TEST_CASE_FIXTURE(FileFixture, "Change a value with set")
TEST_CASE("Change a value with set")
{
constexpr auto newValue = "NewValue"sv;

auto f = File{fileName};
utils::TempFile tmpFile(fileName);
auto f = File{tmpFile.filename()};
f.set("Section1", "Entry1", "NewValue");
CHECK_EQ(f.get<std::string_view>("Section1", "Entry1"), newValue);

const auto f2 = File{fileName};
const auto f2 = File{tmpFile.filename()};
CHECK_EQ(f.get<std::string_view>("Section1", "Entry1"), newValue);
}

Expand Down
Loading

0 comments on commit 9363545

Please sign in to comment.