mirror of
https://github.com/pocoproject/poco.git
synced 2026-02-07 23:20:36 +08:00
ULID Support (#5129)
This commit is contained in:
committed by
GitHub
parent
5bbd542b6b
commit
b24d9ff0b8
3
.gitignore
vendored
3
.gitignore
vendored
@@ -179,6 +179,9 @@ node_modules
|
||||
# Build-time symlinks to bundled libraries #
|
||||
############################################
|
||||
Foundation/src/adler32.c
|
||||
Foundation/src/config.h
|
||||
Foundation/src/pcre2posix.c
|
||||
Foundation/src/pcre2posix.h
|
||||
Foundation/src/compress.c
|
||||
Foundation/src/crc32.c
|
||||
Foundation/src/crc32.h
|
||||
|
||||
@@ -33,7 +33,7 @@ objects = ArchiveStrategy Ascii ASCIIEncoding AsyncChannel AsyncNotificationCent
|
||||
ThreadPool ThreadTarget ActiveDispatcher Timer Timespan Timestamp Timezone Token URI \
|
||||
FileStreamFactory URIStreamFactory URIStreamOpener UTF32Encoding UTF16Encoding UTF8Encoding UTF8String \
|
||||
Unicode UnicodeConverter Windows1250Encoding Windows1251Encoding Windows1252Encoding \
|
||||
UUID UUIDGenerator Void Var VarHolder VarIterator VarVisitor Format Pipe PipeImpl PipeStream SharedMemory \
|
||||
UUID UUIDGenerator ULID ULIDGenerator Void Var VarHolder VarIterator VarVisitor Format Pipe PipeImpl PipeStream SharedMemory \
|
||||
MemoryStream FileStream AtomicCounter DataURIStream DataURIStreamFactory FileStreamRWLock \
|
||||
BufferedBidirectionalStreamBuf BufferedStreamBuf UnbufferedStreamBuf
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
//
|
||||
// Definition of class Base32Decoder.
|
||||
//
|
||||
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
|
||||
// Copyright (c) 2004-2025, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
@@ -37,20 +37,24 @@ class Foundation_API Base32DecoderBuf: public UnbufferedStreamBuf
|
||||
/// its streambuf.
|
||||
{
|
||||
public:
|
||||
Base32DecoderBuf(std::istream& istr);
|
||||
Base32DecoderBuf(std::istream& istr, int options = 0);
|
||||
~Base32DecoderBuf() override;
|
||||
|
||||
private:
|
||||
int readFromDevice() override;
|
||||
int readOne();
|
||||
|
||||
static const unsigned char* encoding(int options);
|
||||
|
||||
unsigned char _group[8];
|
||||
int _groupLength;
|
||||
int _groupIndex;
|
||||
std::streambuf& _buf;
|
||||
const unsigned char* _encoding;
|
||||
|
||||
static unsigned char IN_ENCODING[256];
|
||||
static bool IN_ENCODING_INIT;
|
||||
static const unsigned char REVERSE_DEFAULT_ENCODING[256];
|
||||
static const unsigned char REVERSE_HEX_ENCODING[256];
|
||||
static const unsigned char REVERSE_CROCKFORD_ENCODING[256];
|
||||
|
||||
private:
|
||||
Base32DecoderBuf(const Base32DecoderBuf&);
|
||||
@@ -65,7 +69,7 @@ class Foundation_API Base32DecoderIOS: public virtual std::ios
|
||||
/// order of the stream buffer and base classes.
|
||||
{
|
||||
public:
|
||||
Base32DecoderIOS(std::istream& istr);
|
||||
Base32DecoderIOS(std::istream& istr, int options = 0);
|
||||
~Base32DecoderIOS() override;
|
||||
Base32DecoderBuf* rdbuf();
|
||||
|
||||
@@ -83,6 +87,8 @@ class Foundation_API Base32Decoder: public Base32DecoderIOS, public std::istream
|
||||
/// read from the istream connected to it.
|
||||
///
|
||||
/// The class implements RFC 4648 - https://tools.ietf.org/html/rfc4648
|
||||
/// and additionally supports decoding of Crockford Base 32 encoded
|
||||
/// data.
|
||||
///
|
||||
/// Note: For performance reasons, the characters
|
||||
/// are read directly from the given istream's
|
||||
@@ -91,7 +97,10 @@ class Foundation_API Base32Decoder: public Base32DecoderIOS, public std::istream
|
||||
/// its streambuf.
|
||||
{
|
||||
public:
|
||||
Base32Decoder(std::istream& istr);
|
||||
Base32Decoder(std::istream& istr, int options = 0);
|
||||
/// Creates the Base32Decoder with the given options.
|
||||
/// See Base32EncodingOptions for valid options.
|
||||
|
||||
~Base32Decoder() override;
|
||||
|
||||
private:
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
//
|
||||
// Definition of class Base32Encoder.
|
||||
//
|
||||
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
|
||||
// Copyright (c) 2004-2025, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
@@ -26,6 +26,33 @@
|
||||
namespace Poco {
|
||||
|
||||
|
||||
enum Base32EncodingOptions
|
||||
{
|
||||
BASE32_NO_PADDING = 0x00,
|
||||
/// Don't append padding characters ('=') at end.
|
||||
///
|
||||
/// NOTE: This is provided for consistency with Base64EncodingOptions.
|
||||
|
||||
BASE32_USE_PADDING = 0x01,
|
||||
/// Append padding characters ('=') at end.
|
||||
///
|
||||
/// NOTE: This is provided for backwards compatibility with constructor
|
||||
/// taking a bool padding argument.
|
||||
|
||||
BASE32_USE_HEX_ALPHABET = 0x02,
|
||||
/// Use the RFC 4648 Base32 Extended Hex alphabet.
|
||||
|
||||
BASE32_USE_CROCKFORD_ALPHABET = 0x04
|
||||
/// Use Crockford's Base 32 alphabet for encoding
|
||||
/// (https://www.crockford.com/base32.html)
|
||||
/// instead of RFC 4648 Base32 alphabet.
|
||||
///
|
||||
/// Note: decoding is not case sensitive.
|
||||
/// Furthermore characters 0/O/o and 1/I/i/L/l
|
||||
/// are decoded as 0 and 1, respectively.
|
||||
};
|
||||
|
||||
|
||||
class Foundation_API Base32EncoderBuf: public UnbufferedStreamBuf
|
||||
/// This streambuf base32-encodes all data written
|
||||
/// to it and forwards it to a connected
|
||||
@@ -37,12 +64,17 @@ class Foundation_API Base32EncoderBuf: public UnbufferedStreamBuf
|
||||
/// not updated to match the buffer's state.
|
||||
{
|
||||
public:
|
||||
Base32EncoderBuf(std::ostream& ostr, bool padding = true);
|
||||
Base32EncoderBuf(std::ostream& ostr, int options = BASE32_USE_PADDING);
|
||||
~Base32EncoderBuf() override;
|
||||
|
||||
int close();
|
||||
/// Closes the stream buffer.
|
||||
|
||||
protected:
|
||||
static const unsigned char* encoding(int options);
|
||||
/// Returns the alphabet to be used for encoding/decoding
|
||||
/// according to the specified options.
|
||||
|
||||
private:
|
||||
int writeToDevice(char c) override;
|
||||
|
||||
@@ -50,8 +82,11 @@ private:
|
||||
int _groupLength;
|
||||
std::streambuf& _buf;
|
||||
bool _doPadding;
|
||||
const unsigned char* _encoding;
|
||||
|
||||
static const unsigned char OUT_ENCODING[32];
|
||||
static const unsigned char DEFAULT_ENCODING[32];
|
||||
static const unsigned char HEX_ENCODING[32];
|
||||
static const unsigned char CROCKFORD_ENCODING[32];
|
||||
|
||||
friend class Base32DecoderBuf;
|
||||
|
||||
@@ -67,7 +102,7 @@ class Foundation_API Base32EncoderIOS: public virtual std::ios
|
||||
/// order of the stream buffer and base classes.
|
||||
{
|
||||
public:
|
||||
Base32EncoderIOS(std::ostream& ostr, bool padding = true);
|
||||
Base32EncoderIOS(std::ostream& ostr, int options = BASE32_USE_PADDING);
|
||||
~Base32EncoderIOS() override;
|
||||
int close();
|
||||
Base32EncoderBuf* rdbuf();
|
||||
@@ -90,6 +125,7 @@ class Foundation_API Base32Encoder: public Base32EncoderIOS, public std::ostream
|
||||
/// completion of the encoding operation.
|
||||
///
|
||||
/// The class implements RFC 4648 - https://tools.ietf.org/html/rfc4648
|
||||
/// and additionally supports Crockford's Base 32.
|
||||
///
|
||||
/// Note: The characters are directly written
|
||||
/// to the ostream's streambuf, thus bypassing
|
||||
@@ -97,7 +133,10 @@ class Foundation_API Base32Encoder: public Base32EncoderIOS, public std::ostream
|
||||
/// not updated to match the buffer's state.
|
||||
{
|
||||
public:
|
||||
Base32Encoder(std::ostream& ostr, bool padding = true);
|
||||
Base32Encoder(std::ostream& ostr, int options = BASE32_USE_PADDING);
|
||||
/// Creates the Base32Encoder with the given options.
|
||||
/// See Base32EncodingOptions for supported options.
|
||||
|
||||
~Base32Encoder() override;
|
||||
|
||||
private:
|
||||
|
||||
200
Foundation/include/Poco/ULID.h
Normal file
200
Foundation/include/Poco/ULID.h
Normal file
@@ -0,0 +1,200 @@
|
||||
//
|
||||
// ULID.h
|
||||
//
|
||||
// Library: Foundation
|
||||
// Package: ULID
|
||||
// Module: ULID
|
||||
//
|
||||
// Definition of the ULID class.
|
||||
//
|
||||
// Copyright (c) 2025, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef Foundation_ULID_INCLUDED
|
||||
#define Foundation_ULID_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/Foundation.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
|
||||
|
||||
class Foundation_API ULID
|
||||
/// This class implements a [Universally Unique Lexicographically Sortable Identifier](https://github.com/ulid/spec) (ULID).
|
||||
///
|
||||
/// To generate a new random ULID, see ULIDGenerator::create().
|
||||
{
|
||||
public:
|
||||
ULID() = default;
|
||||
/// Creates a nil (all zero) ULID.
|
||||
|
||||
ULID(const ULID& ulid) = default;
|
||||
/// Copy constructor.
|
||||
|
||||
explicit ULID(const std::string& ulid);
|
||||
/// Parses the ULID from a string.
|
||||
|
||||
explicit ULID(const char* ulid);
|
||||
/// Parses the ULID from a string.
|
||||
|
||||
ULID(UInt64 time, UInt16 randomHigh, UInt64 randomLow);
|
||||
/// Creates a ULID from its components.
|
||||
|
||||
~ULID() = default;
|
||||
/// Destroys the ULID.
|
||||
|
||||
ULID& operator = (const ULID& ulid);
|
||||
/// Assignment operator.
|
||||
|
||||
void swap(ULID& ulid) noexcept;
|
||||
/// Swaps the ULID with another one.
|
||||
|
||||
void parse(const std::string& ulid);
|
||||
/// Parses the ULID from its string representation.
|
||||
|
||||
bool tryParse(const std::string& ulid);
|
||||
/// Tries to interpret the given string as an ULID.
|
||||
/// If the ULID is syntactically valid, assigns the
|
||||
/// members and returns true. Otherwise leaves the
|
||||
/// object unchanged and returns false.
|
||||
|
||||
std::string toString() const;
|
||||
/// Returns a string representation of the ULID,
|
||||
/// using Crockford's Base 32 encoding.
|
||||
|
||||
void copyFrom(const char* buffer);
|
||||
/// Copies the ULID (16 bytes) from a buffer or byte array.
|
||||
/// The ULID fields are expected to be
|
||||
/// stored in network byte order.
|
||||
/// The buffer need not be aligned.
|
||||
|
||||
void copyTo(char* buffer) const;
|
||||
/// Copies the ULID to the buffer. The fields
|
||||
/// are in network byte order.
|
||||
/// The buffer need not be aligned.
|
||||
/// There must have room for at least 16 bytes.
|
||||
|
||||
Poco::UInt64 time() const;
|
||||
/// Returns the 48-bit time part of the ULID
|
||||
/// (milliseconds since Unix epoch).
|
||||
|
||||
Poco::UInt16 randomHigh() const;
|
||||
/// Returns the most significant 16 bits of the 80-bit
|
||||
/// random part of the ULID.
|
||||
|
||||
Poco::UInt64 randomLow() const;
|
||||
/// Returns the least significant 64 bits of the 80-bit
|
||||
/// random part of the ULID.
|
||||
|
||||
bool operator == (const ULID& ulid) const;
|
||||
bool operator != (const ULID& ulid) const;
|
||||
bool operator < (const ULID& ulid) const;
|
||||
bool operator <= (const ULID& ulid) const;
|
||||
bool operator > (const ULID& ulid) const;
|
||||
bool operator >= (const ULID& ulid) const;
|
||||
|
||||
bool isNull() const;
|
||||
/// Returns true iff the ULID is nil (in other words,
|
||||
/// consists of all zeros).
|
||||
|
||||
static const ULID& null();
|
||||
/// Returns a null/nil ULID.
|
||||
|
||||
protected:
|
||||
int compare(const ULID& ulid) const;
|
||||
|
||||
template <typename T>
|
||||
static T decode(char c)
|
||||
{
|
||||
return static_cast<T>(REVERSE_ENCODING[static_cast<unsigned char>(c)]);
|
||||
}
|
||||
|
||||
private:
|
||||
UInt32 _timeHi = 0;
|
||||
UInt16 _timeLo = 0;
|
||||
UInt16 _randomHi = 0;
|
||||
UInt64 _randomLo = 0;
|
||||
|
||||
static const char ENCODING[32];
|
||||
static const UInt8 REVERSE_ENCODING[256];
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
inline Poco::UInt64 ULID::time() const
|
||||
{
|
||||
return (static_cast<Poco::UInt64>(_timeHi) << 16) + _timeLo;
|
||||
}
|
||||
|
||||
|
||||
inline Poco::UInt16 ULID::randomHigh() const
|
||||
{
|
||||
return _randomHi;
|
||||
}
|
||||
|
||||
|
||||
inline Poco::UInt64 ULID::randomLow() const
|
||||
{
|
||||
return _randomLo;
|
||||
}
|
||||
|
||||
|
||||
inline bool ULID::operator == (const ULID& ulid) const
|
||||
{
|
||||
return compare(ulid) == 0;
|
||||
}
|
||||
|
||||
|
||||
inline bool ULID::operator != (const ULID& ulid) const
|
||||
{
|
||||
return compare(ulid) != 0;
|
||||
}
|
||||
|
||||
|
||||
inline bool ULID::operator < (const ULID& ulid) const
|
||||
{
|
||||
return compare(ulid) < 0;
|
||||
}
|
||||
|
||||
|
||||
inline bool ULID::operator <= (const ULID& ulid) const
|
||||
{
|
||||
return compare(ulid) <= 0;
|
||||
}
|
||||
|
||||
|
||||
inline bool ULID::operator > (const ULID& ulid) const
|
||||
{
|
||||
return compare(ulid) > 0;
|
||||
}
|
||||
|
||||
|
||||
inline bool ULID::operator >= (const ULID& ulid) const
|
||||
{
|
||||
return compare(ulid) >= 0;
|
||||
}
|
||||
|
||||
|
||||
inline bool ULID::isNull() const
|
||||
{
|
||||
return compare(null()) == 0;
|
||||
}
|
||||
|
||||
|
||||
inline void swap(ULID& u1, ULID& u2) noexcept
|
||||
{
|
||||
u1.swap(u2);
|
||||
}
|
||||
|
||||
|
||||
} // namespace Poco
|
||||
|
||||
|
||||
#endif // Foundation_ULID_INCLUDED
|
||||
71
Foundation/include/Poco/ULIDGenerator.h
Normal file
71
Foundation/include/Poco/ULIDGenerator.h
Normal file
@@ -0,0 +1,71 @@
|
||||
//
|
||||
// ULIDGenerator.h
|
||||
//
|
||||
// Library: Foundation
|
||||
// Package: ULID
|
||||
// Module: ULID
|
||||
//
|
||||
// Definition of the ULIDGenerator class.
|
||||
//
|
||||
// Copyright (c) 2025, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef Foundation_ULIDGenerator_INCLUDED
|
||||
#define Foundation_ULIDGenerator_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/Foundation.h"
|
||||
#include "Poco/ULID.h"
|
||||
#include "Poco/Mutex.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
|
||||
|
||||
class Foundation_API ULIDGenerator
|
||||
/// This class implements a generator for
|
||||
/// [Universally Unique Lexicographically Sortable Identifier](https://github.com/ulid/spec) (ULID)s.
|
||||
{
|
||||
public:
|
||||
ULIDGenerator();
|
||||
/// Creates the ULIDGenerator.
|
||||
|
||||
~ULIDGenerator();
|
||||
/// Destroys the ULIDGenerator.
|
||||
|
||||
ULID create();
|
||||
/// Creates a new ULID based on the current time.
|
||||
///
|
||||
/// NOTE: In the very rare case that the random part of the ULID overflows due to too many
|
||||
/// subsequent calls to create() in the same millisecond, create() will wait for the
|
||||
/// current millisecond to elapse before generating a new ULID.
|
||||
|
||||
ULID create(UInt64 time);
|
||||
/// Creates a new ULID based on the given time (milliseconds
|
||||
/// since UNIX epoch).
|
||||
///
|
||||
/// NOTE: In the very rare case of an overflow of the random part due to too many subsequent
|
||||
/// calls to create() with the same time, throws a RuntimeException.
|
||||
|
||||
static ULIDGenerator& defaultGenerator();
|
||||
/// Returns a reference to the default ULIDGenerator.
|
||||
|
||||
private:
|
||||
FastMutex _mutex;
|
||||
Poco::UInt64 _lastTime = 0;
|
||||
Poco::UInt16 _lastRandomHi = 0;
|
||||
Poco::UInt64 _lastRandomLo = 0;
|
||||
|
||||
ULIDGenerator(const ULIDGenerator&);
|
||||
ULIDGenerator& operator = (const ULIDGenerator&);
|
||||
};
|
||||
|
||||
|
||||
} // namespace Poco
|
||||
|
||||
|
||||
#endif // Foundation_ULIDGenerator_INCLUDED
|
||||
@@ -42,6 +42,8 @@ class Foundation_API UUID
|
||||
/// and also http://tools.ietf.org/html/draft-mealling-uuid-urn-05
|
||||
///
|
||||
/// Version 6 and 7 UUIDs are based on RFC 9562.
|
||||
///
|
||||
/// To generate a UUID, see UUIDGenerator.
|
||||
{
|
||||
public:
|
||||
enum Version
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
// Package: Streams
|
||||
// Module: Base32
|
||||
//
|
||||
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
|
||||
// Copyright (c) 2004-2025, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
@@ -15,42 +15,129 @@
|
||||
#include "Poco/Base32Decoder.h"
|
||||
#include "Poco/Base32Encoder.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include "Poco/Mutex.h"
|
||||
#include <cstring>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
|
||||
|
||||
unsigned char Base32DecoderBuf::IN_ENCODING[256];
|
||||
bool Base32DecoderBuf::IN_ENCODING_INIT = false;
|
||||
|
||||
|
||||
namespace
|
||||
const unsigned char Base32DecoderBuf::REVERSE_DEFAULT_ENCODING[256] =
|
||||
{
|
||||
static FastMutex mutex;
|
||||
}
|
||||
/* 00 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 08 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 10 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 18 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 20 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 28 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 30 */ 0xFF, 0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
/* 38 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF,
|
||||
/* 40 */ 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
|
||||
/* 48 */ 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
|
||||
/* 50 */ 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
|
||||
/* 58 */ 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 60 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 68 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 70 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 78 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 80 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 88 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 90 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 98 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* A0 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* A8 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* B0 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* B8 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* C0 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* C8 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* D0 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* D8 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* E0 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* E8 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* F0 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* F8 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
|
||||
};
|
||||
|
||||
|
||||
Base32DecoderBuf::Base32DecoderBuf(std::istream& istr):
|
||||
const unsigned char Base32DecoderBuf::REVERSE_HEX_ENCODING[256] =
|
||||
{
|
||||
/* 00 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 08 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 10 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 18 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 20 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 28 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 30 */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
/* 38 */ 0x08, 0x09, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF,
|
||||
/* 40 */ 0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
|
||||
/* 48 */ 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
|
||||
/* 50 */ 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0xFF,
|
||||
/* 58 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 60 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 68 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 70 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 78 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 80 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 88 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 90 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 98 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* A0 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* A8 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* B0 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* B8 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* C0 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* C8 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* D0 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* D8 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* E0 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* E8 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* F0 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* F8 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
|
||||
};
|
||||
|
||||
|
||||
const unsigned char Base32DecoderBuf::REVERSE_CROCKFORD_ENCODING[256] =
|
||||
{
|
||||
/* 00 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 08 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 10 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 18 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 20 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 28 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 30 */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
/* 38 */ 0x08, 0x09, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF,
|
||||
/* 40 */ 0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
|
||||
/* 48 */ 0x11, 0x01, 0x12, 0x13, 0x01, 0x14, 0x15, 0x00,
|
||||
/* 50 */ 0x16, 0x17, 0x18, 0x19, 0x1A, 0xFF, 0x1B, 0x1C,
|
||||
/* 58 */ 0x1D, 0x1E, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 60 */ 0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
|
||||
/* 68 */ 0x11, 0x01, 0x12, 0x13, 0x01, 0x14, 0x15, 0x00,
|
||||
/* 70 */ 0x16, 0x17, 0x18, 0x19, 0x1A, 0xFF, 0x1B, 0x1C,
|
||||
/* 78 */ 0x1D, 0x1E, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 80 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 88 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 90 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 98 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* A0 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* A8 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* B0 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* B8 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* C0 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* C8 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* D0 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* D8 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* E0 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* E8 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* F0 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* F8 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
|
||||
};
|
||||
|
||||
|
||||
Base32DecoderBuf::Base32DecoderBuf(std::istream& istr, int options):
|
||||
_groupLength(0),
|
||||
_groupIndex(0),
|
||||
_buf(*istr.rdbuf())
|
||||
_buf(*istr.rdbuf()),
|
||||
_encoding(encoding(options))
|
||||
{
|
||||
FastMutex::ScopedLock lock(mutex);
|
||||
if (!IN_ENCODING_INIT)
|
||||
{
|
||||
for (unsigned i = 0; i < sizeof(IN_ENCODING); i++)
|
||||
{
|
||||
IN_ENCODING[i] = 0xFF;
|
||||
}
|
||||
for (unsigned i = 0; i < sizeof(Base32EncoderBuf::OUT_ENCODING); i++)
|
||||
{
|
||||
IN_ENCODING[Base32EncoderBuf::OUT_ENCODING[i]] = static_cast<UInt8>(i);
|
||||
}
|
||||
IN_ENCODING[static_cast<unsigned char>('=')] = '\0';
|
||||
IN_ENCODING_INIT = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -74,38 +161,40 @@ int Base32DecoderBuf::readFromDevice()
|
||||
// per RFC-4648, Section 6, permissible block lengths are:
|
||||
// 2, 4, 5, 7, and 8 bytes. Any other length is malformed.
|
||||
//
|
||||
do {
|
||||
do
|
||||
{
|
||||
if ((c = readOne()) == -1) return -1;
|
||||
buffer[0] = (unsigned char) c;
|
||||
if (IN_ENCODING[buffer[0]] == 0xFF) throw DataFormatException();
|
||||
if (_encoding[buffer[0]] == 0xFF) throw DataFormatException();
|
||||
if ((c = readOne()) == -1) throw DataFormatException();
|
||||
buffer[1] = (unsigned char) c;
|
||||
if (IN_ENCODING[buffer[1]] == 0xFF) throw DataFormatException();
|
||||
if (_encoding[buffer[1]] == 0xFF) throw DataFormatException();
|
||||
if ((c = readOne()) == -1) break;
|
||||
buffer[2] = (unsigned char) c;
|
||||
if (IN_ENCODING[buffer[2]] == 0xFF) throw DataFormatException();
|
||||
if (_encoding[buffer[2]] == 0xFF) throw DataFormatException();
|
||||
if ((c = readOne()) == -1) throw DataFormatException();
|
||||
buffer[3] = (unsigned char) c;
|
||||
if (IN_ENCODING[buffer[3]] == 0xFF) throw DataFormatException();
|
||||
if (_encoding[buffer[3]] == 0xFF) throw DataFormatException();
|
||||
if ((c = readOne()) == -1) break;
|
||||
buffer[4] = (unsigned char) c;
|
||||
if (IN_ENCODING[buffer[4]] == 0xFF) throw DataFormatException();
|
||||
if (_encoding[buffer[4]] == 0xFF) throw DataFormatException();
|
||||
if ((c = readOne()) == -1) break;
|
||||
buffer[5] = (unsigned char) c;
|
||||
if (IN_ENCODING[buffer[5]] == 0xFF) throw DataFormatException();
|
||||
if (_encoding[buffer[5]] == 0xFF) throw DataFormatException();
|
||||
if ((c = readOne()) == -1) throw DataFormatException();
|
||||
buffer[6] = (unsigned char) c;
|
||||
if (IN_ENCODING[buffer[6]] == 0xFF) throw DataFormatException();
|
||||
if (_encoding[buffer[6]] == 0xFF) throw DataFormatException();
|
||||
if ((c = readOne()) == -1) break;
|
||||
buffer[7] = (unsigned char) c;
|
||||
if (IN_ENCODING[buffer[7]] == 0xFF) throw DataFormatException();
|
||||
} while (false);
|
||||
if (_encoding[buffer[7]] == 0xFF) throw DataFormatException();
|
||||
}
|
||||
while (false);
|
||||
|
||||
_group[0] = (IN_ENCODING[buffer[0]] << 3) | (IN_ENCODING[buffer[1]] >> 2);
|
||||
_group[1] = ((IN_ENCODING[buffer[1]] & 0x03) << 6) | (IN_ENCODING[buffer[2]] << 1) | (IN_ENCODING[buffer[3]] >> 4);
|
||||
_group[2] = ((IN_ENCODING[buffer[3]] & 0x0F) << 4) | (IN_ENCODING[buffer[4]] >> 1);
|
||||
_group[3] = ((IN_ENCODING[buffer[4]] & 0x01) << 7) | (IN_ENCODING[buffer[5]] << 2) | (IN_ENCODING[buffer[6]] >> 3);
|
||||
_group[4] = ((IN_ENCODING[buffer[6]] & 0x07) << 5) | IN_ENCODING[buffer[7]];
|
||||
_group[0] = (_encoding[buffer[0]] << 3) | (_encoding[buffer[1]] >> 2);
|
||||
_group[1] = ((_encoding[buffer[1]] & 0x03) << 6) | (_encoding[buffer[2]] << 1) | (_encoding[buffer[3]] >> 4);
|
||||
_group[2] = ((_encoding[buffer[3]] & 0x0F) << 4) | (_encoding[buffer[4]] >> 1);
|
||||
_group[3] = ((_encoding[buffer[4]] & 0x01) << 7) | (_encoding[buffer[5]] << 2) | (_encoding[buffer[6]] >> 3);
|
||||
_group[4] = ((_encoding[buffer[6]] & 0x07) << 5) | _encoding[buffer[7]];
|
||||
|
||||
if (buffer[2] == '=')
|
||||
_groupLength = 1;
|
||||
@@ -130,7 +219,18 @@ int Base32DecoderBuf::readOne()
|
||||
}
|
||||
|
||||
|
||||
Base32DecoderIOS::Base32DecoderIOS(std::istream& istr): _buf(istr)
|
||||
const unsigned char* Base32DecoderBuf::encoding(int options)
|
||||
{
|
||||
if ((options & BASE32_USE_HEX_ALPHABET) != 0)
|
||||
return REVERSE_HEX_ENCODING;
|
||||
else if ((options & BASE32_USE_CROCKFORD_ALPHABET) != 0)
|
||||
return REVERSE_CROCKFORD_ENCODING;
|
||||
else
|
||||
return REVERSE_DEFAULT_ENCODING;
|
||||
}
|
||||
|
||||
|
||||
Base32DecoderIOS::Base32DecoderIOS(std::istream& istr, int options): _buf(istr, options)
|
||||
{
|
||||
poco_ios_init(&_buf);
|
||||
}
|
||||
@@ -147,7 +247,7 @@ Base32DecoderBuf* Base32DecoderIOS::rdbuf()
|
||||
}
|
||||
|
||||
|
||||
Base32Decoder::Base32Decoder(std::istream& istr): Base32DecoderIOS(istr), std::istream(&_buf)
|
||||
Base32Decoder::Base32Decoder(std::istream& istr, int options): Base32DecoderIOS(istr, options), std::istream(&_buf)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
// Package: Streams
|
||||
// Module: Base32
|
||||
//
|
||||
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
|
||||
// Copyright (c) 2004-2025, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
@@ -18,19 +18,38 @@
|
||||
namespace Poco {
|
||||
|
||||
|
||||
const unsigned char Base32EncoderBuf::OUT_ENCODING[32] =
|
||||
const unsigned char Base32EncoderBuf::DEFAULT_ENCODING[32] =
|
||||
{
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
|
||||
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
|
||||
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
|
||||
'Y', 'Z', '2', '3', '4', '5', '6', '7',
|
||||
'Y', 'Z', '2', '3', '4', '5', '6', '7'
|
||||
};
|
||||
|
||||
|
||||
Base32EncoderBuf::Base32EncoderBuf(std::ostream& ostr, bool padding):
|
||||
const unsigned char Base32EncoderBuf::HEX_ENCODING[32] =
|
||||
{
|
||||
'0', '1', '2', '3', '4', '5', '6', '7',
|
||||
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
|
||||
'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
|
||||
'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V'
|
||||
};
|
||||
|
||||
|
||||
const unsigned char Base32EncoderBuf::CROCKFORD_ENCODING[32] =
|
||||
{
|
||||
'0', '1', '2', '3', '4', '5', '6', '7',
|
||||
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
|
||||
'G', 'H', 'J', 'K', 'M', 'N', 'P', 'Q',
|
||||
'R', 'S', 'T', 'V', 'W', 'X', 'Y', 'Z'
|
||||
};
|
||||
|
||||
|
||||
Base32EncoderBuf::Base32EncoderBuf(std::ostream& ostr, int options):
|
||||
_groupLength(0),
|
||||
_buf(*ostr.rdbuf()),
|
||||
_doPadding(padding)
|
||||
_doPadding((options & BASE32_USE_PADDING) != 0),
|
||||
_encoding(encoding(options))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -47,7 +66,6 @@ Base32EncoderBuf::~Base32EncoderBuf()
|
||||
}
|
||||
|
||||
|
||||
|
||||
int Base32EncoderBuf::writeToDevice(char c)
|
||||
{
|
||||
static const int eof = std::char_traits<char>::eof();
|
||||
@@ -57,21 +75,21 @@ int Base32EncoderBuf::writeToDevice(char c)
|
||||
{
|
||||
unsigned char idx;
|
||||
idx = _group[0] >> 3;
|
||||
if (_buf.sputc(OUT_ENCODING[idx]) == eof) return eof;
|
||||
if (_buf.sputc(_encoding[idx]) == eof) return eof;
|
||||
idx = ((_group[0] & 0x07) << 2) | (_group[1] >> 6);
|
||||
if (_buf.sputc(OUT_ENCODING[idx]) == eof) return eof;
|
||||
if (_buf.sputc(_encoding[idx]) == eof) return eof;
|
||||
idx = ((_group[1] & 0x3E) >> 1);
|
||||
if (_buf.sputc(OUT_ENCODING[idx]) == eof) return eof;
|
||||
if (_buf.sputc(_encoding[idx]) == eof) return eof;
|
||||
idx = ((_group[1] & 0x01) << 4) | (_group[2] >> 4);
|
||||
if (_buf.sputc(OUT_ENCODING[idx]) == eof) return eof;
|
||||
if (_buf.sputc(_encoding[idx]) == eof) return eof;
|
||||
idx = ((_group[2] & 0x0F) << 1) | (_group[3] >> 7);
|
||||
if (_buf.sputc(OUT_ENCODING[idx]) == eof) return eof;
|
||||
if (_buf.sputc(_encoding[idx]) == eof) return eof;
|
||||
idx = ((_group[3] & 0x7C) >> 2);
|
||||
if (_buf.sputc(OUT_ENCODING[idx]) == eof) return eof;
|
||||
if (_buf.sputc(_encoding[idx]) == eof) return eof;
|
||||
idx = ((_group[3] & 0x03) << 3) | (_group[4] >> 5);
|
||||
if (_buf.sputc(OUT_ENCODING[idx]) == eof) return eof;
|
||||
if (_buf.sputc(_encoding[idx]) == eof) return eof;
|
||||
idx = (_group[4] & 0x1F);
|
||||
if (_buf.sputc(OUT_ENCODING[idx]) == eof) return eof;
|
||||
if (_buf.sputc(_encoding[idx]) == eof) return eof;
|
||||
_groupLength = 0;
|
||||
}
|
||||
return charToInt(c);
|
||||
@@ -88,10 +106,11 @@ int Base32EncoderBuf::close()
|
||||
_group[1] = 0;
|
||||
unsigned char idx;
|
||||
idx = _group[0] >> 3;
|
||||
if (_buf.sputc(OUT_ENCODING[idx]) == eof) return eof;
|
||||
if (_buf.sputc(_encoding[idx]) == eof) return eof;
|
||||
idx = ((_group[0] & 0x07) << 2);
|
||||
if (_buf.sputc(OUT_ENCODING[idx]) == eof) return eof;
|
||||
if (_doPadding) {
|
||||
if (_buf.sputc(_encoding[idx]) == eof) return eof;
|
||||
if (_doPadding)
|
||||
{
|
||||
if (_buf.sputc('=') == eof) return eof;
|
||||
if (_buf.sputc('=') == eof) return eof;
|
||||
if (_buf.sputc('=') == eof) return eof;
|
||||
@@ -105,14 +124,15 @@ int Base32EncoderBuf::close()
|
||||
_group[2] = 0;
|
||||
unsigned char idx;
|
||||
idx = _group[0] >> 3;
|
||||
if (_buf.sputc(OUT_ENCODING[idx]) == eof) return eof;
|
||||
if (_buf.sputc(_encoding[idx]) == eof) return eof;
|
||||
idx = ((_group[0] & 0x07) << 2) | (_group[1] >> 6);
|
||||
if (_buf.sputc(OUT_ENCODING[idx]) == eof) return eof;
|
||||
if (_buf.sputc(_encoding[idx]) == eof) return eof;
|
||||
idx = ((_group[1] & 0x3E) >> 1);
|
||||
if (_buf.sputc(OUT_ENCODING[idx]) == eof) return eof;
|
||||
if (_buf.sputc(_encoding[idx]) == eof) return eof;
|
||||
idx = ((_group[1] & 0x01) << 4);
|
||||
if (_buf.sputc(OUT_ENCODING[idx]) == eof) return eof;
|
||||
if (_doPadding) {
|
||||
if (_buf.sputc(_encoding[idx]) == eof) return eof;
|
||||
if (_doPadding)
|
||||
{
|
||||
if (_buf.sputc('=') == eof) return eof;
|
||||
if (_buf.sputc('=') == eof) return eof;
|
||||
if (_buf.sputc('=') == eof) return eof;
|
||||
@@ -124,16 +144,17 @@ int Base32EncoderBuf::close()
|
||||
_group[3] = 0;
|
||||
unsigned char idx;
|
||||
idx = _group[0] >> 3;
|
||||
if (_buf.sputc(OUT_ENCODING[idx]) == eof) return eof;
|
||||
if (_buf.sputc(_encoding[idx]) == eof) return eof;
|
||||
idx = ((_group[0] & 0x07) << 2) | (_group[1] >> 6);
|
||||
if (_buf.sputc(OUT_ENCODING[idx]) == eof) return eof;
|
||||
if (_buf.sputc(_encoding[idx]) == eof) return eof;
|
||||
idx = ((_group[1] & 0x3E) >> 1);
|
||||
if (_buf.sputc(OUT_ENCODING[idx]) == eof) return eof;
|
||||
if (_buf.sputc(_encoding[idx]) == eof) return eof;
|
||||
idx = ((_group[1] & 0x01) << 4) | (_group[2] >> 4);
|
||||
if (_buf.sputc(OUT_ENCODING[idx]) == eof) return eof;
|
||||
if (_buf.sputc(_encoding[idx]) == eof) return eof;
|
||||
idx = ((_group[2] & 0x0F) << 1);
|
||||
if (_buf.sputc(OUT_ENCODING[idx]) == eof) return eof;
|
||||
if (_doPadding) {
|
||||
if (_buf.sputc(_encoding[idx]) == eof) return eof;
|
||||
if (_doPadding)
|
||||
{
|
||||
if (_buf.sputc('=') == eof) return eof;
|
||||
if (_buf.sputc('=') == eof) return eof;
|
||||
if (_buf.sputc('=') == eof) return eof;
|
||||
@@ -144,19 +165,19 @@ int Base32EncoderBuf::close()
|
||||
_group[4] = 0;
|
||||
unsigned char idx;
|
||||
idx = _group[0] >> 3;
|
||||
if (_buf.sputc(OUT_ENCODING[idx]) == eof) return eof;
|
||||
if (_buf.sputc(_encoding[idx]) == eof) return eof;
|
||||
idx = ((_group[0] & 0x07) << 2) | (_group[1] >> 6);
|
||||
if (_buf.sputc(OUT_ENCODING[idx]) == eof) return eof;
|
||||
if (_buf.sputc(_encoding[idx]) == eof) return eof;
|
||||
idx = ((_group[1] & 0x3E) >> 1);
|
||||
if (_buf.sputc(OUT_ENCODING[idx]) == eof) return eof;
|
||||
if (_buf.sputc(_encoding[idx]) == eof) return eof;
|
||||
idx = ((_group[1] & 0x01) << 4) | (_group[2] >> 4);
|
||||
if (_buf.sputc(OUT_ENCODING[idx]) == eof) return eof;
|
||||
if (_buf.sputc(_encoding[idx]) == eof) return eof;
|
||||
idx = ((_group[2] & 0x0F) << 1) | (_group[3] >> 7);
|
||||
if (_buf.sputc(OUT_ENCODING[idx]) == eof) return eof;
|
||||
if (_buf.sputc(_encoding[idx]) == eof) return eof;
|
||||
idx = ((_group[3] & 0x7C) >> 2);
|
||||
if (_buf.sputc(OUT_ENCODING[idx]) == eof) return eof;
|
||||
if (_buf.sputc(_encoding[idx]) == eof) return eof;
|
||||
idx = ((_group[3] & 0x03) << 3);
|
||||
if (_buf.sputc(OUT_ENCODING[idx]) == eof) return eof;
|
||||
if (_buf.sputc(_encoding[idx]) == eof) return eof;
|
||||
if (_doPadding && _buf.sputc('=') == eof) return eof;
|
||||
}
|
||||
_groupLength = 0;
|
||||
@@ -164,8 +185,19 @@ int Base32EncoderBuf::close()
|
||||
}
|
||||
|
||||
|
||||
Base32EncoderIOS::Base32EncoderIOS(std::ostream& ostr, bool padding):
|
||||
_buf(ostr, padding)
|
||||
const unsigned char* Base32EncoderBuf::encoding(int options)
|
||||
{
|
||||
if ((options & BASE32_USE_HEX_ALPHABET) != 0)
|
||||
return HEX_ENCODING;
|
||||
else if ((options & BASE32_USE_CROCKFORD_ALPHABET) != 0)
|
||||
return CROCKFORD_ENCODING;
|
||||
else
|
||||
return DEFAULT_ENCODING;
|
||||
}
|
||||
|
||||
|
||||
Base32EncoderIOS::Base32EncoderIOS(std::ostream& ostr, int options):
|
||||
_buf(ostr, options)
|
||||
{
|
||||
poco_ios_init(&_buf);
|
||||
}
|
||||
@@ -188,8 +220,8 @@ Base32EncoderBuf* Base32EncoderIOS::rdbuf()
|
||||
}
|
||||
|
||||
|
||||
Base32Encoder::Base32Encoder(std::ostream& ostr, bool padding):
|
||||
Base32EncoderIOS(ostr, padding), std::ostream(&_buf)
|
||||
Base32Encoder::Base32Encoder(std::ostream& ostr, int options):
|
||||
Base32EncoderIOS(ostr, options), std::ostream(&_buf)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
275
Foundation/src/ULID.cpp
Normal file
275
Foundation/src/ULID.cpp
Normal file
@@ -0,0 +1,275 @@
|
||||
//
|
||||
// ULID.cpp
|
||||
//
|
||||
// Library: Foundation
|
||||
// Package: ULID
|
||||
// Module: ULID
|
||||
//
|
||||
// Copyright (c) 2025, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/ULID.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include "Poco/ByteOrder.h"
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
template <typename T>
|
||||
int cmp(T a, T b)
|
||||
{
|
||||
if (a == b)
|
||||
return 0;
|
||||
else if (a < b)
|
||||
return -1;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const char ULID::ENCODING[32] =
|
||||
{
|
||||
'0', '1', '2', '3', '4', '5', '6', '7',
|
||||
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
|
||||
'G', 'H', 'J', 'K', 'M', 'N', 'P', 'Q',
|
||||
'R', 'S', 'T', 'V', 'W', 'X', 'Y', 'Z'
|
||||
};
|
||||
|
||||
|
||||
const UInt8 ULID::REVERSE_ENCODING[256] =
|
||||
{
|
||||
/* 00 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 08 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 10 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 18 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 20 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 28 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 30 */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
/* 38 */ 0x08, 0x09, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF,
|
||||
/* 40 */ 0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
|
||||
/* 48 */ 0x11, 0x01, 0x12, 0x13, 0x01, 0x14, 0x15, 0x00,
|
||||
/* 50 */ 0x16, 0x17, 0x18, 0x19, 0x1A, 0xFF, 0x1B, 0x1C,
|
||||
/* 58 */ 0x1D, 0x1E, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 60 */ 0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
|
||||
/* 68 */ 0x11, 0x01, 0x12, 0x13, 0x01, 0x14, 0x15, 0x00,
|
||||
/* 70 */ 0x16, 0x17, 0x18, 0x19, 0x1A, 0xFF, 0x1B, 0x1C,
|
||||
/* 78 */ 0x1D, 0x1E, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 80 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 88 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 90 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* 98 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* A0 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* A8 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* B0 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* B8 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* C0 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* C8 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* D0 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* D8 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* E0 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* E8 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* F0 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* F8 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
|
||||
};
|
||||
|
||||
|
||||
ULID::ULID(const std::string& ulid)
|
||||
{
|
||||
parse(ulid);
|
||||
}
|
||||
|
||||
|
||||
ULID::ULID(const char* ulid)
|
||||
{
|
||||
poco_check_ptr(ulid);
|
||||
parse(std::string(ulid));
|
||||
}
|
||||
|
||||
|
||||
ULID::ULID(UInt64 time, UInt16 randomHi, UInt64 randomLo):
|
||||
_timeHi(static_cast<UInt32>(time >> 16)),
|
||||
_timeLo(static_cast<UInt16>(time & 0xFFFF)),
|
||||
_randomHi(randomHi),
|
||||
_randomLo(randomLo)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ULID& ULID::operator = (const ULID& ulid)
|
||||
{
|
||||
if (&ulid != this)
|
||||
{
|
||||
_timeHi = ulid._timeHi;
|
||||
_timeLo = ulid._timeLo;
|
||||
_randomHi = ulid._randomHi;
|
||||
_randomLo = ulid._randomLo;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void ULID::swap(ULID& ulid) noexcept
|
||||
{
|
||||
std::swap(_timeHi, ulid._timeHi);
|
||||
std::swap(_timeLo, ulid._timeLo);
|
||||
std::swap(_randomHi, ulid._randomHi);
|
||||
std::swap(_randomLo, ulid._randomLo);
|
||||
}
|
||||
|
||||
|
||||
void ULID::parse(const std::string& ulid)
|
||||
{
|
||||
if (!tryParse(ulid))
|
||||
throw SyntaxException(ulid);
|
||||
}
|
||||
|
||||
|
||||
bool ULID::tryParse(const std::string& ulid)
|
||||
{
|
||||
if (ulid.size() != 26) return false;
|
||||
if (ulid[0] > '7' && !(ulid[0] == 'l' || ulid[0] == 'L' || ulid[0] == 'i' || ulid[0] == 'I' || ulid[0] == 'o' || ulid[0] == 'O')) return false;
|
||||
|
||||
for (auto c: ulid)
|
||||
{
|
||||
if (REVERSE_ENCODING[static_cast<unsigned char>(c)] == 0xFF) return false;
|
||||
}
|
||||
|
||||
_timeHi = (decode<UInt32>(ulid[0]) << 29)
|
||||
| (decode<UInt32>(ulid[1]) << 24)
|
||||
| (decode<UInt32>(ulid[2]) << 19)
|
||||
| (decode<UInt32>(ulid[3]) << 14)
|
||||
| (decode<UInt32>(ulid[4]) << 9)
|
||||
| (decode<UInt32>(ulid[5]) << 4)
|
||||
| (decode<UInt32>(ulid[6]) >> 1);
|
||||
|
||||
_timeLo = ((decode<UInt16>(ulid[6]) & 1) << 15)
|
||||
| (decode<UInt16>(ulid[7]) << 10)
|
||||
| (decode<UInt16>(ulid[8]) << 5)
|
||||
| decode<UInt16>(ulid[9]);
|
||||
|
||||
_randomHi = (decode<UInt16>(ulid[10]) << 11)
|
||||
| (decode<UInt16>(ulid[11]) << 6)
|
||||
| (decode<UInt16>(ulid[12]) << 1)
|
||||
| (decode<UInt16>(ulid[13]) >> 4);
|
||||
|
||||
_randomLo = ((decode<UInt64>(ulid[13]) & 0xF) << 60)
|
||||
| (decode<UInt64>(ulid[14]) << 55)
|
||||
| (decode<UInt64>(ulid[15]) << 50)
|
||||
| (decode<UInt64>(ulid[16]) << 45)
|
||||
| (decode<UInt64>(ulid[17]) << 40)
|
||||
| (decode<UInt64>(ulid[18]) << 35)
|
||||
| (decode<UInt64>(ulid[19]) << 30)
|
||||
| (decode<UInt64>(ulid[20]) << 25)
|
||||
| (decode<UInt64>(ulid[21]) << 20)
|
||||
| (decode<UInt64>(ulid[22]) << 15)
|
||||
| (decode<UInt64>(ulid[23]) << 10)
|
||||
| (decode<UInt64>(ulid[24]) << 5)
|
||||
| decode<UInt64>(ulid[25]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
std::string ULID::toString() const
|
||||
{
|
||||
std::string result(26, 0);
|
||||
|
||||
result[0] = ENCODING[_timeHi >> 29];
|
||||
result[1] = ENCODING[_timeHi >> 24 & 0x1F];
|
||||
result[2] = ENCODING[_timeHi >> 19 & 0x1F];
|
||||
result[3] = ENCODING[_timeHi >> 14 & 0x1F];
|
||||
result[4] = ENCODING[_timeHi >> 9 & 0x1F];
|
||||
result[5] = ENCODING[_timeHi >> 4 & 0x1F];
|
||||
result[6] = ENCODING[((_timeHi & 0x0F) << 1) + (_timeLo >> 15)];
|
||||
result[7] = ENCODING[_timeLo >> 10 & 0x1F];
|
||||
result[8] = ENCODING[_timeLo >> 5 & 0x1F];
|
||||
result[9] = ENCODING[_timeLo & 0x1F];
|
||||
|
||||
result[10] = ENCODING[_randomHi >> 11 & 0x1F];
|
||||
result[11] = ENCODING[_randomHi >> 6 & 0x1F];
|
||||
result[12] = ENCODING[_randomHi >> 1 & 0x1F];
|
||||
result[13] = ENCODING[((_randomHi & 0x01) << 4) + (_randomLo >> 60)];
|
||||
result[14] = ENCODING[_randomLo >> 55 & 0x1F];
|
||||
result[15] = ENCODING[_randomLo >> 50 & 0x1F];
|
||||
result[16] = ENCODING[_randomLo >> 45 & 0x1F];
|
||||
result[17] = ENCODING[_randomLo >> 40 & 0x1F];
|
||||
result[18] = ENCODING[_randomLo >> 35 & 0x1F];
|
||||
result[19] = ENCODING[_randomLo >> 30 & 0x1F];
|
||||
result[20] = ENCODING[_randomLo >> 25 & 0x1F];
|
||||
result[21] = ENCODING[_randomLo >> 20 & 0x1F];
|
||||
result[22] = ENCODING[_randomLo >> 15 & 0x1F];
|
||||
result[23] = ENCODING[_randomLo >> 10 & 0x1F];
|
||||
result[24] = ENCODING[_randomLo >> 5 & 0x1F];
|
||||
result[25] = ENCODING[_randomLo & 0x1F];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void ULID::copyFrom(const char* buffer)
|
||||
{
|
||||
Poco::UInt32 timeHi;
|
||||
std::memcpy(&timeHi, buffer, 4);
|
||||
_timeHi = Poco::ByteOrder::fromNetwork(timeHi);
|
||||
Poco::UInt16 timeLo;
|
||||
std::memcpy(&timeLo, buffer + 4, 2);
|
||||
_timeLo = Poco::ByteOrder::fromNetwork(timeLo);
|
||||
Poco::UInt16 randomHi;
|
||||
std::memcpy(&randomHi, buffer + 6, 2);
|
||||
_randomHi = Poco::ByteOrder::fromNetwork(randomHi);
|
||||
Poco::UInt64 randomLo;
|
||||
std::memcpy(&randomLo, buffer + 8, 8);
|
||||
_randomLo = Poco::ByteOrder::fromNetwork(randomLo);
|
||||
}
|
||||
|
||||
|
||||
void ULID::copyTo(char* buffer) const
|
||||
{
|
||||
Poco::UInt32 timeHi = Poco::ByteOrder::toNetwork(_timeHi);
|
||||
std::memcpy(buffer, &timeHi, 4);
|
||||
Poco::UInt16 timeLo = Poco::ByteOrder::toNetwork(_timeLo);
|
||||
std::memcpy(buffer + 4, &timeLo, 2);
|
||||
Poco::UInt16 randomHi = Poco::ByteOrder::toNetwork(_randomHi);
|
||||
std::memcpy(buffer + 6, &randomHi, 2);
|
||||
Poco::UInt64 randomLo = Poco::ByteOrder::toNetwork(_randomLo);
|
||||
std::memcpy(buffer + 8, &randomLo, 8);
|
||||
}
|
||||
|
||||
|
||||
const ULID& ULID::null()
|
||||
{
|
||||
static const ULID nil;
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
int ULID::compare(const ULID& ulid) const
|
||||
{
|
||||
int c = cmp(_timeHi, ulid._timeHi);
|
||||
if (c == 0)
|
||||
{
|
||||
c = cmp(_timeLo, ulid._timeLo);
|
||||
if (c == 0)
|
||||
{
|
||||
c = cmp(_randomHi, ulid._randomHi);
|
||||
if (c == 0)
|
||||
{
|
||||
c = cmp(_randomLo, ulid._randomLo);
|
||||
}
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
} // namespace Poco
|
||||
116
Foundation/src/ULIDGenerator.cpp
Normal file
116
Foundation/src/ULIDGenerator.cpp
Normal file
@@ -0,0 +1,116 @@
|
||||
//
|
||||
// ULIDGenerator.cpp
|
||||
//
|
||||
// Library: Foundation
|
||||
// Package: ULID
|
||||
// Module: ULID
|
||||
//
|
||||
// Copyright (c) 2025, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/ULIDGenerator.h"
|
||||
#include "Poco/RandomStream.h"
|
||||
#include "Poco/BinaryReader.h"
|
||||
#include "Poco/Exception.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
|
||||
|
||||
ULIDGenerator::ULIDGenerator()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ULIDGenerator::~ULIDGenerator()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ULID ULIDGenerator::create()
|
||||
{
|
||||
Poco::Timestamp now;
|
||||
Poco::UInt64 time = now.epochMicroseconds()/1000;
|
||||
Poco::UInt16 lastRandomHi;
|
||||
Poco::UInt64 lastRandomLo;
|
||||
|
||||
{
|
||||
Poco::FastMutex::ScopedLock lock(_mutex);
|
||||
while (true)
|
||||
{
|
||||
if (time == _lastTime)
|
||||
{
|
||||
if (++_lastRandomLo == 0)
|
||||
{
|
||||
if (++_lastRandomHi == 0)
|
||||
{
|
||||
// random overflow, wait until next millisecond
|
||||
Poco::UInt64 ntime = time;
|
||||
while (ntime == time)
|
||||
{
|
||||
now.update();
|
||||
ntime = now.epochMicroseconds()/1000;
|
||||
}
|
||||
time = ntime;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_lastTime = time;
|
||||
Poco::RandomInputStream random;
|
||||
Poco::BinaryReader reader(random, Poco::BinaryReader::NETWORK_BYTE_ORDER);
|
||||
reader >> _lastRandomHi >> _lastRandomLo;
|
||||
}
|
||||
lastRandomHi = _lastRandomHi;
|
||||
lastRandomLo = _lastRandomLo;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ULID(time, lastRandomHi, lastRandomLo);
|
||||
}
|
||||
|
||||
|
||||
ULID ULIDGenerator::create(UInt64 time)
|
||||
{
|
||||
Poco::UInt16 lastRandomHi;
|
||||
Poco::UInt64 lastRandomLo;
|
||||
|
||||
{
|
||||
Poco::FastMutex::ScopedLock lock(_mutex);
|
||||
if (time == _lastTime)
|
||||
{
|
||||
if (++_lastRandomLo == 0)
|
||||
{
|
||||
if (++_lastRandomHi == 0) throw RuntimeException("Too many ULIDs created in a single millisecond");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_lastTime = time;
|
||||
Poco::RandomInputStream random;
|
||||
Poco::BinaryReader reader(random, Poco::BinaryReader::NETWORK_BYTE_ORDER);
|
||||
reader >> _lastRandomHi >> _lastRandomLo;
|
||||
}
|
||||
lastRandomHi = _lastRandomHi;
|
||||
lastRandomLo = _lastRandomLo;
|
||||
}
|
||||
|
||||
return ULID(time, lastRandomHi, lastRandomLo);
|
||||
}
|
||||
|
||||
|
||||
ULIDGenerator& ULIDGenerator::defaultGenerator()
|
||||
{
|
||||
static ULIDGenerator gen;
|
||||
return gen;
|
||||
}
|
||||
|
||||
|
||||
} // namespace Poco
|
||||
@@ -30,7 +30,8 @@ objects = ActiveMethodTest ActivityTest ActiveDispatcherTest \
|
||||
TextConverterTest TextIteratorTest TextBufferIteratorTest TextTestSuite TextEncodingTest \
|
||||
ThreadLocalTest ThreadPoolTest ActiveThreadPoolTest ThreadTest ThreadingTestSuite TimerTest \
|
||||
TimespanTest TimestampTest TimezoneTest URIStreamOpenerTest URITest \
|
||||
URITestSuite UUIDGeneratorTest UUIDTest UUIDTestSuite ZLibTest \
|
||||
URITestSuite UUIDGeneratorTest UUIDTest UUIDTestSuite \
|
||||
ULIDTest ULIDGeneratorTest ULIDTestSuite ZLibTest \
|
||||
TestPlugin DummyDelegate BasicEventTest FIFOEventTest PriorityEventTest EventTestSuite \
|
||||
LRUCacheTest ExpireCacheTest ExpireLRUCacheTest CacheTestSuite AnyTest FormatTest \
|
||||
HashingTestSuite HashTableTest SimpleHashTableTest LinearHashTableTest \
|
||||
|
||||
@@ -72,6 +72,125 @@ void Base32Test::testEncoder()
|
||||
}
|
||||
|
||||
|
||||
void Base32Test::testEncoderHex()
|
||||
{
|
||||
// RFC 4648 test vectors
|
||||
{
|
||||
std::ostringstream str;
|
||||
Base32Encoder encoder(str, Poco::BASE32_USE_HEX_ALPHABET | Poco::BASE32_USE_PADDING);
|
||||
encoder.close();
|
||||
assertTrue (str.str() == "");
|
||||
}
|
||||
|
||||
{
|
||||
std::ostringstream str;
|
||||
Base32Encoder encoder(str, Poco::BASE32_USE_HEX_ALPHABET | Poco::BASE32_USE_PADDING);
|
||||
encoder << "f";
|
||||
encoder.close();
|
||||
assertTrue (str.str() == "CO======");
|
||||
}
|
||||
|
||||
{
|
||||
std::ostringstream str;
|
||||
Base32Encoder encoder(str, Poco::BASE32_USE_HEX_ALPHABET | Poco::BASE32_USE_PADDING);
|
||||
encoder << "fo";
|
||||
encoder.close();
|
||||
assertTrue (str.str() == "CPNG====");
|
||||
}
|
||||
|
||||
{
|
||||
std::ostringstream str;
|
||||
Base32Encoder encoder(str, Poco::BASE32_USE_HEX_ALPHABET | Poco::BASE32_USE_PADDING);
|
||||
encoder << "foo";
|
||||
encoder.close();
|
||||
assertTrue (str.str() == "CPNMU===");
|
||||
}
|
||||
|
||||
{
|
||||
std::ostringstream str;
|
||||
Base32Encoder encoder(str, Poco::BASE32_USE_HEX_ALPHABET | Poco::BASE32_USE_PADDING);
|
||||
encoder << "foob";
|
||||
encoder.close();
|
||||
assertTrue (str.str() == "CPNMUOG=");
|
||||
}
|
||||
|
||||
{
|
||||
std::ostringstream str;
|
||||
Base32Encoder encoder(str, Poco::BASE32_USE_HEX_ALPHABET | Poco::BASE32_USE_PADDING);
|
||||
encoder << "fooba";
|
||||
encoder.close();
|
||||
assertTrue (str.str() == "CPNMUOJ1");
|
||||
}
|
||||
|
||||
{
|
||||
std::ostringstream str;
|
||||
Base32Encoder encoder(str, Poco::BASE32_USE_HEX_ALPHABET | Poco::BASE32_USE_PADDING);
|
||||
encoder << "foobar";
|
||||
encoder.close();
|
||||
assertTrue (str.str() == "CPNMUOJ1E8======");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Base32Test::testEncoderCrockford()
|
||||
{
|
||||
{
|
||||
std::ostringstream str;
|
||||
Base32Encoder encoder(str, Poco::BASE32_USE_CROCKFORD_ALPHABET);
|
||||
encoder.close();
|
||||
assertTrue (str.str() == "");
|
||||
}
|
||||
|
||||
{
|
||||
std::ostringstream str;
|
||||
Base32Encoder encoder(str, Poco::BASE32_USE_CROCKFORD_ALPHABET);
|
||||
encoder << "f";
|
||||
encoder.close();
|
||||
assertTrue (str.str() == "CR");
|
||||
}
|
||||
|
||||
{
|
||||
std::ostringstream str;
|
||||
Base32Encoder encoder(str, Poco::BASE32_USE_CROCKFORD_ALPHABET);
|
||||
encoder << "fo";
|
||||
encoder.close();
|
||||
assertTrue (str.str() == "CSQG");
|
||||
}
|
||||
|
||||
{
|
||||
std::ostringstream str;
|
||||
Base32Encoder encoder(str, Poco::BASE32_USE_CROCKFORD_ALPHABET);
|
||||
encoder << "foo";
|
||||
encoder.close();
|
||||
assertTrue (str.str() == "CSQPY");
|
||||
}
|
||||
|
||||
{
|
||||
std::ostringstream str;
|
||||
Base32Encoder encoder(str, Poco::BASE32_USE_CROCKFORD_ALPHABET);
|
||||
encoder << "foob";
|
||||
encoder.close();
|
||||
assertTrue (str.str() == "CSQPYRG");
|
||||
}
|
||||
|
||||
{
|
||||
std::ostringstream str;
|
||||
Base32Encoder encoder(str, Poco::BASE32_USE_CROCKFORD_ALPHABET);
|
||||
encoder << "fooba";
|
||||
encoder.close();
|
||||
assertTrue (str.str() == "CSQPYRK1");
|
||||
}
|
||||
|
||||
{
|
||||
std::ostringstream str;
|
||||
Base32Encoder encoder(str, Poco::BASE32_USE_CROCKFORD_ALPHABET);
|
||||
encoder << "foobar";
|
||||
encoder.close();
|
||||
assertTrue (str.str() == "CSQPYRK1E8");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Base32Test::testDecoder()
|
||||
{
|
||||
{
|
||||
@@ -130,6 +249,108 @@ void Base32Test::testDecoder()
|
||||
}
|
||||
|
||||
|
||||
void Base32Test::testDecoderHex()
|
||||
{
|
||||
{
|
||||
std::istringstream istr("CO======");
|
||||
Base32Decoder decoder(istr, Poco::BASE32_USE_HEX_ALPHABET);
|
||||
std::string s;
|
||||
decoder >> s;
|
||||
assertTrue (s == "f");
|
||||
}
|
||||
{
|
||||
std::istringstream istr("CPNG====");
|
||||
Base32Decoder decoder(istr, Poco::BASE32_USE_HEX_ALPHABET);
|
||||
std::string s;
|
||||
decoder >> s;
|
||||
assertTrue (s == "fo");
|
||||
}
|
||||
{
|
||||
std::istringstream istr("CPNMU===");
|
||||
Base32Decoder decoder(istr, Poco::BASE32_USE_HEX_ALPHABET);
|
||||
std::string s;
|
||||
decoder >> s;
|
||||
assertTrue (s == "foo");
|
||||
}
|
||||
{
|
||||
std::istringstream istr("CPNMUOG=");
|
||||
Base32Decoder decoder(istr, Poco::BASE32_USE_HEX_ALPHABET);
|
||||
std::string s;
|
||||
decoder >> s;
|
||||
assertTrue (s == "foob");
|
||||
}
|
||||
{
|
||||
std::istringstream istr("CPNMUOJ1");
|
||||
Base32Decoder decoder(istr, Poco::BASE32_USE_HEX_ALPHABET);
|
||||
std::string s;
|
||||
decoder >> s;
|
||||
assertTrue (s == "fooba");
|
||||
}
|
||||
{
|
||||
std::istringstream istr("CPNMUOJ1E8======");
|
||||
Base32Decoder decoder(istr, Poco::BASE32_USE_HEX_ALPHABET);
|
||||
std::string s;
|
||||
decoder >> s;
|
||||
assertTrue (s == "foobar");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Base32Test::testDecoderCrockford()
|
||||
{
|
||||
{
|
||||
std::istringstream istr("CR");
|
||||
Base32Decoder decoder(istr, Poco::BASE32_USE_CROCKFORD_ALPHABET);
|
||||
std::string s;
|
||||
decoder >> s;
|
||||
assertTrue (s == "f");
|
||||
}
|
||||
{
|
||||
std::istringstream istr("CSQG");
|
||||
Base32Decoder decoder(istr, Poco::BASE32_USE_CROCKFORD_ALPHABET);
|
||||
std::string s;
|
||||
decoder >> s;
|
||||
assertTrue (s == "fo");
|
||||
}
|
||||
{
|
||||
std::istringstream istr("CSQPY");
|
||||
Base32Decoder decoder(istr, Poco::BASE32_USE_CROCKFORD_ALPHABET);
|
||||
std::string s;
|
||||
decoder >> s;
|
||||
assertTrue (s == "foo");
|
||||
}
|
||||
{
|
||||
std::istringstream istr("CSQPYRG");
|
||||
Base32Decoder decoder(istr, Poco::BASE32_USE_CROCKFORD_ALPHABET);
|
||||
std::string s;
|
||||
decoder >> s;
|
||||
assertTrue (s == "foob");
|
||||
}
|
||||
{
|
||||
std::istringstream istr("CSQPYRK1");
|
||||
Base32Decoder decoder(istr, Poco::BASE32_USE_CROCKFORD_ALPHABET);
|
||||
std::string s;
|
||||
decoder >> s;
|
||||
assertTrue (s == "fooba");
|
||||
}
|
||||
{
|
||||
std::istringstream istr("CSQPYRK1E8");
|
||||
Base32Decoder decoder(istr, Poco::BASE32_USE_CROCKFORD_ALPHABET);
|
||||
std::string s;
|
||||
decoder >> s;
|
||||
assertTrue (s == "foobar");
|
||||
}
|
||||
{
|
||||
// alternative decode symbols (lowercase, 1/l)
|
||||
std::istringstream istr("csqpyrkle8");
|
||||
Base32Decoder decoder(istr, Poco::BASE32_USE_CROCKFORD_ALPHABET);
|
||||
std::string s;
|
||||
decoder >> s;
|
||||
assertTrue (s == "foobar");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Base32Test::testEncodeDecode()
|
||||
{
|
||||
{
|
||||
@@ -160,6 +381,66 @@ void Base32Test::testEncodeDecode()
|
||||
}
|
||||
|
||||
|
||||
void Base32Test::testEncodeDecodeHex()
|
||||
{
|
||||
{
|
||||
std::stringstream str;
|
||||
Base32Encoder encoder(str, Poco::BASE32_USE_HEX_ALPHABET);
|
||||
encoder << "The quick brown fox ";
|
||||
encoder << "jumped over the lazy dog.";
|
||||
encoder.close();
|
||||
Base32Decoder decoder(str, Poco::BASE32_USE_HEX_ALPHABET);
|
||||
std::string s;
|
||||
int c = decoder.get();
|
||||
while (c != -1) { s += char(c); c = decoder.get(); }
|
||||
assertTrue (s == "The quick brown fox jumped over the lazy dog.");
|
||||
}
|
||||
{
|
||||
std::string src;
|
||||
for (int i = 0; i < 255; ++i) src += char(i);
|
||||
std::stringstream str;
|
||||
Base32Encoder encoder(str, Poco::BASE32_USE_HEX_ALPHABET);
|
||||
encoder.write(src.data(), (std::streamsize) src.size());
|
||||
encoder.close();
|
||||
Base32Decoder decoder(str, Poco::BASE32_USE_HEX_ALPHABET);
|
||||
std::string s;
|
||||
int c = decoder.get();
|
||||
while (c != -1) { s += char(c); c = decoder.get(); }
|
||||
assertTrue (s == src);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Base32Test::testEncodeDecodeCrockford()
|
||||
{
|
||||
{
|
||||
std::stringstream str;
|
||||
Base32Encoder encoder(str, Poco::BASE32_USE_CROCKFORD_ALPHABET);
|
||||
encoder << "The quick brown fox ";
|
||||
encoder << "jumped over the lazy dog.";
|
||||
encoder.close();
|
||||
Base32Decoder decoder(str, Poco::BASE32_USE_CROCKFORD_ALPHABET);
|
||||
std::string s;
|
||||
int c = decoder.get();
|
||||
while (c != -1) { s += char(c); c = decoder.get(); }
|
||||
assertTrue (s == "The quick brown fox jumped over the lazy dog.");
|
||||
}
|
||||
{
|
||||
std::string src;
|
||||
for (int i = 0; i < 255; ++i) src += char(i);
|
||||
std::stringstream str;
|
||||
Base32Encoder encoder(str, Poco::BASE32_USE_CROCKFORD_ALPHABET);
|
||||
encoder.write(src.data(), (std::streamsize) src.size());
|
||||
encoder.close();
|
||||
Base32Decoder decoder(str, Poco::BASE32_USE_CROCKFORD_ALPHABET);
|
||||
std::string s;
|
||||
int c = decoder.get();
|
||||
while (c != -1) { s += char(c); c = decoder.get(); }
|
||||
assertTrue (s == src);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Base32Test::setUp()
|
||||
{
|
||||
}
|
||||
@@ -175,8 +456,14 @@ CppUnit::Test* Base32Test::suite()
|
||||
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("Base32Test");
|
||||
|
||||
CppUnit_addTest(pSuite, Base32Test, testEncoder);
|
||||
CppUnit_addTest(pSuite, Base32Test, testEncoderHex);
|
||||
CppUnit_addTest(pSuite, Base32Test, testEncoderCrockford);
|
||||
CppUnit_addTest(pSuite, Base32Test, testDecoder);
|
||||
CppUnit_addTest(pSuite, Base32Test, testDecoderHex);
|
||||
CppUnit_addTest(pSuite, Base32Test, testDecoderCrockford);
|
||||
CppUnit_addTest(pSuite, Base32Test, testEncodeDecode);
|
||||
CppUnit_addTest(pSuite, Base32Test, testEncodeDecodeHex);
|
||||
CppUnit_addTest(pSuite, Base32Test, testEncodeDecodeCrockford);
|
||||
|
||||
return pSuite;
|
||||
}
|
||||
|
||||
@@ -25,8 +25,14 @@ public:
|
||||
~Base32Test();
|
||||
|
||||
void testEncoder();
|
||||
void testEncoderHex();
|
||||
void testEncoderCrockford();
|
||||
void testDecoder();
|
||||
void testDecoderHex();
|
||||
void testDecoderCrockford();
|
||||
void testEncodeDecode();
|
||||
void testEncodeDecodeHex();
|
||||
void testEncodeDecodeCrockford();
|
||||
|
||||
void setUp();
|
||||
void tearDown();
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "LoggingTestSuite.h"
|
||||
#include "FilesystemTestSuite.h"
|
||||
#include "UUIDTestSuite.h"
|
||||
#include "ULIDTestSuite.h"
|
||||
#include "TextTestSuite.h"
|
||||
#include "URITestSuite.h"
|
||||
#if !defined(POCO_VXWORKS)
|
||||
@@ -44,6 +45,7 @@ CppUnit::Test* FoundationTestSuite::suite()
|
||||
pSuite->addTest(LoggingTestSuite::suite());
|
||||
pSuite->addTest(FilesystemTestSuite::suite());
|
||||
pSuite->addTest(UUIDTestSuite::suite());
|
||||
pSuite->addTest(ULIDTestSuite::suite());
|
||||
pSuite->addTest(TextTestSuite::suite());
|
||||
pSuite->addTest(URITestSuite::suite());
|
||||
#if !defined(POCO_VXWORKS)
|
||||
|
||||
86
Foundation/testsuite/src/ULIDGeneratorTest.cpp
Normal file
86
Foundation/testsuite/src/ULIDGeneratorTest.cpp
Normal file
@@ -0,0 +1,86 @@
|
||||
//
|
||||
// ULIDGeneratorTest.cpp
|
||||
//
|
||||
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "ULIDGeneratorTest.h"
|
||||
#include "CppUnit/TestCaller.h"
|
||||
#include "CppUnit/TestSuite.h"
|
||||
#include "Poco/ULIDGenerator.h"
|
||||
#include "Poco/ULID.h"
|
||||
#include <set>
|
||||
|
||||
|
||||
using Poco::ULIDGenerator;
|
||||
|
||||
|
||||
ULIDGeneratorTest::ULIDGeneratorTest(const std::string& name): CppUnit::TestCase(name)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ULIDGeneratorTest::~ULIDGeneratorTest()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void ULIDGeneratorTest::testCreate()
|
||||
{
|
||||
ULIDGenerator& gen = ULIDGenerator::defaultGenerator();
|
||||
|
||||
std::set<Poco::ULID> ulids;
|
||||
for (int i = 0; i < 1000; ++i)
|
||||
{
|
||||
Poco::ULID ulid = gen.create();
|
||||
assertTrue (ulids.find(ulid) == ulids.end());
|
||||
ulids.insert(ulid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ULIDGeneratorTest::testCreateTime()
|
||||
{
|
||||
const Poco::UInt64 time = static_cast<Poco::UInt64>(1766090811)*1000;
|
||||
|
||||
ULIDGenerator gen;
|
||||
std::set<Poco::ULID> ulids;
|
||||
for (int i = 0; i < 1000; ++i)
|
||||
{
|
||||
try
|
||||
{
|
||||
Poco::ULID ulid = gen.create(time);
|
||||
assertTrue (ulids.find(ulid) == ulids.end());
|
||||
ulids.insert(ulid);
|
||||
assertTrue (ulid.time() == time);
|
||||
}
|
||||
catch (Poco::RuntimeException&)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ULIDGeneratorTest::setUp()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void ULIDGeneratorTest::tearDown()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
CppUnit::Test* ULIDGeneratorTest::suite()
|
||||
{
|
||||
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ULIDGeneratorTest");
|
||||
|
||||
CppUnit_addTest(pSuite, ULIDGeneratorTest, testCreate);
|
||||
CppUnit_addTest(pSuite, ULIDGeneratorTest, testCreateTime);
|
||||
|
||||
return pSuite;
|
||||
}
|
||||
39
Foundation/testsuite/src/ULIDGeneratorTest.h
Normal file
39
Foundation/testsuite/src/ULIDGeneratorTest.h
Normal file
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// ULIDGeneratorTest.h
|
||||
//
|
||||
// Definition of the ULIDGeneratorTest class.
|
||||
//
|
||||
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef ULIDGeneratorTest_INCLUDED
|
||||
#define ULIDGeneratorTest_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/Foundation.h"
|
||||
#include "CppUnit/TestCase.h"
|
||||
|
||||
|
||||
class ULIDGeneratorTest: public CppUnit::TestCase
|
||||
{
|
||||
public:
|
||||
ULIDGeneratorTest(const std::string& name);
|
||||
~ULIDGeneratorTest();
|
||||
|
||||
void testCreate();
|
||||
void testCreateTime();
|
||||
|
||||
void setUp();
|
||||
void tearDown();
|
||||
|
||||
static CppUnit::Test* suite();
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
|
||||
#endif // ULIDGeneratorTest_INCLUDED
|
||||
167
Foundation/testsuite/src/ULIDTest.cpp
Normal file
167
Foundation/testsuite/src/ULIDTest.cpp
Normal file
@@ -0,0 +1,167 @@
|
||||
//
|
||||
// ULIDTest.cpp
|
||||
//
|
||||
// Copyright (c) 2025, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "ULIDTest.h"
|
||||
#include "CppUnit/TestCaller.h"
|
||||
#include "CppUnit/TestSuite.h"
|
||||
#include "Poco/ULID.h"
|
||||
#include "Poco/Exception.h"
|
||||
|
||||
|
||||
ULIDTest::ULIDTest(const std::string& name): CppUnit::TestCase(name)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ULIDTest::~ULIDTest()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void ULIDTest::testParse()
|
||||
{
|
||||
Poco::ULID ulid("01BX5ZZKBKACTAV9WEVGEMMVRY");
|
||||
assertTrue (ulid.toString() == "01BX5ZZKBKACTAV9WEVGEMMVRY");
|
||||
|
||||
ulid.parse("01bx5zzkbkactav9wevgemmvry");
|
||||
assertTrue (ulid.toString() == "01BX5ZZKBKACTAV9WEVGEMMVRY");
|
||||
|
||||
ulid.parse("olbx5zzkbkactav9wevgemmvry");
|
||||
assertTrue (ulid.toString() == "01BX5ZZKBKACTAV9WEVGEMMVRY");
|
||||
|
||||
ulid.parse("01KCSHHDYBY3J5VRSXHMKNYSE6");
|
||||
assertTrue (ulid.toString() == "01KCSHHDYBY3J5VRSXHMKNYSE6");
|
||||
|
||||
ulid.parse("7ZZZZZZZZZZZZZZZZZZZZZZZZZ");
|
||||
assertTrue (ulid.toString() == "7ZZZZZZZZZZZZZZZZZZZZZZZZZ");
|
||||
|
||||
ulid.parse("00000000000000000000000000");
|
||||
assertTrue (ulid.toString() == "00000000000000000000000000");
|
||||
|
||||
try
|
||||
{
|
||||
ulid.parse("80000000000000000000000000");
|
||||
fail("out of range ULID - must throw");
|
||||
}
|
||||
catch (Poco::SyntaxException&)
|
||||
{
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
ulid.parse("01BX5ZZKBKACTAV9WEVGEMMVR");
|
||||
fail("malformed ULID - must throw");
|
||||
}
|
||||
catch (Poco::SyntaxException&)
|
||||
{
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
ulid.parse("01BX5ZZKBKAUTAV9WEVGEMMVRY");
|
||||
fail("malformed ULID - must throw");
|
||||
}
|
||||
catch (Poco::SyntaxException&)
|
||||
{
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
ulid.parse("");
|
||||
fail("malformed ULID - must throw");
|
||||
}
|
||||
catch (Poco::SyntaxException&)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ULIDTest::testBuffer()
|
||||
{
|
||||
Poco::ULID ulid("01BX5ZZKBKACTAV9WEVGEMMVRY");
|
||||
char buffer[16];
|
||||
ulid.copyTo(buffer);
|
||||
Poco::ULID ulid2;
|
||||
ulid2.copyFrom(buffer);
|
||||
assertTrue (ulid2.toString() == "01BX5ZZKBKACTAV9WEVGEMMVRY");
|
||||
}
|
||||
|
||||
|
||||
void ULIDTest::testCompare()
|
||||
{
|
||||
Poco::ULID null;
|
||||
assertTrue (null.isNull());
|
||||
assertTrue (Poco::ULID::null().isNull());
|
||||
|
||||
Poco::ULID ulid1 = null;
|
||||
Poco::ULID ulid2;
|
||||
assertTrue (ulid1.isNull());
|
||||
assertTrue (ulid1 == null);
|
||||
assertFalse (ulid1 != null);
|
||||
assertTrue (ulid1 >= null);
|
||||
assertTrue (ulid1 <= null);
|
||||
assertFalse (ulid1 > null);
|
||||
assertFalse (ulid1 < null);
|
||||
|
||||
ulid1.parse("01BX5ZZKBKACTAV9WEVGEMMVRY");
|
||||
ulid2.parse("01BX5ZZKBKACTAV9WEVGEMMVRZ");
|
||||
assertTrue (ulid1 < ulid2);
|
||||
assertTrue (ulid1 <= ulid2);
|
||||
assertTrue (ulid2 > ulid1);
|
||||
assertTrue (ulid2 >= ulid1);
|
||||
assertFalse (ulid1 == ulid2);
|
||||
assertFalse (ulid2 == ulid1);
|
||||
}
|
||||
|
||||
|
||||
void ULIDTest::testSwap()
|
||||
{
|
||||
Poco::ULID ulid1("01BX5ZZKBKACTAV9WEVGEMMVRY");
|
||||
Poco::ULID ulid2("01BX5ZZKBKACTAV9WEVGEMMVS1");
|
||||
ulid1.swap(ulid2);
|
||||
assertTrue (ulid1.toString() == "01BX5ZZKBKACTAV9WEVGEMMVS1");
|
||||
assertTrue (ulid2.toString() == "01BX5ZZKBKACTAV9WEVGEMMVRY");
|
||||
}
|
||||
|
||||
|
||||
void ULIDTest::testTryParse()
|
||||
{
|
||||
Poco::ULID ulid;
|
||||
assertTrue (ulid.tryParse("01BX5ZZKBKACTAV9WEVGEMMVRY"));
|
||||
assertTrue (ulid.toString() == "01BX5ZZKBKACTAV9WEVGEMMVRY");
|
||||
|
||||
Poco::ULID notUlid;
|
||||
assertTrue (!notUlid.tryParse("not a uuid"));
|
||||
assertTrue (notUlid.isNull());
|
||||
}
|
||||
|
||||
|
||||
void ULIDTest::setUp()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void ULIDTest::tearDown()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
CppUnit::Test* ULIDTest::suite()
|
||||
{
|
||||
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ULIDTest");
|
||||
|
||||
CppUnit_addTest(pSuite, ULIDTest, testParse);
|
||||
CppUnit_addTest(pSuite, ULIDTest, testBuffer);
|
||||
CppUnit_addTest(pSuite, ULIDTest, testCompare);
|
||||
CppUnit_addTest(pSuite, ULIDTest, testSwap);
|
||||
CppUnit_addTest(pSuite, ULIDTest, testTryParse);
|
||||
|
||||
return pSuite;
|
||||
}
|
||||
42
Foundation/testsuite/src/ULIDTest.h
Normal file
42
Foundation/testsuite/src/ULIDTest.h
Normal file
@@ -0,0 +1,42 @@
|
||||
//
|
||||
// ULIDTest.h
|
||||
//
|
||||
// Definition of the ULIDTest class.
|
||||
//
|
||||
// Copyright (c) 2025, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef ULIDTest_INCLUDED
|
||||
#define ULIDTest_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/Foundation.h"
|
||||
#include "CppUnit/TestCase.h"
|
||||
|
||||
|
||||
class ULIDTest: public CppUnit::TestCase
|
||||
{
|
||||
public:
|
||||
ULIDTest(const std::string& name);
|
||||
~ULIDTest();
|
||||
|
||||
void testParse();
|
||||
void testBuffer();
|
||||
void testCompare();
|
||||
void testSwap();
|
||||
void testTryParse();
|
||||
|
||||
void setUp();
|
||||
void tearDown();
|
||||
|
||||
static CppUnit::Test* suite();
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
|
||||
#endif // ULIDTest_INCLUDED
|
||||
24
Foundation/testsuite/src/ULIDTestSuite.cpp
Normal file
24
Foundation/testsuite/src/ULIDTestSuite.cpp
Normal file
@@ -0,0 +1,24 @@
|
||||
//
|
||||
// ULIDTestSuite.cpp
|
||||
//
|
||||
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "ULIDTestSuite.h"
|
||||
#include "ULIDTest.h"
|
||||
#include "ULIDGeneratorTest.h"
|
||||
|
||||
|
||||
CppUnit::Test* ULIDTestSuite::suite()
|
||||
{
|
||||
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ULIDTestSuite");
|
||||
|
||||
pSuite->addTest(ULIDTest::suite());
|
||||
pSuite->addTest(ULIDGeneratorTest::suite());
|
||||
|
||||
return pSuite;
|
||||
}
|
||||
27
Foundation/testsuite/src/ULIDTestSuite.h
Normal file
27
Foundation/testsuite/src/ULIDTestSuite.h
Normal file
@@ -0,0 +1,27 @@
|
||||
//
|
||||
// ULIDTestSuite.h
|
||||
//
|
||||
// Definition of the ULIDTestSuite class.
|
||||
//
|
||||
// Copyright (c) 2025, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef ULIDTestSuite_INCLUDED
|
||||
#define ULIDTestSuite_INCLUDED
|
||||
|
||||
|
||||
#include "CppUnit/TestSuite.h"
|
||||
|
||||
|
||||
class ULIDTestSuite
|
||||
{
|
||||
public:
|
||||
static CppUnit::Test* suite();
|
||||
};
|
||||
|
||||
|
||||
#endif // ULIDTestSuite_INCLUDED
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "Poco/UUID.h"
|
||||
#include "Poco/Exception.h"
|
||||
|
||||
|
||||
UUIDTest::UUIDTest(const std::string& name): CppUnit::TestCase(name)
|
||||
{
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user