]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Lib: Add functions for reading and writing of bytestrings
authorOndrej Zajicek <santiago@crfreenet.org>
Thu, 24 Aug 2023 01:04:58 +0000 (03:04 +0200)
committerOndrej Zajicek <santiago@crfreenet.org>
Thu, 24 Aug 2023 02:19:07 +0000 (04:19 +0200)
Based on patch from Alexander Zubkov, thanks!

conf/cf-lex.l
lib/string.h
lib/strtoul.c

index 9025a84d8259e8c244ef5e693c8d449c5d27cdcc..965e1e3f98f406a4fb59ba8ddb453085d6351630 100644 (file)
@@ -256,38 +256,22 @@ WHITE [ \t]
 }
 
 ({XIGIT}{2}){16,}|{XIGIT}{2}(:{XIGIT}{2}){15,}|hex:({XIGIT}{2}(:?{XIGIT}{2})*)? {
-  char *s, *sb = yytext;
-  size_t len = 0, i;
-  struct bytestring *bytes;
-  byte *b;
-
-  /* skip 'hex:' prefix */
-  if (sb[0] == 'h' && sb[1] == 'e' && sb[2] == 'x' && sb[3] == ':')
-    sb += 4;
-
-  s = sb;
-  while (*s) {
-    len++;
-    s += 2;
-    if (*s == ':')
-      s++;
-  }
-  bytes = cfg_allocz(sizeof(*bytes) + len);
+  char *s = yytext;
+  struct bytestring *bs;
 
-  bytes->length = len;
-  b = &bytes->data[0];
-  s = sb;
-  errno = 0;
-  for (i = 0; i < len; i++) {
-    *b = bstrtobyte16(s);
-    if (errno == ERANGE)
-      cf_error("Invalid hex string");
-    b++;
-    s += 2;
-    if (*s == ':')
-      s++;
-  }
-  cf_lval.bs = bytes;
+  /* Skip 'hex:' prefix */
+  if (s[0] == 'h' && s[1] == 'e' && s[2] == 'x' && s[3] == ':')
+    s += 4;
+
+  int len = bstrhextobin(s, NULL);
+  if (len < 0)
+    cf_error("Invalid hex string");
+
+  bs = cfg_allocz(sizeof(struct bytestring) + len);
+  bs->length = bstrhextobin(s, bs->data);
+  ASSERT(bs->length == len);
+
+  cf_lval.bs = bs;
   return BYTESTRING;
 }
 
index 2829943de0e9301cc94993fe1e3e248f4f50f4a0..161b7651d9cfa77e28c229e8556195722fd7d4cb 100644 (file)
@@ -33,6 +33,9 @@ u64 bstrtoul10(const char *str, char **end);
 u64 bstrtoul16(const char *str, char **end);
 byte bstrtobyte16(const char *str);
 
+int bstrhextobin(const char *s, byte *b);
+int bstrbintohex(const byte *b, size_t len, char *buf, size_t size, char delim);
+
 int patmatch(const byte *pat, const byte *str);
 
 static inline char *xbasename(const char *str)
index a5b11f68d5ff4d3231bf8dcd0ef96c5d77501b2e..e0c0142f8ab4d1276420231af322048d793e49f4 100644 (file)
@@ -25,7 +25,7 @@ bstrtoul10(const char *str, char **end)
       errno = ERANGE;
       return UINT64_MAX;
     }
-    
+
     out *= 10;
     out += (**end) - '0';
   }
@@ -60,29 +60,91 @@ bstrtoul16(const char *str, char **end)
   return UINT64_MAX;
 }
 
-byte
-bstrtobyte16(const char *str)
+static int
+fromxdigit(char c)
 {
-  byte out = 0;
-  for (int i=0; i<2; i++) {
-    switch (str[i]) {
-      case '0' ... '9':
-       out *= 16;
-       out += str[i] - '0';
-       break;
-      case 'a' ... 'f':
-       out *= 16;
-       out += str[i] + 10 - 'a';
-       break;
-      case 'A' ... 'F':
-       out *= 16;
-       out += str[i] + 10 - 'A';
-       break;
-      default:
-       errno = ERANGE;
+  switch (c)
+  {
+  case '0' ... '9':
+    return c - '0';
+  case 'a' ... 'f':
+    return c + 10 - 'a';
+  case 'A' ... 'F':
+    return c + 10 - 'A';
+  default:
+    return -1;
+  }
+}
+
+int
+bstrhextobin(const char *s, byte *b)
+{
+  int len = 0;
+  int hi = 0;
+
+  for (; *s; s++)
+  {
+    int v = fromxdigit(*s);
+    if (v < 0)
+    {
+      if (strchr(" :-", *s) && !hi)
+       continue;
+      else
        return -1;
     }
+
+    if (len == INT32_MAX)
+      return -1;
+
+    if (b)
+    {
+      if (!hi)
+       b[len] = (v << 4);
+      else
+       b[len] |= v;
+    }
+
+    len += hi;
+    hi = !hi;
   }
 
-  return out;
+  return !hi ? len : -1;
+}
+
+static char
+toxdigit(uint b)
+{
+  if (b < 10)
+    return ('0' + b);
+  else if (b < 16)
+    return ('a' + b - 10);
+  else
+    return 0;
+}
+
+int
+bstrbintohex(const byte *b, size_t len, char *buf, size_t size, char delim)
+{
+  ASSERT(size >= 6);
+  char *bound = buf + size - 3;
+
+  size_t i;
+  for (i = 0; i < len; i++)
+  {
+    if (buf > bound)
+    {
+      strcpy(buf - 4, "...");
+      return -1;
+    }
+
+    uint x = b[i];
+    buf[0] = toxdigit(x >> 4);
+    buf[1] = toxdigit(x & 0xF);
+    buf[2] = delim;
+    buf += 3;
+  }
+
+  buf[i ? -1 : 0] = 0;
+
+  return 0;
 }