You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
655 lines
18 KiB
655 lines
18 KiB
14 years ago
|
//////////////////////////////////////////////////////////////////////////////////
|
||
|
// Name: actUtility.h
|
||
|
// Product: cv act library
|
||
|
// Purpose: useful global functions
|
||
|
//
|
||
|
// Copyright: (c) 2000-2001 cv cryptovision GmbH
|
||
|
// all rights reserved
|
||
|
// Licence: The conditions for the use of this software are regulated
|
||
|
// in the cv act library licence agreement.
|
||
|
//////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
#ifndef ACT_Utility_h
|
||
|
#define ACT_Utility_h
|
||
|
|
||
|
#include "actBlob.h"
|
||
|
#include "actBasics.h"
|
||
|
#include "actException.h"
|
||
|
|
||
|
#include <string>
|
||
|
#include <algorithm>
|
||
|
#include <cctype>
|
||
|
#include <cwctype>
|
||
|
#include <stdio.h>
|
||
|
#include <ctype.h>
|
||
|
|
||
|
#if defined(__GNUC__) && (__GNUC__ < 4)
|
||
|
namespace act { typedef std::basic_string<wchar_t> wstring; }
|
||
|
#else
|
||
|
namespace act { using std::wstring; }
|
||
|
#endif
|
||
|
|
||
|
namespace act
|
||
|
{
|
||
|
class IParam;
|
||
|
|
||
|
//
|
||
|
// Const Values
|
||
|
//
|
||
|
|
||
|
extern const size_t sizeof_uuid;
|
||
|
|
||
|
//
|
||
|
// Prototypes
|
||
|
//
|
||
|
|
||
|
const char* get_string_param(paramid_t id, IParam* owner);
|
||
|
|
||
|
// Converts an unsigned hexadecimal number (independent of prefix "0x")
|
||
|
// into a Blob and backwards.
|
||
|
// - for blob2hex: the user has to allocate hexnumber
|
||
|
Blob& hex2blob(const char* hexnumber, Blob& b);
|
||
|
inline Blob& hex2blob(const std::string& hexnumber, Blob& b)
|
||
|
{
|
||
|
return hex2blob(hexnumber.c_str(), b);
|
||
|
}
|
||
|
inline Blob hex2blob(const char* hexnumber)
|
||
|
{
|
||
|
Blob b;
|
||
|
return move(hex2blob(hexnumber, b));
|
||
|
}
|
||
|
|
||
|
void blob2hex(const Blob& b, char* hexnumber);
|
||
|
std::string blob2hex(const Blob& b);
|
||
|
|
||
|
// file i/o for act::Blob
|
||
|
bool file2blob(const char* filename, Blob &blob);
|
||
|
bool blob2file(const char* filename, const act::Blob &blob);
|
||
|
|
||
|
// Create an ISO 9834-8 / RFC 4122 version 4 (pseudo random) UUID.
|
||
|
// Output string format is "xxxxxxxx-xxxx-4xxx-vxxx-xxxxxxxxxxxx", where
|
||
|
// x is random hex char 0 <= x <= f and v an element of { 8, 9, a, b}.
|
||
|
void createPseudoRandomUUID(Blob& uuid, bool network_byte_order = true);
|
||
|
std::string createPseudoRandomUUID();
|
||
|
std::string uuid2string(const Blob& uuid, bool is_network_byte_order = true);
|
||
|
void swapTimeFields(Blob& uuid);
|
||
|
|
||
|
std::string serno2string(const act::Blob& serno);
|
||
|
std::string id2string(const act::Blob& id, bool is_network_byte_order = true);
|
||
|
|
||
|
// CBCMAC with ISO padding
|
||
|
void iCBCMAC(const char* cipher, const Blob& iv, const Blob& mac_key,
|
||
|
const Blob& mac_data, Blob& mac);
|
||
|
|
||
|
void SetDESKeyParity(Blob &key);
|
||
|
bool CheckDESKeyParity(const Blob &key);
|
||
|
|
||
|
void get_string_seq(const std::string& s, const std::string start, const std::string end,
|
||
|
std::string& result, bool case_sens);
|
||
|
|
||
|
bool wstr2utf8(const wchar_t* str, std::string& utf8);
|
||
|
bool utf82wstr(const char* utf8, act::wstring& wstr);
|
||
|
|
||
|
void ASN1ToSequenceOf(Blob& asn1_data);
|
||
|
Blob GetASN1SequenceOf(const Blob& asn1_data);
|
||
|
Blob GetASN1EncodedLength(size_t length);
|
||
|
|
||
|
size_t SkipTagLength(byte tag, const byte* tlv_data, size_t tlv_data_len);
|
||
|
size_t SkipTLVElement(byte tag, const byte* tlv_data, size_t tlv_data_len, bool skip_value = true);
|
||
|
int FindTlvTemplate(Blob& contentb, const Blob& inb, int intag, int counts);
|
||
|
|
||
|
//
|
||
|
// Implementation
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// --------------------------------------------------------------------
|
||
|
template<typename ConverterT, typename RegistryT, typename TypeT>
|
||
|
const Blob SafeGetName(TypeT* instance)
|
||
|
{
|
||
|
Blob name;
|
||
|
if(instance != 0)
|
||
|
{
|
||
|
const char* cname = RegistryT::GetName(instance->GetCreatePointer());
|
||
|
if(cname != 0) ConverterT(cname).swap(name);
|
||
|
}
|
||
|
return move(name);
|
||
|
}
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
template<typename TypeT>
|
||
|
struct is_whitespace : is_whitespace<typename TypeT::value_type>
|
||
|
{
|
||
|
typedef typename TypeT::value_type argument_type;
|
||
|
using is_whitespace<typename TypeT::value_type>::operator();
|
||
|
};
|
||
|
|
||
|
template<>
|
||
|
struct is_whitespace<char>
|
||
|
{
|
||
|
typedef char argument_type;
|
||
|
bool operator()(unsigned char value) const { return std::isspace(value) != 0; }
|
||
|
};
|
||
|
|
||
|
template<>
|
||
|
struct is_whitespace<wchar_t>
|
||
|
{
|
||
|
typedef wchar_t argument_type;
|
||
|
bool operator()(wchar_t value) const { return std::iswspace(value) != 0; }
|
||
|
};
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
template<typename PredicateT, typename TypeT>
|
||
|
inline TypeT& erase_right(const PredicateT& predicate, TypeT& value)
|
||
|
{
|
||
|
value.erase(std::find_if(value.rbegin(), value.rend(), predicate).base(), value.end());
|
||
|
return value;
|
||
|
}
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
template<typename TypeT>
|
||
|
inline void fill(TypeT* begin, size_t length, byte value)
|
||
|
{
|
||
|
ACT_ASSERT(begin != 0);
|
||
|
std::fill(reinterpret_cast<act::byte*>(begin),
|
||
|
reinterpret_cast<act::byte*>(begin) + length, value);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// scoped_delete<PointerT>
|
||
|
// ---------------------------------------------------------------------------
|
||
|
template<typename PointerT>
|
||
|
struct scoped_delete<PointerT, void, 1>
|
||
|
{
|
||
|
PointerT _ptr;
|
||
|
|
||
|
explicit scoped_delete(PointerT ptr) : _ptr(ptr) { }
|
||
|
~scoped_delete() { delete _ptr; }
|
||
|
|
||
|
PointerT operator->() const
|
||
|
{
|
||
|
if(_ptr == 0) throw NullPointerException();
|
||
|
return _ptr;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
template<typename PointerT>
|
||
|
scoped_delete<PointerT, void, 1> checked_delete(PointerT& ptr_ref)
|
||
|
{
|
||
|
PointerT ptr = ptr_ref; ptr_ref = 0;
|
||
|
return scoped_delete<PointerT, void, 1>(ptr);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// scoped_delete<AutoPtrT>
|
||
|
// ---------------------------------------------------------------------------
|
||
|
template
|
||
|
<
|
||
|
template<class> class AutoPtrT,
|
||
|
class TypeT
|
||
|
>
|
||
|
struct scoped_delete<AutoPtrT<TypeT>, void, 1>
|
||
|
{
|
||
|
AutoPtrT<TypeT> _ptr;
|
||
|
|
||
|
explicit scoped_delete(AutoPtrT<TypeT>& ptr) : _ptr(ptr) { }
|
||
|
~scoped_delete() { AutoPtrT<TypeT>(_ptr); }
|
||
|
|
||
|
TypeT* operator->() const
|
||
|
{
|
||
|
TypeT* ptr = _ptr.get();
|
||
|
if(ptr == 0) throw NullPointerException();
|
||
|
return ptr;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
template
|
||
|
<
|
||
|
template<class> class AutoPtrT,
|
||
|
class TypeT
|
||
|
>
|
||
|
scoped_delete<AutoPtrT<TypeT>, void, 1> checked_delete(AutoPtrT<TypeT>& ptr_ref)
|
||
|
{
|
||
|
return scoped_delete<AutoPtrT<TypeT>, void, 1>(ptr_ref);
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// scoped_delete<ArrayT<TypeT*> >
|
||
|
// ---------------------------------------------------------------------------
|
||
|
template
|
||
|
<
|
||
|
template<class, class> class ArrayT,
|
||
|
class TypeT, class AllocatorT,
|
||
|
typename DestructF
|
||
|
>
|
||
|
struct scoped_delete<ArrayT<TypeT, AllocatorT>, DestructF, 3>
|
||
|
{
|
||
|
typedef ArrayT<TypeT, AllocatorT> container_type;
|
||
|
typedef DestructF destruct_func;
|
||
|
|
||
|
explicit scoped_delete(container_type& _container, const destruct_func& _destruct)
|
||
|
: destruct(_destruct)
|
||
|
{ container.swap(_container); }
|
||
|
|
||
|
~scoped_delete()
|
||
|
{ release(container, destruct); }
|
||
|
|
||
|
static void release(container_type& container, const destruct_func& destruct)
|
||
|
{
|
||
|
if(container.empty() == true) return;
|
||
|
|
||
|
container_type failed;
|
||
|
typedef typename container_type::const_iterator const_iterator;
|
||
|
for(const_iterator i(container.begin()), end(container.end()); i != end; ++i)
|
||
|
try { destruct(*i); }
|
||
|
catch(Exception&) { failed.push_back(*i); }
|
||
|
|
||
|
container.swap(failed);
|
||
|
}
|
||
|
|
||
|
destruct_func destruct;
|
||
|
container_type container;
|
||
|
};
|
||
|
|
||
|
//
|
||
|
// checked_delete(array_of_ptr_to_type, std::mem_fun(&type::destruct));
|
||
|
// ---------------------------------------------------------------------------
|
||
|
template
|
||
|
<
|
||
|
template<class, class> class ArrayT,
|
||
|
class TypeT, class AllocatorT,
|
||
|
typename DestructF
|
||
|
>
|
||
|
scoped_delete<ArrayT<TypeT, AllocatorT>, DestructF, 3>
|
||
|
checked_delete(ArrayT<TypeT, AllocatorT>& container, const DestructF& destruct)
|
||
|
{
|
||
|
return scoped_delete<ArrayT<TypeT, AllocatorT>, DestructF, 3>(container, destruct);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// scoped_delete<MapT<TypeT*> >
|
||
|
// ---------------------------------------------------------------------------
|
||
|
template
|
||
|
<
|
||
|
template<class, class, class, class> class MapT,
|
||
|
class KeyT, class TypeT, class PredT, class AllocatorT,
|
||
|
typename DestructF
|
||
|
>
|
||
|
struct scoped_delete<MapT<KeyT, TypeT, PredT, AllocatorT>, DestructF, 4>
|
||
|
{
|
||
|
typedef MapT<KeyT, TypeT, PredT, AllocatorT> container_type;
|
||
|
typedef DestructF destruct_func;
|
||
|
|
||
|
explicit scoped_delete(container_type& _container, const destruct_func& _destruct)
|
||
|
: destruct(_destruct)
|
||
|
{ container.swap(_container); }
|
||
|
|
||
|
~scoped_delete()
|
||
|
{ release(container, destruct); }
|
||
|
|
||
|
static void release(container_type& container, const destruct_func& destruct)
|
||
|
{
|
||
|
if(container.empty() == true) return;
|
||
|
|
||
|
container_type failed;
|
||
|
typedef typename container_type::const_iterator const_iterator;
|
||
|
for(const_iterator i(container.begin()), end(container.end()); i != end; ++i)
|
||
|
try { destruct(i->second); }
|
||
|
catch(Exception&) { failed.insert(*i); }
|
||
|
|
||
|
container.swap(failed);
|
||
|
}
|
||
|
|
||
|
destruct_func destruct;
|
||
|
container_type container;
|
||
|
};
|
||
|
|
||
|
//
|
||
|
// checked_delete_map(map_of_ptr_to_type, std::mem_fun(&type::destruct));
|
||
|
// ---------------------------------------------------------------------------
|
||
|
template
|
||
|
<
|
||
|
template<class, class, class, class> class MapT,
|
||
|
class KeyT, class TypeT, class PredT, class AllocatorT,
|
||
|
typename DestructF
|
||
|
>
|
||
|
scoped_delete<MapT<KeyT, TypeT, PredT, AllocatorT>, DestructF, 4>
|
||
|
checked_delete_map(MapT<KeyT, TypeT, PredT, AllocatorT>& map_ref, const DestructF& destruct)
|
||
|
{
|
||
|
return scoped_delete<MapT<KeyT, TypeT, PredT, AllocatorT>, DestructF, 4>(map_ref, destruct);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// scoped_delete<>
|
||
|
// ---------------------------------------------------------------------------
|
||
|
template<typename TypeT, typename DestructF>
|
||
|
struct scoped_delete<TypeT, DestructF, 0>
|
||
|
{
|
||
|
scoped_delete(const DestructF& _destruct)
|
||
|
: destruct(_destruct)
|
||
|
{ }
|
||
|
|
||
|
~scoped_delete()
|
||
|
{ if(value.empty() == false) checked_delete(value, destruct); }
|
||
|
|
||
|
DestructF destruct;
|
||
|
TypeT value;
|
||
|
};
|
||
|
|
||
|
//
|
||
|
// checked_static_cast<>
|
||
|
// ---------------------------------------------------------------------------
|
||
|
template<class U, class V>
|
||
|
inline U checked_static_cast(V p)
|
||
|
{
|
||
|
ACT_ASSERT(p != 0);
|
||
|
ACT_ASSERT(dynamic_cast<U>(p) != 0);
|
||
|
return static_cast<U>(p);
|
||
|
}
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
template<typename TypeT>
|
||
|
inline TypeT& byref(const TypeT& e)
|
||
|
{
|
||
|
return const_cast<TypeT&>(e);
|
||
|
}
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
inline int max_int()
|
||
|
{
|
||
|
return int((unsigned(1) << (8 * sizeof(int) - 1)) - 1);
|
||
|
}
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
inline void OS2IP(Blob& number)
|
||
|
{
|
||
|
// octet string to integer presentation
|
||
|
if((number.at(0) & byte(0x80)) != 0)
|
||
|
number.insert(number.begin(), 0);
|
||
|
}
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
inline void I2OSP(Blob& number)
|
||
|
{
|
||
|
// integer to octet string presentation
|
||
|
if(number.at(0) == byte(0))
|
||
|
number.erase(number.begin());
|
||
|
}
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
inline void byte2long(const byte *in, size_t input_len, uint32 *out)
|
||
|
{
|
||
|
size_t i, output_len = input_len / 4;
|
||
|
for(i = 0; i < output_len; i++)
|
||
|
out[i]= in[i*4] | (in[i*4+1] << 8) | (in[i*4+2] << 16) | (in[i*4+3] << 24);
|
||
|
}
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
inline void long2byte(const uint32 *in, size_t input_len, byte *out)
|
||
|
{
|
||
|
size_t i, output_len = input_len * 4;
|
||
|
for(i = 0; i < output_len; i++)
|
||
|
out[i] = byte(in[i/4] >> (8*(i%4)));
|
||
|
}
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
inline void sweep(void* Mem,size_t l)
|
||
|
{
|
||
|
std::fill_n(reinterpret_cast<byte*>(Mem), l, byte(0));
|
||
|
}
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
template<class TypeT>
|
||
|
inline const TypeT Min(const TypeT& a, const TypeT& b)
|
||
|
{
|
||
|
return (a < b) ? a : b;
|
||
|
}
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
template<class TypeT>
|
||
|
inline const TypeT& Max(const TypeT& a, const TypeT& b)
|
||
|
{
|
||
|
return (a<b)? b : a;
|
||
|
}
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
template<class T1, class T2, class T3>
|
||
|
inline void xor_n(T1 a, T2 len, T3 b)
|
||
|
{
|
||
|
for(T2 i = 0; i < len; i++) b[i] ^= a[i];
|
||
|
}
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
template<class T1, class T3> inline void Xor (T1 a, T1 a_end, T3 b)
|
||
|
{
|
||
|
while(a < a_end)
|
||
|
*b++ ^= *a++;
|
||
|
}
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
inline const char* blob2char(Blob& b)
|
||
|
{
|
||
|
b.push_back(byte(0));
|
||
|
return reinterpret_cast<const char*>(&b[0]);
|
||
|
}
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
inline std::string blob2string(const Blob& value)
|
||
|
{
|
||
|
return value.empty() == false ?
|
||
|
std::string(reinterpret_cast<const std::string::value_type*>(&value.at(0)),
|
||
|
reinterpret_cast<const std::string::value_type*>(&value[0] + value.size())) :
|
||
|
std::string();
|
||
|
}
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
inline std::string byte2hex(const byte i)
|
||
|
{
|
||
|
char tmp[3];
|
||
|
sprintf(tmp, "%02x", i);
|
||
|
return tmp;
|
||
|
}
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
inline bool isHex(const byte c)
|
||
|
{
|
||
|
if((c < byte('0') || c > byte('9'))
|
||
|
&& (c < byte('a') || c > byte('f'))
|
||
|
&& (c < byte('A') || c > byte('F')))
|
||
|
return false;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
inline bool isHex(const Blob& b)
|
||
|
{
|
||
|
size_t i, b_len = b.size();
|
||
|
|
||
|
for(i = 0; i < b_len; ++i)
|
||
|
if(!isHex(b[i]))
|
||
|
return false;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
inline bool isAlphanumeric(const byte c)
|
||
|
{
|
||
|
if((c < byte('0') || c > byte('9'))
|
||
|
&& (c < byte('a') || c > byte('z'))
|
||
|
&& (c < byte('A') || c > byte('Z')))
|
||
|
return false;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
inline bool isAlphanumeric(const Blob& b)
|
||
|
{
|
||
|
size_t i, b_len = b.size();
|
||
|
|
||
|
for(i = 0; i < b_len; ++i)
|
||
|
if(!isAlphanumeric(b[i]))
|
||
|
return false;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
inline bool isPrintable(const Blob& b)
|
||
|
{
|
||
|
size_t i, b_len = b.size();
|
||
|
|
||
|
for(i = 0; i < b_len; ++i)
|
||
|
if(isprint(int(b[i])) == 0)
|
||
|
return false;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
inline bool isUUIDFormat(const Blob& b)
|
||
|
{
|
||
|
size_t b_len = b.size();
|
||
|
|
||
|
if(b_len != sizeof_uuid)
|
||
|
return false;
|
||
|
|
||
|
// check if the Blob contains only hexadecimal characters,
|
||
|
// separated by '-' (UUID string representation)
|
||
|
for(size_t i = 0; i < b_len; ++i)
|
||
|
if(!isHex(b[i]) && (b[i] != byte('-')))
|
||
|
return false;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
inline std::string short2hex(const unsigned short i)
|
||
|
{
|
||
|
char tmp[5];
|
||
|
sprintf(tmp,"%04x",i);
|
||
|
return tmp;
|
||
|
}
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
inline std::string long2hex(const unsigned long i)
|
||
|
{
|
||
|
char tmp[9];
|
||
|
sprintf(tmp,"%08lx",i);
|
||
|
return tmp;
|
||
|
}
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
inline unsigned long blob2long(const Blob& b)
|
||
|
{
|
||
|
if(b.size() == 0)
|
||
|
throw LogicalException("bad size","blob2long");
|
||
|
|
||
|
Blob tmp(b);
|
||
|
while(tmp[0] == 0 && tmp.size() > sizeof(long))
|
||
|
tmp.erase(tmp.begin());
|
||
|
|
||
|
if(tmp.size() > sizeof(long))
|
||
|
throw LogicalException("bad size", "blob2long");
|
||
|
|
||
|
unsigned long n = tmp[0];
|
||
|
for(unsigned int i = 1; i < tmp.size(); ++i)
|
||
|
{
|
||
|
n <<= 8;
|
||
|
n |= tmp[i];
|
||
|
}
|
||
|
return n;
|
||
|
}
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
inline Blob& long2blob(unsigned long n, Blob& value)
|
||
|
{
|
||
|
value.resize(sizeof(long));
|
||
|
for(size_t i = sizeof(long) - 1, j = 0; j < sizeof(long); --i, ++j)
|
||
|
value[j] = byte((n >> (8 * i)) & 0xff);
|
||
|
return value;
|
||
|
}
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
inline Blob long2blob(unsigned long n)
|
||
|
{
|
||
|
Blob value;
|
||
|
return move(long2blob(n, value));
|
||
|
}
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
inline Blob size2blob(size_t size)
|
||
|
{
|
||
|
Blob tmp;
|
||
|
tmp.reserve(8);
|
||
|
|
||
|
if(size == 0)
|
||
|
{
|
||
|
tmp.resize(1);
|
||
|
return move(tmp);
|
||
|
}
|
||
|
size_t remaining = size;
|
||
|
while(remaining > 0)
|
||
|
{
|
||
|
tmp.insert(tmp.begin(), byte(remaining & 0xFF));
|
||
|
remaining >>= 8;
|
||
|
}
|
||
|
return move(tmp);
|
||
|
}
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
inline unsigned short blob2short(const Blob& b)
|
||
|
{
|
||
|
if(b.size() != sizeof(short))
|
||
|
throw LogicalException("bad size", "blob2short");
|
||
|
|
||
|
unsigned short n = b[1];
|
||
|
n += (b[0] << 8);
|
||
|
return n;
|
||
|
}
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
// Input: a (big endian byte arrays)
|
||
|
// Output: ++a (increment with carry)
|
||
|
inline byte memincr(byte* a, int len)
|
||
|
{
|
||
|
int i = len-1;
|
||
|
byte carry;
|
||
|
do {
|
||
|
carry = ++a[i] == 0 ? 1 : 0;
|
||
|
} while( --i >= 0 && carry != 0);
|
||
|
return carry;
|
||
|
}
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
// Input: a, b (big endian byte arrays)
|
||
|
// Output: a += b (add with carry)
|
||
|
inline byte memadd(byte* a, const byte* b, int len, byte carry = 0)
|
||
|
{
|
||
|
int i = len - 1;
|
||
|
unsigned long tmp;
|
||
|
for(; i >= 0; --i)
|
||
|
{
|
||
|
tmp = a[i] + b[i] + carry;
|
||
|
a[i] = byte(tmp & 0xff);
|
||
|
carry = byte(tmp >> 8);
|
||
|
}
|
||
|
return carry;
|
||
|
}
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
inline void convert_to_upper(std::string& s)
|
||
|
{
|
||
|
for(std::string::iterator it = s.begin(); it != s.end() ; ++it)
|
||
|
*it = toupper(*it);
|
||
|
}
|
||
|
|
||
|
} //namespace act
|
||
|
|
||
|
#endif // ACT_Utility_h
|