tlv8.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. #include <string.h>
  2. #include "tlv8.h"
  3. void tlv8_encoder_init(tlv8_encoder_t *enc, uint8_t *buffer, size_t capacity) {
  4. enc->buffer = buffer;
  5. enc->size = 0;
  6. enc->capacity = capacity;
  7. }
  8. bool tlv8_encode(tlv8_encoder_t *enc, uint8_t type, const uint8_t *value,
  9. size_t len) {
  10. size_t offset = 0;
  11. while (offset < len || (offset == 0 && len == 0)) {
  12. size_t chunk_len = len - offset;
  13. if (chunk_len > 255) {
  14. chunk_len = 255;
  15. }
  16. // Check if we have space
  17. if (enc->size + 2 + chunk_len > enc->capacity) {
  18. return false;
  19. }
  20. enc->buffer[enc->size++] = type;
  21. enc->buffer[enc->size++] = (uint8_t)chunk_len;
  22. if (chunk_len > 0) {
  23. memcpy(enc->buffer + enc->size, value + offset, chunk_len);
  24. enc->size += chunk_len;
  25. }
  26. offset += chunk_len;
  27. // For zero-length values, only write one TLV
  28. if (len == 0) {
  29. break;
  30. }
  31. }
  32. return true;
  33. }
  34. bool tlv8_encode_byte(tlv8_encoder_t *enc, uint8_t type, uint8_t value) {
  35. return tlv8_encode(enc, type, &value, 1);
  36. }
  37. size_t tlv8_encoder_size(const tlv8_encoder_t *enc) {
  38. return enc->size;
  39. }
  40. const uint8_t *tlv8_find(const uint8_t *data, size_t data_len, uint8_t type,
  41. size_t *value_len) {
  42. size_t offset = 0;
  43. while (offset + 2 <= data_len) {
  44. uint8_t t = data[offset];
  45. uint8_t l = data[offset + 1];
  46. if (offset + 2 + l > data_len) {
  47. break; // Invalid TLV
  48. }
  49. if (t == type) {
  50. *value_len = l;
  51. return data + offset + 2;
  52. }
  53. offset += 2 + l;
  54. }
  55. *value_len = 0;
  56. return NULL;
  57. }
  58. bool tlv8_decode_concat(const uint8_t *data, size_t data_len, uint8_t type,
  59. uint8_t *out_buffer, size_t out_capacity,
  60. size_t *out_len) {
  61. size_t offset = 0;
  62. size_t out_offset = 0;
  63. bool found = false;
  64. bool in_sequence = false;
  65. while (offset + 2 <= data_len) {
  66. uint8_t t = data[offset];
  67. uint8_t l = data[offset + 1];
  68. if (offset + 2 + l > data_len) {
  69. break; // Invalid TLV
  70. }
  71. if (t == type) {
  72. found = true;
  73. in_sequence = true;
  74. if (out_offset + l > out_capacity) {
  75. return false; // Buffer too small
  76. }
  77. memcpy(out_buffer + out_offset, data + offset + 2, l);
  78. out_offset += l;
  79. } else if (in_sequence) {
  80. // Different type encountered after our type - stop concatenating
  81. break;
  82. }
  83. offset += 2 + l;
  84. }
  85. *out_len = out_offset;
  86. return found;
  87. }