diff --git a/libraries/AP_Common/ExpandingString.cpp b/libraries/AP_Common/ExpandingString.cpp new file mode 100644 index 0000000000..c6a701eec3 --- /dev/null +++ b/libraries/AP_Common/ExpandingString.cpp @@ -0,0 +1,102 @@ +/* + 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 . + */ +/* + expanding string for easy construction of text buffers + */ + +#include "ExpandingString.h" + +extern const AP_HAL::HAL& hal; + +#define EXPAND_INCREMENT 512 + +/* + expand the string buffer + */ +bool ExpandingString::expand(uint32_t min_extra_space_needed) +{ + // expand a reasonable amount + uint32_t newsize = (5*buflen/4) + EXPAND_INCREMENT; + if (newsize - used < min_extra_space_needed) { + newsize = used + min_extra_space_needed; + } + + // add one to ensure we are always null terminated + void *newbuf = hal.util->std_realloc(buf, newsize+1); + + if (newbuf == nullptr) { + allocation_failed = true; + return false; + } + + buflen = newsize; + buf = (char *)newbuf; + + return true; +} + +/* + print into the buffer, expanding if needed + */ +void ExpandingString::printf(const char *format, ...) +{ + if (allocation_failed) { + return; + } + if (buflen == used && !expand(0)) { + return; + } + int n; + + /* + print into the buffer, expanding the buffer if needed + */ + while (true) { + va_list arg; + va_start(arg, format); + n = hal.util->vsnprintf(&buf[used], buflen-used, format, arg); + va_end(arg); + if (n < 0) { + return; + } + if (uint32_t(n) < buflen - used) { + break; + } + if (!expand(n+1)) { + return; + } + } + used += n; +} + +/* + print into the buffer, expanding if needed + */ +void ExpandingString::append(const char *s, uint32_t len) +{ + if (allocation_failed) { + return; + } + if (buflen - used < len && !expand(len)) { + return; + } + memcpy(&buf[used], s, len); + used += len; +} + +ExpandingString::~ExpandingString() +{ + free(buf); +} diff --git a/libraries/AP_Common/ExpandingString.h b/libraries/AP_Common/ExpandingString.h new file mode 100644 index 0000000000..54a124def0 --- /dev/null +++ b/libraries/AP_Common/ExpandingString.h @@ -0,0 +1,54 @@ +/* + 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 . + */ +/* + expanding string for easy construction of text buffers + */ + +#pragma once + +#include + +class ExpandingString { +public: + + const char *get_string(void) const { + return buf; + } + uint32_t get_length(void) const { + return used; + } + + // print into the string + void printf(const char *format, ...) FMT_PRINTF(2,3); + + // append data to the string + void append(const char *s, uint32_t len); + + // destructor + ~ExpandingString(); + + bool has_failed_allocation() const { + return allocation_failed; + } + +private: + char *buf; + uint32_t buflen; + uint32_t used; + bool allocation_failed; + + // try to expand the buffer + bool expand(uint32_t min_needed) WARN_IF_UNUSED; +};