mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-07-22 06:09:09 -04:00
195 lines
6 KiB
C++
195 lines
6 KiB
C++
#pragma once
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include <string>
|
|
#include <algorithm>
|
|
#include <vector>
|
|
#include <list>
|
|
|
|
#include "util/rsprint.h"
|
|
#include "util/rsdebug.h"
|
|
|
|
// This class re-implements QByteArray from Qt library.
|
|
|
|
class ByteArray: public std::vector<unsigned char>
|
|
{
|
|
public:
|
|
ByteArray() =default;
|
|
explicit ByteArray(int n) : std::vector<unsigned char>(n) {}
|
|
explicit ByteArray(const unsigned char *d,int n) : std::vector<unsigned char>(n) { memcpy(data(),d,n); }
|
|
virtual ~ByteArray() =default;
|
|
|
|
ByteArray(const std::string& c) { resize(c.size()); memcpy(data(),c.c_str(),c.size()); }
|
|
const ByteArray& operator=(const std::string& c) { resize(c.size()); memcpy(data(),c.c_str(),c.size()); return *this; }
|
|
|
|
bool isNull() const { return empty(); }
|
|
ByteArray toHex() const { return ByteArray(RsUtil::BinToHex(data(),size(),0)); }
|
|
std::string toString() const { std::string res; for(auto c:*this) res += c; return res; }
|
|
|
|
ByteArray operator+(const ByteArray& b) const { auto res(*this); for(unsigned char c:b) res.push_back(c); return res; }
|
|
ByteArray operator+(const std::string& b) const { return operator+(ByteArray(b)); }
|
|
|
|
void append(const ByteArray& b) { for(auto c:b) push_back(c); }
|
|
void append(const char *b) { for(uint32_t n=0;b[n]!=0;++n) push_back(b[n]); }
|
|
|
|
template<class T> void append(const T) = delete;// Prevents any implicit when calling the preceding functions which actually causes real bugs.
|
|
|
|
ByteArray& operator+=(char b) { push_back(b); return *this; }
|
|
ByteArray& operator+=(const ByteArray& b) { for(auto c:b) push_back(c); return *this; }
|
|
ByteArray& operator+=(const char *b) { for(uint32_t n=0;b[n]!=0;++n) push_back(b[n]); return *this;}
|
|
|
|
ByteArray left(uint32_t l) const { auto res = *this; res.resize(std::min((uint32_t)size(),l)); return res; }
|
|
ByteArray toUpper() const { auto res = *this; for(uint32_t i=0;i<size();++i) if( res[i]<='z' && res[i]>='a') res[i] += int('A')-int('a'); return res; }
|
|
ByteArray toLower() const { auto res = *this; for(uint32_t i=0;i<size();++i) if( res[i]<='Z' && res[i]>='A') res[i] += int('a')-int('A'); return res; }
|
|
|
|
int toInt() const
|
|
{
|
|
std::istringstream is(toString().c_str());
|
|
|
|
int res = -1;
|
|
is >> res ;
|
|
|
|
return res;
|
|
}
|
|
bool endsWith(const ByteArray& b) const { return size() >= b.size() && !memcmp(&data()[size()-b.size()],b.data(),b.size()); }
|
|
bool endsWith(char b) const { return size() > 0 && back()==b; }
|
|
bool startsWith(const ByteArray& b) const { return b.size() <= size() && !strncmp((char*)b.data(),(char*)data(),std::min(size(),b.size())); }
|
|
bool startsWith(const char *b) const
|
|
{
|
|
for(uint32_t n=0;b[n]!=0;++n)
|
|
if(n >= size() || b[n]!=(*this)[n])
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool operator==(const char *b) const
|
|
{
|
|
uint32_t n;
|
|
for(n=0;b[n]!=0;++n)
|
|
if(n >= size() || b[n]!=(*this)[n])
|
|
return false;
|
|
|
|
return n==size();
|
|
}
|
|
|
|
ByteArray mid(uint32_t n,int s=-1) const
|
|
{
|
|
ByteArray res((s>=0)?s:(size()-n));
|
|
memcpy(res.data(),&data()[n],res.size());
|
|
return res;
|
|
}
|
|
|
|
int indexOf(unsigned char c,int from=0) const
|
|
{
|
|
for(uint32_t i=from;i<size();++i)
|
|
if((*this)[i]==c)
|
|
return (int)i;
|
|
return -1;
|
|
}
|
|
|
|
ByteArray replace(const ByteArray& b1,const ByteArray& b2)
|
|
{
|
|
if(b1.empty())
|
|
{
|
|
RsErr() << "Attempting to replace an empty string!";
|
|
return *this;
|
|
}
|
|
ByteArray res ;
|
|
|
|
for(uint32_t i=0;i+b1.size()<=size();)
|
|
if(!memcmp(&(*this)[i],b1.data(),b1.size()))
|
|
{
|
|
res.append(b2);
|
|
i += b1.size();
|
|
}
|
|
else
|
|
res.push_back((*this)[i++]);
|
|
|
|
return res;
|
|
}
|
|
|
|
// Splits the byte array using sep as separator.
|
|
|
|
std::list<ByteArray> split(unsigned char sep)
|
|
{
|
|
std::list<ByteArray> res;
|
|
ByteArray current_block;
|
|
|
|
for(uint32_t i=0;i<size();++i)
|
|
if(operator[](i) == sep)
|
|
{
|
|
res.push_back(current_block);
|
|
current_block.clear();
|
|
}
|
|
else
|
|
current_block += (*this)[i];
|
|
|
|
if(!current_block.empty())
|
|
res.push_back(current_block);
|
|
|
|
return res;
|
|
}
|
|
|
|
// Splits the byte array using any of the characters in sep as separators.
|
|
|
|
std::list<ByteArray> split(const ByteArray& sep)
|
|
{
|
|
std::list<ByteArray> res;
|
|
ByteArray current_block;
|
|
|
|
for(uint32_t i=0;i<size();++i)
|
|
if(std::find(sep.begin(),sep.end(),operator[](i)) != sep.end())
|
|
{
|
|
res.push_back(current_block);
|
|
current_block.clear();
|
|
}
|
|
else
|
|
current_block += operator[](i);
|
|
|
|
if(!current_block.empty())
|
|
res.push_back(current_block);
|
|
|
|
return res;
|
|
}
|
|
|
|
// Removes the following characters from the beginning and from the end of the array:
|
|
// '\t', '\n', '\v', '\f', '\r', and ' '.
|
|
|
|
ByteArray trimmed() const
|
|
{
|
|
auto res(*this);
|
|
|
|
while(!res.empty() && ( res.back() == '\t' || res.back() == '\n' || res.back() == '\v'
|
|
|| res.back() == '\f' || res.back() == '\r' || res.back() == ' ' ) )
|
|
res.pop_back();
|
|
|
|
uint32_t i=0;
|
|
|
|
for(;i<res.size();++i)
|
|
if(res[i] != '\t' && res[i] != '\n' && res[i] != '\v' && res[i] != '\f' && res[i] != '\r' && res[i] != ' ')
|
|
break;
|
|
|
|
return res.mid(i);
|
|
}
|
|
|
|
// Removes n bytes from the end of the array
|
|
|
|
void chop(uint32_t n)
|
|
{
|
|
resize(std::max(0,(int)size() - (int)n));
|
|
}
|
|
|
|
// Returns the last index of a given byte, -1 if not found.
|
|
|
|
int lastIndexOf(unsigned char s)
|
|
{
|
|
for(int i=size()-1;i>=0;--i)
|
|
if(operator[](i) == s)
|
|
return i;
|
|
|
|
return -1;
|
|
}
|
|
};
|