hexio.c 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <stdint.h>
  5. #include <ctype.h>
  6. #include <errno.h>
  7. #include "bit_array.h"
  8. #include "hexio.h"
  9. int bitmask_scnprintf(char *buf, size_t buflen, const BIT_ARRAY *bmp)
  10. {
  11. int i = HOW_MANY(bmp->num_of_bits, HEXCHUNKSZ) - 1;
  12. int len = 0;
  13. uint32_t val;
  14. buf[0] = 0;
  15. for (; i >= 0; i--) {
  16. val = bit_array_get_word32(bmp, i * HEXCHUNKSZ);
  17. if (val != 0 || len != 0 || i == 0 )
  18. len += snprintf(buf + len, MAX(buflen - len, 0),
  19. len ? ",%0*x" : "%0*x", HEXCHARSZ, val);
  20. }
  21. return len;
  22. }
  23. /*
  24. * Converts one hex digit to int
  25. */
  26. int hex_to_dec(char c)
  27. {
  28. if (c >= '0' && c <= '9')
  29. return c - '0';
  30. else if (c >= 'a' && c <= 'f')
  31. return c - 'a' + 10;
  32. else if (c >= 'A' && c <= 'F')
  33. return c - 'A' + 10;
  34. else
  35. return -EINVAL;
  36. }
  37. /*
  38. * Returns 32-bit token or -EOVERFLOW or -EINVAL in case of error
  39. */
  40. int64_t next_chunk(const char **buf, size_t *buflen)
  41. {
  42. uint32_t chunk = 0;
  43. int h;
  44. while (*buflen) {
  45. if (**buf == '\0' || **buf == ',') {
  46. (*buf)++, (*buflen)--;
  47. return chunk;
  48. }
  49. if (isspace(**buf)) {
  50. while (isspace(**buf) && *buflen)
  51. (*buf)++, (*buflen)--;
  52. if (buflen && **buf != '\0')
  53. return -EINVAL;
  54. else
  55. return chunk;
  56. }
  57. h = hex_to_dec(**buf);
  58. if (h < 0)
  59. return h;
  60. if (chunk > CHUNK_MASK >> 4)
  61. return -EOVERFLOW;
  62. chunk = (chunk << 4) | h;
  63. (*buf)++, (*buflen)--;
  64. }
  65. return chunk;
  66. }
  67. int count_chunks(const char *buf, size_t buflen)
  68. {
  69. int chunks = 0;
  70. int64_t chunk;
  71. while (buflen && *buf != '\0') {
  72. if ((chunk = next_chunk(&buf, &buflen)) >= 0)
  73. chunks++;
  74. else
  75. return (int)chunk;
  76. }
  77. return chunks;
  78. }
  79. /*
  80. * Returns 0 or -EOVERFLOW or -EINVAL in case of error
  81. */
  82. int bitmask_parse_user(const char *buf, size_t buflen, BIT_ARRAY *bmp)
  83. {
  84. int nchunks = 0;
  85. int64_t chunk;
  86. nchunks = count_chunks(buf, buflen);
  87. if (nchunks < 0)
  88. return nchunks;
  89. bit_array_clear_all(bmp);
  90. while (nchunks) {
  91. chunk = next_chunk(&buf, &buflen);
  92. if (chunk < 0)
  93. return chunk;
  94. nchunks--;
  95. bit_array_set_word32(bmp, nchunks * HEXCHUNKSZ, (uint32_t)chunk);
  96. }
  97. return 0;
  98. }