lib/pattern: Support NULL output buffer in parse_and_fill_pattern()
authorLogan Gunthorpe <logang@deltatee.com>
Fri, 18 Nov 2022 23:15:57 +0000 (16:15 -0700)
committerVincent Fu <vincent.fu@samsung.com>
Sat, 19 Nov 2022 00:36:10 +0000 (19:36 -0500)
Support passing a NULL output buffer to parse_and_fill_pattern().
Each formatting function simply needs to avoid accessing the buffer
when it is NULL. This allows calculating the required size of the
buffer before one might be allocated.

This will be useful in a subsequent patch for dynamically allocating
the pattern buffers.

Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
Signed-off-by: Vincent Fu <vincent.fu@samsung.com>
lib/pattern.c

index d8203630d3ed9c2c81b35df8dfb9842d0a86644e..70d0313d237e204c0a49ad0808ad0af170c02d95 100644 (file)
@@ -51,9 +51,17 @@ static const char *parse_file(const char *beg, char *out,
        if (fd < 0)
                goto err_free_out;
 
-       count = read(fd, out, out_len);
-       if (count == -1)
-               goto err_free_close_out;
+       if (out) {
+               count = read(fd, out, out_len);
+               if (count == -1)
+                       goto err_free_close_out;
+       } else {
+               count = lseek(fd, 0, SEEK_END);
+               if (count == -1)
+                       goto err_free_close_out;
+               if (count >= out_len)
+                       count = out_len;
+       }
 
        *filled = count;
        close(fd);
@@ -100,7 +108,8 @@ static const char *parse_string(const char *beg, char *out,
        if (end - beg > out_len)
                return NULL;
 
-       memcpy(out, beg, end - beg);
+       if (out)
+               memcpy(out, beg, end - beg);
        *filled = end - beg;
 
        /* Catch up quote */
@@ -156,12 +165,14 @@ static const char *parse_number(const char *beg, char *out,
                i = 0;
                if (!lval) {
                        num    = 0;
-                       out[i] = 0x00;
+                       if (out)
+                               out[i] = 0x00;
                        i      = 1;
                } else {
                        val = (unsigned int)lval;
                        for (; val && out_len; out_len--, i++, val >>= 8)
-                               out[i] = val & 0xff;
+                               if (out)
+                                       out[i] = val & 0xff;
                        if (val)
                                return NULL;
                }
@@ -183,7 +194,8 @@ static const char *parse_number(const char *beg, char *out,
                        const char *fmt;
 
                        fmt = (num & 1 ? "%1hhx" : "%2hhx");
-                       sscanf(beg, fmt, &out[i]);
+                       if (out)
+                               sscanf(beg, fmt, &out[i]);
                        if (num & 1) {
                                num++;
                                beg--;
@@ -251,7 +263,8 @@ static const char *parse_format(const char *in, char *out, unsigned int parsed,
        if (f->desc->len > out_len)
                return NULL;
 
-       memset(out, '\0', f->desc->len);
+       if (out)
+               memset(out, '\0', f->desc->len);
        *filled = f->desc->len;
 
        return in + len;
@@ -262,7 +275,9 @@ static const char *parse_format(const char *in, char *out, unsigned int parsed,
  *                            numbers and pattern formats.
  * @in - string input
  * @in_len - size of the input string
- * @out - output buffer where parsed result will be put
+ * @out - output buffer where parsed result will be put, may be NULL
+ *       in which case this function just calculates the required
+ *       length of the buffer
  * @out_len - lengths of the output buffer
  * @fmt_desc - array of pattern format descriptors [input]
  * @fmt - array of pattern formats [output]
@@ -314,7 +329,7 @@ int parse_and_fill_pattern(const char *in, unsigned int in_len,
        const char *beg, *end, *out_beg = out;
        unsigned int total = 0, fmt_rem = 0;
 
-       if (!in || !in_len || !out || !out_len)
+       if (!in || !in_len || !out_len)
                return -EINVAL;
        if (fmt_sz_out)
                fmt_rem = *fmt_sz_out;