initial commit

This commit is contained in:
Roland Conybeare 2024-04-12 20:45:04 -04:00
commit 75799f4652
9 changed files with 316 additions and 0 deletions

57
CMakeLists.txt Normal file
View file

@ -0,0 +1,57 @@
# xo-stringliteral/CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(xo_stringliteral VERSION 1.0)
enable_language(CXX)
# common XO cmake macros (see proj/xo-cmake)
include(cmake/xo-bootstrap-macros.cmake)
# ----------------------------------------------------------------
# unit test setup
enable_testing()
# activate code coverage for all executables + libraries (when configured with -DCODE_COVERAGE=ON)
add_code_coverage()
# 1. assuming that /nix/store/ prefixes .hpp files belonging to gcc, catch2 etc.
# we're not interested in code coverage for these sources.
# 2. exclude the utest/ subdir, we don't need coverage on the unit tests themselves;
# rather, want coverage on the code that the unit tests exercise.
#
# NOTE: this seems to work only with the 'ccov-all' target. In particular, doesn't seem to do anything with the 'ccov' target
#
add_code_coverage_all_targets(EXCLUDE /nix/store/* ${PROJECT_SOURCE_DIR}/utest/* ${PROJECT_BINARY_DIR}/local/* ${PROJECT_SOURCE_DIR}/repo/*)
# ----------------------------------------------------------------
# c++ settings
# one-time project-specific c++ flags. usually empty
set(PROJECT_CXX_FLAGS "")
#set(PROJECT_CXX_FLAGS "-fconcepts-diagnostics-depth=2")
add_definitions(${PROJECT_CXX_FLAGS})
xo_toplevel_compile_options()
# ----------------------------------------------------------------
add_subdirectory(example)
#add_subdirectory(utest)
#add_subdirectory(docs)
# ----------------------------------------------------------------
# provide find_package() support for projects using this library
set(SELF_LIB xo_stringliteral)
xo_add_headeronly_library(${SELF_LIB})
xo_install_library4(${SELF_LIB} ${PROJECT_NAME}Targets)
xo_export_cmake_config(${PROJECT_NAME} ${PROJECT_VERSION} ${PROJECT_NAME}Targets)
# ----------------------------------------------------------------
# dependencies
#xo_headeronly_dependency(${SELF_LIB} randomgen)
# etc..
# end CMakeLists.txt

View file

@ -0,0 +1,26 @@
# ----------------------------------------------------------------
# for example use
# $ PREFIX=/usr/local # for example
# $ cmake -DCMAKE_MODULE_PATH=prefix -DCMAKE_INSTALL_PREFIX=$PREFIX -B .build
#
# will set
# CMAKE_MODULE_PATH = /usr/local/share/cmake
# and expect .cmake macros in
# /usr/local/share/cmake/xo_macros/xo-project-macros.cmake
# ----------------------------------------------------------------
if (("${CMAKE_MODULE_PATH}" STREQUAL "") OR ("${CMAKE_MODULE_PATH}" STREQUAL prefix))
# default to typical install location for xo-project-macros
set(CMAKE_MODULE_PATH ${CMAKE_INSTALL_PREFIX}/share/cmake)
endif()
if (NOT XO_SUBMODULE_BUILD)
message("-- GUESSED_CMAKE_CMD=cmake -DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD} -DCMAKE_MODULE_PATH=${CMAKE_MODULE_PATH} -DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -B ${CMAKE_BINARY_DIR}")
message("-- CMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}")
message("-- CMAKE_MODULE_PATH=${CMAKE_MODULE_PATH}")
endif()
# needs to have been installed somewhere on CMAKE_MODULE_PATH,
# (e.g. from xo-cmake with the same value for CMAKE_INSTALL_PREFIX)
#
include(xo_macros/xo-project-macros)

View file

@ -0,0 +1,17 @@
@PACKAGE_INIT@
include(CMakeFindDependencyMacro)
# note: changes to find_dependency() calls here
# must coordinate with xo_dependency() calls
# in xo-reactor/src/reactor/CMakeLists.txt
#
#find_dependency(reflect)
#find_dependency(subsys)
#find_dependency(Eigen3)
#find_dependency(webutil)
#find_dependency(printjson)
#find_dependency(callback)
include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
check_required_components("@PROJECT_NAME@")

1
example/CMakeLists.txt Normal file
View file

@ -0,0 +1 @@
add_subdirectory(ex1)

View file

@ -0,0 +1,15 @@
# xo-stringliteral/example/ex1/CMakeLists.txt
set(SELF_EXE xo_stringliteral_ex1)
set(SELF_SRCS ex1.cpp)
add_executable(${SELF_EXE} ${SELF_SRCS})
xo_include_options2(${SELF_EXE})
# ----------------------------------------------------------------
# dependencies..
xo_self_dependency(${SELF_EXE} xo_stringliteral)
#xo_dependency(${SELF_EXE} reflect)
# end CMakeLists.txt

38
example/ex1/ex1.cpp Normal file
View file

@ -0,0 +1,38 @@
/* @file ex1.cpp */
#include "xo/stringliteral/stringliteral.hpp"
#include "xo/stringliteral/stringliteral_iostream.hpp"
#include "xo/stringliteral/string_view_concat.hpp"
#include <iostream>
int
main() {
using namespace std;
using xo::stringliteral;
using xo::stringliteral_compare;
#ifdef NOT_USING
constexpr stringliteral s1("hello");
static_assert(stringliteral_compare(s1, s1) == 0);
cerr << s1 << endl;
constexpr stringliteral s2 = stringliteral_concat(stringliteral("hello"),
stringliteral(", world"));
#endif
static constexpr string_view hello("hello");
static constexpr string_view world(" world");
static constexpr auto s2 = concat_v<hello, world>;
static constexpr string_view hello_world("hello world");
static_assert(s2 == hello_world);
cerr << hello_world << endl;
}
/* end ex1.cpp */

View file

@ -0,0 +1,30 @@
#include <string_view>
#include <array>
template <std::string_view const & ... Strings>
struct sv_concat
{
static constexpr auto impl() noexcept {
constexpr std::size_t n = (Strings.size() + ... + 0);
std::array<char, n + 1> arr{};
auto append = [i=0, &arr](const auto & s) mutable {
for (auto c : s)
arr[i++] = c;
};
(append(Strings), ...);
arr[n] = '\0';
return arr;
}
static constexpr auto arr = impl();
static constexpr std::string_view value {
arr.data(),
arr.size() - 1
};
};
template <std::string_view const & ... Strings>
static constexpr auto concat_v = sv_concat<Strings...>::value;

View file

@ -0,0 +1,96 @@
/** @file stringliteral.hpp
*
* Author: Roland Conybeare
**/
#pragma once
#include <string_view>
#include <algorithm>
#include <cstdint>
namespace xo {
/** @class stringliteral
*
* @brief class to represent a literal string at compile time, for use as template argument
**/
template <std::size_t N>
struct stringliteral {
constexpr stringliteral() { if (N > 0) value_[0] = '\0'; }
constexpr stringliteral(const char (&str)[N]) { std::copy_n(str, N, value_); }
constexpr int size() const { return N; }
constexpr char const * c_str() const { return value_; }
char value_[N];
};
/** @brief all_same_v<T1, .., Tn> is true iff types T1 = .. = Tn
**/
template < typename First, typename... Rest >
constexpr auto
all_same_v = std::conjunction_v< std::is_same<First, Rest>... >;
/** @brief concatenate string literals
*
* NOTE: this isn't constexpr in clang16
**/
template < typename... Ts>
constexpr auto
stringliteral_concat(Ts && ... args)
{
#ifdef NOT_USING
static_assert(all_same_v<std::decay_t<Ts>...>,
"string must share the same char type");
using char_type = std::remove_const_t< std::remove_pointer_t < std::common_type_t < Ts... > > >;
#endif
using char_type = char;
/** n1: total number of bytes used by arguments **/
constexpr size_t n1 = (sizeof(Ts) + ...);
/** z1: each string arg has a null terminator included in its size,
* z1 is the number of arguments in parameter pack Ts,
* which equals the number of null terminators used
**/
constexpr size_t z1 = sizeof...(Ts);
/** n: number of chars in concatenated string. +1 for final null **/
constexpr size_t n
= (n1 / sizeof(char_type)) - z1 + 1;
stringliteral<n> result;
size_t pos = 0;
auto detail_concat = [ &pos, &result ](auto && arg) {
constexpr auto count = (sizeof(arg) - sizeof(char_type)) / sizeof(char_type);
std::copy_n(arg.c_str(), count, result.value_ + pos);
pos += count;
};
(detail_concat(args), ...);
//return stringliteral("");
return result;
}
#ifdef NOT_USING
template <std::size_t N1, std::size_t N2>
constexpr auto
stringliteral_compare(stringliteral<N1> && s1, stringliteral<N2> && s2)
{
return std::string_view(s1.value_) <=> std::string_view(s2.value_);
}
#endif
template <std::size_t N1, std::size_t N2>
constexpr auto
stringliteral_compare(const stringliteral<N1> & s1, const stringliteral<N2> & s2)
{
return std::string_view(s1.value_) <=> std::string_view(s2.value_);
}
} /*namespace xo*/
/** end stringliteral.hpp **/

View file

@ -0,0 +1,36 @@
/** @file stringliteral_iostream.hpp
*
* Author: Roland Conybeare
**/
#pragma once
#include "stringliteral.hpp"
#include <ostream>
//#include <cstdint>
namespace xo {
/** @brief print stringliteral on stream os.
*
**/
template <std::size_t N>
void
print_stringliteral (std::ostream & os, const stringliteral<N> & x) {
os << x.c_str();
}
/** @brief print stringliteral x on stream os.
*
* Example
* @code
* cout << stringliteral("foo"); // outputs "foo"
**/
template <std::size_t N>
inline std::ostream &
operator<< (std::ostream & os, const stringliteral<N> & x) {
print_stringliteral(os, x);
return os;
}
} /*namespace xo*/
/** end stringliteral_iostream.hpp **/