1#ifndef _PAINLESS_MESH_BUFFER_HPP_
2#define _PAINLESS_MESH_BUFFER_HPP_
38 auto len = strnlen(data_ptr, length);
43 auto read_len = (std::min)(len, buf.
length - 1);
44 memcpy(buf.
buffer, data_ptr, read_len);
45 buf.
buffer[read_len] =
'\0';
46 auto newBuffer = T(buf.
buffer);
47 stringAppend(buffer, newBuffer);
48 len -= newBuffer.length();
49 length -= newBuffer.length();
50 data_ptr += newBuffer.length() *
sizeof(char);
55 data_ptr += 1 *
sizeof(char);
56 if (buffer.length() > 0) {
57 jsonStrings.push_back(buffer);
68 if (!
empty())
return jsonStrings.front();
80 bool empty() {
return jsonStrings.empty(); }
92 std::list<T> jsonStrings;
98 inline void stringAppend(T &buffer, T &newBuffer) {
99 buffer.concat(newBuffer);
103#ifdef PAINLESSMESH_ENABLE_STD_STRING
105inline void ReceiveBuffer<std::string>::stringAppend(std::string &buffer,
106 std::string &newBuffer) {
107 buffer.append(newBuffer);
117#ifndef PAINLESSMESH_MAX_SENT_BUFFER_MESSAGES
118#define PAINLESSMESH_MAX_SENT_BUFFER_MESSAGES 64
140 current_read_iterator = prioritizedMessages.end();
154 bool push(
const T &message,
bool priority =
false) {
156 uint8_t priorityLevel = priority ? 1 : 2;
180 if (priorityLevel > 3) priorityLevel = 3;
183 !evictLowerPriority(priorityLevel)) {
191 totalMessagesQueued++;
192 switch(priorityLevel) {
193 case 0: criticalQueued++;
break;
194 case 1: highQueued++;
break;
195 case 2: normalQueued++;
break;
196 case 3: lowQueued++;
break;
208 auto* msg = getNextMessage();
216 if (buffer_length == 0)
return 0;
219 return (std::min)(buffer_length - 1, msg->length() + 1);
235 auto* msg = getNextMessage();
237 msg->toCharArray(buf.
buffer, length + 1);
238 last_read_size = length;
239 last_read_priority = getCurrentMessagePriority();
251 auto* msg = getNextMessage();
253 last_read_size = length;
254 last_read_priority = getCurrentMessagePriority();
266 if (prioritizedMessages.empty()) {
268 current_read_iterator = prioritizedMessages.end();
273 auto it = findHighestPriorityMessage();
274 if (it != prioritizedMessages.end()) {
275 auto& msg = it->message;
277 if (last_read_size == msg.length() + 1) {
280 switch(it->priority) {
281 case 0: criticalSent++;
break;
282 case 1: highSent++;
break;
283 case 2: normalSent++;
break;
284 case 3: lowSent++;
break;
286 prioritizedMessages.erase(it);
287 current_read_iterator = prioritizedMessages.end();
291 stringEraseFront(msg, last_read_size);
299 bool empty() {
return prioritizedMessages.empty(); }
302 prioritizedMessages.clear();
303 current_read_iterator = prioritizedMessages.end();
305 totalMessagesQueued = 0;
306 criticalQueued = highQueued = normalQueued = lowQueued = 0;
307 criticalSent = highSent = normalSent = lowSent = 0;
310 size_t size() {
return prioritizedMessages.size(); }
337 stats.
dropped = messagesDropped;
351 size_t last_read_size = 0;
352 uint8_t last_read_priority = 2;
354 std::list<PrioritizedMessage<T>> prioritizedMessages;
355 typename std::list<PrioritizedMessage<T>>::iterator current_read_iterator;
358 uint32_t messagesDropped = 0;
359 uint32_t totalMessagesQueued = 0;
360 uint32_t criticalQueued = 0;
361 uint32_t highQueued = 0;
362 uint32_t normalQueued = 0;
363 uint32_t lowQueued = 0;
364 uint32_t criticalSent = 0;
365 uint32_t highSent = 0;
366 uint32_t normalSent = 0;
367 uint32_t lowSent = 0;
377 typename std::list<PrioritizedMessage<T>>::iterator findHighestPriorityMessage() {
378 if (prioritizedMessages.empty()) {
379 return prioritizedMessages.end();
384 if (!clean && current_read_iterator != prioritizedMessages.end()) {
385 return current_read_iterator;
389 auto highest = prioritizedMessages.begin();
390 for (
auto it = prioritizedMessages.begin(); it != prioritizedMessages.end(); ++it) {
391 if (it->priority < highest->priority) {
397 current_read_iterator = highest;
404 T* getNextMessage() {
405 auto it = findHighestPriorityMessage();
406 if (it != prioritizedMessages.end()) {
407 return &(it->message);
415 uint8_t getCurrentMessagePriority() {
416 auto it = findHighestPriorityMessage();
417 if (it != prioritizedMessages.end()) {
429 bool evictLowerPriority(uint8_t newPriority) {
430 auto victim = prioritizedMessages.end();
431 for (
auto it = prioritizedMessages.begin();
432 it != prioritizedMessages.end(); ++it) {
433 if (!clean && it == current_read_iterator)
continue;
434 if (it->priority <= newPriority)
continue;
437 if (victim == prioritizedMessages.end() ||
438 it->priority >= victim->priority)
441 if (victim == prioritizedMessages.end())
return false;
443 prioritizedMessages.erase(victim);
446 if (clean) current_read_iterator = prioritizedMessages.end();
450 inline void stringEraseFront(T &
string,
size_t length) {
451 string.remove(0, length);
455#ifdef PAINLESSMESH_ENABLE_STD_STRING
458 auto* msg = getNextMessage();
460 msg->copy(buf.buffer, length);
464 if (length == msg->length() + 1) buf.buffer[length - 1] =
'\0';
465 buf.buffer[length] =
'\0';
466 last_read_size = length;
467 last_read_priority = getCurrentMessagePriority();
472inline void SentBuffer<std::string>::stringEraseFront(std::string &
string,
474 string.erase(0, length);
#define TCP_MSS
Definition asynctcp.hpp:9
#define PAINLESSMESH_MAX_SENT_BUFFER_MESSAGES
Definition buffer.hpp:118
ReceivedBuffer handles cstrings and stores them as strings.
Definition buffer.hpp:28
void clear()
Definition buffer.hpp:85
ReceiveBuffer()
Definition buffer.hpp:30
bool empty()
Definition buffer.hpp:80
void push(const char *cstr, size_t length, temp_buffer_t &buf)
Definition buffer.hpp:35
void pop_front()
Definition buffer.hpp:75
T front()
Definition buffer.hpp:67
SentBuffer stores messages (strings) and allows them to be read in any length with priority-based sch...
Definition buffer.hpp:137
SentBuffer()
Definition buffer.hpp:139
bool pushWithPriority(const T &message, uint8_t priorityLevel)
Definition buffer.hpp:178
bool push(const T &message, bool priority=false)
Definition buffer.hpp:154
size_t requestLength(size_t buffer_length)
Definition buffer.hpp:206
void read(size_t length, temp_buffer_t &buf)
Definition buffer.hpp:231
void clear()
Definition buffer.hpp:301
size_t size()
Definition buffer.hpp:310
const char * readPtr(size_t length)
Definition buffer.hpp:250
bool empty()
Definition buffer.hpp:299
void freeRead()
Definition buffer.hpp:265
SendStats getStats() const
Definition buffer.hpp:335
uint8_t getLastReadPriority() const
Definition buffer.hpp:315
Definition buffer.hpp:125
uint8_t priority
Definition buffer.hpp:127
T message
Definition buffer.hpp:126
PrioritizedMessage(const T &msg, uint8_t prio=2)
Definition buffer.hpp:129
Definition buffer.hpp:320
uint32_t highSent
Definition buffer.hpp:327
uint32_t normalSent
Definition buffer.hpp:328
uint32_t lowQueued
Definition buffer.hpp:325
uint32_t highQueued
Definition buffer.hpp:323
uint32_t totalQueued
Definition buffer.hpp:321
uint32_t criticalQueued
Definition buffer.hpp:322
uint32_t criticalSent
Definition buffer.hpp:326
uint32_t lowSent
Definition buffer.hpp:329
uint32_t normalQueued
Definition buffer.hpp:324
uint32_t dropped
Definition buffer.hpp:332
char buffer[TCP_MSS]
Definition buffer.hpp:21
size_t length
Definition buffer.hpp:20