172
173
#define USTRING_WITH_LEN(X) ((unsigned char*) X), ((size_t) (sizeof(X) - 1))
173
174
#define C_STRING_WITH_LEN(X) ((char *) (X)), ((size_t) (sizeof(X) - 1))
175
/* SPACE_INT is a word that contains only spaces */
177
#define SPACE_INT 0x20202020
178
#elif SIZEOF_INT == 8
179
#define SPACE_INT 0x2020202020202020
181
#error define the appropriate constant for a word full of spaces
185
177
Skip trailing space.
187
On most systems reading memory in larger chunks (ideally equal to the size of
188
the chinks that the machine physically reads from memory) causes fewer memory
189
access loops and hence increased performance.
190
This is why the 'int' type is used : it's closest to that (according to how
192
So when we determine the amount of whitespace at the end of a string we do
194
1. We divide the string into 3 zones :
195
a) from the start of the string (__start) to the first multiple
196
of sizeof(int) (__start_words)
197
b) from the end of the string (__end) to the last multiple of sizeof(int)
199
c) a zone that is aligned to sizeof(int) and can be safely accessed
201
2. We start comparing backwards from (c) char-by-char. If all we find is
202
space then we continue
203
3. If there are elements in zone (b) we compare them as unsigned ints to a
204
int mask (SPACE_INT) consisting of all spaces
205
4. Finally we compare the remaining part (a) of the string char by char.
206
This covers for the last non-space unsigned int from 3. (if any)
208
This algorithm works well for relatively larger strings, but it will slow
209
the things down for smaller strings (because of the additional calculations
210
and checks compared to the naive method). Thus the barrier of length 20
213
179
@param ptr pointer to the input string
214
180
@param len the length of the string
215
181
@return the last non-space character
218
static inline const unsigned char *skip_trailing_space(const unsigned char *ptr,size_t len)
184
static inline const unsigned char *
185
skip_trailing_space(const unsigned char *ptr,size_t len)
220
187
const unsigned char *end= ptr + len;
224
const unsigned char *end_words= (const unsigned char *)(intptr_t)
225
(((uint64_t)(intptr_t)end) / SIZEOF_INT * SIZEOF_INT);
226
const unsigned char *start_words= (const unsigned char *)(intptr_t)
227
((((uint64_t)(intptr_t)ptr) + SIZEOF_INT - 1) / SIZEOF_INT * SIZEOF_INT);
229
assert(((uint64_t)(intptr_t)ptr) >= SIZEOF_INT);
232
while (end > end_words && end[-1] == 0x20)
234
if (end[-1] == 0x20 && start_words < end_words)
235
while (end > start_words && ((const unsigned *)end)[-1] == SPACE_INT)
239
while (end > ptr && end[-1] == 0x20)
189
while (end > ptr && isspace(*--end))