AceCommon
1.1.2
Arduino library for low-level common functions and features with no external dependencies
|
Base class for all template instances of the PrintStr<SIZE> class. More...
#include <PrintStr.h>
Public Member Functions | |
size_t | write (uint8_t c) override |
Write a single character into the internal buffer. | |
size_t | write (const uint8_t *buf, size_t size) override |
Write the buf string of size into the internal buffer. | |
void | flush () override |
Clear the internal buffer. | |
const char * | getCstr () const |
Return the NUL terminated c-string buffer. More... | |
size_t | length () const |
Return the length of the internal c-string buffer. | |
Protected Member Functions | |
PrintStrBase (uint16_t size, char *buf) | |
Constructor. More... | |
Protected Attributes | |
char *const | buf_ |
This is the pointer to the character array buffer. More... | |
Base class for all template instances of the PrintStr<SIZE> class.
A common base class reduces the code size because only one copy of the core code is included across all possible template instances. Otherwise, PrintStr<10> is a different class than PrintStr<20> and would pull in duplicate copies of the code.
Usually the Print
base class can be used to accept instances of the PrintStr<SIZE>
objects. However, if you need access to the lenth()
method, then you need to use the PrintStrBase
class instead, since the Print
class does not have a length()
method.
Here are the actual numbers. I modified tests/CommonTest.ino program to use 2 template instances, PrintStr<10> and PrintStr<20> instead of just PrintStr<10>. Without this base class optimization, the sketch uses:
After inserting this PrintStrBase class in the class hierarchy, the same sketch uses:
So we save 94 bytes of flash memory, and 12 bytes of static RAM. And even better, the program and RAM size was the same as using 2 PrintStr<10> instances. In other words, the amount of flash and static RAM remains constant no matter how many template instances we create.
Definition at line 63 of file PrintStr.h.
|
inlineprotected |
Constructor.
size | the maximum size of the given buf buffer |
buf | pointer to the character buffer created by the subclass. The buffer will be either on the stack or on the heap. |
Definition at line 125 of file PrintStr.h.
|
inline |
Return the NUL terminated c-string buffer.
After the buffer is no longer needed, the flush() method should be called to reset the internal buffer index to 0.
Definition at line 108 of file PrintStr.h.
|
protected |
This is the pointer to the character array buffer.
For instances of PrintStr<SIZE>
, this points to actualBuf_
which is created on the stack. For instances of PrintStrN
, it points to the char array allocated on the heap.
In the case of PrintStr
, there might be a way to remove this member variable by calculating the pointer to the stack buffer, by extending the pointer from the last element of this object (i.e. &index_), and thereby saving some memory.
But I am not convinced that I have the knowledge do that properly without triggering UB (undefined behavior) in the C++ language. Do I define buf_[0] here and will it point exactly where actualBuf_[] is allocated? Or do I use [&PrintStrBase + sizeof(PrintStrBase)] to calculate the pointer to actualBuf_. I just don't know what's actually allowed in the language spec versus something that works by pure luck on a particular microcontroller and compiler. So I'll pay the cost of the 2 extra bytes (8-bit) or 4 extra bytes (32-bit processors) of RAM and store the pointer to actualBuf_ explicitly here in the base class.
Definition at line 161 of file PrintStr.h.