JustAudio/io/idm.cpp

433 lines
8.3 KiB
C++
Raw Normal View History

#include "idm.h"
const QByteArray Idm::TAG = "IDM";
const int Idm::MAX_MAJOR = 1;
const int Idm::MAX_MINOR = 0;
int Idm::DEFAULT_INT_SIZE = 3;
int Idm::DEFAULT_FLAGS = 1; // FIXED_KEY_LEN
int Idm::DEFAULT_KEY_LEN = 1;
int Idm::CURRENT_MAJOR = Idm::MAX_MAJOR;
int Idm::CURRENT_MINOR = Idm::MAX_MINOR;
Idm::Idm(const QByteArray &data, QObject *parent) : QObject(parent)
{
buffPtr = data;
init();
}
Idm::Idm(QObject *parent) : QObject(parent)
{
init();
}
void Idm::init()
{
header = 0;
intSize = DEFAULT_INT_SIZE;
keyLen = DEFAULT_KEY_LEN;
flags = DEFAULT_FLAGS;
}
void Idm::loadData(const QByteArray &data)
{
op(RELOAD, data);
}
QByteArray &Idm::getBuff()
{
op(GET_BUFF, QByteArray(), QByteArray(), new QByteArray());
return buffPtr;
}
bool Idm::rdHeader()
{
return rdExHeader(buffPtr);
}
bool Idm::rdExHeader(const QByteArray &data)
{
bool ret;
op(RD_HEADER, data, QByteArray(), 0, 0, 0, &ret);
return ret;
}
bool Idm::rdExHeader(const QByteArray &data, int &major, int &minor, int &intSz, int &flgs, int &keyLen)
{
bool ret = false;
if (data.startsWith(TAG))
{
int pos = TAG.size();
major = rdInt(data.mid(pos++, 1));
minor = rdInt(data.mid(pos++, 1));
intSz = rdInt(data.mid(pos++, 1));
keyLen = rdInt(data.mid(pos++, 1));
flgs = rdInt(data.mid(pos, 4));
if ((major <= MAX_MAJOR) && (minor <= MAX_MINOR))
{
ret = true;
}
}
return ret;
}
bool Idm::verifyExHeader(const QByteArray &data, int major, int minor)
{
bool ret = false;
if (data.startsWith(TAG) && (data.size() == 11))
{
int pos = TAG.size();
int ma = rdInt(data.mid(pos++, 1));
int mi = rdInt(data.mid(pos++, 1));
ret = ((ma <= major) && (mi <= minor));
}
return ret;
}
QByteArray Idm::buildHeader(int major, int minor, int intSz, int flgs, int keyLen)
{
QByteArray ret = TAG;
ret.append(wrInt(major, 1));
ret.append(wrInt(minor, 1));
ret.append(wrInt(intSz, 1));
ret.append(wrInt(keyLen, 1));
ret.append(wrInt(flgs, 4));
return ret;
}
void Idm::setKeyLen(int len)
{
op(SET_KEY_LEN, QByteArray(), QByteArray(), 0, len);
}
void Idm::setFlags(int flgs)
{
op(SET_FLAGS, QByteArray(), QByteArray(), 0, flgs);
}
void Idm::wrHeader()
{
op(WR_HEADER);
}
void Idm::setIntSize(int bytes)
{
op(SET_INT_SIZE, QByteArray(), QByteArray(), 0, bytes);
}
void Idm::setVersion(int major, int minor)
{
op(SET_VERSION, QByteArray(), QByteArray(), 0, major, minor);
}
QByteArray Idm::rdData(int addr, int len, bool *ret)
{
bool ok = false;
if ((addr < buffPtr.size()) && (addr >= 0))
{
if ((len + addr) <= buffPtr.size())
{
ok = true;
}
}
if (ret) *ret = ok;
if (ok)
{
return QByteArray::fromRawData(buffPtr.data() + addr, len);
}
else
{
return QByteArray();
}
}
bool Idm::findKey(int &addr, int &dataLen, const QByteArray &key)
{
bool ok = true;
bool found = false;
while(addr < buffPtr.size() && ok)
{
int keySize;
if (flags & FIXED_KEY_LEN)
{
keySize = keyLen;
}
else
{
keySize = rdInt(rdData(addr, intSize, &ok));
addr += intSize;
}
if (ok)
{
if (key == rdData(addr, keySize, &ok))
{
found = true;
}
addr += keySize;
if (ok)
{
dataLen = rdInt(rdData(addr, intSize, &ok));
addr += intSize;
if (found && ok)
{
break;
}
else
{
addr += dataLen;
}
}
}
}
return found;
}
QByteArray Idm::value(const QByteArray &key)
{
QByteArray ret;
op(RD_VALUE, key, QByteArray(), &ret);
return ret;
}
QByteArray Idm::value(quint64 key)
{
int keySize;
if (flags & FIXED_KEY_LEN) keySize = keyLen;
else keySize = intSize;
return value(wrInt(key, keySize));
}
quint64 Idm::intValue(const QByteArray &key)
{
return rdInt(value(key));
}
quint64 Idm::intValue(quint64 key)
{
return rdInt(value(key));
}
bool Idm::remove(const QByteArray &key)
{
bool ret;
op(RM_VALUE, key, QByteArray(), 0, 0, 0, &ret);
return ret;
}
bool Idm::remove(quint64 key)
{
int keySize;
if (flags & FIXED_KEY_LEN) keySize = keyLen;
else keySize = intSize;
return remove(wrInt(key, keySize));
}
bool Idm::insert(const QByteArray &key, const QByteArray &data)
{
bool ret;
op(WR_VALUE, key, data, 0, 0, 0, &ret);
return ret;
}
bool Idm::insert(quint64 key, quint64 num)
{
int keySize;
if (flags & FIXED_KEY_LEN) keySize = keyLen;
else keySize = intSize;
return insert(wrInt(key, keySize), wrInt(num, intSize));
}
bool Idm::insert(quint64 key, const QByteArray &data)
{
int keySize;
if (flags & FIXED_KEY_LEN) keySize = keyLen;
else keySize = intSize;
return insert(wrInt(key, keySize), data);
}
void Idm::op(Operation opr,
const QByteArray &inA,
const QByteArray &inB,
QByteArray *out,
int intA,
int intB,
bool *ok)
{
QMutex m;
m.lock();
switch(opr)
{
case SET_KEY_LEN:
{
keyLen = intA; break;
}
case SET_FLAGS:
{
flags = intA; break;
}
case GET_BUFF:
{
out = &buffPtr; break;
}
case RELOAD:
{
buffPtr = inA; break;
}
case SET_INT_SIZE:
{
intSize = intA; break;
}
case SET_VERSION:
{
CURRENT_MAJOR = intA;
CURRENT_MINOR = intB;
break;
}
case WR_HEADER:
{
if (buffPtr.startsWith(TAG))
{
int pos = TAG.size();
buffPtr.replace(pos++, 1, wrInt(CURRENT_MAJOR, 1));
buffPtr.replace(pos++, 1, wrInt(CURRENT_MINOR, 1));
buffPtr.replace(pos++, 1, wrInt(intSize, 1));
buffPtr.replace(pos++, 1, wrInt(keyLen, 1));
buffPtr.replace(pos++, 4, wrInt(flags, 4));
}
else
{
buffPtr.insert(0, wrInt(flags, 4));
buffPtr.insert(0, wrInt(keyLen, 1));
buffPtr.insert(0, wrInt(intSize, 1));
buffPtr.insert(0, wrInt(CURRENT_MINOR, 1));
buffPtr.insert(0, wrInt(CURRENT_MAJOR, 1));
buffPtr.insert(0, TAG);
}
header = 8 + TAG.size();
break;
}
case RD_HEADER:
{
*ok = rdExHeader(inA, CURRENT_MAJOR, CURRENT_MINOR, intSize, flags, keyLen);
if (*ok) header = 8 + TAG.size();
break;
}
case RD_VALUE:
{
int pos = header;
int len = 0;
if (findKey(pos, len, inA))
{
out->clear();
out->append(buffPtr.mid(pos, len));
}
break;
}
case RM_VALUE:
{
int pos = header;
int len = 0;
*ok = false;
if (findKey(pos, len, inA))
{
if (flags & FIXED_KEY_LEN)
{
pos -= keyLen + intSize;
len += keyLen + intSize;
}
else
{
pos -= inA.size() + (intSize * 2);
len += inA.size() + (intSize * 2);
}
buffPtr.remove(pos, len);
*ok = true;
}
break;
}
case WR_VALUE:
{
*ok = false;
remove(inA);
if (flags & FIXED_KEY_LEN)
{
if (inA.size() == keyLen)
{
buffPtr.append(inA + wrInt(inB.size(), intSize) + inB);
*ok = true;
}
}
else
{
if (!inA.isEmpty())
{
buffPtr.append(wrInt(inA.size(), intSize) + inA);
buffPtr.append(wrInt(inB.size(), intSize) + inB);
*ok = true;
}
}
break;
}
}
m.unlock();
}