hexio.c 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  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. {
  46. if (**buf == '\0' || **buf == ',')
  47. {
  48. (*buf)++, (*buflen)--;
  49. return chunk;
  50. }
  51. if (isspace(**buf))
  52. {
  53. while (isspace(**buf) && *buflen)
  54. (*buf)++, (*buflen)--;
  55. if (buflen && **buf != '\0')
  56. return -EINVAL;
  57. else
  58. return chunk;
  59. }
  60. h = hex_to_dec(**buf);
  61. if (h < 0)
  62. return h;
  63. if (chunk > CHUNK_MASK >> 4)
  64. return -EOVERFLOW;
  65. chunk = (chunk << 4) | h;
  66. (*buf)++, (*buflen)--;
  67. }
  68. return chunk;
  69. }
  70. int count_chunks(const char *buf, size_t buflen)
  71. {
  72. int chunks = 0;
  73. int64_t chunk;
  74. while (buflen && *buf != '\0')
  75. {
  76. if ((chunk = next_chunk(&buf, &buflen)) >= 0)
  77. chunks++;
  78. else
  79. return (int)chunk;
  80. }
  81. return chunks;
  82. }
  83. /*
  84. * Returns 0 or -EOVERFLOW or -EINVAL in case of error
  85. */
  86. int bitmask_parse_user(const char *buf, size_t buflen, BIT_ARRAY *bmp)
  87. {
  88. int nchunks = 0;
  89. int64_t chunk;
  90. nchunks = count_chunks(buf, buflen);
  91. if (nchunks < 0)
  92. return nchunks;
  93. bit_array_clear_all(bmp);
  94. while (nchunks)
  95. {
  96. chunk = next_chunk(&buf, &buflen);
  97. if (chunk < 0)
  98. return chunk;
  99. nchunks--;
  100. bit_array_set_word32(bmp, nchunks * HEXCHUNKSZ, (uint32_t)chunk);
  101. }
  102. return 0;
  103. }