Message.h 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. /* vim: set expandtab ts=4 sw=4: */
  2. /*
  3. * You may redistribute this program and/or modify it under the terms of
  4. * the GNU General Public License as published by the Free Software Foundation,
  5. * either version 3 of the License, or (at your option) any later version.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. * You should have received a copy of the GNU General Public License
  13. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. #ifndef Message_H
  16. #define Message_H
  17. #include "util/Assert.h"
  18. #include <stdint.h>
  19. #include "memory/Allocator.h"
  20. #include "util/Bits.h"
  21. #include "util/UniqueName.h"
  22. struct Message
  23. {
  24. /** The length of the message. */
  25. int32_t length;
  26. /** The number of bytes of padding BEFORE where bytes begins. */
  27. int32_t padding;
  28. /** The content. */
  29. uint8_t* bytes;
  30. /** Amount of bytes of storage space available in the message. */
  31. uint32_t capacity;
  32. /** The allocator which allocated space for this message. */
  33. struct Allocator* alloc;
  34. };
  35. #define Message_STACK(name, messageLength, amountOfPadding) \
  36. uint8_t UniqueName_get()[messageLength + amountOfPadding]; \
  37. name = &(struct Message){ \
  38. .length = messageLength, \
  39. .bytes = UniqueName_get() + amountOfPadding, \
  40. .padding = amountOfPadding, \
  41. .capacity = messageLength \
  42. }
  43. static inline struct Message* Message_clone(struct Message* toClone,
  44. struct Allocator* allocator)
  45. {
  46. uint32_t len = toClone->length + toClone->padding;
  47. if (len < (toClone->capacity + toClone->padding)) {
  48. len = (toClone->capacity + toClone->padding);
  49. }
  50. uint8_t* allocation = Allocator_malloc(allocator, len);
  51. Bits_memcpy(allocation, toClone->bytes - toClone->padding, len);
  52. return Allocator_clone(allocator, (&(struct Message) {
  53. .length = toClone->length,
  54. .padding = toClone->padding,
  55. .bytes = allocation + toClone->padding,
  56. .capacity = toClone->length,
  57. .alloc = allocator
  58. }));
  59. }
  60. static inline void Message_copyOver(struct Message* output,
  61. struct Message* input,
  62. struct Allocator* allocator)
  63. {
  64. size_t inTotalLength = input->length + input->padding;
  65. size_t outTotalLength = output->length + output->padding;
  66. uint8_t* allocation = output->bytes - output->padding;
  67. if (inTotalLength > outTotalLength) {
  68. allocation = Allocator_realloc(allocator, allocation, inTotalLength);
  69. }
  70. Bits_memcpy(allocation, input->bytes - input->padding, inTotalLength);
  71. output->bytes = allocation + input->padding;
  72. output->length = input->length;
  73. output->padding = input->padding;
  74. }
  75. /**
  76. * Pretend to shift the content forward by amount.
  77. * Really it shifts the bytes value backward.
  78. */
  79. static inline int Message_shift(struct Message* toShift, int32_t amount)
  80. {
  81. if (amount > 0) {
  82. Assert_true(toShift->padding >= amount);
  83. } else {
  84. Assert_true(toShift->length >= (-amount));
  85. }
  86. toShift->length += amount;
  87. toShift->capacity += amount;
  88. toShift->bytes -= amount;
  89. toShift->padding -= amount;
  90. return 1;
  91. }
  92. static inline void Message_push(struct Message* restrict msg,
  93. const void* restrict object,
  94. size_t size)
  95. {
  96. Message_shift(msg, (int)size);
  97. Bits_memcpy(msg->bytes, object, size);
  98. }
  99. static inline void Message_pop(struct Message* restrict msg,
  100. void* restrict object,
  101. size_t size)
  102. {
  103. Bits_memcpy(object, msg->bytes, size);
  104. Message_shift(msg, -((int)size));
  105. }
  106. #endif