Skip to content

Commit 9363545

Browse files
committed
Finish v0.2.1
This fixes incorrect usage of the C API in the unit tests ultimately leading to a crash
2 parents 2f5bff0 + abec693 commit 9363545

File tree

9 files changed

+153
-84
lines changed

9 files changed

+153
-84
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
cmake_minimum_required(VERSION 3.24)
2-
project(cppIni LANGUAGES CXX VERSION 0.2.0)
2+
project(cppIni LANGUAGES CXX VERSION 0.2.1)
33

44
set(CMAKE_CXX_STANDARD 20)
55
set(CMAKE_CXX_STANDARD_REQUIRED ON)

README.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,29 @@ On every write, the file is completely rewritten.
4545

4646
## Usage
4747

48+
### C++:
49+
4850
``` cpp
4951
#include <cppIni/cppIni.hpp>
5052

5153
File ini("test.ini");
52-
const auto intValue = init.get<int>("section", "key");
54+
const auto intValue = ini.get<int>("section", "key");
5355
const auto newValue = 42;
5456
ini.set("section", "key", newValue);
5557
```
5658
59+
### C:
60+
61+
``` c
62+
#include <cppIni/cppIni_c.h>
63+
64+
void* ini = cppIni_open("test.ini");
65+
const int intValue = cppIni_geti(ini, "section", "key");
66+
const int newValue = 42;
67+
cppIni_set(ini, "section", "key", newValue);
68+
cppIni_close(&ini);
69+
```
70+
5771
## License
5872

59-
cppIni is licensed under the MIT license. See [COPYING](https://github.com/Master92/cppIni/COPYING) for more information.
73+
cppIni is licensed under the GPLv3. See [COPYING](https://github.com/Master92/cppIni/blob/master/COPYING) for more information.

conanfile.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,19 @@
2626
#
2727
# You should have received a copy of the GNU General Public License
2828
# along with this program. If not, see <https://www.gnu.org/licenses/>.
29+
#
30+
# This program is free software: you can redistribute it and/or modify
31+
# it under the terms of the GNU General Public License as published by
32+
# the Free Software Foundation, either version 3 of the License, or
33+
# (at your option) any later version.
34+
#
35+
# This program is distributed in the hope that it will be useful,
36+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
37+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38+
# GNU General Public License for more details.
39+
#
40+
# You should have received a copy of the GNU General Public License
41+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
2942

3043
from conan import ConanFile
3144
from conan.tools.build import check_min_cppstd
@@ -34,7 +47,7 @@
3447

3548
class cppiniRecipe(ConanFile):
3649
name = "cppini"
37-
version = "0.2.0"
50+
version = "0.2.1"
3851
package_type = "library"
3952

4053
# Optional metadata

include/cppIni/cppIni_c.h

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
extern "C" {
2424
#endif
2525

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

35-
CPPINI_EXPORT pFile cppIni_open(const char* filename); ///< Opens a file
36-
CPPINI_EXPORT void cppIni_close(pFile* file); ///< Closes a file
37-
CPPINI_EXPORT void cppIni_set(pFile file, const char* section, const char* key, const char* value); ///< Sets a value
38-
CPPINI_EXPORT const char* cppIni_gets(pFile file, const char* section, const char* key, char* out, size_t outSize); ///< Gets a string
39-
CPPINI_EXPORT int cppIni_geti(pFile file, const char* section, const char* key); ///< Gets an integer
40-
CPPINI_EXPORT float cppIni_getf(pFile file, const char* section, const char* key); ///< Gets a float
34+
CPPINI_EXPORT void* cppIni_open(const char* filename); ///< Opens a file
35+
CPPINI_EXPORT void cppIni_close(void** file); ///< Closes a file
36+
37+
CPPINI_EXPORT void cppIni_set(void* file, const char* section, const char* key, const char* value); ///< Sets a value
38+
39+
CPPINI_EXPORT const char* cppIni_gets(const void* file, const char* section, const char* key, char* out, size_t outSize); ///< Gets a string
40+
CPPINI_EXPORT int cppIni_geti(const void* file, const char* section, const char* key); ///< Gets an integer
41+
CPPINI_EXPORT float cppIni_getf(const void* file, const char* section, const char* key); ///< Gets a float
4142

4243
#ifdef __cplusplus
4344
}

src/CInterface.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,14 @@
2424
///
2525
/// \param[in] filename The name of the file to open
2626
/// \return A pointer to a File object
27-
pFile cppIni_open(const char* filename)
27+
void* cppIni_open(const char* filename)
2828
{
2929
return new File(filename);
3030
}
3131

3232
/// Closes a file that was opened with cppIni_open().
3333
/// \param[in] file A pointer to a File object
34-
void cppIni_close(pFile* file)
34+
void cppIni_close(void** const file)
3535
{
3636
delete static_cast<File*>(*file);
3737
}
@@ -40,7 +40,7 @@ void cppIni_close(pFile* file)
4040
/// \param[in] section The name of the section to add
4141
/// \param[in] key The name of the key to add
4242
/// \param[in] value The value to add
43-
void cppIni_set(pFile file, const char* section, const char* key, const char* value)
43+
void cppIni_set(void* const file, const char* const section, const char* const key, const char* value)
4444
{
4545
static_cast<File*>(file)->set(section, key, value);
4646
}
@@ -51,9 +51,9 @@ void cppIni_set(pFile file, const char* section, const char* key, const char* va
5151
/// \param[out] out A buffer to store the value in
5252
/// \param[in] outSize The size of the buffer
5353
/// \return A pointer to the buffer
54-
const char* cppIni_gets(pFile file, const char* section, const char* key, char* out, size_t outSize)
54+
const char* cppIni_gets(const void* const file, const char* const section, const char* const key, char* out, size_t outSize)
5555
{
56-
const auto value = static_cast<File*>(file)->get<std::string>(section, key);
56+
const auto value = static_cast<const File*>(file)->get<std::string>(section, key);
5757

5858
if (value.empty()) {
5959
return out;
@@ -68,17 +68,17 @@ const char* cppIni_gets(pFile file, const char* section, const char* key, char*
6868
/// \param[in] section The name of the section to get
6969
/// \param[in] key The name of the key to get
7070
/// \return The value of the key
71-
int cppIni_geti(pFile file, const char* section, const char* key)
71+
int cppIni_geti(const void* const file, const char* const section, const char* const key)
7272
{
73-
return static_cast<File*>(file)->get<int>(section, key);
73+
return static_cast<const File*>(file)->get<int>(section, key);
7474
}
7575

7676
/// \see cppIni_gets
7777
/// \param[in] file A pointer to a File object
7878
/// \param[in] section The name of the section to get
7979
/// \param[in] key The name of the key to get
8080
/// \return The value of the key
81-
float cppIni_getf(pFile file, const char* section, const char* key)
81+
float cppIni_getf(const void* const file, const char* const section, const char* const key)
8282
{
83-
return static_cast<File*>(file)->get<float>(section, key);
83+
return static_cast<const File*>(file)->get<float>(section, key);
8484
}

tests/CInterfaceTest.cpp

Lines changed: 33 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,28 @@
1-
// cppIni - A C++20 library for reading and writing INI files
2-
// Copyright (C) 2023-2024 Nils Hofmann <nils.friedchen@googlemail.com>
3-
//
4-
// This program is free software: you can redistribute it and/or modify
5-
// it under the terms of the GNU General Public License as published by
6-
// the Free Software Foundation, either version 3 of the License, or
7-
// (at your option) any later version.
8-
//
9-
// This program is distributed in the hope that it will be useful,
10-
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11-
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12-
// GNU General Public License for more details.
13-
//
14-
// You should have received a copy of the GNU General Public License
15-
// along with this program. If not, see <https://www.gnu.org/licenses/>.
1+
/*
2+
* cppIni - A C++20 library for reading and writing INI files
3+
* Copyright (C) 2023-2024 Nils Hofmann <nils.friedchen@googlemail.com>
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
17+
*/
1618

1719
#include <array>
1820
#include <filesystem>
1921
#include <format>
2022

2123
#include <cppIni/cppIni_c.h>
2224
#include <doctest/doctest.h>
25+
#include "utils.h"
2326

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

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

36-
struct ScopeGuard
37-
{
38-
ScopeGuard(pFile file) : file(file){};
39-
~ScopeGuard(){ cppIni_close(&file); };
40-
pFile file;
41-
};
42-
4339
TEST_CASE("Read a string entry")
4440
{
45-
void* file = cppIni_open(fileName.c_str());
46-
ScopeGuard guard{file};
41+
auto file = utils::ScopeGuard<void*, cppIni_close>(cppIni_open(fileName.c_str()));
4742

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

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

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

5953
std::array<char, 64> buffer{0};
60-
CHECK_EQ(cppIni_gets(file, "Section1", "NonExistingEntry", buffer.data(), buffer.size()), buffer.data());
54+
CHECK_EQ(cppIni_gets(*file, "Section1", "NonExistingEntry", buffer.data(), buffer.size()), buffer.data());
6155
CHECK_EQ(buffer[0], '\0');
6256
}
6357

6458
TEST_CASE("Change a value")
6559
{
66-
constexpr auto tempFileName = "tmp.ini";
67-
std::filesystem::copy_file(fileName, tempFileName);
68-
69-
{
70-
constexpr auto newValue = 1337;
71-
void* file = cppIni_open(tempFileName);
72-
ScopeGuard guard{file};
60+
constexpr auto newValue = 1337;
7361

74-
const auto previousValue = cppIni_geti(file, "Section1", "IntEntry");
75-
CHECK_NE(previousValue, newValue);
76-
cppIni_set(file, "Section1", "IntEntry", std::to_string(newValue).c_str());
77-
CHECK_EQ(cppIni_geti(file, "Section1", "IntEntry"), newValue);
78-
}
62+
utils::TempFile tmpFile(fileName);
63+
auto file = utils::ScopeGuard<void*, cppIni_close>(cppIni_open(tmpFile.filename().data()));
7964

80-
std::filesystem::remove(tempFileName);
65+
const auto previousValue = cppIni_geti(*file, "Section1", "IntEntry");
66+
CHECK_NE(previousValue, newValue);
67+
cppIni_set(*file, "Section1", "IntEntry", std::to_string(newValue).c_str());
68+
CHECK_EQ(cppIni_geti(*file, "Section1", "IntEntry"), newValue);
8169
}
8270

8371
TEST_CASE("Read an integer entry")
8472
{
85-
void* file = cppIni_open(fileName.c_str());
86-
ScopeGuard guard{file};
73+
auto file = utils::ScopeGuard<void*, cppIni_close>(cppIni_open(fileName.c_str()));
8774

88-
CHECK_EQ(cppIni_geti(file, "Section1", "IntEntry"), 42);
75+
CHECK_EQ(cppIni_geti(*file, "Section1", "IntEntry"), 42);
8976
}
9077

9178
TEST_CASE("Read a floating point value entry")
9279
{
93-
void* file = cppIni_open(fileName.c_str());
94-
ScopeGuard guard{file};
80+
auto file = utils::ScopeGuard<void*, cppIni_close>(cppIni_open(fileName.c_str()));
9581

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

9985
TEST_SUITE_END();

tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ set(TEST_SOURCES
77
FileTest.cpp
88
SectionTest.cpp
99
CInterfaceTest.cpp
10+
utils.h
1011
)
1112

1213
add_executable(${PROJECT_NAME}_tests ${TEST_SOURCES})

tests/FileTest.cpp

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* cppIni - A C++20 library for reading and writing INI files
3-
* Copyright (C) 2023 Nils Hofmann <nils.friedchen@googlemail.com>
3+
* Copyright (C) 2023-2024 Nils Hofmann <nils.friedchen@googlemail.com>
44
*
55
* This program is free software: you can redistribute it and/or modify
66
* it under the terms of the GNU General Public License as published by
@@ -21,26 +21,14 @@
2121
#include <doctest/doctest.h>
2222

2323
#include <cppIni/File.h>
24+
#include "utils.h"
2425

2526
using namespace std::literals;
2627

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

2930
TEST_SUITE_BEGIN("File");
3031

31-
class FileFixture
32-
{
33-
public:
34-
FileFixture() {
35-
std::filesystem::copy_file(::fileName, fileName);
36-
}
37-
~FileFixture() {
38-
std::filesystem::remove(fileName);
39-
}
40-
protected:
41-
const std::string fileName = std::format("{}{}", WORKING_DIR, "/res/tmp.ini");
42-
};
43-
4432
TEST_CASE("Failing construction of an empty File object")
4533
{
4634
CHECK_THROWS(File{""});
@@ -145,15 +133,16 @@ TEST_CASE("Equality operator")
145133
CHECK_EQ(f, f2);
146134
}
147135

148-
TEST_CASE_FIXTURE(FileFixture, "Change a value with set")
136+
TEST_CASE("Change a value with set")
149137
{
150138
constexpr auto newValue = "NewValue"sv;
151139

152-
auto f = File{fileName};
140+
utils::TempFile tmpFile(fileName);
141+
auto f = File{tmpFile.filename()};
153142
f.set("Section1", "Entry1", "NewValue");
154143
CHECK_EQ(f.get<std::string_view>("Section1", "Entry1"), newValue);
155144

156-
const auto f2 = File{fileName};
145+
const auto f2 = File{tmpFile.filename()};
157146
CHECK_EQ(f.get<std::string_view>("Section1", "Entry1"), newValue);
158147
}
159148

0 commit comments

Comments
 (0)