jack2 codebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

154 lines
4.7KB

  1. /*
  2. * Copyright (c) 2023 Florian Walpen <dev@submerge.ch>
  3. *
  4. * Permission to use, copy, modify, and distribute this software for any
  5. * purpose with or without fee is hereby granted, provided that the above
  6. * copyright notice and this permission notice appear in all copies.
  7. *
  8. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. #ifndef SOSSO_BUFFER_HPP
  17. #define SOSSO_BUFFER_HPP
  18. #include <cstring>
  19. namespace sosso {
  20. /*!
  21. * \brief Buffer Management
  22. *
  23. * Provides means to access and manipulate externally allocated buffer memory.
  24. * It stores a memory pointer, length and a read / write position. The buffer
  25. * memory can be passed from one Buffer instance to another, through move
  26. * constructor and move assignment. This prevents multiple Buffer instances from
  27. * referencing the same memory.
  28. */
  29. class Buffer {
  30. public:
  31. //! Construct an empty and invalid Buffer.
  32. Buffer() = default;
  33. /*!
  34. * \brief Construct Buffer operating on given memory.
  35. * \param buffer Pointer to the externally allocated memory.
  36. * \param length Length of the memory dedicated to this Buffer.
  37. */
  38. Buffer(char *buffer, std::size_t length)
  39. : _data(buffer), _length(length), _position(0) {}
  40. /*!
  41. * \brief Move construct a buffer.
  42. * \param other Adopt memory from this Buffer, leaving it empty.
  43. */
  44. Buffer(Buffer &&other) noexcept
  45. : _data(other._data), _length(other._length), _position(other._position) {
  46. other._data = nullptr;
  47. other._position = 0;
  48. other._length = 0;
  49. }
  50. /*!
  51. * \brief Move assign memory from another Buffer.
  52. * \param other Adopt memory from this Buffer, leaving it empty.
  53. * \return This newly assigned Buffer.
  54. */
  55. Buffer &operator=(Buffer &&other) {
  56. _data = other._data;
  57. _position = other._position;
  58. _length = other._length;
  59. other._data = nullptr;
  60. other._position = 0;
  61. other._length = 0;
  62. return *this;
  63. }
  64. //! Buffer is valid if the memory is accessable.
  65. bool valid() const { return (_data != nullptr) && (_length > 0); }
  66. //! Access the underlying memory, null if invalid.
  67. char *data() const { return _data; }
  68. //! Length of the underlying memory in bytes, 0 if invalid.
  69. std::size_t length() const { return _length; }
  70. //! Access buffer memory at read / write position.
  71. char *position() const { return _data + _position; }
  72. //! Get read / write progress from buffer start, in bytes.
  73. std::size_t progress() const { return _position; }
  74. //! Remaining buffer memory in bytes.
  75. std::size_t remaining() const { return _length - _position; }
  76. /*!
  77. * \brief Cap given progress by remaining buffer memory.
  78. * \param progress Progress in bytes.
  79. * \return Progress limited by the remaining buffer memory.
  80. */
  81. std::size_t remaining(std::size_t progress) const {
  82. if (progress > remaining()) {
  83. progress = remaining();
  84. }
  85. return progress;
  86. }
  87. //! Indicate that the buffer is fully processed.
  88. bool done() const { return _position == _length; }
  89. //! Advance the buffer read / write position.
  90. std::size_t advance(std::size_t progress) {
  91. progress = remaining(progress);
  92. _position += progress;
  93. return progress;
  94. }
  95. //! Rewind the buffer read / write position.
  96. std::size_t rewind(std::size_t progress) {
  97. if (progress > _position) {
  98. progress = _position;
  99. }
  100. _position -= progress;
  101. return progress;
  102. }
  103. /*!
  104. * \brief Erase an already processed part, rewind.
  105. * \param begin Start position of the region to be erased.
  106. * \param end End position of the region to be erased.
  107. * \return The number of bytes that were effectively erased.
  108. */
  109. std::size_t erase(std::size_t begin, std::size_t end) {
  110. if (begin < _position && begin < end) {
  111. if (end > _position) {
  112. end = _position;
  113. }
  114. std::size_t copy = _position - end;
  115. if (copy > 0) {
  116. std::memmove(_data + begin, _data + end, copy);
  117. }
  118. _position -= (end - begin);
  119. return (end - begin);
  120. }
  121. return 0;
  122. }
  123. //! Reset the buffer position to zero.
  124. void reset() { _position = 0; }
  125. private:
  126. char *_data = nullptr; // External buffer memory, null if invalid.
  127. std::size_t _length = 0; // Total length of the buffer memory.
  128. std::size_t _position = 0; // Current read / write position.
  129. };
  130. } // namespace sosso
  131. #endif // SOSSO_BUFFER_HPP