Skip to content

Commit

Permalink
C iterator API test
Browse files Browse the repository at this point in the history
  • Loading branch information
amunra committed Jan 29, 2024
1 parent 7a4265c commit 13b3fc9
Show file tree
Hide file tree
Showing 4 changed files with 160 additions and 0 deletions.
11 changes: 11 additions & 0 deletions questdb-confstr-ffi/cpp_test/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
******************************************************************************/

#include <iostream>
#include <unordered_map>

#include <questdb/conf_str.hpp>

Expand Down Expand Up @@ -56,4 +57,14 @@ TEST_CASE("parse error")
}
}

TEST_CASE("iter params") {
const auto c1 = conf_str::parse("http::host=localhost;port=9000;");
std::unordered_map<std::string, std::string> params;
for (auto it = c1.begin(); it != c1.end(); ++it) {
params.emplace(it.key(), it.value());
}
CHECK(params.size() == 2);
CHECK(params["host"] == "localhost");
CHECK(params["port"] == "9000");
}

15 changes: 15 additions & 0 deletions questdb-confstr-ffi/include/questdb/conf_str.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include <stdint.h>
#include <stdbool.h>

#if defined(__cplusplus)
extern "C" {
Expand All @@ -18,6 +19,8 @@ typedef struct questdb_conf_str_parse_err questdb_conf_str_parse_err;

void questdb_conf_str_parse_err_free(questdb_conf_str_parse_err* err);

typedef struct questdb_conf_str_iter questdb_conf_str_iter;

questdb_conf_str* questdb_conf_str_parse(
const char* str,
size_t len,
Expand All @@ -33,6 +36,18 @@ const char* questdb_conf_str_get(
size_t key_len,
size_t* val_len_out);

questdb_conf_str_iter* questdb_conf_str_iter_pairs(
const questdb_conf_str* conf_str);

bool questdb_conf_str_iter_next(
questdb_conf_str_iter* iter,
const char** key_out,
size_t* key_len_out,
const char** val_out,
size_t* val_len_out);

void questdb_conf_str_iter_free(questdb_conf_str_iter* iter);

void questdb_conf_str_free(questdb_conf_str* str);

#if defined(__cplusplus)
Expand Down
82 changes: 82 additions & 0 deletions questdb-confstr-ffi/include/questdb/conf_str.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,77 @@ class parse_err
questdb_conf_str_parse_err* _impl;
};

class pair_iter
{
public:
pair_iter(const pair_iter&) = delete;

bool operator==(const pair_iter& other) const noexcept
{
return _impl == other._impl;
}

bool operator!=(const pair_iter& other) const noexcept
{
return !(*this == other);
}

void operator++() noexcept
{
const char* key = nullptr;
size_t key_len = 0;
const char* val = nullptr;
size_t val_len = 0;
const bool has = ::questdb_conf_str_iter_next(
_impl,
&key,
&key_len,
&val,
&val_len);
if (has)
{
_key = { key, key_len };
_val = { val, val_len };
}
else
{
_key = {};
_val = {};
::questdb_conf_str_iter_free(_impl);
_impl = nullptr;
}
}

~pair_iter() noexcept
{
if (_impl != nullptr)
{
::questdb_conf_str_iter_free(_impl);
}
}

std::string_view key() const noexcept
{
return _key;
}

std::string_view value() const noexcept
{
return _val;
}
private:
friend class conf_str;
pair_iter(::questdb_conf_str_iter* impl) : _impl(impl)
{
if (_impl != nullptr)
{
++(*this);
}
}
::questdb_conf_str_iter* _impl;
std::string_view _key;
std::string_view _val;
};

class conf_str
{
Expand Down Expand Up @@ -66,6 +137,17 @@ class conf_str
return {};
}

pair_iter begin() const noexcept
{
auto iter = ::questdb_conf_str_iter_pairs(_impl);
return { iter };
}

pair_iter end() const noexcept
{
return pair_iter{ nullptr };
}

~conf_str() noexcept
{
::questdb_conf_str_free(_impl);
Expand Down
52 changes: 52 additions & 0 deletions questdb-confstr-ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#![allow(clippy::missing_safety_doc)]

use questdb_confstr::{parse_conf_str, ConfStr};
use std::collections::hash_map;
use std::os::raw::c_char;
use std::ptr;
use std::slice;
Expand Down Expand Up @@ -128,6 +129,57 @@ pub unsafe extern "C" fn questdb_conf_str_get(
}
}

#[repr(C)]
pub struct questdb_conf_str_iter {
inner: hash_map::Iter<'static, String, String>,
}

#[no_mangle]
pub unsafe extern "C" fn questdb_conf_str_iter_pairs(
conf_str: *const questdb_conf_str,
) -> *mut questdb_conf_str_iter {
if conf_str.is_null() {
return ptr::null_mut();
}
let conf_str = &(*conf_str).inner;
let iter = questdb_conf_str_iter {
inner: conf_str.params().iter(),
};
Box::into_raw(Box::new(iter))
}

#[no_mangle]
pub unsafe extern "C" fn questdb_conf_str_iter_next(
iter: *mut questdb_conf_str_iter,
key_out: *mut *const c_char,
key_len_out: *mut usize,
val_out: *mut *const c_char,
val_len_out: *mut usize,
) -> bool {
let iter = &mut *iter;
match iter.inner.next() {
Some((key, val)) => {
let key_str = key.as_ptr() as *const c_char;
let val_str = val.as_ptr() as *const c_char;
unsafe {
*key_out = key_str;
*key_len_out = key.len();
*val_out = val_str;
*val_len_out = val.len();
}
true
}
None => false,
}
}

#[no_mangle]
pub unsafe extern "C" fn questdb_conf_str_iter_free(iter: *mut questdb_conf_str_iter) {
if !iter.is_null() {
drop(Box::from_raw(iter));
}
}

#[no_mangle]
pub unsafe extern "C" fn questdb_conf_str_free(conf_str: *mut questdb_conf_str) {
if !conf_str.is_null() {
Expand Down

0 comments on commit 13b3fc9

Please sign in to comment.