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
60 changes: 0 additions & 60 deletions .github/workflows/cla.yml

This file was deleted.

48 changes: 48 additions & 0 deletions .github/workflows/macos-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: macOS CI
on:
push:
branches: [development, main]
pull_request:
branches: [development, main]
types: [opened, synchronize, reopened, ready_for_review]
workflow_dispatch: {}

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
build:
if: github.event.pull_request.draft == false
runs-on: macos-15-intel
steps:
- uses: actions/checkout@v4

- uses: conan-io/setup-conan@v1
with:
cache_packages: true

- name: Install cmake and ninja
run: pip install cmake ninja

- name: Conan install
run: >
conan install . --output-folder=build --build=missing
-s build_type=RelWithDebInfo -s compiler.cppstd=20
-o "plotjuggler_core/*:with_tests=True"
-o "plotjuggler_core/*:with_parquet_example=False"

- name: Configure
run: >
cmake -S . -B build -G Ninja
-DCMAKE_TOOLCHAIN_FILE=${{ github.workspace }}/build/conan_toolchain.cmake
-DCMAKE_BUILD_TYPE=RelWithDebInfo
-DPJ_BUILD_PARQUET_IMPORT_EXAMPLE=OFF

- name: Build
run: cmake --build build

- name: Test
env:
QT_QPA_PLATFORM: offscreen
run: ctest --test-dir build --output-on-failure
25 changes: 25 additions & 0 deletions .github/workflows/pre-commit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: pre-commit
on:
push:
branches: [development, main]
pull_request:
branches: [development, main]
types: [opened, synchronize, reopened, ready_for_review]
workflow_dispatch: {}

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
pre-commit:
if: github.event.pull_request.draft == false
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: '3.12'

- uses: pre-commit/action@v3.0.1
95 changes: 0 additions & 95 deletions CLA.md

This file was deleted.

62 changes: 62 additions & 0 deletions pj_base/include/pj_base/number_parse.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#pragma once

#include <cerrno>
#include <charconv>
#include <cstdlib>
#include <optional>
#include <string>
#include <string_view>
#include <system_error>
#include <type_traits>

namespace PJ {

/// Parse the *entire* @p text as a number of type T, returning nullopt unless
/// the whole string is a valid, in-range value (empty input, trailing
/// characters, or overflow all yield nullopt).
///
/// Use this instead of std::from_chars when T may be floating-point: Apple
/// Clang's libc++ does not implement the std::from_chars floating-point
/// overloads, so those are routed through std::strto* here. Integral types go
/// straight to std::from_chars on every toolchain.
template <typename T>
[[nodiscard]] std::optional<T> parseNumber(std::string_view text) {
static_assert(
std::is_arithmetic_v<T> && !std::is_same_v<T, bool>,
"parseNumber supports integral and floating-point types, not bool");
if (text.empty()) {
return std::nullopt;
}
if constexpr (std::is_floating_point_v<T>) {
// std::strto* needs a null-terminated buffer and @p text may be a
// non-terminated view, so copy it. Number strings are short — the
// allocation is negligible for the config/settings paths this serves.
const std::string buffer(text);
const char* begin = buffer.c_str();
char* last = nullptr;
errno = 0;
T out{};
if constexpr (std::is_same_v<T, float>) {
out = std::strtof(begin, &last);
} else if constexpr (std::is_same_v<T, long double>) {
out = std::strtold(begin, &last);
} else {
out = std::strtod(begin, &last);
}
if (errno != 0 || last != begin + buffer.size()) {
return std::nullopt;
}
return out;
} else {
T out{};
const char* begin = text.data();
const char* end = begin + text.size();
const auto [ptr, ec] = std::from_chars(begin, end, out);
if (ec != std::errc{} || ptr != end) {
return std::nullopt;
}
return out;
}
}

} // namespace PJ
18 changes: 3 additions & 15 deletions pj_base/include/pj_base/sdk/plugin_data_api.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// Copyright 2026 Davide Faconti
// SPDX-License-Identifier: Apache-2.0

#include <charconv>
#include <cstdint>
#include <cstring>
#include <functional>
Expand All @@ -18,6 +17,7 @@

#include "pj_base/builtin/builtin_object.hpp"
#include "pj_base/expected.hpp"
#include "pj_base/number_parse.hpp"
#include "pj_base/plugin_data_api.h"
#include "pj_base/sdk/arrow.hpp"
#include "pj_base/sdk/object_bytes.hpp"
Expand Down Expand Up @@ -1309,11 +1309,11 @@ class SettingsValue {
}

[[nodiscard]] std::int64_t toInt(std::int64_t def = 0) const {
return parse<std::int64_t>(def);
return raw_.has_value() ? parseNumber<std::int64_t>(*raw_).value_or(def) : def;
}

[[nodiscard]] double toDouble(double def = 0.0) const {
return parse<double>(def);
return raw_.has_value() ? parseNumber<double>(*raw_).value_or(def) : def;
}

/// "true"/"1"/"on" → true; "false"/"0"/"off" → false; otherwise @p def.
Expand All @@ -1332,18 +1332,6 @@ class SettingsValue {
}

private:
template <typename T>
[[nodiscard]] T parse(T def) const {
if (!raw_.has_value()) {
return def;
}
T out{};
const char* begin = raw_->data();
const char* end = begin + raw_->size();
auto [ptr, ec] = std::from_chars(begin, end, out);
return (ec == std::errc{} && ptr == end) ? out : def;
}

std::optional<std::string> raw_;
};

Expand Down
Loading