fields.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. /* Copyright (C) 2022-2023 Salvatore Sanfilippo -- All Rights Reserved
  2. * See the LICENSE file for information about the license.
  3. *
  4. * Protocol fields implementation. */
  5. #include "app.h"
  6. /* Create a new field of the specified type. Without populating its
  7. * type-specific value. */
  8. static ProtoViewField *field_new(ProtoViewFieldType type, const char *name) {
  9. ProtoViewField *f = malloc(sizeof(*f));
  10. f->type = type;
  11. f->name = strdup(name);
  12. return f;
  13. }
  14. /* Free a field an associated data. */
  15. static void field_free(ProtoViewField *f) {
  16. free(f->name);
  17. switch(f->type) {
  18. case FieldTypeStr: free(f->str); break;
  19. case FieldTypeBytes: free(f->bytes); break;
  20. default: break; // Nothing to free for other types.
  21. }
  22. free(f);
  23. }
  24. /* Return the type of the field as string. */
  25. const char *field_get_type_name(ProtoViewField *f) {
  26. switch(f->type) {
  27. case FieldTypeStr: return "str";
  28. case FieldTypeSignedInt: return "int";
  29. case FieldTypeUnsignedInt: return "uint";
  30. case FieldTypeBinary: return "bin";
  31. case FieldTypeHex: return "hex";
  32. case FieldTypeBytes: return "bytes";
  33. case FieldTypeFloat: return "float";
  34. }
  35. return "unknown";
  36. }
  37. /* Free a field set and its contained fields. */
  38. void fieldset_free(ProtoViewFieldSet *fs) {
  39. for (uint32_t j = 0; j < fs->numfields; j++)
  40. field_free(fs->fields[j]);
  41. free(fs->fields);
  42. free(fs);
  43. }
  44. /* Allocate and init an empty field set. */
  45. ProtoViewFieldSet *fieldset_new(void) {
  46. ProtoViewFieldSet *fs = malloc(sizeof(*fs));
  47. fs->numfields = 0;
  48. fs->fields = NULL;
  49. return fs;
  50. }
  51. /* Append an already allocated field at the end of the specified field set. */
  52. static void fieldset_add_field(ProtoViewFieldSet *fs, ProtoViewField *field) {
  53. fs->numfields++;
  54. fs->fields = realloc(fs->fields,sizeof(ProtoViewField*)*fs->numfields);
  55. fs->fields[fs->numfields-1] = field;
  56. }
  57. /* Allocate and append an integer field. */
  58. void fieldset_add_int(ProtoViewFieldSet *fs, const char *name, int64_t val, uint8_t bits) {
  59. ProtoViewField *f = field_new(FieldTypeSignedInt,name);
  60. f->value = val;
  61. f->len = bits;
  62. fieldset_add_field(fs,f);
  63. }
  64. /* Allocate and append an unsigned field. */
  65. void fieldset_add_uint(ProtoViewFieldSet *fs, const char *name, uint64_t uval, uint8_t bits) {
  66. ProtoViewField *f = field_new(FieldTypeUnsignedInt,name);
  67. f->uvalue = uval;
  68. f->len = bits;
  69. fieldset_add_field(fs,f);
  70. }
  71. /* Allocate and append a hex field. This is an unsigned number but
  72. * with an hex representation. */
  73. void fieldset_add_hex(ProtoViewFieldSet *fs, const char *name, uint64_t uval, uint8_t bits) {
  74. ProtoViewField *f = field_new(FieldTypeHex,name);
  75. f->uvalue = uval;
  76. f->len = bits;
  77. fieldset_add_field(fs,f);
  78. }
  79. /* Allocate and append a bin field. This is an unsigned number but
  80. * with a binary representation. */
  81. void fieldset_add_bin(ProtoViewFieldSet *fs, const char *name, uint64_t uval, uint8_t bits) {
  82. ProtoViewField *f = field_new(FieldTypeBinary,name);
  83. f->uvalue = uval;
  84. f->len = bits;
  85. fieldset_add_field(fs,f);
  86. }
  87. /* Allocate and append a string field. */
  88. void fieldset_add_str(ProtoViewFieldSet *fs, const char *name, const char *s) {
  89. ProtoViewField *f = field_new(FieldTypeStr,name);
  90. f->str = strdup(s);
  91. f->len = strlen(s);
  92. fieldset_add_field(fs,f);
  93. }
  94. /* Allocate and append a bytes field. Note that 'count' is specified in
  95. * nibbles (bytes*2). */
  96. void fieldset_add_bytes(ProtoViewFieldSet *fs, const char *name, const uint8_t *bytes, uint32_t count_nibbles) {
  97. uint32_t numbytes = (count_nibbles+count_nibbles%2)/2;
  98. ProtoViewField *f = field_new(FieldTypeBytes,name);
  99. f->bytes = malloc(numbytes);
  100. memcpy(f->bytes,bytes,numbytes);
  101. f->len = count_nibbles;
  102. fieldset_add_field(fs,f);
  103. }
  104. /* Allocate and append a float field. */
  105. void fieldset_add_float(ProtoViewFieldSet *fs, const char *name, float val, uint32_t digits_after_dot) {
  106. ProtoViewField *f = field_new(FieldTypeFloat,name);
  107. f->fvalue = val;
  108. f->len = digits_after_dot;
  109. fieldset_add_field(fs,f);
  110. }