PiPedal 1.2.33 initial commit

This commit is contained in:
Robin Davies
2024-08-08 12:53:02 -04:00
parent 0e378997a5
commit a3847c8184
255 changed files with 22008 additions and 1791 deletions
+19
View File
@@ -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());
}
}
};
}
+37
View File
@@ -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);
};
}
+60
View File
@@ -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;
}
+55
View File
@@ -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"
+75
View File
@@ -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;
};
}
+39
View File
@@ -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);
};
}
+29
View File
@@ -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
+550
View File
@@ -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
+38
View File
@@ -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;}
}