//------------------------------------------------------------------------------
// File: BinarySerializer.cc
// Author: Georgios Bitzes - CERN
//------------------------------------------------------------------------------
/************************************************************************
* qclient - A simple redis C++ client with support for redirects *
* Copyright (C) 2020 CERN/Switzerland *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see .*
************************************************************************/
#include "BinarySerializer.hh"
#include
#include
#ifdef __APPLE__
#include
#define htobe16(x) OSSwapHostToBigInt16(x)
#define htole16(x) OSSwapHostToLittleInt16(x)
#define be16toh(x) OSSwapBigToHostInt16(x)
#define le16toh(x) OSSwapLittleToHostInt16(x)
#define htobe32(x) OSSwapHostToBigInt32(x)
#define htole32(x) OSSwapHostToLittleInt32(x)
#define be32toh(x) OSSwapBigToHostInt32(x)
#define le32toh(x) OSSwapLittleToHostInt32(x)
#define htobe64(x) OSSwapHostToBigInt64(x)
#define htole64(x) OSSwapHostToLittleInt64(x)
#define be64toh(x) OSSwapBigToHostInt64(x)
#define le64toh(x) OSSwapLittleToHostInt64(x)
#endif
namespace qclient {
static void intToBinaryString(int64_t num, char* buff) {
int64_t be = htobe64(num);
memcpy(buff, &be, sizeof(be));
}
static int64_t binaryStringToInt(const char* buff) {
int64_t result;
memcpy(&result, buff, sizeof(result));
return be64toh(result);
}
//------------------------------------------------------------------------------
//! Constructor
//------------------------------------------------------------------------------
BinarySerializer::BinarySerializer(std::string &trg, size_t size)
: target(trg) {
target.resize(size);
currentPosition = 0;
}
//------------------------------------------------------------------------------
// Get current position for write
//------------------------------------------------------------------------------
char* BinarySerializer::pos() {
return ((char*) target.data()) + currentPosition;
}
//------------------------------------------------------------------------------
// Append int64_t
//------------------------------------------------------------------------------
void BinarySerializer::appendInt64(int64_t num) {
intToBinaryString(num, pos());
currentPosition += sizeof(int64_t);
}
//------------------------------------------------------------------------------
// Append raw bytes
//------------------------------------------------------------------------------
void BinarySerializer::appendBytes(const char* source, size_t len) {
memcpy(pos(), source, len);
currentPosition += len;
}
//------------------------------------------------------------------------------
// Append string, including the length
//------------------------------------------------------------------------------
void BinarySerializer::appendString(const std::string &str) {
appendInt64(str.size());
appendBytes(str.data(), str.size());
}
//------------------------------------------------------------------------------
// Get size remaining
//------------------------------------------------------------------------------
int64_t BinarySerializer::getRemaining() const {
return target.size() - currentPosition;
}
//------------------------------------------------------------------------------
//! Constructor
//------------------------------------------------------------------------------
BinaryDeserializer::BinaryDeserializer(const std::string &src)
: source(src), currentPosition(0) {}
//------------------------------------------------------------------------------
//! Fetch int64_t
//------------------------------------------------------------------------------
bool BinaryDeserializer::consumeInt64(int64_t &out) {
if(!canConsume(8)) {
return false;
}
out = binaryStringToInt(source.data()+currentPosition);
currentPosition += 8;
return true;
}
//------------------------------------------------------------------------------
//! Consume that many raw bytes
//------------------------------------------------------------------------------
bool BinaryDeserializer::consumeRawBytes(std::string &str, size_t sz) {
if(!canConsume(sz)) {
return false;
}
str.resize(sz);
memcpy( (char*) str.data(), source.data()+currentPosition, sz);
currentPosition += sz;
return true;
}
//------------------------------------------------------------------------------
//! Fetch string
//------------------------------------------------------------------------------
bool BinaryDeserializer::consumeString(std::string &str) {
int64_t sz = 0;
if(!consumeInt64(sz)) {
return false;
}
return consumeRawBytes(str, sz);
}
//------------------------------------------------------------------------------
//! Get number of bytes left
//------------------------------------------------------------------------------
size_t BinaryDeserializer::bytesLeft() const {
return (source.size() - currentPosition);
}
//------------------------------------------------------------------------------
//! Check if it's possible to consume N bytes
//------------------------------------------------------------------------------
bool BinaryDeserializer::canConsume(size_t b) const {
return (source.size() - currentPosition) >= b;
}
}