-
-
Notifications
You must be signed in to change notification settings - Fork 19.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
93ffd57
commit 9752310
Showing
26 changed files
with
441 additions
and
176 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,219 @@ | ||
/** | ||
* Marlin 3D Printer Firmware | ||
* Copyright (c) 2022 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] | ||
* | ||
* Based on Sprinter and grbl. | ||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm | ||
* | ||
* 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 <https://www.gnu.org/licenses/>. | ||
* | ||
*/ | ||
#pragma once | ||
|
||
/** | ||
* Lightweight Arduino string class providing operators for all common tasks | ||
* and conversion from F() and PSTR() strings into SRAM strings, that reside | ||
* on the stack or persistently. | ||
* | ||
* Usage: | ||
* Create a string object with the usual construction methods. | ||
*/ | ||
|
||
#include "types.h" | ||
#include "utility.h" // AXIS_CHAR | ||
#include "../lcd/fontutils.h" | ||
|
||
#ifndef DEFAULT_MSTRING_SIZE | ||
#define DEFAULT_MSTRING_SIZE 20 | ||
#endif | ||
|
||
// Light declarations for serial.h | ||
template <typename T> void SERIAL_ECHO(T x); | ||
template <typename T> void SERIAL_ECHOLN(T x); | ||
|
||
//#define DJB2_HASH // 32-bit hash with Djb2 algorithm | ||
|
||
#define START_OF_UTF8_CHAR(C) (((C) & 0xC0u) != 0x80U) | ||
|
||
typedef struct { float value; int prec; } prec_float_t; | ||
|
||
/** | ||
* A simple string template class to compose temporary strings on the stack | ||
*/ | ||
template <int SIZE=DEFAULT_MSTRING_SIZE> | ||
class MString { | ||
public: | ||
char str[SIZE+1]; | ||
MString() { str[0] = '\0'; str[SIZE] = '\0'; } | ||
|
||
template<typename T> | ||
MString(const T v) { set(v); } | ||
|
||
static_assert(SIZE > 0, "Bad SIZE for MString <= 0"); | ||
|
||
// Chainable String Setters | ||
MString& set() { str[0] = '\0'; return *this; } | ||
MString& set(const char *s) { strncpy(str, s, SIZE); return *this; } | ||
MString& set_P(PGM_P const s) { strncpy_P(str, s, SIZE); return *this; } | ||
MString& set(FSTR_P const f) { set_P(FTOP(f)); return *this; } | ||
MString& set(const MString &s) { strncpy(str, s.str, SIZE); return *this; } | ||
MString& set(const bool &b) { set(b ? F("true") : F("false")); return *this; } | ||
MString& set(const char c) { str[0] = c; str[1] = '\0'; return *this; } | ||
MString& set(const short &i) { snprintf(str, SIZE, "%d", i); return *this; } | ||
MString& set(const int &i) { snprintf(str, SIZE, "%d", i); return *this; } | ||
MString& set(const long &l) { snprintf(str, SIZE, "%ld", l); return *this; } | ||
MString& set(const unsigned char &i) { snprintf(str, SIZE, "%u", i); return *this; } | ||
MString& set(const unsigned short &i) { snprintf(str, SIZE, "%u", i); return *this; } | ||
MString& set(const unsigned int &i) { snprintf(str, SIZE, "%u", i); return *this; } | ||
MString& set(const unsigned long &l) { snprintf(str, SIZE, "%lu", l); return *this; } | ||
MString& set(const float &f) { set(prec_float_t({ f, SERIAL_FLOAT_PRECISION })); return *this; } | ||
MString& set(const prec_float_t &pf) { char f1[12]; set(dtostrf(pf.value, 0, pf.prec, f1)); return *this; } | ||
MString& set(const serial_char_t &v) { set(char(v.c)); return *this; } | ||
MString& set(const xyz_pos_t &v) { set(); append(v); return *this; } | ||
MString& set(const xyze_pos_t &v) { set(); append(v); return *this; } | ||
|
||
// Chainable String appenders | ||
MString& append() { return *this; } // for macros that might emit no output | ||
MString& append(const char *s) { strncat(str, s, SIZE); return *this; } | ||
MString& append(const MString &s) { append(s.str); return *this; } | ||
MString& append_P(PGM_P const s) { strncat_P(str, s, SIZE); return *this; } | ||
MString& append(FSTR_P const f) { append_P(FTOP(f)); return *this; } | ||
MString& append(const bool &b) { append(b ? F("true") : F("false")); return *this; } | ||
MString& append(const char c) { const int last = strlen(str); if (last < SIZE) { str[last] = c; str[last+1] = '\0'; } | ||
return *this; } | ||
MString& append(const short &i) { char buf[32]; sprintf(buf, "%d", i); append(buf); return *this; } | ||
MString& append(const int &i) { char buf[32]; sprintf(buf, "%d", i); append(buf); return *this; } | ||
MString& append(const long &l) { char buf[32]; sprintf(buf, "%ld", l); append(buf); return *this; } | ||
MString& append(const unsigned char &i) { char buf[32]; sprintf(buf, "%u", i); append(buf); return *this; } | ||
MString& append(const unsigned short &i) { char buf[32]; sprintf(buf, "%u", i); append(buf); return *this; } | ||
MString& append(const unsigned int &i) { char buf[32]; sprintf(buf, "%u", i); append(buf); return *this; } | ||
MString& append(const unsigned long &l) { char buf[32]; sprintf(buf, "%lu", l); append(buf); return *this; } | ||
MString& append(const float &f) { append(prec_float_t({ f, SERIAL_FLOAT_PRECISION })); return *this; } | ||
MString& append(const prec_float_t &pf) { char f1[12]; append(dtostrf(pf.value, 0, pf.prec, f1)); return *this; } | ||
MString& append(const serial_char_t &v) { append(char(v.c)); return *this; } | ||
MString& append(const xyz_pos_t &v) { LOOP_NUM_AXES(i) append(AXIS_CHAR(i), v[i], ' '); return *this; } | ||
MString& append(const xyze_pos_t &v) { LOOP_LOGICAL_AXES(i) append(AXIS_CHAR(i), v[i], ' '); return *this; } | ||
|
||
MString& eol() { append('\n'); } | ||
|
||
// Instantiate with a list of things | ||
template <typename T, typename... Args> | ||
MString(T arg1, Args... more) { set(arg1); append(more...); } | ||
|
||
// Take a list of any number of arguments and append them to the string | ||
template<typename T, typename... Args> | ||
MString& append(T arg1, Args... more) { return append(arg1).append(more...); } | ||
|
||
// Take a list of any number of arguments and set them in the string | ||
template<typename T, typename... Args> | ||
MString& set(T arg1, Args... more) { return set(arg1).append(more...); } | ||
|
||
MString& operator=(const char *s) { set(s); return *this; } | ||
MString& operator=(FSTR_P const f) { set(f); return *this; } | ||
MString& operator=(const MString &s) { set(s.str); return *this; } | ||
MString& operator=(const bool &b) { set(b); return *this; } | ||
MString& operator=(const char &c) { set(c); return *this; } | ||
MString& operator=(const short &i) { set(i); return *this; } | ||
MString& operator=(const int &i) { set(i); return *this; } | ||
MString& operator=(const long &l) { set(l); return *this; } | ||
MString& operator=(const unsigned char &i) { set(i); return *this; } | ||
MString& operator=(const unsigned short &i) { set(i); return *this; } | ||
MString& operator=(const unsigned int &i) { set(i); return *this; } | ||
MString& operator=(const unsigned long &l) { set(l); return *this; } | ||
MString& operator=(const float &f) { set(f); return *this; } | ||
MString& operator=(const prec_float_t &p) { set(p); return *this; } | ||
MString& operator=(const serial_char_t &c) { set(c); return *this; } | ||
MString& operator=(const xyz_pos_t &v) { set(v); return *this; } | ||
MString& operator=(const xyze_pos_t &v) { set(v); return *this; } | ||
|
||
MString& operator+=(const char *s) { append(s); return *this; } | ||
MString& operator+=(FSTR_P const f) { append(f); return *this; } | ||
MString& operator+=(const MString &s) { append(s); return *this; } | ||
MString& operator+=(const bool &b) { append(b); return *this; } | ||
MString& operator+=(const char &c) { append(c); return *this; } | ||
MString& operator+=(const short &i) { append(i); return *this; } | ||
MString& operator+=(const int &i) { append(i); return *this; } | ||
MString& operator+=(const long &l) { append(l); return *this; } | ||
MString& operator+=(const unsigned char &i) { append(i); return *this; } | ||
MString& operator+=(const unsigned short &i) { append(i); return *this; } | ||
MString& operator+=(const unsigned int &i) { append(i); return *this; } | ||
MString& operator+=(const unsigned long &l) { append(l); return *this; } | ||
MString& operator+=(const float &f) { append(f); return *this; } | ||
MString& operator+=(const prec_float_t &p) { append(p); return *this; } | ||
MString& operator+=(const serial_char_t &c) { append(c); return *this; } | ||
MString& operator+=(const xyz_pos_t &v) { append(v); return *this; } | ||
MString& operator+=(const xyze_pos_t &v) { append(v); return *this; } | ||
|
||
MString operator+(const char *s) { return MString(str, s); } | ||
MString operator+(FSTR_P const f) { return MString(str, f); } | ||
MString operator+(const MString &s) { return MString(str, s); } | ||
MString operator+(const bool &b) { return MString(str, b); } | ||
MString operator+(const char c) { return MString(str, c); } | ||
MString operator+(const short &i) { return MString(str, i); } | ||
MString operator+(const int &i) { return MString(str, i); } | ||
MString operator+(const long &l) { return MString(str, l); } | ||
MString operator+(const unsigned char &i) { return MString(str, i); } | ||
MString operator+(const unsigned short &i) { return MString(str, i); } | ||
MString operator+(const unsigned int &i) { return MString(str, i); } | ||
MString operator+(const unsigned long &l) { return MString(str, l); } | ||
MString operator+(const float &f) { return MString(str, f); } | ||
MString operator+(const prec_float_t &p) { return MString(str, p); } | ||
MString operator+(const serial_char_t &c) { return MString(str, c); } | ||
MString operator+(const xyz_pos_t &v) { return MString(str, v); } | ||
MString operator+(const xyze_pos_t &v) { return MString(str, v); } | ||
|
||
#ifndef __AVR__ | ||
MString(const double d) { set(d); } | ||
MString& set(const double &d) { char d1[12]; dtostrf(d, 0, SERIAL_FLOAT_PRECISION, d1); return set(d1); } | ||
MString& append(const double &d) { char d1[12]; dtostrf(d, 0, SERIAL_FLOAT_PRECISION, d1); return append(d1); } | ||
MString& operator=(const double &d) { set(d); return *this; } | ||
MString& operator+=(const double &d) { append(d); return *this; } | ||
MString operator+(const double &d) { return MString(str, d); } | ||
#endif | ||
|
||
char operator[](const int i) const { return str[i]; } | ||
|
||
char* buffer() { return str; } | ||
size_t length() const { return strlen(str); } | ||
int glyphs() { return utf8_strlen(str); } | ||
bool empty() { return !str[0]; } | ||
|
||
// Quick hash to detect change (e.g., to avoid expensive drawing) | ||
typedef IF<ENABLED(DJB2_HASH), uint32_t, uint16_t>::type hash_t; | ||
hash_t hash() const { | ||
#if ENABLED(DJB2_HASH) | ||
hash_t hval = 5381; | ||
char c; | ||
while ((c = *str++)) hval += (hval << 5) + c; // = hval * 33 + c | ||
#else | ||
const size_t len = length(); | ||
hash_t hval = hash_t(len); | ||
for (size_t i = 0; i < len; i++) hval = ((hval << 1) | (hval << 15)) ^ str[i]; // ROL, XOR | ||
#endif | ||
return hval; | ||
} | ||
|
||
void copyto(char * const dst) const { strcpy(dst, str); } | ||
void copyto(char * const dst, const size_t len) const { strncpy(dst, str, len); } | ||
|
||
MString& clear() { return set(); } | ||
MString& concat(const int &i) { if (i <= SIZE) str[i] = '\0'; return *this; } | ||
MString& echo() { SERIAL_ECHO(str); return *this; } | ||
MString& echoln() { SERIAL_ECHOLN(str); return *this; } | ||
}; | ||
|
||
#ifndef TS_SIZE | ||
#define TS_SIZE 20 | ||
#endif | ||
#define TS(V...) MString<TS_SIZE>(V) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.