Skip to content
Open
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
81 changes: 81 additions & 0 deletions .github/workflows/cpp.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
name: cpp

on:
push:
branches: main
paths:
- 'cpp/**'
- '.github/workflows/cpp.yml'
pull_request:
paths:
- 'cpp/**'
- '.github/workflows/cpp.yml'

defaults:
run:
working-directory: cpp

jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
compiler: [gcc-11, clang-12]
include:
- compiler: gcc-11
cc: gcc-11
cxx: g++-11
- compiler: clang-12
cc: clang-12
cxx: clang++-12

steps:
- uses: actions/checkout@v3
with:
submodules: recursive

- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y cmake ninja-build
sudo apt-get install -y gcc-11 g++-11 clang-12

- name: Setup Conan
run: |
pip install conan==1.59.0
conan profile new default --detect
conan profile update settings.compiler.libcxx=libstdc++11 default
conan remote add linksplatform https://linksplatform.jfrog.io/artifactory/api/conan/linksplatform || true

- name: Create build directory
run: mkdir -p build

- name: Install Conan dependencies
run: |
cd build
conan install .. --build=missing
env:
CC: ${{ matrix.cc }}
CXX: ${{ matrix.cxx }}

- name: Configure CMake
run: |
cd build
cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Release
env:
CC: ${{ matrix.cc }}
CXX: ${{ matrix.cxx }}

- name: Build
run: |
cd build
ninja
env:
CC: ${{ matrix.cc }}
CXX: ${{ matrix.cxx }}

- name: Test run (basic smoke test)
run: |
cd build
timeout 30s ./bin/Examples.Doublets.CRUD.Cpp || true
echo "Build completed successfully"
54 changes: 54 additions & 0 deletions cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
cmake_minimum_required(VERSION 3.13)

project(Examples.Doublets.CRUD.Cpp CXX)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# Set output directory
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)

# Add conan packages if available
if(EXISTS "${CMAKE_CURRENT_BINARY_DIR}/conanbuildinfo.cmake")
include(${CMAKE_CURRENT_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup()
endif()

# Find required packages
find_package(Platform.Interfaces)
find_package(Platform.Collections.Methods)
find_package(Platform.Collections)
find_package(Platform.Numbers)
find_package(Platform.Memory)
find_package(Platform.Exceptions)
find_package(Platform.Data)
find_package(Platform.Setters)
find_package(Platform.Ranges)
find_package(mio)

# Create the executable
add_executable(${PROJECT_NAME} main.cpp)

# Set C++20 standard
set_target_properties(${PROJECT_NAME} PROPERTIES CXX_STANDARD 20)

# Link required libraries
target_link_libraries(${PROJECT_NAME} PRIVATE Platform.Interfaces::Platform.Interfaces)
target_link_libraries(${PROJECT_NAME} PRIVATE Platform.Collections.Methods::Platform.Collections.Methods)
target_link_libraries(${PROJECT_NAME} PRIVATE Platform.Collections::Platform.Collections)
target_link_libraries(${PROJECT_NAME} PRIVATE Platform.Numbers::Platform.Numbers)
target_link_libraries(${PROJECT_NAME} PRIVATE Platform.Memory::Platform.Memory)
target_link_libraries(${PROJECT_NAME} PRIVATE Platform.Exceptions::Platform.Exceptions)
target_link_libraries(${PROJECT_NAME} PRIVATE Platform.Data::Platform.Data)
target_link_libraries(${PROJECT_NAME} PRIVATE Platform.Setters::Platform.Setters)
target_link_libraries(${PROJECT_NAME} PRIVATE Platform.Ranges::Platform.Ranges)
target_link_libraries(${PROJECT_NAME} PRIVATE mio::mio)

# Add additional linker libraries
target_link_libraries(${PROJECT_NAME} PRIVATE ${CMAKE_DL_LIBS})

# Include the Platform.Data.Doublets headers if available locally
# This assumes the Platform.Data.Doublets repository is available
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../Platform.Data.Doublets")
target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../Platform.Data.Doublets/cpp)
endif()
121 changes: 121 additions & 0 deletions cpp/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
[![Actions Status](https://github.com/linksplatform/Examples.Doublets.CRUD/workflows/CI/badge.svg)](https://github.com/linksplatform/Examples.Doublets.CRUD/actions?workflow=CI)

# Examples.Doublets.CRUD.Cpp

A quick start example that shows how to create, read, update and delete the first [link](https://github.com/Konard/LinksPlatform/wiki/FAQ#what-does-the-link-mean) using [Doublets](https://github.com/linksplatform/Data.Doublets) in C++.

## Prerequisites
* Linux, macOS or Windows
* [CMake 3.13+](https://cmake.org/download/)
* C++20 compatible compiler (GCC 10+, Clang 10+, or MSVC 19.29+)
* [Conan package manager](https://conan.io/downloads.html) (optional but recommended)
* [Platform.Data.Doublets](https://github.com/linksplatform/Data.Doublets) library

## Building

### Using Conan (Recommended)

```bash
mkdir build && cd build
conan install .. --build=missing
cmake ..
cmake --build .
```

### Using CMake directly

If you have the Platform.Data.Doublets repository cloned locally:

```bash
mkdir build && cd build
cmake ..
cmake --build .
```

## Running

After building, run the executable:

```bash
./bin/Examples.Doublets.CRUD.Cpp
```

## [The code](https://github.com/linksplatform/Examples.Doublets.CRUD/blob/main/cpp/main.cpp)

```cpp
#include <iostream>
#include <memory>
#include <cstdio>
#include <Platform.Data.Doublets.h>

using namespace Platform::Data::Doublets;
using namespace Platform::Data::Doublets::Memory::United::Generic;
using namespace Platform::Memory;
using namespace Platform::Interfaces;

int main() {
try {
// A doublet links store is mapped to the "db.links" file:
using TLinkAddress = std::uint64_t;
using LinksOptionsType = LinksOptions<TLinkAddress>;

FileMappedResizableDirectMemory memory{"db.links"};
UnitedMemoryLinks<LinksOptionsType> links{std::move(memory)};

// Creating a doublet link:
auto link = Create(links);

// The link is updated to reference itself twice (as a source and as a target):
// The passed arguments are: an updated address, a new source, and a new target
link = Update(links, link, link, link);

// Read operations:
std::cout << "The number of links in the data store is " << Count(links) << "." << std::endl;
std::cout << "Data store contents:" << std::endl;

// Means any link address or that there is no restriction on link address
const auto any = links.Constants.Any;

// The arguments of a query are restrictions: on address, on source, on target
typename UnitedMemoryLinks<LinksOptionsType>::LinkType query{any, any, any};

links.Each(query, [&links](const auto& foundLink) -> TLinkAddress {
std::cout << "(" << foundLink.Index << ": " << foundLink.Source << " " << foundLink.Target << ")" << std::endl;
return links.Constants.Continue;
});

// Cleaning (resetting) the contents of the link:
link = Update(links, link, TLinkAddress{0}, TLinkAddress{0});

// Removing the link
Delete(links, link);

} catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
return 1;
} catch (...) {
std::cerr << "Unknown error occurred" << std::endl;
return 1;
}

return 0;
}
```

The expected output is:

```
The number of links in the data store is 1.
Data store contents:
(1: 1 1)
```

Look at [Platform.Data.Doublets C++ documentation](https://github.com/linksplatform/Data.Doublets/tree/main/cpp) for more details.

## Looking for something more interesting?
* [Comparison between SQLite and Doublets](https://github.com/linksplatform/Comparisons.SQLiteVSDoublets)
* [Search engine with its web crawler, that stores web-pages in the Doublets](https://github.com/linksplatform/Crawler)
* [GraphQL server that uses Doublets as the database behind the universal API](https://github.com/linksplatform/Data.Doublets.GraphQL)
* [GitHub bot that uses Doublets as the dababase for file templates](https://github.com/linksplatform/Bot)
* [JSON to Doublets importer and Doublets to JSON exporter](https://github.com/linksplatform/Data.Doublets.Json)
* [XML to Doublets importer and Doublets to XML exporter](https://github.com/linksplatform/Data.Doublets.Xml)
14 changes: 14 additions & 0 deletions cpp/conanfile.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[requires]
platform.interfaces/0.3.7@linksplatform/stable
platform.collections.methods/0.1.5@linksplatform/stable
platform.collections/0.0.5@linksplatform/stable
platform.numbers/0.2.0@linksplatform/stable
platform.memory/0.5.2@linksplatform/stable
platform.exceptions/0.4.2@linksplatform/stable
platform.data/0.4.4@linksplatform/stable
platform.setters/0.0.4@linksplatform/stable
platform.ranges/0.1.3@linksplatform/stable
mio/0.0.1@linksplatform/stable

[generators]
cmake
57 changes: 57 additions & 0 deletions cpp/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#include <iostream>
#include <memory>
#include <cstdio>
#include <Platform.Data.Doublets.h>

using namespace Platform::Data::Doublets;
using namespace Platform::Data::Doublets::Memory::United::Generic;
using namespace Platform::Memory;
using namespace Platform::Interfaces;

int main() {
try {
// A doublet links store is mapped to the "db.links" file:
using TLinkAddress = std::uint64_t;
using LinksOptionsType = LinksOptions<TLinkAddress>;

FileMappedResizableDirectMemory memory{"db.links"};
UnitedMemoryLinks<LinksOptionsType> links{std::move(memory)};

// Creating a doublet link:
auto link = Create(links);

// The link is updated to reference itself twice (as a source and as a target):
// The passed arguments are: an updated address, a new source, and a new target
link = Update(links, link, link, link);

// Read operations:
std::cout << "The number of links in the data store is " << Count(links) << "." << std::endl;
std::cout << "Data store contents:" << std::endl;

// Means any link address or that there is no restriction on link address
const auto any = links.Constants.Any;

// The arguments of a query are restrictions: on address, on source, on target
typename UnitedMemoryLinks<LinksOptionsType>::LinkType query{any, any, any};

links.Each(query, [&links](const auto& foundLink) -> TLinkAddress {
std::cout << "(" << foundLink.Index << ": " << foundLink.Source << " " << foundLink.Target << ")" << std::endl;
return links.Constants.Continue;
});

// Cleaning (resetting) the contents of the link:
link = Update(links, link, TLinkAddress{0}, TLinkAddress{0});

// Removing the link
Delete(links, link);

Check notice on line 47 in cpp/main.cpp

View check run for this annotation

codefactor.io / CodeFactor

cpp/main.cpp#L47

Redundant blank line at the end of a code block should be deleted. (whitespace/blank_line)
} catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
return 1;
} catch (...) {
std::cerr << "Unknown error occurred" << std::endl;
return 1;
}

return 0;
}
Loading