|
@@ -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;
|
|
|
}
|