PiPedal 1.2.33 initial commit
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "WifiRegulations.hpp"
|
||||
struct nl_sock;
|
||||
struct nl_cache;
|
||||
struct genl_family;
|
||||
|
||||
namespace pipedal
|
||||
{
|
||||
|
||||
WifiInfo getWifiInfo(const std::string&countryIso3661);
|
||||
int32_t getWifiRegClass(const std::string &countryIso3661, int32_t channel,int32_t maxChannelWidthMhz);
|
||||
std::vector<int32_t> getValidChannels(const std::string&countryIso3661,int32_t maxChannelWidthMhz);
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,369 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022 Robin E. R. Davies
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is furnished to do
|
||||
* so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <exception>
|
||||
#include "autoptr_vector.h"
|
||||
#include <unordered_map>
|
||||
#include <fstream>
|
||||
|
||||
namespace config_serializer
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
std::string trim(const std::string &v);
|
||||
|
||||
std::vector<std::string> split(const std::string &v, char seperator);
|
||||
|
||||
/**
|
||||
* @brief Convert string to config file format.
|
||||
*
|
||||
* Adds quotes and escapes, but only if neccessary.
|
||||
*
|
||||
* Source text is assumed to be UTF-8. Escapes for the
|
||||
* following values only: \r \n \t \" \\.
|
||||
*
|
||||
*
|
||||
* @param s
|
||||
* @return std::string Encoded string.
|
||||
*/
|
||||
std::string EncodeString(const std::string &s);
|
||||
|
||||
/**
|
||||
* @brief Config file format to string.
|
||||
*
|
||||
* Decodes quotes and escapes, but only if neccessary.
|
||||
*
|
||||
* Source text is assumed to be UTF-8. Escapes for the
|
||||
* following values only: \r \n \t \" \\.
|
||||
*
|
||||
* @param s
|
||||
* @return std::string
|
||||
*/
|
||||
std::string DecodeString(const std::string &s);
|
||||
|
||||
/**
|
||||
* @brief Convert a string to an integer.
|
||||
*
|
||||
* @tparam T A signed or unsigned integral type.
|
||||
* @param value The string to parse.
|
||||
* @return T The parsed result.
|
||||
* @throws std::invalid_argument if the supplied string is not a valid integer.
|
||||
*/
|
||||
template <class T>
|
||||
T ToInt(const std::string &value)
|
||||
{
|
||||
std::stringstream s(value);
|
||||
T result;
|
||||
s >> result;
|
||||
if (s.fail())
|
||||
{
|
||||
throw std::invalid_argument("Invalid integer value.");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
using namespace detail;
|
||||
|
||||
template <class OBJ>
|
||||
class ConfigSerializerBase
|
||||
{
|
||||
protected:
|
||||
ConfigSerializerBase(const std::string &name, const std::string &comment)
|
||||
: name(name),
|
||||
comment(comment)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
using Obj = OBJ;
|
||||
virtual ~ConfigSerializerBase() {}
|
||||
|
||||
const std::string &GetName() const { return name; }
|
||||
const std::string &GetComment() const { return comment; }
|
||||
virtual void SetValue(Obj &configurable, const std::string &value) const = 0;
|
||||
virtual const std::string GetValue(Obj &configurable) const = 0;
|
||||
|
||||
private:
|
||||
std::string name;
|
||||
std::string comment;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class ConfigConverter
|
||||
{
|
||||
public:
|
||||
static T FromString(const std::string &value)
|
||||
{
|
||||
T result;
|
||||
std::stringstream s(value);
|
||||
s >> result;
|
||||
return result;
|
||||
}
|
||||
|
||||
static std::string ToString(const T &value)
|
||||
{
|
||||
std::stringstream s;
|
||||
s << value;
|
||||
return s.str();
|
||||
}
|
||||
};
|
||||
|
||||
// string specializations.
|
||||
template <>
|
||||
inline std::string ConfigConverter<std::string>::FromString(const std::string &value)
|
||||
{
|
||||
return DecodeString(value);
|
||||
}
|
||||
template <>
|
||||
inline std::string ConfigConverter<std::string>::ToString(const std::string &config)
|
||||
{
|
||||
return EncodeString(config);
|
||||
}
|
||||
// bool specializations.
|
||||
template <>
|
||||
inline bool ConfigConverter<bool>::FromString(const std::string &value)
|
||||
{
|
||||
bool result = false;
|
||||
if (value == "")
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
else if (value == "true")
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
else if (value == "false")
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
int t = ToInt<int>(value);
|
||||
result = (t != 0);
|
||||
}
|
||||
catch (const std::exception &)
|
||||
{
|
||||
throw std::invalid_argument("Expecting true or false.");
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
template <>
|
||||
inline std::string ConfigConverter<bool>::ToString(const bool &value)
|
||||
{
|
||||
return value ? "true" : "false";
|
||||
}
|
||||
|
||||
template <class OBJ, class T>
|
||||
class ConfigSerializer : public ConfigSerializerBase<OBJ>
|
||||
{
|
||||
public:
|
||||
using Obj = OBJ;
|
||||
using pointer_type = T Obj::*;
|
||||
using base = ConfigSerializerBase<Obj>;
|
||||
using converter = ConfigConverter<T>;
|
||||
|
||||
ConfigSerializer(const std::string &name,
|
||||
pointer_type pMember,
|
||||
const std::string &comment)
|
||||
: base(name, comment),
|
||||
pMember(pMember)
|
||||
{
|
||||
}
|
||||
virtual void SetValue(Obj &configurable, const std::string &value) const
|
||||
{
|
||||
configurable.*pMember = ConfigConverter<T>::FromString(value);
|
||||
}
|
||||
virtual const std::string GetValue(Obj &configurable) const
|
||||
{
|
||||
return ConfigConverter<T>::ToString(configurable.*pMember);
|
||||
}
|
||||
|
||||
private:
|
||||
pointer_type pMember;
|
||||
};
|
||||
|
||||
template <class OBJ>
|
||||
class ConfigSerializable
|
||||
{
|
||||
private:
|
||||
using Obj = OBJ;
|
||||
|
||||
using serializer_t = ConfigSerializerBase<OBJ>;
|
||||
using serializers_t = p2p::autoptr_vector<serializer_t>;
|
||||
|
||||
const serializers_t &serializers;
|
||||
|
||||
protected:
|
||||
ConfigSerializable(const serializers_t &serializers)
|
||||
: serializers(serializers)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
virtual void Save(std::ostream &f)
|
||||
{
|
||||
bool firstLine = true;
|
||||
for (const serializer_t *serializer : serializers)
|
||||
{
|
||||
if (serializer->GetComment().length() != 0)
|
||||
{
|
||||
if (!firstLine)
|
||||
{
|
||||
f << std::endl;
|
||||
}
|
||||
firstLine = false;
|
||||
std::vector<std::string> comments = split(serializer->GetComment(), '\n');
|
||||
|
||||
if (comments.size() != 0)
|
||||
for (const std::string &comment : comments)
|
||||
{
|
||||
f << "# " << comment << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
f << serializer->GetName() << '=' << serializer->GetValue((Obj &)*this) << std::endl;
|
||||
}
|
||||
}
|
||||
void Save(const std::string &path)
|
||||
{
|
||||
std::ofstream f;
|
||||
f.open(path);
|
||||
if (!f.is_open())
|
||||
{
|
||||
throw std::invalid_argument("Can't write to file " + path);
|
||||
}
|
||||
try
|
||||
{
|
||||
Save(f);
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
throw std::invalid_argument("Error writing to '" + path + "'. " + e.what());
|
||||
}
|
||||
}
|
||||
|
||||
virtual void Load(std::istream &f)
|
||||
{
|
||||
std::unordered_map<std::string, serializer_t *> index;
|
||||
|
||||
for (serializer_t *serializer : serializers)
|
||||
{
|
||||
index[serializer->GetName()] = serializer;
|
||||
}
|
||||
|
||||
std::string line;
|
||||
int nLine = 0;
|
||||
while (true)
|
||||
{
|
||||
if (f.eof())
|
||||
break;
|
||||
getline(f, line);
|
||||
++nLine;
|
||||
|
||||
// remove comments.
|
||||
auto npos = line.find_first_of('#');
|
||||
if (npos != std::string::npos)
|
||||
{
|
||||
line = line.substr(0, npos);
|
||||
}
|
||||
size_t start = 0;
|
||||
while (start < line.size() && line[start] == ' ')
|
||||
{
|
||||
++start;
|
||||
}
|
||||
if (start == line.size())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
auto pos = line.find_first_of('=', start);
|
||||
if (pos == std::string::npos)
|
||||
{
|
||||
std::stringstream msg;
|
||||
|
||||
msg << "(" << nLine << "," << (start + 1) << "): Syntax error. Expecting '='.";
|
||||
throw std::logic_error(msg.str());
|
||||
}
|
||||
std::string label = trim(line.substr(start, pos - start));
|
||||
std::string value = trim(line.substr(pos + 1));
|
||||
|
||||
if (index.contains(label))
|
||||
{
|
||||
serializer_t *serializer = index[label];
|
||||
try
|
||||
{
|
||||
serializer->SetValue((Obj &)*this, value);
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
std::stringstream msg;
|
||||
msg << "(" << nLine << ',' << (pos + 1) << "): " << e.what();
|
||||
throw std::logic_error(msg.str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::stringstream msg;
|
||||
msg << "(" << nLine << ',' << (start) << "): "
|
||||
<< "Invalid property: " + label;
|
||||
throw std::logic_error(
|
||||
msg.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Load(const std::string &path, bool throwIfNotFound = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::ifstream f;
|
||||
f.open(path);
|
||||
if (!f.is_open())
|
||||
{
|
||||
if (throwIfNotFound)
|
||||
{
|
||||
throw std::logic_error("Can't open file.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
Load(f);
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
std::stringstream msg;
|
||||
msg << "Error: " << path << " " << e.what();
|
||||
throw std::logic_error(msg.str());
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022 Robin E. R. Davies
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is furnished to do
|
||||
* so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace pipedal {
|
||||
class ConfigUtil {
|
||||
public:
|
||||
static bool GetConfigLine(const std::string & filePath,const std::string & key, std::string *pValue);
|
||||
|
||||
static std::string QuoteString(const std::string &value);
|
||||
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
#include <type_traits>
|
||||
|
||||
#define ENABLE_ENUM_FLAGS(enum_type)\
|
||||
template<> struct enum_traits<enum_type> :\
|
||||
enum_traits<>::allow_bitops {};\
|
||||
|
||||
|
||||
template<class T = void> struct enum_traits {};
|
||||
|
||||
template<> struct enum_traits<void> {
|
||||
struct _allow_bitops {
|
||||
static constexpr bool allow_bitops = true;
|
||||
};
|
||||
using allow_bitops = _allow_bitops;
|
||||
|
||||
template<class T, class R = T>
|
||||
using t = typename std::enable_if<std::is_enum<T>::value and
|
||||
enum_traits<T>::allow_bitops, R>::type;
|
||||
|
||||
template<class T>
|
||||
using u = typename std::underlying_type<T>::type;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
constexpr enum_traits<>::t<T> operator~(T a) {
|
||||
return static_cast<T>(~static_cast<enum_traits<>::u<T>>(a));
|
||||
}
|
||||
template<class T>
|
||||
constexpr enum_traits<>::t<T> operator|(T a, T b) {
|
||||
return static_cast<T>(
|
||||
static_cast<enum_traits<>::u<T>>(a) |
|
||||
static_cast<enum_traits<>::u<T>>(b));
|
||||
}
|
||||
template<class T>
|
||||
constexpr enum_traits<>::t<T> operator&(T a, T b) {
|
||||
return static_cast<T>(
|
||||
static_cast<enum_traits<>::u<T>>(a) &
|
||||
static_cast<enum_traits<>::u<T>>(b));
|
||||
}
|
||||
template<class T>
|
||||
constexpr enum_traits<>::t<T> operator^(T a, T b) {
|
||||
return static_cast<T>(
|
||||
static_cast<enum_traits<>::u<T>>(a) ^
|
||||
static_cast<enum_traits<>::u<T>>(b));
|
||||
}
|
||||
template<class T>
|
||||
constexpr enum_traits<>::t<T, T&> operator|=(T& a, T b) {
|
||||
a = a | b;
|
||||
return a;
|
||||
}
|
||||
template<class T>
|
||||
constexpr enum_traits<>::t<T, T&> operator&=(T& a, T b) {
|
||||
a = a & b;
|
||||
return a;
|
||||
}
|
||||
template<class T>
|
||||
constexpr enum_traits<>::t<T, T&> operator^=(T& a, T b) {
|
||||
a = a ^ b;
|
||||
return a;
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
// Copyright (c) 2022 Robin Davies
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace pipedal {
|
||||
|
||||
class HtmlHelper {
|
||||
|
||||
public:
|
||||
static std::string timeToHttpDate();
|
||||
static std::string timeToHttpDate(time_t time);
|
||||
|
||||
|
||||
static std::string encode_url_segment(const char*pStart, const char*pEnd, bool isQuerySegment = false);
|
||||
static void encode_url_segment(std::ostream&os, const char*pStart, const char *pEnd, bool isQuerySegment = false);
|
||||
static void encode_url_segment(std::ostream&os, const std::string&segment, bool isQuerySegment = false)
|
||||
{
|
||||
const char*p = segment.c_str();
|
||||
encode_url_segment(os,p, p + segment.length(),isQuerySegment);
|
||||
}
|
||||
|
||||
|
||||
static std::string decode_url_segment(const char*pStart, const char*pEnd, bool isQuerySegment = false);
|
||||
|
||||
static std::string decode_url_segment(const char*text, bool isQuerySegment = false);
|
||||
|
||||
static void utf32_to_utf8_stream(std::ostream &s, uint32_t uc);
|
||||
|
||||
static std::string Rfc5987EncodeFileName(const std::string&name);
|
||||
|
||||
static std::string SafeFileName(const std::string &name);
|
||||
static std::string HtmlEncode(const std::string& text);
|
||||
|
||||
};
|
||||
|
||||
} // namespace.
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
Copyright (c) 2007, 2008 Johannes Berg
|
||||
Copyright (c) 2007 Andy Lutomirski
|
||||
Copyright (c) 2007 Mike Kershaw
|
||||
Copyright (c) 2008 Luis R. Rodriguez
|
||||
Copyright (c) 2024 Robin Davies
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
*/
|
||||
/*
|
||||
Heavily based on code borrowed from iw (1) command.
|
||||
https://kernel.googlesource.com/pub/scm/linux/kernel/git/jberg/iw/+/v0.9/COPYING
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "WifiRegulations.hpp"
|
||||
struct nl_sock;
|
||||
struct nl_cache;
|
||||
struct genl_family;
|
||||
|
||||
|
||||
namespace pipedal
|
||||
{
|
||||
|
||||
WifiInfo getWifiInfo(const char *phyName, const char *countryIso3661);
|
||||
std::vector<WifiP2PChannelInfo> getWifiP2pInfo(const char *phyName, const char *countryIso3661);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
Copyright (c) 2007, 2008 Johannes Berg
|
||||
Copyright (c) 2007 Andy Lutomirski
|
||||
Copyright (c) 2007 Mike Kershaw
|
||||
Copyright (c) 2008 Luis R. Rodriguez
|
||||
Copyright (c) 2024 Robin Davies
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in sourcpe and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
*/
|
||||
/*
|
||||
Heavily based on code borrowed from iw (1) command.
|
||||
https://kernel.googlesource.com/pub/scm/linux/kernel/git/jberg/iw/+/v0.9/COPYING
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "WifiRegulations.hpp"
|
||||
struct nl_sock;
|
||||
struct nl_cache;
|
||||
struct genl_family;
|
||||
|
||||
|
||||
namespace pipedal
|
||||
{
|
||||
|
||||
WifiInfo getWifiInfo(const char *phyName, const char *countryIso3661);
|
||||
std::vector<WifiP2PChannelInfo> getWifiP2pInfo(const char *phyName, const char *countryIso3661);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022 Robin E. R. Davies
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is furnished to do
|
||||
* so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#define DEVICE_GUID_FILE "/etc/pipedal/config/device_uuid"
|
||||
|
||||
#define PIPEDAL_P2PD_CONF_PATH "/etc/pipedal/config/pipedal_p2pd.conf"
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
// Copyright (c) 2022 Robin Davies
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include "WifiRegulations.hpp"
|
||||
#include <filesystem>
|
||||
|
||||
namespace pipedal
|
||||
{
|
||||
|
||||
|
||||
|
||||
// struct FrequencyRule
|
||||
// {
|
||||
// uint32_t minFrequencyKHz;
|
||||
// uint32_t maxFrequencyKhz;
|
||||
// uint32_t maximumAntennaGain; // in mBiu (100*dBi)
|
||||
// uint32_t maximumEirp; // in mBm (100*dBm)
|
||||
// RegRuleFlags flags;
|
||||
|
||||
// bool hasFlag(RegRuleFlags flag) const { return (((int)flag) & (int)this->flags) != 0; }
|
||||
// };
|
||||
|
||||
|
||||
class RegDb
|
||||
{
|
||||
private:
|
||||
friend class CrdbRules;
|
||||
uint8_t *pData;
|
||||
|
||||
public:
|
||||
static RegDb&GetInstance();
|
||||
|
||||
RegDb();
|
||||
RegDb(const std::filesystem::path&path); // for testing only.
|
||||
~RegDb();
|
||||
|
||||
const std::vector<WifiRegulations>&Regulations() const { return regulations;}
|
||||
|
||||
bool IsValid() const { return isValid; }
|
||||
|
||||
const WifiRegulations&getWifiRegulations(const std::string&countryIso3661) const;
|
||||
|
||||
private:
|
||||
bool isValid = false;
|
||||
|
||||
std::vector<uint8_t> data;
|
||||
void *ptr() { return (void *)&(data[0]); }
|
||||
void Load19();
|
||||
void Load20();
|
||||
|
||||
std::vector<WifiRegulations> regulations;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022 Robin E. R. Davies
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is furnished to do
|
||||
* so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include "ConfigSerializer.hpp"
|
||||
|
||||
namespace pipedal {
|
||||
using namespace config_serializer;
|
||||
|
||||
class ServiceConfiguration: protected ConfigSerializable<ServiceConfiguration> {
|
||||
public:
|
||||
using base = ConfigSerializable<ServiceConfiguration>;
|
||||
|
||||
ServiceConfiguration();
|
||||
|
||||
static const char DEVICEID_FILE_NAME[];
|
||||
|
||||
void Load();
|
||||
void Save();
|
||||
|
||||
|
||||
std::string uuid;
|
||||
std::string deviceName = "PiPedal";
|
||||
uint32_t server_port = 80;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
// Copyright (c) 2022 Robin Davies
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include <string>
|
||||
|
||||
namespace pipedal {
|
||||
// exec a command, returning the actual exit code (unlike execXX() or system() )
|
||||
int sysExec(const char*szCommand);
|
||||
|
||||
// execute a command, suppressing output.
|
||||
int silentSysExec(const char *szCommand);
|
||||
|
||||
|
||||
using ProcessId = int64_t; // platform-agnostic wrapper for pid_t;
|
||||
// Returns a pid or -1 on errror.
|
||||
ProcessId sysExecAsync(const std::string&command);
|
||||
|
||||
void sysExecTerminate(ProcessId pid_,int termTimeoutMs = 1000,int killTimeoutMs = 500 ); // returns the process's exit status.
|
||||
int sysExecWait(ProcessId pid);
|
||||
|
||||
std::string getSelfExePath();
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
// Copyright (c) 2022 Robin Davies
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "json.hpp"
|
||||
|
||||
namespace pipedal {
|
||||
|
||||
|
||||
uint32_t ChannelToWifiFrequency(const std::string &channel);
|
||||
uint32_t ChannelToWifiFrequency(uint32_t channel);
|
||||
int32_t ChannelToChannelNumber(const std::string&channel);
|
||||
|
||||
class WifiConfigSettings {
|
||||
public:
|
||||
bool valid_ = false;
|
||||
bool wifiWarningGiven_ = false;
|
||||
bool rebootRequired_ = false;
|
||||
bool enable_ = false;
|
||||
std::string countryCode_ = "US"; // iso 3661
|
||||
std::string hotspotName_ = "pipedal";
|
||||
std::string mdnsName_ = "pipedal";
|
||||
bool hasPassword_ = false;
|
||||
std::string password_;
|
||||
std::string channel_ = "g6";
|
||||
|
||||
void ParseArguments(const std::vector<std::string> &arguments);
|
||||
static bool ValidateCountryCode(const std::string&value);
|
||||
static bool ValidateChannel(const std::string&countryCode,const std::string&value);
|
||||
public:
|
||||
DECLARE_JSON_MAP(WifiConfigSettings);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022 Robin E. R. Davies
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is furnished to do
|
||||
* so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "json.hpp"
|
||||
|
||||
namespace pipedal {
|
||||
|
||||
class WifiDirectConfigSettings {
|
||||
public:
|
||||
bool valid_ = false;
|
||||
bool rebootRequired_ = false;
|
||||
bool enable_ = false;
|
||||
std::string countryCode_ = ""; // iso 3661
|
||||
std::string hotspotName_ = "pipedal";
|
||||
bool pinChanged_ = false;
|
||||
std::string pin_;
|
||||
std::string channel_ = "0"; // "0" -> select automatically.
|
||||
std::string wlan_ = "wlan0";
|
||||
|
||||
void ParseArguments(const std::vector<std::string> &arguments);
|
||||
void Save() const;
|
||||
void Load();
|
||||
|
||||
public:
|
||||
DECLARE_JSON_MAP(WifiDirectConfigSettings);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// Copyright (c) 2024 Robin Davies
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
namespace pipedal {
|
||||
// returns frequency in MHz.
|
||||
int32_t wifiChannelToFrequency(int32_t channel);
|
||||
int32_t wifiFrequencyToChannel(
|
||||
int32_t frequency // frequency in Mhz
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "EnumFlags.hpp"
|
||||
|
||||
|
||||
namespace pipedal
|
||||
{
|
||||
|
||||
enum class SecondaryChannelLocation
|
||||
{
|
||||
None,
|
||||
Above,
|
||||
Below
|
||||
};
|
||||
|
||||
enum class WifiMode
|
||||
{
|
||||
IEEE80211G,
|
||||
IEEE80211A,
|
||||
IEEE80211B,
|
||||
IEEE80211AD,
|
||||
IEEE80211AX,
|
||||
IEEE80211ANY,
|
||||
};
|
||||
|
||||
enum class WifiBandwidth
|
||||
{
|
||||
BW20,
|
||||
BW40MINUS, // g and a.
|
||||
BW40PLUS,
|
||||
BW40, // wifi 6 only. Must come after BW40PLUS, BW40MINUS.
|
||||
BW80,
|
||||
BW160,
|
||||
BW80P80,
|
||||
BW2160,
|
||||
BW4320,
|
||||
BW6480,
|
||||
BW8640
|
||||
};
|
||||
|
||||
enum class DfsRegion
|
||||
{
|
||||
Unset = 0,
|
||||
Fcc = 1,
|
||||
Etsi = 2,
|
||||
Japan = 3
|
||||
};
|
||||
|
||||
// sync with <linux/nl80211.h
|
||||
enum class RegRuleFlags: uint32_t
|
||||
{
|
||||
NONE = 0,
|
||||
NO_OFDM = 1 << 0,
|
||||
NO_CCK = 1 << 1,
|
||||
NO_INDOOR = 1 << 2,
|
||||
NO_OUTDOOR = 1 << 3,
|
||||
DFS = 1 << 4,
|
||||
PTP_ONLY = 1 << 5,
|
||||
PTMP_ONLY = 1 << 6,
|
||||
NO_IR = 1 << 7,
|
||||
__NO_IBSS = 1 << 8,
|
||||
AUTO_BW = 1 << 11,
|
||||
IR_CONCURRENT = 1 << 12,
|
||||
NO_HT40MINUS = 1 << 13,
|
||||
NO_HT40PLUS = 1 << 14,
|
||||
NO_80MHZ = 1 << 15,
|
||||
NO_160MHZ = 1 << 16,
|
||||
NO_HE = 1 << 17,
|
||||
};
|
||||
|
||||
struct WifiRule
|
||||
{
|
||||
RegRuleFlags flags = RegRuleFlags::NONE;
|
||||
|
||||
uint32_t start_freq_khz = 0;
|
||||
uint32_t end_freq_khz = 0;
|
||||
uint32_t max_bandwidth_khz = 0;
|
||||
uint32_t max_antenna_gain = 0;
|
||||
uint32_t max_eirp = 0;
|
||||
uint32_t dfs_cac_ms = 0;
|
||||
uint32_t psd = 0;
|
||||
|
||||
bool HasFlag(RegRuleFlags flag) const {
|
||||
return ((uint32_t)flag & (uint32_t)this->flags) != 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct WifiRegulations
|
||||
{
|
||||
|
||||
std::string reg_alpha2;
|
||||
DfsRegion dfs_region;
|
||||
std::vector<WifiRule> rules;
|
||||
const WifiRule*GetRule(int32_t frequencyMhz) const;
|
||||
};
|
||||
|
||||
struct WifiChannelInfo
|
||||
{
|
||||
int channelNumber = -1;
|
||||
WifiMode hardwareMode;
|
||||
int mhz = 0;
|
||||
bool disabled = false;
|
||||
bool ir = true;
|
||||
bool radarDetection = false;
|
||||
std::vector<float> bitrates;
|
||||
bool indoorOnly = false;
|
||||
bool outdoorsOnly = false;
|
||||
bool noHt40Minus = false;
|
||||
bool noHt40Plus = false;
|
||||
bool no10MHz = false;
|
||||
bool no20MHz = false;
|
||||
bool no80MHz = false;
|
||||
bool no160MHz = false;
|
||||
int32_t maxAntennaGain = 0;
|
||||
int32_t maxEirp = 0;
|
||||
WifiBandwidth bandwidth;
|
||||
int32_t regDomain = -1;
|
||||
};
|
||||
|
||||
struct WifiP2PChannelInfo : public WifiChannelInfo
|
||||
{
|
||||
};
|
||||
|
||||
struct WifiInfo
|
||||
{
|
||||
std::string reg_alpha2;
|
||||
std::vector<std::string> supportedIfTypes;
|
||||
DfsRegion dfsRegion;
|
||||
std::vector<WifiChannelInfo> channels;
|
||||
|
||||
const WifiChannelInfo *getChannelInfo(int channel) const;
|
||||
};
|
||||
|
||||
}
|
||||
ENABLE_ENUM_FLAGS(pipedal::RegRuleFlags)
|
||||
@@ -0,0 +1,45 @@
|
||||
// Copyright (c) 2022 Robin Davies
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <filesystem>
|
||||
|
||||
|
||||
namespace pipedal {
|
||||
void WriteTemplateFile(
|
||||
const std::map<std::string,std::string> &map,
|
||||
const std::filesystem::path& inputFile,
|
||||
const std::filesystem::path& outputFile);
|
||||
|
||||
/**
|
||||
* @brief Write template file.
|
||||
*
|
||||
* The input file is
|
||||
*
|
||||
* /etc/pipedal/config/template/<filename>.template
|
||||
*
|
||||
* @param map Dictionary of values to substitute.
|
||||
* @param outputFile The full path of the output file.
|
||||
*/
|
||||
void WriteTemplateFile(
|
||||
const std::map<std::string,std::string> &map,
|
||||
const std::filesystem::path &outputFile);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022 Robin E. R. Davies
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is furnished to do
|
||||
* so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vector>
|
||||
|
||||
|
||||
|
||||
namespace p2p {
|
||||
|
||||
template <typename T> class autoptr_vector
|
||||
{
|
||||
std::vector<T*> v;
|
||||
private:
|
||||
// no copy no move.
|
||||
autoptr_vector(const autoptr_vector<T> &) = delete;
|
||||
autoptr_vector(autoptr_vector<T> && ) = delete;
|
||||
public:
|
||||
using iterator = std::vector<T*>::const_iterator;
|
||||
|
||||
autoptr_vector() { }
|
||||
autoptr_vector(std::initializer_list<T*> l)
|
||||
:v(l)
|
||||
{
|
||||
|
||||
}
|
||||
~autoptr_vector() {
|
||||
for (T *i: v)
|
||||
{
|
||||
delete i;
|
||||
}
|
||||
}
|
||||
void push_back(T*value) { v.push_back(value);}
|
||||
|
||||
iterator begin() const { return v.begin(); }
|
||||
iterator end() const { return v.end(); }
|
||||
|
||||
T*operator[](size_t index) const { return v[index]; }
|
||||
|
||||
size_t size() const { return v.size(); }
|
||||
};
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,550 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 Robin E. R. Davies
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is furnished to do
|
||||
* so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include <variant>
|
||||
#include <map>
|
||||
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
#include "json.hpp"
|
||||
|
||||
namespace pipedal
|
||||
{
|
||||
class json_null
|
||||
{
|
||||
public:
|
||||
static json_null instance;
|
||||
bool operator==(const json_null &other) const { return true; }
|
||||
bool operator!=(const json_null &other) const { return (!((*this) == other)); }
|
||||
|
||||
private:
|
||||
int value = 0;
|
||||
};
|
||||
|
||||
class json_object;
|
||||
class json_array;
|
||||
|
||||
class json_variant
|
||||
: public JsonSerializable
|
||||
{
|
||||
public:
|
||||
enum class ContentType
|
||||
{
|
||||
Null,
|
||||
Bool,
|
||||
Number,
|
||||
String,
|
||||
Object,
|
||||
Array
|
||||
};
|
||||
using object_ptr = std::shared_ptr<json_object>;
|
||||
using array_ptr = std::shared_ptr<json_array>;
|
||||
|
||||
private:
|
||||
public:
|
||||
~json_variant();
|
||||
json_variant();
|
||||
json_variant(json_variant &&);
|
||||
json_variant(const json_variant &);
|
||||
|
||||
json_variant(json_null value);
|
||||
json_variant(bool value);
|
||||
json_variant(double value);
|
||||
json_variant(const std::string &value);
|
||||
json_variant(std::shared_ptr<json_object> &&value);
|
||||
json_variant(const std::shared_ptr<json_object> &value);
|
||||
json_variant(std::shared_ptr<json_array> &&value);
|
||||
json_variant(const std::shared_ptr<json_array> &value);
|
||||
json_variant(json_array &&array);
|
||||
json_variant(json_object &&object);
|
||||
json_variant(const char*sz);
|
||||
|
||||
json_variant(const void*) = delete; // do NOT allow implicit conversion of pointers to bool
|
||||
|
||||
json_variant &operator=(json_variant &&value);
|
||||
json_variant &operator=(const json_variant &value);
|
||||
json_variant &operator=(bool value);
|
||||
json_variant &operator=(double value);
|
||||
json_variant &operator=(const std::string &value);
|
||||
json_variant &operator=(std::string &&value);
|
||||
json_variant &operator=(json_object &&value);
|
||||
json_variant &operator=(json_array &&value);
|
||||
|
||||
json_variant &operator=(const char*sz) { return (*this) = std::string(sz); }
|
||||
|
||||
json_variant &operator=(void*) = delete; // do NOT allow implicit conversion of pointers to bool
|
||||
|
||||
void require_type(ContentType content_type) const
|
||||
{
|
||||
if (this->content_type != content_type)
|
||||
{
|
||||
throw std::logic_error("Content type is not valid.");
|
||||
}
|
||||
}
|
||||
bool is_null() const { return content_type == ContentType::Null; }
|
||||
bool is_bool() const { return content_type == ContentType::Bool; }
|
||||
bool is_number() const { return content_type == ContentType::Number; }
|
||||
bool is_string() const { return content_type == ContentType::String; }
|
||||
bool is_object() const { return content_type == ContentType::Object; }
|
||||
bool is_array() const { return content_type == ContentType::Array; }
|
||||
|
||||
const json_null &as_null() const
|
||||
{
|
||||
require_type(ContentType::Bool);
|
||||
return json_null::instance;
|
||||
}
|
||||
json_null &as_null()
|
||||
{
|
||||
require_type(ContentType::Null);
|
||||
return json_null::instance;
|
||||
}
|
||||
|
||||
bool as_bool() const
|
||||
{
|
||||
require_type(ContentType::Bool);
|
||||
return content.bool_value;
|
||||
}
|
||||
bool &as_bool()
|
||||
{
|
||||
require_type(ContentType::Bool);
|
||||
return content.bool_value;
|
||||
}
|
||||
|
||||
double as_number() const
|
||||
{
|
||||
require_type(ContentType::Number);
|
||||
return content.double_value;
|
||||
}
|
||||
double &as_number()
|
||||
{
|
||||
require_type(ContentType::Number);
|
||||
return content.double_value;
|
||||
}
|
||||
|
||||
const std::string &as_string() const;
|
||||
std::string &as_string();
|
||||
|
||||
const std::shared_ptr<json_object> &as_object() const;
|
||||
std::shared_ptr<json_object> &as_object();
|
||||
|
||||
const std::shared_ptr<json_array> &as_array() const;
|
||||
std::shared_ptr<json_array> &as_array();
|
||||
|
||||
template <typename U>
|
||||
U &as() { static_assert("Invalid type."); }
|
||||
|
||||
// convenience methods for object and array manipulation.
|
||||
static json_variant make_object();
|
||||
static json_variant make_array();
|
||||
|
||||
void resize(size_t size);
|
||||
size_t size() const;
|
||||
|
||||
bool contains(const std::string &index) const;
|
||||
|
||||
json_variant &at(size_t index);
|
||||
const json_variant &at(size_t index) const;
|
||||
|
||||
json_variant &operator[](size_t index);
|
||||
const json_variant &operator[](size_t index) const;
|
||||
|
||||
json_variant &operator[](const std::string &index);
|
||||
const json_variant &operator[](const std::string &index) const;
|
||||
|
||||
bool operator==(const json_variant &other) const;
|
||||
bool operator!=(const json_variant &other) const;
|
||||
|
||||
std::string to_string() const;
|
||||
private:
|
||||
void free();
|
||||
void write_double_value(json_writer &writer, double value) const;
|
||||
void write_float_value(json_writer &writer, double value) const;
|
||||
virtual void read_json(json_reader &reader);
|
||||
virtual void write_json(json_writer &writer) const;
|
||||
|
||||
static constexpr size_t stringSize = sizeof(std::string);
|
||||
static constexpr size_t objectSize = sizeof(std::shared_ptr<json_variant>);
|
||||
static constexpr size_t memSize = stringSize > objectSize ? stringSize : objectSize;
|
||||
union Content
|
||||
{
|
||||
bool bool_value;
|
||||
double double_value;
|
||||
float float_value;
|
||||
int32_t int32_value;
|
||||
uint8_t mem[memSize];
|
||||
};
|
||||
|
||||
ContentType content_type = ContentType::Null;
|
||||
Content content;
|
||||
|
||||
std::string &memString();
|
||||
object_ptr &memObject();
|
||||
array_ptr &memArray();
|
||||
|
||||
const std::string &memString() const;
|
||||
const object_ptr &memObject() const;
|
||||
const array_ptr &memArray() const;
|
||||
};
|
||||
class json_array : public JsonSerializable
|
||||
{
|
||||
private:
|
||||
json_array(const json_array&) { } // deleted.
|
||||
public:
|
||||
using ptr = std::shared_ptr<json_array>;
|
||||
|
||||
json_array() { ++allocation_count_; }
|
||||
json_array(json_array&&other);
|
||||
~json_array() { --allocation_count_; }
|
||||
|
||||
json_variant &at(size_t index);
|
||||
const json_variant &at(size_t index) const;
|
||||
|
||||
json_variant &operator[](size_t index);
|
||||
const json_variant &operator[](size_t &index) const;
|
||||
|
||||
void resize(size_t size) { values.resize(size); }
|
||||
size_t size() const { return values.size(); }
|
||||
void push_back(json_variant &&value) { values.push_back(std::move(value)); }
|
||||
template <typename U>
|
||||
void push_back(U &&value) { values.push_back(value); }
|
||||
void push_back(double value) { values.push_back(json_variant{value}); }
|
||||
void push_back(const std::string &value) { values.push_back(json_variant{value}); }
|
||||
void push_back(bool value) { values.push_back(json_variant{value}); }
|
||||
void push_back(const std::shared_ptr<json_array> &value) { values.push_back(json_variant(value)); }
|
||||
void push_back(const std::shared_ptr<json_object> &value) { values.push_back(json_variant(value)); }
|
||||
|
||||
bool operator==(const json_array &other) const;
|
||||
bool operator!=(const json_array &other) const { return (!((*this) == other)); }
|
||||
|
||||
// Strictly for testing purposes. Not thread-safe.
|
||||
static int64_t allocation_count()
|
||||
{
|
||||
return allocation_count_;
|
||||
}
|
||||
using iterator = std::vector<json_variant>::iterator;
|
||||
using const_iterator = std::vector<json_variant>::const_iterator;
|
||||
|
||||
iterator begin() { return values.begin(); }
|
||||
iterator end() { return values.end(); }
|
||||
const_iterator begin() const { return values.begin(); }
|
||||
const_iterator end() const { return values.end(); }
|
||||
|
||||
private:
|
||||
static int64_t allocation_count_; // strictly for testing purposes. not thread safe.
|
||||
|
||||
virtual void read_json(json_reader &reader);
|
||||
virtual void write_json(json_writer &writer) const;
|
||||
|
||||
void check_index(size_t size) const;
|
||||
|
||||
std::vector<json_variant> values;
|
||||
};
|
||||
class json_object : public JsonSerializable
|
||||
{
|
||||
private:
|
||||
json_object(const json_object&) { } // deleted.
|
||||
public:
|
||||
using ptr = std::shared_ptr<json_object>;
|
||||
|
||||
json_object() { ++ allocation_count_;}
|
||||
json_object(json_object&&other);
|
||||
~json_object() { --allocation_count_;}
|
||||
|
||||
size_t size() const { return values.size(); }
|
||||
json_variant &at(const std::string &index);
|
||||
const json_variant &at(const std::string &index) const;
|
||||
|
||||
json_variant &operator[](const std::string &index);
|
||||
const json_variant &operator[](const std::string &index) const;
|
||||
|
||||
bool operator==(const json_object &other) const;
|
||||
bool operator!=(const json_object &other) const { return (!((*this) == other)); }
|
||||
bool contains(const std::string &index) const;
|
||||
|
||||
|
||||
using values_t = std::vector< std::pair<std::string, json_variant> >;
|
||||
using iterator = values_t::iterator;
|
||||
using const_iterator = values_t::const_iterator;
|
||||
|
||||
iterator begin() { return values.begin(); }
|
||||
iterator end() { return values.end(); }
|
||||
const_iterator begin() const { return values.begin(); }
|
||||
const_iterator end() const { return values.end(); }
|
||||
|
||||
iterator find(const std::string& key);
|
||||
const_iterator find(const std::string& key) const;
|
||||
|
||||
|
||||
// strictly for testing purposes. Not thread-safe.
|
||||
static int64_t allocation_count()
|
||||
{
|
||||
return allocation_count_;
|
||||
}
|
||||
private:
|
||||
virtual void read_json(json_reader &reader);
|
||||
virtual void write_json(json_writer &writer) const;
|
||||
|
||||
static int64_t allocation_count_;
|
||||
values_t values;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////
|
||||
|
||||
inline std::string &json_variant::memString() { return *(std::string *)content.mem; }
|
||||
inline const std::string &json_variant::memString() const { return *(const std::string *)content.mem; }
|
||||
|
||||
template <>
|
||||
inline json_null &json_variant::as<json_null>() { return as_null(); }
|
||||
|
||||
template <>
|
||||
inline bool &json_variant::as<bool>() { return as_bool(); }
|
||||
|
||||
template <>
|
||||
inline double &json_variant::as<double>() { return as_number(); }
|
||||
|
||||
template <>
|
||||
inline std::string &json_variant::as<std::string>() { return as_string(); }
|
||||
|
||||
template <>
|
||||
inline std::shared_ptr<json_object> &json_variant::as<std::shared_ptr<json_object>>() { return as_object(); }
|
||||
|
||||
template <>
|
||||
inline std::shared_ptr<json_array> &json_variant::as<std::shared_ptr<json_array>>() { return as_array(); }
|
||||
|
||||
template <>
|
||||
inline json_variant &json_variant::as<json_variant>() { return *this; }
|
||||
|
||||
inline json_variant::object_ptr &json_variant::memObject()
|
||||
{
|
||||
return *(object_ptr *)content.mem;
|
||||
}
|
||||
inline json_variant::array_ptr &json_variant::memArray()
|
||||
{
|
||||
return *(array_ptr *)content.mem;
|
||||
}
|
||||
|
||||
inline const json_variant::object_ptr &json_variant::memObject() const
|
||||
{
|
||||
return *(const object_ptr *)content.mem;
|
||||
}
|
||||
inline const json_variant::array_ptr &json_variant::memArray() const
|
||||
{
|
||||
return *(const array_ptr *)content.mem;
|
||||
}
|
||||
|
||||
inline json_variant::json_variant(json_array &&array)
|
||||
{
|
||||
this->content_type = ContentType::Null;
|
||||
new (content.mem) std::shared_ptr<json_array>{new json_array(std::move(array))};
|
||||
this->content_type = ContentType::Array;
|
||||
}
|
||||
inline json_variant::json_variant(json_object &&object)
|
||||
{
|
||||
this->content_type = ContentType::Null;
|
||||
new (content.mem) std::shared_ptr<json_object>{new json_object(std::move(object))};
|
||||
this->content_type = ContentType::Object;
|
||||
}
|
||||
|
||||
inline json_variant::json_variant(const std::string &value)
|
||||
{
|
||||
this->content_type = ContentType::Null;
|
||||
new (content.mem) std::string(value); // placement new.
|
||||
content_type = ContentType::String;
|
||||
}
|
||||
|
||||
inline json_variant::json_variant(std::shared_ptr<json_object> &&value)
|
||||
{
|
||||
this->content_type = ContentType::Null;
|
||||
new (content.mem) std::shared_ptr<json_object>(std::move(value)); // placement new.
|
||||
content_type = ContentType::Object;
|
||||
}
|
||||
inline json_variant::json_variant(const std::shared_ptr<json_object> &value)
|
||||
{
|
||||
// don't deep copy!
|
||||
std::shared_ptr<json_object> t = const_cast<std::shared_ptr<json_object> &>(value);
|
||||
this->content_type = ContentType::Null;
|
||||
new (content.mem) std::shared_ptr<json_object>(t); // placement new.
|
||||
content_type = ContentType::Object;
|
||||
}
|
||||
|
||||
inline json_variant::json_variant(const std::shared_ptr<json_array> &value)
|
||||
{
|
||||
// Make sure we don't deep copy!
|
||||
std::shared_ptr<json_array> t = const_cast<std::shared_ptr<json_array> &>(value);
|
||||
this->content_type = ContentType::Null;
|
||||
new (content.mem) std::shared_ptr<json_array>(t); // placement new.
|
||||
content_type = ContentType::Array;
|
||||
}
|
||||
inline json_variant::json_variant(array_ptr &&value)
|
||||
{
|
||||
this->content_type = ContentType::Null;
|
||||
new (content.mem) std::shared_ptr<json_array>(std::move(value)); // placement new.
|
||||
content_type = ContentType::Array;
|
||||
}
|
||||
inline json_variant::json_variant()
|
||||
{
|
||||
content_type = ContentType::Null;
|
||||
}
|
||||
inline json_variant::json_variant(json_null value)
|
||||
{
|
||||
content_type = ContentType::Null;
|
||||
}
|
||||
inline json_variant::json_variant(bool value)
|
||||
{
|
||||
content_type = ContentType::Bool;
|
||||
content.bool_value = value;
|
||||
}
|
||||
|
||||
inline json_variant::json_variant(double value)
|
||||
{
|
||||
content_type = ContentType::Number;
|
||||
content.double_value = value;
|
||||
}
|
||||
inline std::string &json_variant::as_string()
|
||||
{
|
||||
require_type(ContentType::String);
|
||||
return memString();
|
||||
}
|
||||
|
||||
inline const std::string &json_variant::as_string() const
|
||||
{
|
||||
require_type(ContentType::String);
|
||||
return memString();
|
||||
}
|
||||
|
||||
inline const json_variant::object_ptr &json_variant::as_object() const
|
||||
{
|
||||
require_type(ContentType::Object);
|
||||
return memObject();
|
||||
}
|
||||
|
||||
inline json_variant::object_ptr &json_variant::as_object()
|
||||
{
|
||||
require_type(ContentType::Object);
|
||||
return memObject();
|
||||
}
|
||||
|
||||
inline const json_variant::array_ptr &json_variant::as_array() const
|
||||
{
|
||||
require_type(ContentType::Array);
|
||||
return memArray();
|
||||
}
|
||||
|
||||
inline json_variant::array_ptr &json_variant::as_array()
|
||||
{
|
||||
require_type(ContentType::Array);
|
||||
return memArray();
|
||||
}
|
||||
|
||||
inline /*static*/ json_variant json_variant::make_object()
|
||||
{
|
||||
return json_variant{std::make_shared<json_object>()};
|
||||
};
|
||||
inline /*static */ json_variant json_variant::make_array()
|
||||
{
|
||||
return json_variant{std::make_shared<json_array>()};
|
||||
};
|
||||
|
||||
inline void json_variant::resize(size_t size)
|
||||
{
|
||||
as_array()->resize(size);
|
||||
}
|
||||
|
||||
inline json_variant &json_variant::at(size_t index)
|
||||
{
|
||||
return as_array()->at(index);
|
||||
}
|
||||
inline const json_variant &json_variant::at(size_t index) const
|
||||
{
|
||||
return as_array()->at(index);
|
||||
}
|
||||
|
||||
inline json_variant &json_variant::operator[](size_t index)
|
||||
{
|
||||
return as_array()->at(index);
|
||||
}
|
||||
inline const json_variant &json_variant::operator[](size_t index) const
|
||||
{
|
||||
return as_array()->at(index);
|
||||
}
|
||||
|
||||
inline const json_variant &json_variant::operator[](const std::string &index) const
|
||||
{
|
||||
return (*as_object())[index];
|
||||
}
|
||||
inline json_variant &json_variant::operator[](const std::string &index)
|
||||
{
|
||||
return (*as_object())[index];
|
||||
}
|
||||
|
||||
inline const json_variant &json_array::operator[](size_t &index) const
|
||||
{
|
||||
check_index(index);
|
||||
return values[index];
|
||||
}
|
||||
|
||||
inline json_variant &json_array::operator[](size_t index)
|
||||
{
|
||||
return at(index);
|
||||
}
|
||||
|
||||
inline void json_array::check_index(size_t size) const
|
||||
{
|
||||
if (size >= values.size())
|
||||
{
|
||||
throw std::out_of_range("index out of range.");
|
||||
}
|
||||
}
|
||||
|
||||
inline bool json_variant::operator!=(const json_variant &other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
|
||||
// Holds a string but is json_read and json_written as an unqoted json object.
|
||||
class raw_json_string: public JsonSerializable {
|
||||
public:
|
||||
raw_json_string() { }
|
||||
raw_json_string(const std::string &value) : value(value) {}
|
||||
const std::string& as_string() const { return value; }
|
||||
|
||||
void Set(const std::string&value) { this->value = value; }
|
||||
|
||||
private:
|
||||
|
||||
virtual void write_json(json_writer &writer) const {
|
||||
writer.write_raw(value.c_str());
|
||||
}
|
||||
virtual void read_json(json_reader &reader) {
|
||||
throw std::logic_error("Not implemented.");
|
||||
}
|
||||
|
||||
std::string value;
|
||||
};
|
||||
|
||||
} // namespace pipedal
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2023 Robin E. R. Davies
|
||||
* All rights reserved.
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <filesystem>
|
||||
|
||||
namespace pipedal {
|
||||
|
||||
inline bool endsWith(const std::string& str, const std::string& suffix)
|
||||
{
|
||||
return str.size() >= suffix.size() && 0 == str.compare(str.size()-suffix.size(), suffix.size(), suffix);
|
||||
}
|
||||
void SetThreadName(const std::string &name);
|
||||
|
||||
std::u32string ToUtf32(const std::string &s);
|
||||
|
||||
inline bool isPathSeperator(char c) { return c == '/' || c == std::filesystem::path::preferred_separator;}
|
||||
}
|
||||
Reference in New Issue
Block a user