Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions include/cppIni/cppIni_c.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// cppIni - A C++20 library for reading and writing INI files
// Copyright (C) 2023-2024 Nils Hofmann <nils.friedchen@googlemail.com>
//
// 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/>.

#pragma once

#include <stdlib.h>
#include <cppIni/cppini_export.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef void* pFile;
/// \file cppIni_c.h
/// \brief The C API for cppIni
///
/// \details
/// This file contains the C API for cppIni. It is a very thin wrapper around
/// 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

#ifdef __cplusplus
}
#endif
84 changes: 84 additions & 0 deletions src/CInterface.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// cppIni - A C++20 library for reading and writing INI files
// Copyright (C) 2023-2024 Nils Hofmann <nils.friedchen@googlemail.com>
//
// 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 <cstring>

#include <cppIni/cppIni_c.h>
#include <cppIni/cppIni.h>

/// Opens a file for reading and writing. Throws an exception if the file cannot
/// be opened.
///
/// \param[in] filename The name of the file to open
/// \return A pointer to a File object
pFile 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)
{
delete static_cast<File*>(*file);
}

/// \param[in] file A pointer to a File object
/// \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)
{
static_cast<File*>(file)->set(section, key, value);
}

/// \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
/// \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 auto value = static_cast<File*>(file)->get<std::string>(section, key);

if (value.empty()) {
return out;
}

std::strncpy(out, value.data(), outSize);
return out;
}

/// \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
int cppIni_geti(pFile file, const char* section, const char* key)
{
return static_cast<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)
{
return static_cast<File*>(file)->get<float>(section, key);
}
2 changes: 2 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ cmake_minimum_required(VERSION 3.24)
set(CMAKE_DEBUG_POSTFIX d)

set(SOURCES
CInterface.cpp
Entry.cpp
File.cpp
Section.cpp
)

set(API_HEADERS
cppIni.h
cppIni_c.h
Entry.h
File.h
Section.h
Expand Down
99 changes: 99 additions & 0 deletions tests/CInterfaceTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// cppIni - A C++20 library for reading and writing INI files
// Copyright (C) 2023-2024 Nils Hofmann <nils.friedchen@googlemail.com>
//
// 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>

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

TEST_SUITE_BEGIN("CInterface");

TEST_CASE("Construction of File object")
{
void* file;
CHECK_NOTHROW(file = cppIni_open(fileName.c_str()));
CHECK_NE(file, nullptr);
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};

std::array<char, 64> buffer{0};
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};

std::array<char, 64> buffer{0};
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};

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);
}

std::filesystem::remove(tempFileName);
}

TEST_CASE("Read an integer entry")
{
void* file = cppIni_open(fileName.c_str());
ScopeGuard guard{file};

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};

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 @@ -6,6 +6,7 @@ set(TEST_SOURCES
EntryTest.cpp
FileTest.cpp
SectionTest.cpp
CInterfaceTest.cpp
)

add_executable(${PROJECT_NAME}_tests ${TEST_SOURCES})
Expand Down
Loading