AceCommon  1.6.0
Arduino library for low-level common functions and features with no external dependencies
Public Member Functions | Protected Member Functions | Protected Attributes | List of all members
ace_common::PrintStrBase Class Reference

Base class for all template instances of the PrintStr<SIZE> class. More...

#include <PrintStr.h>

Inheritance diagram for ace_common::PrintStrBase:
Inheritance graph
[legend]
Collaboration diagram for ace_common::PrintStrBase:
Collaboration graph
[legend]

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. More...
 
const char * cstr () const
 Return the NUL terminated c-string buffer. More...
 
const char * getCstr () const
 Backwards compatible version of cstr(). More...
 
size_t length () const
 Return the length of the internal c-string buffer, not including the NUL terminator.
 

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...
 

Detailed Description

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 length() 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.

Constructor & Destructor Documentation

◆ PrintStrBase()

ace_common::PrintStrBase::PrintStrBase ( uint16_t  size,
char *  buf 
)
inlineprotected

Constructor.

Parameters
sizethe maximum size of the given buf buffer
bufpointer to the character buffer created by the subclass. The buffer will be either on the stack or on the heap.

Definition at line 163 of file PrintStr.h.

Member Function Documentation

◆ cstr()

const char* ace_common::PrintStrBase::cstr ( ) const
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.

The cstr() name was deliberately chosen to be different from the c_str() method in the C++ std::string class or the Arduino String class. When we see an object being called with cstr(), we can infer that its type is PrintStr or PrintStrN.

Definition at line 142 of file PrintStr.h.

◆ flush()

void ace_common::PrintStrBase::flush ( )
inlineoverride

Clear the internal buffer.

On most platforms (AVR, SAMD21, ESP8266, Teensy), the Print::flush() method is virtual, so this would normally be tagged with the 'override' keyword. But until recently, the ESP32 and STM32 platforms implemented the flush() method as non-virtual methods. So I was forced to avoid marking this implementation with the override keyword, which unfortunately triggered warning messages when compiled with clang++ compiler on Linux or MacOS using the EpoxyDuino environment.

The STM32 platform fixed this in v2.0.0 on 2021-04-21, and the ESP32 platform fixed this in v2.0.3 on 2022-05-04. I think we can finally assume that most platforms implement a virtual flush() and apply the override keyword here, which also fixes the compiler warnings in EpoxyDuino.

The only platform that is officially supported by AceCommon where the override will cause problems is the https://github.com/SpenceKonde/ATTinyCore platform whose Print class does not implement flush() at all. I have to make an exception for that Core, but there does not seem to be a single macro symbol that identifies the ATTinyCore. I have to enumerate each microcontroller type supported by that Core. Other platforms which also implement a non-virtual flush() can be listed in the exception list.

Definition at line 127 of file PrintStr.h.

◆ getCstr()

const char* ace_common::PrintStrBase::getCstr ( ) const
inline

Backwards compatible version of cstr().

New code should use cstr().

Definition at line 148 of file PrintStr.h.

Member Data Documentation

◆ buf_

char* const ace_common::PrintStrBase::buf_
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 199 of file PrintStr.h.


The documentation for this class was generated from the following file: