aRts audio server
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.

pipebuffer.cc 3.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. /*
  2. Copyright (C) 2000 Stefan Westerfeld
  3. stefan@space.twc.de
  4. This library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Library General Public
  6. License as published by the Free Software Foundation; either
  7. version 2 of the License, or (at your option) any later version.
  8. This library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Library General Public License for more details.
  12. You should have received a copy of the GNU Library General Public License
  13. along with this library; see the file COPYING.LIB. If not, write to
  14. the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  15. Boston, MA 02110-1301, USA.
  16. */
  17. #include "pipebuffer.h"
  18. #include <assert.h>
  19. #include <cstring>
  20. using namespace std;
  21. using namespace Arts;
  22. PipeSegment::PipeSegment(long size, void *buffer)
  23. {
  24. this->buffer = new char[size];
  25. this->currentpos = this->buffer;
  26. memcpy(this->buffer,buffer,size);
  27. _remaining = size;
  28. }
  29. PipeSegment::~PipeSegment()
  30. {
  31. delete[] buffer;
  32. }
  33. void *PipeSegment::data()
  34. {
  35. return currentpos;
  36. }
  37. long PipeSegment::remaining()
  38. {
  39. return _remaining;
  40. }
  41. void PipeSegment::skip(long count)
  42. {
  43. _remaining -= count;
  44. currentpos += count;
  45. assert(_remaining >= 0);
  46. }
  47. PipeBuffer::PipeBuffer()
  48. {
  49. _size = 0;
  50. }
  51. PipeBuffer::~PipeBuffer()
  52. {
  53. clear();
  54. }
  55. void PipeBuffer::clear()
  56. {
  57. while(segments.size() != 0)
  58. {
  59. PipeSegment *first = *segments.begin();
  60. delete first;
  61. segments.pop_front();
  62. }
  63. _size = 0;
  64. }
  65. void *PipeBuffer::peek(long size)
  66. {
  67. while(!segments.empty())
  68. {
  69. PipeSegment *first = *segments.begin();
  70. if(size <= first->remaining())
  71. return first->data();
  72. }
  73. return 0;
  74. }
  75. void PipeBuffer::skip(long size)
  76. {
  77. while(!segments.empty() && size > 0)
  78. {
  79. PipeSegment *first = *segments.begin();
  80. // if we have less data to skip than the first segment contains
  81. if(size < first->remaining())
  82. {
  83. // skip the data inside the segment
  84. _size -= size;
  85. first->skip(size);
  86. return;
  87. }
  88. else
  89. {
  90. // otherwise erase the first segment
  91. _size -= first->remaining();
  92. size -= first->remaining();
  93. delete first;
  94. segments.pop_front();
  95. }
  96. }
  97. }
  98. long PipeBuffer::read(long size, void *buffer)
  99. {
  100. long readbytes = 0;
  101. char *bptr = (char *)buffer;
  102. while(!segments.empty() && size > 0)
  103. {
  104. PipeSegment *first = *segments.begin();
  105. long readCnt = size;
  106. if(readCnt > first->remaining()) readCnt = first->remaining();
  107. memcpy(bptr,first->data(),readCnt);
  108. first->skip(readCnt);
  109. size -= readCnt;
  110. bptr += readCnt;
  111. readbytes += readCnt;
  112. if(first->remaining() == 0)
  113. {
  114. delete first;
  115. segments.pop_front();
  116. }
  117. }
  118. _size -= readbytes;
  119. return readbytes;
  120. }
  121. long PipeBuffer::size()
  122. {
  123. return _size;
  124. }
  125. void PipeBuffer::write(long size, void *buffer)
  126. {
  127. segments.push_back(new PipeSegment(size,buffer));
  128. _size += size;
  129. }
  130. void PipeBuffer::unRead(long size, void *buffer)
  131. {
  132. segments.push_front(new PipeSegment(size,buffer));
  133. _size += size;
  134. }