__FlashStringHelper Length

I'm trying to write a few things to my OLED using the SSD1306ASCII library. Everything works great. Right now, however, to center the text on the OLED, I'm using const char* instead of __FlashStringHelper.

I wrote a function that calculates the center point to print a line of text. It works fine for const char*. Is there an easy way to create an overload and do the same with __FlashStringHelper?

void writeText(const char* text) {
	_oled.clear();
	_oled.setFont(System5x7);
	_oled.set2X();
	_oled.setCursor((128 - (10 * strlen(text))) / 2, 0);
	_oled.println(text);
}

Is there an easy way to create an overload and do the same with __FlashStringHelper?

Yes.

Clearly, Serial.print() needs to understand how much data to actually write to the serial port, so look at how the Print class (that HardwareSerial derives from) does it.

I was digging into that earlier today, and was bummed to see it just iterate it, one character at a time.

(For knowledge’s sake) HardwareSerial inherits from Stream which inherits from Print. This is from Print.cpp:

size_t Print::print(const __FlashStringHelper *ifsh)
{
  PGM_P p = reinterpret_cast<PGM_P>(ifsh);
  size_t n = 0;
  while (1) {
    unsigned char c = pgm_read_byte(p++);
    if (c == 0) break;
    if (write(c)) n++;
    else break;
  }
  return n;
}

Are you suggesting just:

size_t getLength(const __FlashStringHelper *ifsh)
{
  PGM_P p = reinterpret_cast<PGM_P>(ifsh);
  size_t n = 0;
  while (1) {
    unsigned char c = pgm_read_byte(p++);
    if (c == 0) break;
    n++;
  }
  return n;
}

Is that efficient or a waste of resources? (Forgive me; I’m a C# developer and worrying about efficiency isn’t normally a priority, so I’m having to relearn.) Especially since it seems like I’d have to iterate the *ifsh twice: once for length to calculate screen position then a second time to actually write the letters to the screen.

I was digging into that earlier today, and was bummed to see it just iterate it, one character at a time.

The point is it knows how many times to iterate, based on the length of the string. That is what you want to know - the length of the string.

Is that efficient or a waste of resources?

It is looking at the first character in the string, as it is stored in flash memory. If that character is not the null, it counts it, and looks at the next one. If it is, it returns the number of non-NULL characters it looked at. That is exactly what strlen() does for strings that are copied into SRAM.

So, yes, it is efficient.

Especially since it seems like I'd have to iterate the *ifsh twice: once for length to calculate screen position then a second time to actually write the letters to the screen.

Yes. But, so what? It will take a few hundred nanoseconds to do each traversal, plus whatever length of time it takes to deal with the character (none on the first pass, probably considerable on the second pass).

Your concern is about carrying a clean 5 pound brick for 5 miles vs. carrying a dusty 5 pound brick for 5 miles. At the end, the dust isn't going to matter. It's the f**king brick you are going to hate.

That's all I needed to know. As always, thanks for your help!