Skip to content

Commit 27fb6ea

Browse files
authored
This is in response to a 'to-do' in the codebase, the idea is to complete an IP address with 0s.
1 parent def319a commit 27fb6ea

File tree

2 files changed

+72
-38
lines changed

2 files changed

+72
-38
lines changed

cores/esp32/IPAddress.cpp

+69-38
Original file line numberDiff line numberDiff line change
@@ -116,48 +116,79 @@ bool IPAddress::fromString(const char *address) {
116116
}
117117

118118
bool IPAddress::fromString4(const char *address) {
119-
// TODO: add support for "a", "a.b", "a.b.c" formats
120119

121-
int16_t acc = -1; // Accumulator
122-
uint8_t dots = 0;
120+
// 192 will be interpreted as 192.0.0.0
121+
// 192.168 will be interpreted as 192.168.0.0
122+
// 192.168.1 will be interpreted as 192.168.1.0
123+
// 192.168.1.1 will be interpreted as 192.168.1.1
123124

124-
memset(_address.bytes, 0, sizeof(_address.bytes));
125-
while (*address) {
126-
char c = *address++;
127-
if (c >= '0' && c <= '9') {
128-
acc = (acc < 0) ? (c - '0') : acc * 10 + (c - '0');
129-
if (acc > 255) {
130-
// Value out of [0..255] range
131-
return false;
132-
}
133-
} else if (c == '.') {
134-
if (dots == 3) {
135-
// Too many dots (there must be 3 dots)
136-
return false;
137-
}
138-
if (acc < 0) {
139-
/* No value between dots, e.g. '1..' */
140-
return false;
141-
}
142-
_address.bytes[IPADDRESS_V4_BYTES_INDEX + dots++] = acc;
143-
acc = -1;
144-
} else {
145-
// Invalid char
146-
return false;
125+
// Should we have made it end in .1?
126+
127+
uint8_t parts[4] = {0};
128+
int part = 0;
129+
130+
memset(_address.bytes, 0, sizeof(_address.bytes));
131+
132+
while (*address && part < 4) {
133+
if (!parseIPv4Part(address, parts[part])) {
134+
return false;
135+
}
136+
part++;
137+
138+
if (*address == '.') {
139+
address++;
140+
141+
} else if (*address != '\0') {
142+
143+
return false;
144+
}
147145
}
148-
}
149146

150-
if (dots != 3) {
151-
// Too few dots (there must be 3 dots)
152-
return false;
153-
}
154-
if (acc < 0) {
155-
/* No value between dots, e.g. '1..' */
156-
return false;
157-
}
158-
_address.bytes[IPADDRESS_V4_BYTES_INDEX + 3] = acc;
159-
_type = IPv4;
160-
return true;
147+
// If address is incomplete, simply add more zeros until it's full
148+
for (int i = part; i < 4; i++) {
149+
parts[i] = 0;
150+
}
151+
152+
// Build the address
153+
for (int i = 0; i < 4; i++) {
154+
_address.bytes[IPADDRESS_V4_BYTES_INDEX + i] = parts[i];
155+
}
156+
157+
_type = IPv4;
158+
return true;
159+
}
160+
161+
bool IPAddress::parseIPv4Part(const char*& address, uint8_t& result) {
162+
163+
// This works by parsing each section of the IP address
164+
// It checks if the value is within the value space (<= 255)
165+
// Uses the 'dot' as a delineater
166+
167+
168+
int acc = 0;
169+
int dots = 0;
170+
171+
while (*address) {
172+
char c = *address;
173+
if (c >= '0' && c <= '9') {
174+
acc = acc * 10 + (c - '0');
175+
if (acc > 255) {
176+
return false;
177+
}
178+
} else if (c == '.' || c == '\0') {
179+
if (dots == 3 || acc > 255) {
180+
return false;
181+
}
182+
result = acc;
183+
return true;
184+
} else {
185+
return false;
186+
}
187+
address++;
188+
}
189+
190+
result = acc;
191+
return true;
161192
}
162193

163194
bool IPAddress::fromString6(const char *address) {

cores/esp32/IPAddress.h

+3
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ class IPAddress : public Printable {
4444
IPType _type;
4545
uint8_t _zone;
4646

47+
// Helper for parsing IPv4 address sections
48+
bool parseIPv4Part(const char*& address, uint8_t& result);
49+
4750
// Access the raw byte array containing the address. Because this returns a pointer
4851
// to the internal structure rather than a copy of the address this function should only
4952
// be used when you know that the usage of the returned uint8_t* will be transient and not

0 commit comments

Comments
 (0)