Browse Source

rewrite hex input/output

Semyon Verchenko 6 years ago
parent
commit
bef42bf776
3 changed files with 95 additions and 117 deletions
  1. 2 2
      cpumask.h
  2. 87 108
      hexio.c
  3. 6 7
      hexio.h

+ 2 - 2
cpumask.h

@@ -48,6 +48,6 @@ static inline int __first_cpu(const cpumask_t srcp)
 int __next_cpu(int n, const cpumask_t *srcp);
 #define next_cpu(n, src) __next_cpu((n), (src))
 
-#define cpumask_scnprintf(buf, len, src) bitmask_displayhex((buf), (len), (src).bits)
-#define cpumask_parse_user(ubuf, ulen, dst) bitmask_parsehex((ubuf), (dst).bits)
+#define cpumask_scnprintf(buf, len, src) bitmask_scnprintf((buf), (len), (src).bits)
+#define cpumask_parse_user(ubuf, ulen, dst) bitmask_parse_user((ubuf), (ulen), (dst).bits)
 #endif /* CPUMASK_H */

+ 87 - 108
hexio.c

@@ -1,137 +1,116 @@
-/*
- * Temporaly use displayhex and parsehex from LGPL libbitmask 
- * Start of libbitmask code
- */
-
-/*
- * bitmask user library implementation.
- *
- * Copyright (c) 2004-2006 Silicon Graphics, Inc. All rights reserved.
- *
- * Paul Jackson <pj@sgi.com>
- */
-
-/*
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU Lesser General Public License as published by
- *  the Free Software Foundation; either version 2.1 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
- */
-
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
 #include <stdint.h>
+#include <ctype.h>
+#include <errno.h>
 #include "bit_array.h"
 #include "hexio.h"
 
-/*
- * Write hex word representation of bmp to buf, 32 bits per
- * comma-separated, zero-filled hex word.  Do not write more
- * than buflen chars to buf.
- *
- * Return number of chars that would have been written
- * if buf were large enough.
- */
-
-const char *nexttoken(const char *q,  int sep)
+int bitmask_scnprintf(char *buf, size_t buflen, const BIT_ARRAY *bmp)
 {
-	if (q)
-		q = strchr(q, sep);
-	if (q)
-		q++;
-	return q;
+	int i = HOW_MANY(bmp->num_of_bits, HEXCHUNKSZ) - 1;
+	int len = 0;
+	uint32_t val;
+	buf[0] = 0;
+
+	for (; i >= 0; i--) {
+		val = bit_array_get_word32(bmp, i * HEXCHUNKSZ);
+		if (val != 0 || len != 0 || i == 0 )
+			len += snprintf(buf + len, MAX(buflen - len, 0),
+				len ? ",%0*x" : "%0*x", HEXCHARSZ, val);
+	}
+	return len;
 }
 
-char _getbit(const BIT_ARRAY* bitarr, bit_index_t b)
+/*
+ * Converts one hex digit to int
+ */
+int hex_to_dec(char c)
 {
-  if (b >= bitarr->num_of_bits)
-  	return 0;
-  return bit_array_get_bit(bitarr, b);
+	if (c >= '0' && c <= '9')
+		return c - '0';
+	else if (c >= 'a' && c <= 'f')
+		return c - 'a' + 10;
+	else if (c >= 'A' && c <= 'F')
+		return c - 'A' + 10;
+	else
+		return -EINVAL;
 }
 
-int bitmask_displayhex(char *buf, int buflen, const BIT_ARRAY *bmp)
+/*
+ * Returns 32-bit token or -EOVERFLOW or -EINVAL in case of error
+ */
+int64_t next_chunk(const char **buf, size_t *buflen)
 {
-	int chunk;
-	int cnt = 0;
-	const char *sep = "";
+	uint32_t chunk = 0;
+	int h;
+	while (*buflen)
+	{
+		if (**buf == '\0' || **buf == ',')
+		{
+			(*buf)++, (*buflen)--;
+			return chunk;
+		}
+		
+		if (isspace(**buf))
+		{
+			while (isspace(**buf) && *buflen)
+				(*buf)++, (*buflen)--;
+			if (buflen && **buf != '\0')
+				return -EINVAL;
+			else
+				return chunk;
+		}
 
-	if (buflen < 1)
-		return 0;
-	buf[0] = 0;
+		h = hex_to_dec(**buf);
+		if (h < 0)
+			return h;
 
-	for (chunk = howmany(bmp->num_of_bits, HEXCHUNKSZ); chunk >= 0; chunk--) {
-		uint32_t val = 0;
-		int bit;
+		if (chunk > CHUNK_MASK >> 4)
+			return -EOVERFLOW;
 
-		for (bit = HEXCHUNKSZ - 1; bit >= 0; bit--)
-			val = val << 1 | _getbit(bmp, chunk * HEXCHUNKSZ + bit);
-		if (val != 0 || cnt != 0 || chunk == 0 )
-		{
-			cnt += snprintf(buf + cnt, max(buflen - cnt, 0), "%s%0*x",
-				sep, HEXCHARSZ, val);
-			sep = ",";
-		}
+		chunk = (chunk << 4) | h;
+		(*buf)++, (*buflen)--;
+	}
+	return chunk;
+}
+
+int count_chunks(const char *buf, size_t buflen)
+{
+	int chunks = 0;
+	int64_t chunk;
+	while (buflen && *buf != '\0')
+	{
+		if ((chunk = next_chunk(&buf, &buflen)) >= 0)
+			chunks++;
+		else
+			return (int)chunk;
 	}
-	return cnt;
+	return chunks;
 }
 
 /*
- * Parse hex word representation in buf to bmp.
- *
- * Returns -1 on error, leaving unspecified results in bmp.
+ * Returns 0 or -EOVERFLOW or -EINVAL in case of error
  */
-
-int bitmask_parsehex(const char *buf, BIT_ARRAY *bmp)
+int bitmask_parse_user(const char *buf, size_t buflen, BIT_ARRAY *bmp)
 {
-	const char *p, *q;
-	int nchunks = 0, chunk;
-
-	bit_array_clear_all(bmp);
-
-	q = buf;
-	while (p = q, q = nexttoken(q, ','), p)
-		nchunks++;
-
-	chunk = nchunks - 1;
-	q = buf;
-	while (p = q, q = nexttoken(q, ','), p) {
-		uint32_t val;
-		int bit;
-		char *endptr;
-		int nchars_read, nchars_unread;
+	int nchunks = 0;
+	int64_t chunk;
 
-		val = strtoul(p, &endptr, 16);
+	nchunks = count_chunks(buf, buflen);
+	if (nchunks < 0)
+		return nchunks;
 
-		/* We should have consumed 1 to 8 (HEXCHARSZ) chars */
-		nchars_read = endptr - p;
-		if (nchars_read < 1 || nchars_read > HEXCHARSZ)
-			goto err;
-
-		/* We should have consumed up to next comma */
-		nchars_unread = q - endptr;
-		if (q != NULL && nchars_unread != 1)
-			goto err;
+	bit_array_clear_all(bmp);
 
-		for (bit = HEXCHUNKSZ - 1; bit >= 0; bit--) {
-			int n = chunk * HEXCHUNKSZ + bit;
-			if (n >= bmp->num_of_bits)
-				goto err;
-			bit_array_assign_bit(bmp, n, (val >> bit) & 1);
-		}
-		chunk--;
+	while (nchunks)
+	{
+		chunk = next_chunk(&buf, &buflen);
+		if (chunk < 0)
+			return chunk;
+		nchunks--;
+		bit_array_set_word32(bmp, nchunks * HEXCHUNKSZ, (uint32_t)chunk);
 	}
 	return 0;
-err:
-	bit_array_clear_all(bmp);
-	return -1;
 }

+ 6 - 7
hexio.h

@@ -4,14 +4,13 @@
 #define HEX_IO_H
 #define HEXCHUNKSZ 32
 #define HEXCHARSZ 8
-#ifndef max
-	#define max(x,y) ((x) > (y) ? (x) : (y))
-#endif
-#ifndef howmany
-	#define howmany(x, y) (((x)+((y)-1))/(y))
+#define CHUNK_MASK ((1ULL << HEXCHUNKSZ) - 1)
+#define HOW_MANY(x, y) (((x) + (y) - 1) / (y))
+#ifndef MAX
+	#define MAX(x,y) ((x) > (y) ? (x) : (y))
 #endif
 
-int bitmask_displayhex(char *buf, int buflen, const BIT_ARRAY *bmp);;
-int bitmask_parsehex(const char *buf, BIT_ARRAY *bmp);
+int bitmask_scnprintf(char *buf, size_t buflen, const BIT_ARRAY *bmp);
+int bitmask_parse_user(const char *buf, size_t buflen, BIT_ARRAY *bmp);
 
 #endif