31 localtime_s(&local_tm, &time_value);
32#elif defined(__unix__) || defined(__APPLE__)
33 localtime_r(&time_value, &local_tm);
35 const std::tm* local_tm_ptr = std::localtime(&time_value);
37 local_tm = *local_tm_ptr;
52 gmtime_s(&utc_tm, &time_value);
53#elif defined(__unix__) || defined(__APPLE__)
54 gmtime_r(&time_value, &utc_tm);
56 const std::tm* utc_tm_ptr = std::gmtime(&time_value);
71#if defined(__unix__) || defined(__APPLE__)
73 return local_tm.tm_gmtoff;
76 _get_timezone(&tz_seconds);
78 if (local_tm.tm_isdst > 0) {
80 _get_dstbias(&dstbias);
81 tz_seconds += dstbias;
89 utc_tm.tm_isdst = local_tm.tm_isdst;
90 std::time_t local_time = std::mktime(&local_tm);
91 std::time_t utc_time = std::mktime(&utc_tm);
92 if (local_time ==
static_cast<std::time_t
>(-1)
93 || utc_time ==
static_cast<std::time_t
>(-1))
97 return static_cast<long>(std::difftime(local_time, utc_time));
108 const char sign = (offset_seconds < 0) ?
'-' :
'+';
109 long abs_offset = (offset_seconds < 0) ? -offset_seconds : offset_seconds;
110 long hours = abs_offset / 3600;
111 long minutes = (abs_offset % 3600) / 60;
113 std::ostringstream oss;
114 oss << sign << std::setw(2) << std::setfill(
'0') << hours <<
':'
115 << std::setw(2) << std::setfill(
'0') << minutes;
127 || (defined(__BYTE_ORDER__) \
128 && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
131 return static_cast<uint16_t
>((value >> 8) | (value << 8));
142 std::array<uint8_t, 16> bytes {};
143 std::random_device rd;
144 std::mt19937 gen(rd());
145 std::uniform_int_distribution<uint32_t> dist(0, 0xFFFFFFFF);
147 for (
size_t i = 0; i < bytes.size(); i += 4) {
148 uint32_t random_value = dist(gen);
149 bytes[i] =
static_cast<uint8_t
>(random_value & 0xFF);
150 bytes[i + 1] =
static_cast<uint8_t
>((random_value >> 8) & 0xFF);
151 bytes[i + 2] =
static_cast<uint8_t
>((random_value >> 16) & 0xFF);
152 bytes[i + 3] =
static_cast<uint8_t
>((random_value >> 24) & 0xFF);
156 bytes[6] =
static_cast<uint8_t
>((bytes[6] & 0x0F) | 0x40);
157 bytes[8] =
static_cast<uint8_t
>((bytes[8] & 0x3F) | 0x80);
159 std::ostringstream oss;
160 oss << std::hex << std::nouppercase << std::setfill(
'0');
161 for (
size_t i = 0; i < bytes.size(); ++i) {
162 if (i == 4 || i == 6 || i == 8 || i == 10) {
165 oss << std::setw(2) << static_cast<int>(bytes[i]);
176 auto now = std::chrono::system_clock::now();
177 auto seconds = std::chrono::time_point_cast<std::chrono::seconds>(now);
179 std::chrono::duration_cast<std::chrono::microseconds>(now - seconds)
181 std::time_t time_value = std::chrono::system_clock::to_time_t(seconds);
185 std::ostringstream oss;
186 oss << std::put_time(&local_tm,
"%Y-%m-%dT%H:%M:%S");
187 oss <<
'.' << std::setw(6) << std::setfill(
'0') << micros;
204 const std::string iso8601Pattern =
205 R
"(^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+[+-]\d{2}:\d{2}$)";
206 std::regex pattern(iso8601Pattern);
209 return std::regex_match(dateStr, pattern);
219static inline std::shared_ptr<IO::BaseIO>
createIO(
const std::string& type,
220 const std::string& filename)
222 if (type ==
"HDF5") {
223 return std::make_shared<AQNWB::IO::HDF5::HDF5IO>(filename);
225 throw std::invalid_argument(
"Invalid IO type");
242static inline std::string
mergePaths(
const std::string& path1,
243 const std::string& path2)
245 std::string result = path1;
247 while (!result.empty() && result.back() ==
'/' && result !=
"/") {
252 while (start < path2.size() && path2[start] ==
'/') {
256 std::string path2Clean = path2.substr(start);
257 while (!path2Clean.empty() && path2Clean.back() ==
'/' && path2Clean !=
"/") {
258 path2Clean.pop_back();
261 if (!result.empty() && !path2Clean.empty()) {
264 result += path2Clean;
267 size_t pos = result.find(
"//");
268 while (pos != std::string::npos) {
269 result.replace(pos, 2,
"/");
270 pos = result.find(
"//", pos);
274 while (!result.empty() && result.back() ==
'/' && result !=
"/") {
296 auto maxVal =
static_cast<double>(0x7fff);
297 auto intData =
static_cast<char*
>(dest);
299 for (
SizeType i = 0; i < numSamples; ++i) {
301 std::clamp(maxVal *
static_cast<double>(source[i]), -maxVal, maxVal);
303 static_cast<uint16_t
>(
static_cast<int16_t
>(std::round(clampedValue)));
305 *
reinterpret_cast<uint16_t*
>(intData) = intValue;
317 SizeType numSamples,
float conversion_factor,
const float* data)
319 std::unique_ptr<float[]> scaledData = std::make_unique<float[]>(numSamples);
320 std::unique_ptr<int16_t[]> intData = std::make_unique<int16_t[]>(numSamples);
323 float multFactor = 1.0f / (32767.0f * conversion_factor);
327 [multFactor](
float value) { return value * multFactor; });
353 return (status < 0) ? Status::Failure : Status::Success;
363 if (status != Status::Success) {
364 std::cerr << operation <<
" failed" << std::endl;
AQNWB::Types::Status Status
Definition BaseIO.hpp:21
AQNWB::Types::SizeType SizeType
Definition Channel.hpp:8
static constexpr SizeType SizeTypeNotSet
Value to use to indicate that a SizeType index is not set.
Definition Types.hpp:105
std::tm to_utc_time(std::time_t time_value)
Convert a std::time_t value to a UTC std::tm structure.
Definition Utils.hpp:48
std::tm to_local_time(std::time_t time_value)
Convert a std::time_t value to a local std::tm structure.
Definition Utils.hpp:27
std::string format_utc_offset(long offset_seconds)
Format a UTC offset in seconds as a string (+HH:MM or -HH:MM).
Definition Utils.hpp:106
uint16_t to_little_endian_u16(uint16_t value)
Convert a 16-bit unsigned integer to little-endian byte order.
Definition Utils.hpp:124
long get_utc_offset_seconds(std::time_t time_value)
Get the UTC offset in seconds for a given time_t value.
Definition Utils.hpp:69
The main namespace for AqNWB.
Definition Channel.hpp:11
static Status intToStatus(int status)
Convert an integer status code to a Types::Status enum value. Shorthand for return (status < 0) ?...
Definition Utils.hpp:351
static std::unique_ptr< int16_t[]> transformToInt16(SizeType numSamples, float conversion_factor, const float *data)
Method to scale float values and convert to int16 values.
Definition Utils.hpp:316
static void convertFloatToInt16LE(const float *source, void *dest, SizeType numSamples)
Method to convert float values to uint16 values. This method was adapted from JUCE AudioDataConverter...
Definition Utils.hpp:289
static std::string mergePaths(const std::string &path1, const std::string &path2)
Merge two paths into a single path, handling extra trailing and starting "/".
Definition Utils.hpp:242
static bool isISO8601Date(const std::string &dateStr)
Check that a string is formatted in ISO8601 format.
Definition Utils.hpp:200
static std::string generateUuid()
Generates a UUID (Universally Unique Identifier) as a string.
Definition Utils.hpp:140
static void checkStatus(Status status, const std::string &operation)
Check status and print to standard error.
Definition Utils.hpp:361
static std::shared_ptr< IO::BaseIO > createIO(const std::string &type, const std::string &filename)
Factory method to create an IO object of the specified type.
Definition Utils.hpp:219
static std::string getCurrentTime()
Get the current time in ISO 8601 format with the UTC offset.
Definition Utils.hpp:174
static bool isValidIndex(SizeType index)
Check if a SizeType index is valid (i.e., not equal to SizeTypeNotSet).
Definition Utils.hpp:340