1 /** @file
2
3 A brief file description
4
5 @section license License
6
7 Licensed to the Apache Software Foundation (ASF) under one
8 or more contributor license agreements. See the NOTICE file
9 distributed with this work for additional information
10 regarding copyright ownership. The ASF licenses this file
11 to you under the Apache License, Version 2.0 (the
12 "License"); you may not use this file except in compliance
13 with the License. You may obtain a copy of the License at
14
15 http://www.apache.org/licenses/LICENSE-2.0
16
17 Unless required by applicable law or agreed to in writing, software
18 distributed under the License is distributed on an "AS IS" BASIS,
19 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 See the License for the specific language governing permissions and
21 limitations under the License.
22 */
23
24 #pragma once
25
26 #include <cstring>
27 // I had to move this here, because I really needed to avoid including ink_platform.h in here,
28 // because of a conflict on linux/tcp.h vs netinet/tcp.h.
29 #include <limits.h> // NOLINT(modernize-deprecated-headers)
30
31 #include "tscore/ink_defs.h"
32 #include "tscore/ink_apidefs.h"
33
34 typedef unsigned int CTypeResult;
35
36 // Set this to 0 to disable SI
37 // decimal multipliers
38 #define USE_SI_MULTIPLIERS 1
39
40 #define is_char_BIT (1 << 0)
41 #define is_upalpha_BIT (1 << 1)
42 #define is_loalpha_BIT (1 << 2)
43 #define is_alpha_BIT (1 << 3)
44 #define is_digit_BIT (1 << 4)
45 #define is_ctl_BIT (1 << 5)
46 #define is_ws_BIT (1 << 6)
47 #define is_hex_BIT (1 << 7)
48 #define is_pchar_BIT (1 << 8)
49 #define is_extra_BIT (1 << 9)
50 #define is_safe_BIT (1 << 10)
51 #define is_unsafe_BIT (1 << 11)
52 #define is_national_BIT (1 << 12)
53 #define is_reserved_BIT (1 << 13)
54 #define is_unreserved_BIT (1 << 14)
55 #define is_punct_BIT (1 << 15)
56 #define is_end_of_url_BIT (1 << 16)
57 #define is_tspecials_BIT (1 << 17)
58 #define is_spcr_BIT (1 << 18)
59 #define is_splf_BIT (1 << 19)
60 #define is_wslfcr_BIT (1 << 20)
61 #define is_eow_BIT (1 << 21)
62 #define is_token_BIT (1 << 22)
63 #define is_uri_BIT (1 << 23)
64 #define is_sep_BIT (1 << 24)
65 #define is_empty_BIT (1 << 25)
66 #define is_alnum_BIT (1 << 26)
67 #define is_space_BIT (1 << 27)
68 #define is_control_BIT (1 << 28)
69 #define is_mime_sep_BIT (1 << 29)
70 #define is_http_field_name_BIT (1 << 30)
71 /* shut up the DEC compiler */
72 #define is_http_field_value_BIT (((CTypeResult)1) << 31)
73
74 extern ink_undoc_liapi const CTypeResult parseRulesCType[];
75 inkcoreapi extern const char parseRulesCTypeToUpper[];
76 inkcoreapi extern const char parseRulesCTypeToLower[];
77
78 class ParseRules
79 {
80 public:
81 ParseRules();
82
83 ////////////////////////////
84 // whitespace definitions //
85 ////////////////////////////
86
87 enum {
88 CHAR_SP = 32, /* space */
89 CHAR_HT = 9, /* horizontal tab */
90 CHAR_LF = 10, /* line feed */
91 CHAR_VT = 11, /* vertical tab */
92 CHAR_NP = 12, /* new page */
93 CHAR_CR = 13 /* carriage return */
94 };
95
96 /////////////////////
97 // character tests //
98 /////////////////////
99
100 static CTypeResult is_type(char c, uint32_t bit);
101
102 static CTypeResult is_char(char c); // ASCII 0-127
103 static CTypeResult is_upalpha(char c); // A-Z
104 static CTypeResult is_loalpha(char c); // a-z
105 static CTypeResult is_alpha(char c); // A-Z,a-z
106 static CTypeResult is_digit(char c); // 0-9
107 static CTypeResult is_ctl(char c); // ASCII 0-31,127 (includes ws)
108 static CTypeResult is_hex(char c); // 0-9,A-F,a-f
109 static CTypeResult is_ws(char c); // SP,HT
110 static CTypeResult is_cr(char c); // CR
111 static CTypeResult is_lf(char c); // LF
112 static CTypeResult is_spcr(char c); // SP,CR
113 static CTypeResult is_splf(char c); // SP,LF
114 static CTypeResult is_wslfcr(char c); // SP,HT,LF,CR
115 static CTypeResult is_tspecials(char c); // HTTP chars that need quoting
116 static CTypeResult is_token(char c); // token (not CTL or specials)
117 static CTypeResult is_extra(char c); // !,*,QUOT,(,),COMMA
118 static CTypeResult is_safe(char c); // [$-_.+]
119 static CTypeResult is_unsafe(char c); // SP,DBLQUOT,#,%,<,>
120 static CTypeResult is_national(char c); // {,},|,BACKSLASH,^,~,[,],`
121 static CTypeResult is_reserved(char c); // :,/,?,:,@,&,=
122 static CTypeResult is_unreserved(char c); // alpha,digit,safe,extra,nat.
123 static CTypeResult is_punct(char c); // !"#$%&'()*+,-./:;<>=?@_{}|~
124 static CTypeResult is_end_of_url(char c); // NUL,CR,SP
125 static CTypeResult is_eow(char c); // NUL,CR,LF
126 static CTypeResult is_uri(char c); // A-Z,a-z,0-9 :/?#[]@!$&'()*+,;=-._~%
127 static CTypeResult is_sep(char c); // nullptr,COMMA,':','!',wslfcr
128 static CTypeResult is_empty(char c); // wslfcr,#
129 static CTypeResult is_alnum(char c); // 0-9,A-Z,a-z
130 static CTypeResult is_space(char c); // ' ' HT,VT,NP,CR,LF
131 static CTypeResult is_control(char c); // 0-31 127
132 static CTypeResult is_mime_sep(char c); // ()<>,;\"/[]?{} \t
133 static CTypeResult is_http_field_name(char c); // not : or mime_sep except for @
134 static CTypeResult is_http_field_value(char c); // not CR, LF, comma, or "
135
136 //////////////////
137 // string tests //
138 //////////////////
139
140 static CTypeResult is_escape(const char *seq); // %<hex><hex>
141 static CTypeResult is_uchar(const char *seq); // starts unreserved or is escape
142 static CTypeResult is_pchar(const char *seq); // uchar,:,@,&,=,+ (see code)
143
144 ///////////////////
145 // unimplemented //
146 ///////////////////
147
148 // static CTypeResult is_comment(const char * str);
149 // static CTypeResult is_ctext(const char * str);
150
151 ////////////////
152 // operations //
153 ////////////////
154
155 static CTypeResult strncasecmp_eow(const char *s1, const char *s2, int n);
156 static const char *strcasestr(const char *s1, const char *s2);
157 static int strlen_eow(const char *s);
158 static const char *strstr_eow(const char *s1, const char *s2);
159
160 static char ink_toupper(char c);
161 static char ink_tolower(char c);
162 static const char *memchr(const char *s, char c, int max_length);
163 static const char *strchr(const char *s, char c);
164
165 // noncopyable
166 ParseRules(const ParseRules &) = delete;
167 ParseRules &operator=(const ParseRules &) = delete;
168 };
169
170 /* * * * * * * * * * * * * * * * * * * * * * * * * * * *
171 * inline functions definitions
172 * * * * * * * * * * * * * * * * * * * * * * * * * * * */
173
174 inline CTypeResult
is_type(char c,uint32_t bitmask)175 ParseRules::is_type(char c, uint32_t bitmask)
176 {
177 return (parseRulesCType[(unsigned char)c] & bitmask);
178 }
179
180 inline CTypeResult
is_char(char c)181 ParseRules::is_char(char c)
182 {
183 #ifndef COMPILE_PARSE_RULES
184 return (parseRulesCType[(unsigned char)c] & is_char_BIT);
185 #else
186 return ((c & 0x80) == 0);
187 #endif
188 }
189
190 inline CTypeResult
is_upalpha(char c)191 ParseRules::is_upalpha(char c)
192 {
193 #ifndef COMPILE_PARSE_RULES
194 return (parseRulesCType[(unsigned char)c] & is_upalpha_BIT);
195 #else
196 return (c >= 'A' && c <= 'Z');
197 #endif
198 }
199
200 inline CTypeResult
is_loalpha(char c)201 ParseRules::is_loalpha(char c)
202 {
203 #ifndef COMPILE_PARSE_RULES
204 return (parseRulesCType[(unsigned char)c] & is_loalpha_BIT);
205 #else
206 return (c >= 'a' && c <= 'z');
207 #endif
208 }
209
210 inline CTypeResult
is_alpha(char c)211 ParseRules::is_alpha(char c)
212 {
213 #ifndef COMPILE_PARSE_RULES
214 return (parseRulesCType[(unsigned char)c] & is_alpha_BIT);
215 #else
216 return (is_upalpha(c) || is_loalpha(c));
217 #endif
218 }
219
220 inline CTypeResult
is_digit(char c)221 ParseRules::is_digit(char c)
222 {
223 #ifndef COMPILE_PARSE_RULES
224 return (parseRulesCType[(unsigned char)c] & is_digit_BIT);
225 #else
226 return (c >= '0' && c <= '9');
227 #endif
228 }
229
230 inline CTypeResult
is_alnum(char c)231 ParseRules::is_alnum(char c)
232 {
233 #ifndef COMPILE_PARSE_RULES
234 return (parseRulesCType[(unsigned char)c] & is_alnum_BIT);
235 #else
236 return (is_alpha(c) || is_digit(c));
237 #endif
238 }
239
240 inline CTypeResult
is_ctl(char c)241 ParseRules::is_ctl(char c)
242 {
243 #ifndef COMPILE_PARSE_RULES
244 return (parseRulesCType[(unsigned char)c] & is_ctl_BIT);
245 #else
246 return ((!(c & 0x80) && c <= 31) || c == 127);
247 #endif
248 }
249
250 inline CTypeResult
is_ws(char c)251 ParseRules::is_ws(char c)
252 {
253 #ifndef COMPILE_PARSE_RULES
254 return (parseRulesCType[(unsigned char)c] & is_ws_BIT);
255 #else
256 return (c == CHAR_SP || c == CHAR_HT);
257 #endif
258 }
259
260 inline CTypeResult
is_hex(char c)261 ParseRules::is_hex(char c)
262 {
263 #ifndef COMPILE_PARSE_RULES
264 return (parseRulesCType[(unsigned char)c] & is_hex_BIT);
265 #else
266 return ((c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f') || (c >= '0' && c <= '9'));
267 #endif
268 }
269
270 inline CTypeResult
is_cr(char c)271 ParseRules::is_cr(char c)
272 {
273 return (c == CHAR_CR);
274 }
275
276 inline CTypeResult
is_lf(char c)277 ParseRules::is_lf(char c)
278 {
279 return (c == CHAR_LF);
280 }
281
282 inline CTypeResult
is_splf(char c)283 ParseRules::is_splf(char c)
284 {
285 #ifndef COMPILE_PARSE_RULES
286 return (parseRulesCType[(unsigned char)c] & is_splf_BIT);
287 #else
288 return (c == CHAR_SP || c == CHAR_LF);
289 #endif
290 }
291
292 inline CTypeResult
is_spcr(char c)293 ParseRules::is_spcr(char c)
294 {
295 #ifndef COMPILE_PARSE_RULES
296 return (parseRulesCType[(unsigned char)c] & is_spcr_BIT);
297 #else
298 return (c == CHAR_SP || c == CHAR_CR);
299 #endif
300 }
301
302 inline CTypeResult
is_wslfcr(char c)303 ParseRules::is_wslfcr(char c)
304 {
305 #ifndef COMPILE_PARSE_RULES
306 return (parseRulesCType[(unsigned char)c] & is_wslfcr_BIT);
307 #else
308 return ParseRules::is_ws(c) || ParseRules::is_splf(c) || ParseRules::is_spcr(c);
309 #endif
310 }
311
312 inline CTypeResult
is_extra(char c)313 ParseRules::is_extra(char c)
314 {
315 #ifndef COMPILE_PARSE_RULES
316 return (parseRulesCType[(unsigned char)c] & is_extra_BIT);
317 #else
318 switch (c) {
319 case '!':
320 case '*':
321 case '\'':
322 case '(':
323 case ')':
324 case ',':
325 return (true);
326 }
327 return (false);
328 #endif
329 }
330
331 inline CTypeResult
is_safe(char c)332 ParseRules::is_safe(char c)
333 {
334 #ifndef COMPILE_PARSE_RULES
335 return (parseRulesCType[(unsigned char)c] & is_safe_BIT);
336 #else
337 return (c == '$' || c == '-' || c == '_' || c == '.' || c == '+');
338 #endif
339 }
340
341 inline CTypeResult
is_unsafe(char c)342 ParseRules::is_unsafe(char c)
343 {
344 #ifndef COMPILE_PARSE_RULES
345 return (parseRulesCType[(unsigned char)c] & is_unsafe_BIT);
346 #else
347 if (is_ctl(c))
348 return (true);
349
350 switch (c) {
351 case ' ':
352 case '\"':
353 case '#':
354 case '%':
355 case '<':
356 case '>':
357 return (true);
358 }
359 return (false);
360 #endif
361 }
362
363 inline CTypeResult
is_reserved(char c)364 ParseRules::is_reserved(char c)
365 {
366 #ifndef COMPILE_PARSE_RULES
367 return (parseRulesCType[(unsigned char)c] & is_reserved_BIT);
368 #else
369 switch (c) {
370 case ';':
371 case '/':
372 case '?':
373 case ':':
374 case '@':
375 case '&':
376 case '=':
377 return (true);
378 }
379 return (false);
380 #endif
381 }
382
383 inline CTypeResult
is_national(char c)384 ParseRules::is_national(char c)
385 {
386 #ifndef COMPILE_PARSE_RULES
387 return (parseRulesCType[(unsigned char)c] & is_national_BIT);
388 #else
389 switch (c) {
390 case '{':
391 case '}':
392 case '|':
393 case '\\':
394 case '^':
395 case '~':
396 case '[':
397 case ']':
398 case '`':
399 return (true);
400 }
401 return (false);
402 #endif
403 }
404
405 inline CTypeResult
is_unreserved(char c)406 ParseRules::is_unreserved(char c)
407 {
408 #ifndef COMPILE_PARSE_RULES
409 return (parseRulesCType[(unsigned char)c] & is_unreserved_BIT);
410 #else
411 return (is_alpha(c) || is_digit(c) || is_safe(c) || is_extra(c) || is_national(c));
412 #endif
413 }
414
415 inline CTypeResult
is_punct(char c)416 ParseRules::is_punct(char c)
417 {
418 #ifndef COMPILE_PARSE_RULES
419 return (parseRulesCType[(unsigned char)c] & is_punct_BIT);
420 #else
421 switch (c) {
422 case '!':
423 case '"':
424 case '#':
425 case '%':
426 case '&':
427 case '\'':
428 case '(':
429 case ')':
430 case '*':
431 case '+':
432 case ',':
433 case '-':
434 case '.':
435 case '/':
436 case ':':
437 case ';':
438 case '<':
439 case '=':
440 case '>':
441 case '?':
442 case '@':
443 case '[':
444 case '\\':
445 case ']':
446 case '^':
447 case '_':
448 case '`':
449 case '{':
450 case '|':
451 case '}':
452 case '~':
453 return (true);
454 }
455 return (false);
456 #endif
457 }
458
459 inline CTypeResult
is_end_of_url(char c)460 ParseRules::is_end_of_url(char c)
461 {
462 #ifndef COMPILE_PARSE_RULES
463 return (parseRulesCType[(unsigned char)c] & is_end_of_url_BIT);
464 #else
465 return (c == '\0' || c == '\n' || c == ' ' || ParseRules::is_ctl(c));
466 #endif
467 }
468
469 inline CTypeResult
is_escape(const char * seq)470 ParseRules::is_escape(const char *seq)
471 {
472 return (seq[0] == '%' && is_hex(seq[1]) && is_hex(seq[2]));
473 }
474
475 inline CTypeResult
is_uchar(const char * seq)476 ParseRules::is_uchar(const char *seq)
477 {
478 return (is_unreserved(seq[0]) || is_escape(seq));
479 }
480
481 //
482 // have to cheat on this one
483 //
484 inline CTypeResult
is_pchar(const char * seq)485 ParseRules::is_pchar(const char *seq)
486 {
487 #ifndef COMPILE_PARSE_RULES
488 if (*seq != '%')
489 return (parseRulesCType[(uint8_t)*seq] & is_pchar_BIT);
490 else
491 return is_hex(seq[1]) && is_hex(seq[2]);
492 #else
493 if (is_unreserved(*seq))
494 return (true);
495
496 switch (seq[0]) {
497 case ':':
498 case '@':
499 case '&':
500 case '=':
501 case '+':
502 return (true);
503 }
504 return (false);
505 #endif
506 }
507
508 inline CTypeResult
is_tspecials(char c)509 ParseRules::is_tspecials(char c)
510 {
511 #ifndef COMPILE_PARSE_RULES
512 return (parseRulesCType[(unsigned char)c] & is_tspecials_BIT);
513 #else
514 switch (c) {
515 case '(':
516 case ')':
517 case '<':
518 case '>':
519 case '@':
520 case ',':
521 case ';':
522 case ':':
523 case '\\':
524 case '"':
525 case '/':
526 case '[':
527 case ']':
528 case '?':
529 case '=':
530 case '{':
531 case '}':
532 case CHAR_SP:
533 case CHAR_HT:
534 return (true);
535 }
536 return (false);
537 #endif
538 }
539
540 inline CTypeResult
is_token(char c)541 ParseRules::is_token(char c)
542 {
543 #ifndef COMPILE_PARSE_RULES
544 return (parseRulesCType[(unsigned char)c] & is_token_BIT);
545 #else
546 return (is_char(c) && !(is_ctl(c) || is_tspecials(c)));
547 #endif
548 }
549
550 inline char
ink_toupper(char c)551 ParseRules::ink_toupper(char c)
552 {
553 #ifndef COMPILE_PARSE_RULES
554 return parseRulesCTypeToUpper[(unsigned char)c];
555 #else
556 int up_case = c;
557 const int up_case_diff = 'a' - 'A';
558
559 if (c >= 'a' && c <= 'z') {
560 up_case = c - up_case_diff;
561 }
562 return (up_case);
563 #endif
564 }
565
566 inline char
ink_tolower(char c)567 ParseRules::ink_tolower(char c)
568 {
569 #ifndef COMPILE_PARSE_RULES
570 return parseRulesCTypeToLower[(unsigned char)c];
571 #else
572 int lo_case = c;
573 const int lo_case_diff = 'a' - 'A';
574
575 if (c >= 'A' && c <= 'Z') {
576 lo_case = c + lo_case_diff;
577 }
578 return (lo_case);
579 #endif
580 }
581
582 inline CTypeResult
is_eow(char c)583 ParseRules::is_eow(char c)
584 {
585 #ifndef COMPILE_PARSE_RULES
586 return (parseRulesCType[(unsigned char)c] & is_eow_BIT);
587 #else
588 return (c == '\0' || c == '\r' || c == '\n');
589 #endif
590 }
591
592 inline CTypeResult
is_uri(char c)593 ParseRules::is_uri(char c)
594 {
595 #ifndef COMPILE_PARSE_RULES
596 return (parseRulesCType[(unsigned char)c] & is_uri_BIT);
597 #else
598 if (is_alnum(c))
599 return (true);
600
601 switch (c) {
602 case ':':
603 case '/':
604 case '?':
605 case '#':
606 case '[':
607 case ']':
608 case '@':
609 case '!':
610 case '$':
611 case '&':
612 case '\'':
613 case '(':
614 case ')':
615 case '*':
616 case '+':
617 case ',':
618 case ';':
619 case '=':
620 case '-':
621 case '.':
622 case '_':
623 case '~':
624 case '%':
625 return (true);
626 }
627 return (false);
628 #endif
629 }
630
631 inline CTypeResult
is_sep(char c)632 ParseRules::is_sep(char c)
633 {
634 #ifndef COMPILE_PARSE_RULES
635 return (parseRulesCType[(unsigned char)c] & is_sep_BIT);
636 #else
637 return (!c || c == ',' || c == ':' || c == '!' || is_wslfcr(c));
638 #endif
639 }
640
641 inline CTypeResult
is_empty(char c)642 ParseRules::is_empty(char c)
643 {
644 #ifndef COMPILE_PARSE_RULES
645 return (parseRulesCType[(unsigned char)c] & is_empty_BIT);
646 #else
647 return (c == '#' || is_wslfcr(c));
648 #endif
649 }
650
651 inline CTypeResult
is_space(char c)652 ParseRules::is_space(char c)
653 {
654 #ifndef COMPILE_PARSE_RULES
655 return (parseRulesCType[(unsigned char)c] & is_space_BIT);
656 #else
657 switch (c) {
658 case CHAR_SP:
659 case CHAR_HT:
660 case CHAR_LF:
661 case CHAR_VT:
662 case CHAR_NP:
663 case CHAR_CR:
664 return (true);
665 }
666 return (false);
667 #endif
668 }
669
670 inline CTypeResult
is_control(char c)671 ParseRules::is_control(char c)
672 {
673 #ifndef COMPILE_PARSE_RULES
674 return (parseRulesCType[(unsigned char)c] & is_control_BIT);
675 #else
676 if (((unsigned char)c) < 32 || ((unsigned char)c) == 127)
677 return true;
678 return false;
679 #endif
680 }
681
682 inline CTypeResult
is_mime_sep(char c)683 ParseRules::is_mime_sep(char c)
684 {
685 #ifndef COMPILE_PARSE_RULES
686 return (parseRulesCType[(unsigned char)c] & is_mime_sep_BIT);
687 #else
688 if ((c == '(') || (c == ')') || (c == '<') || (c == '>') || (c == '@') || (c == ',') || (c == ';') || (c == '\\') ||
689 (c == '\"') || (c == '/') || (c == '[') || (c == ']') || (c == '?') || (c == '{') || (c == '}') || (c == ' ') || (c == '\t'))
690 return true;
691 return false;
692 #endif
693 }
694
695 inline CTypeResult
is_http_field_name(char c)696 ParseRules::is_http_field_name(char c)
697 {
698 #ifndef COMPILE_PARSE_RULES
699 return (parseRulesCType[(unsigned char)c] & is_http_field_name_BIT);
700 #else
701 if ((c == ':') || (is_mime_sep(c) && (c != '@')))
702 return false;
703 return true;
704 #endif
705 }
706
707 inline CTypeResult
is_http_field_value(char c)708 ParseRules::is_http_field_value(char c)
709 {
710 #ifndef COMPILE_PARSE_RULES
711 return (CTypeResult)(parseRulesCType[(unsigned char)c] & is_http_field_value_BIT);
712 #else
713 switch (c) {
714 case CHAR_CR:
715 case CHAR_LF:
716 case '\"':
717 case ',':
718 return false;
719 }
720 return true;
721 #endif
722 }
723
724 //////////////////////////////////////////////////////////////////////////////
725 //
726 // inline CTypeResult ParseRules::strncasecmp_eol(s1, s2, count)
727 //
728 // This wacky little function compares if two strings <s1> and <s2> match
729 // (case-insensitively) up to <count> characters long, stopping not only
730 // at the end of string ('\0'), but also at end of line (CR or LF).
731 //
732 //////////////////////////////////////////////////////////////////////////////
733
734 inline CTypeResult
strncasecmp_eow(const char * s1,const char * s2,int count)735 ParseRules::strncasecmp_eow(const char *s1, const char *s2, int count)
736 {
737 for (int i = 0; i < count; i++) {
738 const char &a = s1[i];
739 const char &b = s2[i];
740
741 ///////////////////////////////////////////////////////////////
742 // if they are different; only match if both are terminators //
743 ///////////////////////////////////////////////////////////////
744 if (ink_tolower(a) != ink_tolower(b))
745 return (is_eow(a) && is_eow(b));
746 }
747 return (true);
748 }
749
750 //////////////////////////////////////////////////////////////////////////////
751 //
752 // strlen_eow()
753 //
754 // return the length of a string
755 //////////////////////////////////////////////////////////////////////////////
756 inline int
strlen_eow(const char * s)757 ParseRules::strlen_eow(const char *s)
758 {
759 for (int i = 0; true; i++) {
760 if (is_eow(s[i]))
761 return (i);
762 }
763 }
764
765 //////////////////////////////////////////////////////////////////////////////
766 //
767 // strstr_eow()
768 //
769 // This function is the same as strstr(), except that it accepts strings
770 // that are terminated with '\r', '\n' or null.
771 // It returns a pointer to the first occurrence of s2 within s1 (or null).
772 //////////////////////////////////////////////////////////////////////////////
773 inline const char *
strstr_eow(const char * s1,const char * s2)774 ParseRules::strstr_eow(const char *s1, const char *s2)
775 {
776 int i1;
777
778 int s2_len = strlen_eow(s2);
779
780 for (i1 = 0; !is_eow(s1[i1]); i1++)
781 if (ink_tolower(s1[i1]) == ink_tolower(s2[0]))
782 if (strncasecmp_eow(&s1[i1], &s2[0], s2_len))
783 return (&s1[i1]);
784
785 return (nullptr);
786 }
787
788 inline const char *
strcasestr(const char * s1,const char * s2)789 ParseRules::strcasestr(const char *s1, const char *s2)
790 {
791 int i1;
792
793 size_t s2_len = strlen(s2);
794
795 for (i1 = 0; s1[i1] != '\0'; i1++)
796 if (ink_tolower(s1[i1]) == ink_tolower(s2[0]))
797 if (strncasecmp_eow(&s1[i1], &s2[0], (int)s2_len))
798 return (&s1[i1]);
799
800 return (nullptr);
801 }
802
803 inline const char *
memchr(const char * s,char c,int max_length)804 ParseRules::memchr(const char *s, char c, int max_length)
805 {
806 for (int i = 0; i < max_length; i++)
807 if (s[i] == c)
808 return (&s[i]);
809 return (nullptr);
810 }
811
812 inline const char *
strchr(const char * s,char c)813 ParseRules::strchr(const char *s, char c)
814 {
815 for (int i = 0; s[i] != '\0'; i++)
816 if (s[i] == c)
817 return (&s[i]);
818 return (nullptr);
819 }
820
821 static inline int
ink_get_hex(char c)822 ink_get_hex(char c)
823 {
824 if (ParseRules::is_digit(c))
825 return (int)(c - '0');
826 c = ParseRules::ink_tolower(c);
827 return (int)((c - 'a') + 10);
828 }
829
830 int64_t ink_atoi64(const char *, const char **end = nullptr);
831 uint64_t ink_atoui64(const char *);
832 int64_t ink_atoi64(const char *, int);
833
834 static inline int
ink_atoi(const char * str)835 ink_atoi(const char *str)
836 {
837 int64_t val = ink_atoi64(str);
838
839 if (val > INT_MAX)
840 return INT_MAX;
841 else if (val < INT_MIN)
842 return INT_MIN;
843 else
844 return static_cast<int>(val);
845 }
846
847 static inline int
ink_atoi(const char * str,int len)848 ink_atoi(const char *str, int len)
849 {
850 int64_t val = ink_atoi64(str, len);
851
852 if (val > INT_MAX)
853 return INT_MAX;
854 else if (val < INT_MIN)
855 return INT_MIN;
856 else
857 return static_cast<int>(val);
858 }
859
860 static inline unsigned int
ink_atoui(const char * str)861 ink_atoui(const char *str)
862 {
863 uint64_t val = ink_atoui64(str);
864
865 if (val > INT_MAX)
866 return INT_MAX;
867 else
868 return static_cast<int>(val);
869 }
870