202 lines
5.4 KiB
C++
202 lines
5.4 KiB
C++
/*
|
|
osc/argument.cpp
|
|
|
|
Copyright (c) 2023 Kevin Matz (kevin.matz@gmail.com)
|
|
|
|
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.
|
|
*/
|
|
#include "argument.h"
|
|
#include <cassert>
|
|
#include "message.h"
|
|
|
|
namespace OSC {
|
|
|
|
/**
|
|
* @brief Argument::type
|
|
* @return
|
|
*/
|
|
std::string Argument::type() const
|
|
{
|
|
return std::string(1, type_);
|
|
}
|
|
|
|
|
|
size_t string::streamSize() const
|
|
{
|
|
auto length = value.size(); // character count
|
|
length += 1; // null terminated
|
|
length += length % 4 ? 4 - (length % 4) : 0; // padding bytes
|
|
assert(0 == length % 4);
|
|
return length;
|
|
}
|
|
|
|
|
|
void string::iStream(std::shared_ptr<bufferstream> stream)
|
|
{
|
|
stream->readString(value);
|
|
auto pad = (value.size() + 1) % 4;
|
|
for (uint i = 0; i < pad; i++)
|
|
stream->readType<uint8_t>();
|
|
}
|
|
|
|
|
|
void string::oStream(std::shared_ptr<bufferstream> stream) const
|
|
{
|
|
stream->writeString(value);
|
|
auto pad = (value.size() + 1) % 4;
|
|
for (uint i = 0; i < pad; i++)
|
|
stream->writeType<uint8_t>(0x00);
|
|
}
|
|
|
|
|
|
size_t blob::streamSize() const
|
|
{
|
|
auto length = 4 + value.size(); // length + byte count
|
|
length += length % 4 ? 4 - (length % 4) : 0; // padding bytes
|
|
assert(0 == length % 4);
|
|
return length;
|
|
}
|
|
|
|
|
|
void blob::iStream(std::shared_ptr<bufferstream> stream)
|
|
{
|
|
auto length = stream->readType<int32_t>();
|
|
value.resize(length);
|
|
stream->read(value.data(), length);
|
|
auto pad = length % 4;
|
|
for (int i = 0; i < pad; i++)
|
|
stream->readType<uint8_t>();
|
|
}
|
|
|
|
|
|
void blob::oStream(std::shared_ptr<bufferstream> stream) const
|
|
{
|
|
stream->writeType<int32_t>(value.size());
|
|
auto pad = value.size() % 4;
|
|
for (uint i = 0; i < pad; i++)
|
|
stream->readType<uint8_t>();
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief timetag::time_point
|
|
* @return
|
|
*
|
|
* Convert \cite NTPv4 NTP timestamp to a system referanced time_point, with
|
|
* not greater than nanosecond resolution.
|
|
*
|
|
* \warning \cite Spec11 OSC Spec 1.1 leaves unchanged the reliance on the 64-bit NTP
|
|
* timestamp format. The NTP Epoch 0 ends on February 7, 2036, at which time OSC
|
|
* timetag values will rollover.
|
|
*/
|
|
std::chrono::time_point<std::chrono::system_clock> timetag::time() const
|
|
{
|
|
std::chrono::time_point<std::chrono::system_clock> time; // POSIX epoch
|
|
time -= std::chrono::seconds(2208988800); // NTP epoch offset
|
|
time += std::chrono::seconds(seconds);
|
|
time += std::chrono::nanoseconds(
|
|
(uint32_t)(((double)fractional
|
|
*(1.0/(double)std::numeric_limits<typeof(fractional)>::max()))
|
|
*1e9));
|
|
/// \test validate time conversion from fractional seconds.
|
|
return time;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief timetag::setTime
|
|
* @param time
|
|
*
|
|
* Convert system referanced time_point to \cite NTPv4 NTP timestamps, with
|
|
* not greater than nanosecond resolution.
|
|
*
|
|
* \warning \cite Spec11 OSC Spec 1.1 leaves unchanged the reliance on the 64-bit NTP
|
|
* timestamp format. The NTP Epoch 0 ends on February 7, 2036, at which time OSC
|
|
* timetag values will rollover.
|
|
*/
|
|
void timetag::setTime(std::chrono::time_point<std::chrono::system_clock> time)
|
|
{
|
|
auto t = time.time_since_epoch(); // POSIX epoch
|
|
auto s = std::chrono::duration_cast<std::chrono::seconds>(t);
|
|
auto f = std::chrono::duration_cast<std::chrono::nanoseconds>(t - s);
|
|
s += std::chrono::seconds(2208988800); // NTP epoch offset
|
|
seconds = s.count();
|
|
fractional = ((double)f.count()
|
|
*1e-9)
|
|
*(1.0/(double)std::numeric_limits<typeof(fractional)>::max());
|
|
/// \test validate time conversion to fractional seconds.
|
|
}
|
|
|
|
|
|
void character::iStream(std::shared_ptr<bufferstream> stream)
|
|
{
|
|
value = stream->readType<int32_t>();
|
|
}
|
|
|
|
|
|
void character::oStream(std::shared_ptr<bufferstream> stream) const
|
|
{
|
|
stream->writeType(static_cast<int32_t>(value));
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief array::setTypes
|
|
* @param types
|
|
*/
|
|
void array::setTypes(std::string types)
|
|
{
|
|
members = Message::createArguments(types);
|
|
}
|
|
|
|
|
|
std::string array::type() const
|
|
{
|
|
std::string ret = "[";
|
|
for (const auto &member: members)
|
|
ret += member->type();
|
|
ret += "]";
|
|
return ret;
|
|
}
|
|
|
|
|
|
size_t array::streamSize() const
|
|
{
|
|
size_t size = 0;
|
|
for (const auto &member: members)
|
|
size += member->streamSize();
|
|
return size;
|
|
}
|
|
|
|
|
|
void array::iStream(std::shared_ptr<bufferstream> stream)
|
|
{
|
|
for (auto & member: members)
|
|
member->iStream(stream);
|
|
}
|
|
|
|
|
|
void array::oStream(std::shared_ptr<bufferstream> stream) const
|
|
{
|
|
for (const auto &member: members)
|
|
member->oStream(stream);
|
|
}
|
|
|
|
} // namespace OSC
|