Skip to content

Commit 1a5d044

Browse files
Add non-standard library calls used by String
Borrowed from https://github.com/esp8266/Arduino , include dtostrf() and others. Fixes earlephilhower#13
1 parent aa110a6 commit 1a5d044

File tree

2 files changed

+245
-0
lines changed

2 files changed

+245
-0
lines changed

cores/rp2040/stdlib_noniso.cpp

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
/*
2+
stdlib_noniso.h - nonstandard (but useful) conversion functions
3+
4+
Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
5+
Copyright (c) 2021 David Gauchard. All rights reserved.
6+
This file is part of the esp8266 core for Arduino environment.
7+
8+
This library is free software; you can redistribute it and/or
9+
modify it under the terms of the GNU Lesser General Public
10+
License as published by the Free Software Foundation; either
11+
version 2.1 of the License, or (at your option) any later version.
12+
13+
This library is distributed in the hope that it will be useful,
14+
but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16+
Lesser General Public License for more details.
17+
18+
You should have received a copy of the GNU Lesser General Public
19+
License along with this library; if not, write to the Free Software
20+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21+
*/
22+
23+
#include <stdlib.h>
24+
#include <string.h>
25+
#include <stdbool.h>
26+
#include <stdint.h>
27+
#include <math.h>
28+
#include <limits>
29+
#include "stdlib_noniso.h"
30+
31+
// ulltoa() is slower than std::to_char() (1.6 times)
32+
// but is smaller by ~800B/flash and ~250B/rodata
33+
34+
// ulltoa fills str backwards and can return a pointer different from str
35+
extern "C" char* ulltoa(unsigned long long val, char* str, int slen, unsigned int radix)
36+
{
37+
str += --slen;
38+
*str = 0;
39+
do
40+
{
41+
auto mod = val % radix;
42+
val /= radix;
43+
*--str = mod + ((mod > 9) ? ('a' - 10) : '0');
44+
} while (--slen && val);
45+
return val? nullptr: str;
46+
}
47+
48+
// lltoa fills str backwards and can return a pointer different from str
49+
extern "C" char* lltoa (long long val, char* str, int slen, unsigned int radix)
50+
{
51+
bool neg;
52+
if (val < 0)
53+
{
54+
val = -val;
55+
neg = true;
56+
}
57+
else
58+
{
59+
neg = false;
60+
}
61+
char* ret = ulltoa(val, str, slen, radix);
62+
if (neg)
63+
{
64+
if (ret == str || ret == nullptr)
65+
return nullptr;
66+
*--ret = '-';
67+
}
68+
return ret;
69+
}
70+
71+
extern "C" char* ltoa(long value, char* result, int base) {
72+
return itoa((int)value, result, base);
73+
}
74+
75+
extern "C" char* ultoa(unsigned long value, char* result, int base) {
76+
return utoa((unsigned int)value, result, base);
77+
}
78+
79+
extern "C" char * dtostrf(double number, signed char width, unsigned char prec, char *s) {
80+
bool negative = false;
81+
82+
if (isnan(number)) {
83+
strcpy(s, "nan");
84+
return s;
85+
}
86+
if (isinf(number)) {
87+
strcpy(s, "inf");
88+
return s;
89+
}
90+
91+
char* out = s;
92+
93+
int fillme = width; // how many cells to fill for the integer part
94+
if (prec > 0) {
95+
fillme -= (prec+1);
96+
}
97+
98+
// Handle negative numbers
99+
if (number < 0.0) {
100+
negative = true;
101+
fillme--;
102+
number = -number;
103+
}
104+
105+
// Round correctly so that print(1.999, 2) prints as "2.00"
106+
// I optimized out most of the divisions
107+
double rounding = 2.0;
108+
for (uint8_t i = 0; i < prec; ++i)
109+
rounding *= 10.0;
110+
rounding = 1.0 / rounding;
111+
112+
number += rounding;
113+
114+
// Figure out how big our number really is
115+
double tenpow = 1.0;
116+
int digitcount = 1;
117+
double nextpow;
118+
while (number >= (nextpow = (10.0 * tenpow))) {
119+
tenpow = nextpow;
120+
digitcount++;
121+
}
122+
123+
// minimal compensation for possible lack of precision (#7087 addition)
124+
number *= 1 + std::numeric_limits<decltype(number)>::epsilon();
125+
126+
number /= tenpow;
127+
fillme -= digitcount;
128+
129+
// Pad unused cells with spaces
130+
while (fillme-- > 0) {
131+
*out++ = ' ';
132+
}
133+
134+
// Handle negative sign
135+
if (negative) *out++ = '-';
136+
137+
// Print the digits, and if necessary, the decimal point
138+
digitcount += prec;
139+
int8_t digit = 0;
140+
while (digitcount-- > 0) {
141+
digit = (int8_t)number;
142+
if (digit > 9) digit = 9; // insurance
143+
*out++ = (char)('0' | digit);
144+
if ((digitcount == prec) && (prec > 0)) {
145+
*out++ = '.';
146+
}
147+
number -= digit;
148+
number *= 10.0;
149+
}
150+
151+
// make sure the string is terminated
152+
*out = 0;
153+
return s;
154+
}
155+
156+
/*
157+
strrstr (static)
158+
159+
Backwards search for p_pcPattern in p_pcString
160+
Based on: https://stackoverflow.com/a/1634398/2778898
161+
162+
*/
163+
extern "C" const char* strrstr(const char*__restrict p_pcString,
164+
const char*__restrict p_pcPattern)
165+
{
166+
const char* pcResult = 0;
167+
168+
size_t stStringLength = (p_pcString ? strlen(p_pcString) : 0);
169+
size_t stPatternLength = (p_pcPattern ? strlen(p_pcPattern) : 0);
170+
171+
if ((stStringLength) &&
172+
(stPatternLength) &&
173+
(stPatternLength <= stStringLength))
174+
{
175+
// Pattern is shorter or has the same length than the string
176+
for (const char* s = (p_pcString + stStringLength - stPatternLength); s >= p_pcString; --s)
177+
{
178+
if (0 == strncmp(s, p_pcPattern, stPatternLength))
179+
{
180+
pcResult = s;
181+
break;
182+
}
183+
}
184+
}
185+
return pcResult;
186+
}

cores/rp2040/stdlib_noniso.h

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
stdlib_noniso.h - nonstandard (but useful) conversion functions
3+
4+
Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
5+
This file is part of the esp8266 core for Arduino environment.
6+
7+
This library is free software; you can redistribute it and/or
8+
modify it under the terms of the GNU Lesser General Public
9+
License as published by the Free Software Foundation; either
10+
version 2.1 of the License, or (at your option) any later version.
11+
12+
This library is distributed in the hope that it will be useful,
13+
but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15+
Lesser General Public License for more details.
16+
17+
You should have received a copy of the GNU Lesser General Public
18+
License along with this library; if not, write to the Free Software
19+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20+
*/
21+
22+
#ifndef STDLIB_NONISO_H
23+
#define STDLIB_NONISO_H
24+
25+
#ifdef __cplusplus
26+
extern "C"{
27+
#endif
28+
29+
int atoi(const char *s);
30+
31+
long atol(const char* s);
32+
33+
double atof(const char* s);
34+
35+
char* itoa (int val, char *s, int radix);
36+
37+
char* ltoa (long val, char *s, int radix);
38+
39+
char* lltoa (long long val, char* str, int slen, unsigned int radix);
40+
41+
char* utoa (unsigned int val, char *s, int radix);
42+
43+
char* ultoa (unsigned long val, char *s, int radix);
44+
45+
char* ulltoa (unsigned long long val, char* str, int slen, unsigned int radix);
46+
47+
char* dtostrf (double val, signed char width, unsigned char prec, char *s);
48+
49+
void reverse(char* begin, char* end);
50+
51+
const char* strrstr(const char*__restrict p_pcString,
52+
const char*__restrict p_pcPattern);
53+
54+
#ifdef __cplusplus
55+
} // extern "C"
56+
#endif
57+
58+
59+
#endif

0 commit comments

Comments
 (0)