]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
sbuff: Add additional macros and fix fr_sbuff_parse
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Thu, 25 Jun 2020 01:49:11 +0000 (20:49 -0500)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Thu, 25 Jun 2020 01:49:11 +0000 (20:49 -0500)
src/lib/util/dict_util.c
src/lib/util/sbuff.c
src/lib/util/sbuff.h

index b395653b8aac86f39085050c1c23868369bc0740..b506e029e1b27e95dd0487aeeedff14711746afd 100644 (file)
@@ -1841,7 +1841,7 @@ ssize_t fr_dict_attr_by_qualified_name_substr(fr_dict_attr_err_t *err, fr_dict_a
                /*
                 *      Next thing SHOULD be a '.'
                 */
-               if (fr_sbuff_next_char(&our_name) != '.') {
+               if (fr_sbuff_next(&our_name) != '.') {
                        if (err) *err = FR_DICT_ATTR_PARSE_ERROR;
                        return 0;
                }
index 2fa71a35d4cca029242e739725691a042a5315df..20c9dc1e1861e5eabf500be632f108eb50592633 100644 (file)
@@ -270,20 +270,21 @@ size_t fr_sbuff_strncpy_until(char *out, size_t outlen, fr_sbuff_t *in, size_t l
  *     - >0 the number of bytes copied.
  */
 #define PARSE_INT_DEF(_name, _type, _min, _max) \
-size_t fr_sbuff_parse_##_name(fr_sbuff_parse_error_t *err, _type *out, fr_sbuff_t *in) \
+size_t fr_sbuff_parse_##_name(fr_sbuff_parse_error_t *err, _type *out, fr_sbuff_t *in, bool no_trailing) \
 { \
        char            buff[sizeof(STRINGIFY(_min)) + 1]; \
        char            *end; \
        size_t          len; \
        long long       num; \
-       len = fr_sbuff_strncpy(buff, sizeof(buff), &FR_SBUFF_NO_ADVANCE(in), sizeof(STRINGIFY(_min))); \
+       fr_sbuff_t      our_in = FR_SBUFF_NO_ADVANCE(in); \
+       len = fr_sbuff_strncpy(buff, sizeof(buff), &our_in, sizeof(STRINGIFY(_min))); \
        if ((len == 0) && err) *err = FR_SBUFF_PARSE_ERROR_NOT_FOUND; \
        num = strtoll(buff, &end, 10); \
        if (end == buff) { \
                if (err) *err = FR_SBUFF_PARSE_ERROR_NOT_FOUND; \
                return 0; \
        } \
-       if ((num > (_max)) || ((errno == EINVAL) && (num == LLONG_MAX)))  { \
+       if ((num > (_max)) || ((errno == EINVAL) && (num == LLONG_MAX)) || (no_trailing && fr_sbuff_is_digit(&our_in)))  { \
                if (err) *err = FR_SBUFF_PARSE_ERROR_INTEGER_OVERFLOW; \
                *out = (_type)(_max); \
        } else if (num < (_min) || ((errno == EINVAL) && (num == LLONG_MIN))) { \
@@ -293,7 +294,7 @@ size_t fr_sbuff_parse_##_name(fr_sbuff_parse_error_t *err, _type *out, fr_sbuff_
                if (err) *err = FR_SBUFF_PARSE_ERROR_NOT_FOUND; \
                *out = (_type)(num); \
        } \
-       fr_sbuff_advance(in, end - buff); \
+       fr_sbuff_set(in, &our_in); \
        return end - buff; \
 }
 
@@ -309,27 +310,28 @@ PARSE_INT_DEF(int64, int64_t, INT64_MIN, INT64_MAX)
  * @param[in] _max     value.
  */
 #define PARSE_UINT_DEF(_name, _type, _max) \
-size_t fr_sbuff_parse_##_name(fr_sbuff_parse_error_t *err, _type *out, fr_sbuff_t *in) \
+size_t fr_sbuff_parse_##_name(fr_sbuff_parse_error_t *err, _type *out, fr_sbuff_t *in, bool no_trailing) \
 { \
        char                    buff[sizeof(STRINGIFY(_max)) + 1]; \
        char                    *end; \
        size_t                  len; \
        unsigned long long      num; \
-       len = fr_sbuff_strncpy(buff, sizeof(buff), &FR_SBUFF_NO_ADVANCE(in), sizeof(STRINGIFY(_max))); \
+       fr_sbuff_t              our_in = FR_SBUFF_NO_ADVANCE(in); \
+       len = fr_sbuff_strncpy(buff, sizeof(buff), &our_in, sizeof(STRINGIFY(_max))); \
        if ((len == 0) && err) *err = FR_SBUFF_PARSE_ERROR_NOT_FOUND; \
        num = strtoull(buff, &end, 10); \
        if (end == buff) { \
                if (err) *err = FR_SBUFF_PARSE_ERROR_NOT_FOUND; \
                return 0; \
        } \
-       if ((num > (_max)) || ((errno == EINVAL) && (num == ULLONG_MAX))) { \
+       if ((num > (_max)) || ((errno == EINVAL) && (num == ULLONG_MAX)) || (no_trailing && fr_sbuff_is_digit(&our_in))) { \
                if (err) *err = FR_SBUFF_PARSE_ERROR_INTEGER_OVERFLOW; \
                *out = (_type)(_max); \
        } else { \
                if (err) *err = FR_SBUFF_PARSE_ERROR_NOT_FOUND; \
                *out = (_type)(num); \
        } \
-       fr_sbuff_advance(in, end - buff); \
+       fr_sbuff_set(in, &our_in); \
        return end - buff; \
 }
 
index 45932147f4b1385a78466dcdc0f2bac78a6205a6..650a473c334f6f40575fe0ede0b1b37ebc3d110c 100644 (file)
@@ -29,11 +29,12 @@ RCSIDH(sbuff_h, "$Id$")
 extern "C" {
 #  endif
 
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
 #include <stdbool.h>
 #include <stdint.h>
 #include <sys/types.h>
-#include <limits.h>
-#include <errno.h>
 
 typedef struct fr_sbuff_ptr_s fr_sbuff_marker_t;
 struct fr_sbuff_ptr_s {
@@ -253,6 +254,25 @@ _fr_sbuff_set(_dst, \
                        size_t          : ((_dst)->p += (uintptr_t)(_src)) \
              ))
 
+/** Find the longest prefix in an sbuff
+ *
+ * @param[out] _match_len      The length of the matched string.
+ *                             May be NULL.
+ * @param[out] _out            The value resolve in the table.
+ * @param[in] _table           to find longest match in.
+ * @param[in] _sbuff           containing the needle.
+ * @param[in] _def             Default value if no match is found.
+ */
+#define fr_sbuff_table_value_by_longest_prefix(_match_len, _out, _table, _sbuff, _def) \
+do { \
+       size_t          _match_len_tmp; \
+       fr_sbuff_t      _sbuff_tmp = FR_SBUFF_COPY(_sbuff); \
+       *(_out) = fr_table_value_by_longest_prefix(&_match_len_tmp, _table, &_sbuff_tmp, \
+                                                  fr_sbuff_available(&_sbuff_tmp), _def); \
+       (void) fr_sbuff_advance(_match_len); \
+       if (_match_len) *(_match_len) = _match_len_tmp; \
+} while (0)
+
 /** Advance position in sbuff by N bytes
  *
  * @param[in] sbuff    to advance.
@@ -271,14 +291,16 @@ static inline ssize_t fr_sbuff_advance(fr_sbuff_t *sbuff, size_t n)
 }
 #define FR_SBUFF_ADVANCE_RETURN(_sbuff, _n) FR_SBUFF_RETURN(fr_sbuff_advance, _sbuff, _n)
 
-/** Return the current char and advance
+/** Advance the sbuff by one char
  *
  */
-static inline char fr_sbuff_next_char(fr_sbuff_t *sbuff)
+static inline char fr_sbuff_next(fr_sbuff_t *sbuff)
 {
        if (sbuff->p >= sbuff->end) return '\0';
 
-       return *(sbuff->p++);
+       sbuff->p++;
+
+       return *sbuff->p;
 }
 
 /** Set the start pointer to the current value of p
@@ -313,6 +335,80 @@ static inline void fr_sbuff_reset_end(fr_sbuff_t *sbuff)
        _fr_sbuff_set_recurse(sbuff, sbuff->end);
 }
 
+/** @name Conditions
+ * @{
+ */
+
+/** Return true if the current char matches, and if it does, advance
+ *
+ */
+static inline bool fr_sbuff_next_if_char(fr_sbuff_t *sbuff, char c)
+{
+       if (sbuff->p >= sbuff->end) return false;
+       if (*sbuff->p != c) return false;
+
+       fr_sbuff_advance(sbuff, 1);
+
+       return true;
+}
+
+static inline bool fr_sbuff_next_unless_char(fr_sbuff_t *sbuff, char c)
+{
+       if (sbuff->p >= sbuff->end) return false;
+       if (*sbuff->p == c) return false;
+
+       fr_sbuff_advance(sbuff, 1);
+
+       return true;
+}
+
+/** Return true if the current char matches, and advance
+ *
+ */
+static inline bool fr_sbuff_next_char(fr_sbuff_t *sbuff, char c)
+{
+       bool ret;
+
+       if (sbuff->p >= sbuff->end) return false;
+
+       ret = *sbuff->p == c;
+
+       fr_sbuff_advance(sbuff, 1);
+
+       return ret;
+}
+
+static inline bool fr_sbuff_is_digit(fr_sbuff_t *sbuff)
+{
+       if (sbuff->p >= sbuff->end) return false;
+       return isdigit(*sbuff->p);
+}
+
+static inline bool fr_sbuff_is_upper(fr_sbuff_t *sbuff)
+{
+       if (sbuff->p >= sbuff->end) return false;
+       return isupper(*sbuff->p);
+}
+
+static inline bool fr_sbuff_is_lower(fr_sbuff_t *sbuff)
+{
+       if (sbuff->p >= sbuff->end) return false;
+       return islower(*sbuff->p);
+}
+
+static inline bool fr_sbuff_is_alpha(fr_sbuff_t *sbuff)
+{
+       if (sbuff->p >= sbuff->end) return false;
+       return isalpha(*sbuff->p);
+}
+
+static inline bool fr_sbuff_is_space(fr_sbuff_t *sbuff)
+{
+       if (sbuff->p >= sbuff->end) return false;
+       return isspace(*sbuff->p);
+}
+/** @} */
+
 /** Adds a new pointer to the beginning of the list of pointers to update
  *
  */
@@ -381,22 +477,21 @@ size_t fr_sbuff_strncpy_until(char *out, size_t outlen, fr_sbuff_t *sbuff, size_
  * so that if the output variable type changes, the parse rules are automatically changed.
  * @{
  */
-size_t fr_sbuff_parse_int8(fr_sbuff_parse_error_t *err, int8_t *out, fr_sbuff_t *sbuff);
-
-size_t fr_sbuff_parse_int16(fr_sbuff_parse_error_t *err, int16_t *out, fr_sbuff_t *sbuff);
+size_t fr_sbuff_parse_int8(fr_sbuff_parse_error_t *err, int8_t *out, fr_sbuff_t *sbuff, bool no_trailing);
 
-size_t fr_sbuff_parse_int32(fr_sbuff_parse_error_t *err, int32_t *out, fr_sbuff_t *sbuff);
+size_t fr_sbuff_parse_int16(fr_sbuff_parse_error_t *err, int16_t *out, fr_sbuff_t *sbuff, bool no_trailing);
 
-size_t fr_sbuff_parse_int64(fr_sbuff_parse_error_t *err, int64_t *out, fr_sbuff_t *sbuff);
+size_t fr_sbuff_parse_int32(fr_sbuff_parse_error_t *err, int32_t *out, fr_sbuff_t *sbuff, bool no_trailing);
 
-size_t fr_sbuff_parse_uint8(fr_sbuff_parse_error_t *err, uint8_t *out, fr_sbuff_t *sbuff);
+size_t fr_sbuff_parse_int64(fr_sbuff_parse_error_t *err, int64_t *out, fr_sbuff_t *sbuff, bool no_trailing);
 
-size_t fr_sbuff_parse_uint16(fr_sbuff_parse_error_t *err, uint16_t *out, fr_sbuff_t *sbuff);
+size_t fr_sbuff_parse_uint8(fr_sbuff_parse_error_t *err, uint8_t *out, fr_sbuff_t *sbuff, bool no_trailing);
 
-size_t fr_sbuff_parse_uint32(fr_sbuff_parse_error_t *err, uint32_t *out, fr_sbuff_t *sbuff);
+size_t fr_sbuff_parse_uint16(fr_sbuff_parse_error_t *err, uint16_t *out, fr_sbuff_t *sbuff, bool no_trailing);
 
-size_t fr_sbuff_parse_uint64(fr_sbuff_parse_error_t *err, uint64_t *out, fr_sbuff_t *sbuff);
+size_t fr_sbuff_parse_uint32(fr_sbuff_parse_error_t *err, uint32_t *out, fr_sbuff_t *sbuff, bool no_trailing);
 
+size_t fr_sbuff_parse_uint64(fr_sbuff_parse_error_t *err, uint64_t *out, fr_sbuff_t *sbuff, bool no_trailing);
 
 /** Parse a value based on the output type
  *
@@ -408,14 +503,14 @@ size_t fr_sbuff_parse_uint64(fr_sbuff_parse_error_t *err, uint64_t *out, fr_sbuf
  */
 #define fr_sbuff_parse(_err, _out, _in) \
        _Generic((_out), \
-                int8_t *       : fr_sbuff_parse_int8(_err, _out, _in), \
-                int16_t *      : fr_sbuff_parse_int16(_err, _out, _in), \
-                int32_t *      : fr_sbuff_parse_int32(_err, _out, _in), \
-                int64_t *      : fr_sbuff_parse_int64(_err, _out, _in), \
-                uint8_t *      : fr_sbuff_parse_uint8(_err, _out, _in), \
-                uint16_t *     : fr_sbuff_parse_uint16(_err, _out, _in), \
-                uint32_t *     : fr_sbuff_parse_uint32(_err, _out, _in), \
-                uint64_t *     : fr_sbuff_parse_uint64(_err, _out, _in) \
+                int8_t *       : fr_sbuff_parse_int8(_err, (int8_t *)_out, _in, true), \
+                int16_t *      : fr_sbuff_parse_int16(_err, (int16_t *)_out, _in, true), \
+                int32_t *      : fr_sbuff_parse_int32(_err, (int32_t *)_out, _in, true), \
+                int64_t *      : fr_sbuff_parse_int64(_err, (int64_t *)_out, _in, true), \
+                uint8_t *      : fr_sbuff_parse_uint8(_err, (uint8_t *)_out, _in, true), \
+                uint16_t *     : fr_sbuff_parse_uint16(_err, (uint16_t *)_out, _in, true), \
+                uint32_t *     : fr_sbuff_parse_uint32(_err, (uint32_t *)_out, _in, true), \
+                uint64_t *     : fr_sbuff_parse_uint64(_err, (uint64_t *)_out, _in, true) \
        )
 /** @} */