AceCommon  1.5.2
Arduino library for low-level common functions and features with no external dependencies
KString.cpp
1 #include <Arduino.h>
2 #include <string.h>
3 #include "KString.h"
4 
5 namespace ace_common {
6 
7 int KString::compareTo(const char* s) {
8  if (string_ == s) { return 0; }
9  if (string_ == nullptr) { return -1; }
10  if (s == nullptr) { return 1; }
11 
12  const char* a = (const char*) string_;
13  const char* b = s;
14  bool isCstring = (type_ == kTypeCstring);
15  while (true) {
16  uint8_t cb = *b;
17 
18  Restart:
19  // Extract the current character depending on the 'type_'. Normally doing a
20  // conditional check inside an inner loop is not good for performance.
21  // However, when I pulled this code out into a template function (using a
22  // thin-wrapper CString and FString), the AceTime/AutoBenchmark program
23  // showed that it made no perceptible difference in performance. I think
24  // this is because there is enough overhead in the rest of function to make
25  // this conditional code unimportant.
26  uint8_t ca = isCstring ? *a : pgm_read_byte(a);
27 
28  if (ca != cb) {
29  // If ca is a keyword reference, then compare against the keyword.
30  // Recursive keyword substitution not allowed, because I don't want to
31  // make this function recursive.
32  if (0 < ca && ca < numKeywords_) {
33  const char* k = keywords_[ca];
34  while (true) {
35  ca = *k;
36  cb = *b;
37  if (ca == '\0') {
38  a++;
39  // Terrible goto, but it's the easiest way to bail out of the inner
40  // loop and continue the outer loop at the correct character.
41  goto Restart;
42  }
43  if (ca != cb) {
44  return (int) ca - (int) cb;
45  }
46  k++;
47  b++;
48  }
49  } else {
50  return (int) ca - (int) cb;
51  }
52  }
53  if (ca == '\0') return 0;
54  a++;
55  b++;
56  }
57 }
58 
59 int KString::compareTo(const KString& s) {
60  if (this == &s) { return 0; }
61  if (string_ == s.string_) { return 0; }
62  if (string_ == nullptr) { return -1; }
63  if (s.string_ == nullptr) { return 1; }
64 
65  KStringIterator aiter(*this);
66  KStringIterator biter(s);
67  while (true) {
68  char ca = aiter.get();
69  char cb = biter.get();
70 
71  if (ca == cb) {
72  if (ca == '\0') {
73  return 0;
74  }
75  } else {
76  return ca - cb;
77  }
78  aiter.next();
79  biter.next();
80  }
81 }
82 
83 void KString::printTo(Print& printer) {
84  const char* s = (const char*) string_;
85  if (s == nullptr) return;
86 
87  bool isCstring = (type_ == kTypeCstring);
88  while (true) {
89  // Same comment as above, doing a conditional check inside an inner loop is
90  // usually not good for performance. But the templatized version of
91  // compareTo() made no difference, and this function which outputs to a
92  // Printer is not expected to be in a performance critical section.
93  char c = isCstring ? *s : pgm_read_byte(s);
94 
95  s++;
96  if (c == 0) break;
97  if (c < numKeywords_) {
98  printer.print(keywords_[(uint8_t) c]);
99  } else {
100  printer.write(c);
101  }
102  }
103 }
104 
105 } // ace_common
An interator that points to a character inside a KString.
Definition: KString.h:127
void next()
Advance the iterator one character,.
Definition: KString.h:176
char get()
Return the current character referenced by the iterator.
Definition: KString.h:147
A wrapper class around a normal c-string or Arduino f-string which is encoded and compressed using ke...
Definition: KString.h:53
void printTo(Print &printer)
Expand and print the current string to the given printer.
Definition: KString.cpp:83
int compareTo(const char *s)
Compare this string against a c-string s and return <0, 0 or >0 if this string is <,...
Definition: KString.cpp:7