c_datapump.h 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. #ifndef __C_DATAPUMP_H__
  2. #define __C_DATAPUMP_H__
  3. #include <stdlib.h>
  4. #include <memory.h>
  5. #include <stddef.h>
  6. #pragma intrinsic(memcpy,memset)
  7. template<class T> class C_DATAPUMP {
  8. private:
  9. protected:
  10. T *BufferBottom; // bottom of the physical buffer
  11. T *BufferTop; // top of the physical buffer
  12. T *BufferStart; // start of the logical buffer
  13. T *BufferEnd; // end of the logical buffer
  14. virtual void addItems(T *inputBuffer, size_t inputSize) { // inputSize = number of <T> records inputBuffer contains
  15. if(inputBuffer && inputSize) {
  16. memcpy(BufferEnd,inputBuffer,inputSize*sizeof(T)); // copy our records in
  17. BufferEnd += inputSize;
  18. if(BufferEnd >= BufferTop) BufferEnd = BufferBottom + (BufferEnd-BufferTop);
  19. }
  20. }
  21. virtual void delItems(int where, size_t numItems) { // where: 0 = start, 1 = end
  22. if(numItems > 0) {
  23. if(numItems > size()) { // just void everything
  24. BufferEnd = BufferStart;
  25. } else {
  26. if(where == 0) { // start
  27. BufferStart += numItems;
  28. if(BufferStart >= BufferTop) BufferStart = BufferBottom + (BufferTop-BufferStart);
  29. } else if(where == 1) { // end
  30. BufferEnd -= numItems;
  31. if(BufferEnd < BufferBottom) BufferEnd = BufferTop - (BufferBottom-BufferEnd);
  32. }
  33. }
  34. }
  35. }
  36. virtual void getItems(T *outputBuffer, size_t outputSize) { // outputSize = number of <T> records outputBuffer needs
  37. if(outputBuffer && outputSize) {
  38. memcpy(outputBuffer,BufferStart,outputSize*sizeof(T));
  39. }
  40. }
  41. public:
  42. C_DATAPUMP(int bufferSize) { // bufferSize = number of <T> records
  43. BufferBottom = NULL;
  44. BufferTop = NULL;
  45. BufferStart = NULL;
  46. BufferEnd = NULL;
  47. resizeBuffer(bufferSize);
  48. }
  49. virtual ~C_DATAPUMP() {
  50. if(getBufferSize() && BufferBottom) {
  51. free(BufferBottom);
  52. BufferBottom = NULL;
  53. }
  54. }
  55. virtual void resizeBuffer(size_t bufferSize) { // bufferSize = number of <T> records
  56. // this will invalidate any data in the buffer, so be careful when calling this function
  57. if(bufferSize) {
  58. if(getBufferSize() != bufferSize) {
  59. if(BufferBottom && BufferTop && getBufferSize()) { // buffer is valid
  60. if(getBufferSize() > bufferSize) { // buffer is getting smaller (will invalidate buffer)
  61. BufferTop -= getBufferSize()-bufferSize;
  62. invalidate();
  63. } else { // buffer is getting larger (will _NOT_ invalidate buffer... nicely moves the data over =)
  64. T *newBuffer = (T *)malloc(bufferSize * sizeof(T));
  65. // new
  66. BufferEnd = newBuffer + get(newBuffer,bufferSize);
  67. free(BufferBottom);
  68. BufferBottom = newBuffer;
  69. BufferTop = BufferBottom + bufferSize;
  70. BufferStart = BufferBottom;
  71. /* old
  72. T *bufptr = newBuffer;
  73. int top = BufferEnd >= BufferStart ? BufferEnd-BufferStart : BufferTop-BufferStart; // number of <T> records at top of physical buffer
  74. int bottom = BufferEnd >= BufferStart ? 0 : BufferEnd-BufferBottom; // number of <T> records at bottom of physical buffer
  75. if(top > 0) {
  76. memcpy(bufptr,BufferStart,top*sizeof(T));
  77. bufptr += top;
  78. }
  79. if(bottom > 0) {
  80. memcpy(bufptr,BufferBottom,bottom*sizeof(T));
  81. bufptr += bottom;
  82. }
  83. free(BufferBottom);
  84. BufferBottom = newBuffer;
  85. BufferTop = BufferBottom + bufferSize;
  86. BufferStart = BufferBottom;
  87. BufferEnd = bufptr;
  88. */
  89. }
  90. } else { // no buffer, create (invalidates the buffer... duh)
  91. BufferBottom = (T *)malloc(bufferSize * sizeof(T));
  92. BufferTop = BufferBottom + bufferSize;
  93. invalidate();
  94. }
  95. }
  96. }
  97. }
  98. virtual size_t size() { // will get the number of <T> records the logical buffer contains
  99. return BufferEnd >= BufferStart ? BufferEnd-BufferStart : (BufferTop-BufferStart)+(BufferEnd-BufferBottom);
  100. }
  101. virtual size_t put(T *inputBuffer, size_t inputSize) { // inputSize = number of <T> records inputBuffer contains
  102. // returns number of <T> records added to logical buffer
  103. size_t retval = 0;
  104. if(inputBuffer && inputSize) {
  105. size_t fitting = ((BufferTop-BufferBottom)-1) - size(); // can't go over our logical boundary.... blah
  106. if(fitting > inputSize) fitting = inputSize; // the entire thing can fit. yeay!
  107. retval = fitting;
  108. if(fitting > 0) {
  109. T *bufptr = inputBuffer;
  110. size_t top = BufferEnd >= BufferStart ? BufferTop-BufferEnd : 0; // number of <T> records free at top of physical buffer
  111. size_t bottom = BufferEnd >= BufferStart ? BufferStart-BufferBottom : (BufferStart-BufferEnd); // number of <T> records free at bottom of physical buffer
  112. if(top > 0) {
  113. if(top > fitting) top = fitting;
  114. addItems(bufptr,top);
  115. fitting -= top;
  116. bufptr += top;
  117. }
  118. if(bottom > 0 && fitting > 0) {
  119. if(bottom > fitting) bottom = fitting;
  120. addItems(bufptr,bottom);
  121. }
  122. }
  123. }
  124. return retval;
  125. }
  126. virtual size_t get(T *outputBuffer, size_t outputSize) { // outputSize = number of <T> records outputBuffer needs
  127. // returns number of <T> records pulled from the logical buffer
  128. size_t retval = 0;
  129. if(outputBuffer && outputSize) {
  130. size_t fitting = size();
  131. if(fitting > outputSize) fitting = outputSize;
  132. retval = fitting;
  133. if(fitting > 0) {
  134. T *bufptr = outputBuffer;
  135. size_t top = BufferEnd >= BufferStart ? BufferEnd-BufferStart : BufferTop-BufferStart; // number of <T> records at top of physical buffer
  136. size_t bottom = BufferEnd >= BufferStart ? 0 : BufferEnd-BufferBottom; // number of <T> records at bottom of physical buffer
  137. if(top > 0) {
  138. if(top > fitting) top = fitting;
  139. getItems(bufptr,top);
  140. delItems(0,top);
  141. fitting -= top;
  142. bufptr += top;
  143. }
  144. if(bottom > 0 && fitting > 0) {
  145. if(bottom > fitting) bottom = fitting;
  146. getItems(bufptr,bottom);
  147. delItems(0,bottom);
  148. }
  149. }
  150. }
  151. return retval;
  152. }
  153. virtual size_t getBufferSize() { // returns the size of the physical buffer in <T> items
  154. return BufferTop-BufferBottom;
  155. }
  156. virtual void invalidate() { // calling this will wipe all data in the buffer and reset the logical pointers
  157. BufferStart = BufferEnd = BufferBottom;
  158. }
  159. };
  160. #endif // !__C_DATAPUMP_H__