Optimized socket library, added generic splitter function

This commit is contained in:
Thulinma 2017-06-01 20:52:32 +02:00
parent c7c94dc3c3
commit 05387f01fb
2 changed files with 51 additions and 12 deletions

View file

@ -65,6 +65,10 @@ std::string uint2string(unsigned int i){
return st.str(); return st.str();
} }
Socket::Buffer::Buffer(){
splitter = "\n";
}
/// Returns the amount of elements in the internal std::deque of std::string objects. /// Returns the amount of elements in the internal std::deque of std::string objects.
/// The back is popped as long as it is empty, first - this way this function is /// The back is popped as long as it is empty, first - this way this function is
/// guaranteed to return 0 if the buffer is empty. /// guaranteed to return 0 if the buffer is empty.
@ -83,26 +87,58 @@ unsigned int Socket::Buffer::bytes(unsigned int max){
return i; return i;
} }
/// Returns how many bytes to read until the next splitter, or 0 if none found.
unsigned int Socket::Buffer::bytesToSplit(){
unsigned int i = 0;
for (std::deque<std::string>::reverse_iterator it = data.rbegin(); it != data.rend(); ++it){
i += (*it).size();
if ((*it).size() >= splitter.size() && (*it).substr((*it).size()-splitter.size()) == splitter){
return i;
}
}
return 0;
}
/// Appends this string to the internal std::deque of std::string objects. /// Appends this string to the internal std::deque of std::string objects.
/// It is automatically split every BUFFER_BLOCKSIZE bytes. /// It is automatically split every BUFFER_BLOCKSIZE bytes and when the splitter string is encountered.
void Socket::Buffer::append(const std::string &newdata){ void Socket::Buffer::append(const std::string &newdata){
append(newdata.c_str(), newdata.size()); append(newdata.data(), newdata.size());
}
///Helper function that does a short-circuiting string compare
inline bool string_compare(const char *a, const char *b, const size_t len){
for (size_t i = 0; i < len; ++i){
if (a[i] != b[i]){return false;}
}
return true;
} }
/// Appends this data block to the internal std::deque of std::string objects. /// Appends this data block to the internal std::deque of std::string objects.
/// It is automatically split every BUFFER_BLOCKSIZE bytes. /// It is automatically split every BUFFER_BLOCKSIZE bytes and when the splitter string is encountered.
void Socket::Buffer::append(const char *newdata, const unsigned int newdatasize){ void Socket::Buffer::append(const char *newdata, const unsigned int newdatasize){
unsigned int i = 0, j = 0; uint32_t i = 0;
while (i < newdatasize){ while (i < newdatasize){
j = i; uint32_t j = 0;
while (j < newdatasize && j - i <= BUFFER_BLOCKSIZE){ if (!splitter.size()){
j++; if (newdatasize - i > BUFFER_BLOCKSIZE){
if (newdata[j - 1] == '\n'){break;} j = BUFFER_BLOCKSIZE;
} }else{
if (i != j){ j = newdatasize - i;
data.push_front(std::string(newdata + i, (size_t)(j - i))); }
i = j;
}else{ }else{
while (j+i < newdatasize && j < BUFFER_BLOCKSIZE){
j++;
if (j >= splitter.size()){
if (string_compare(newdata+i+j-splitter.size(), splitter.data(), splitter.size())){break;}
}
}
}
if (j){
data.push_front("");
data.front().assign(newdata + i, (size_t)j);
i += j;
}else{
FAIL_MSG("Appended an empty string to buffer: aborting!");
break; break;
} }
} }

View file

@ -32,8 +32,11 @@ namespace Socket{
std::deque<std::string> data; std::deque<std::string> data;
public: public:
std::string splitter;///<String to automatically split on if encountered. \n by default
Buffer();
unsigned int size(); unsigned int size();
unsigned int bytes(unsigned int max); unsigned int bytes(unsigned int max);
unsigned int bytesToSplit();
void append(const std::string &newdata); void append(const std::string &newdata);
void append(const char *newdata, const unsigned int newdatasize); void append(const char *newdata, const unsigned int newdatasize);
void prepend(const std::string &newdata); void prepend(const std::string &newdata);