bytestream.cc 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. // Protocol Buffers - Google's data interchange format
  2. // Copyright 2008 Google Inc. All rights reserved.
  3. // https://developers.google.com/protocol-buffers/
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are
  7. // met:
  8. //
  9. // * Redistributions of source code must retain the above copyright
  10. // notice, this list of conditions and the following disclaimer.
  11. // * Redistributions in binary form must reproduce the above
  12. // copyright notice, this list of conditions and the following disclaimer
  13. // in the documentation and/or other materials provided with the
  14. // distribution.
  15. // * Neither the name of Google Inc. nor the names of its
  16. // contributors may be used to endorse or promote products derived from
  17. // this software without specific prior written permission.
  18. //
  19. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. #include <google/protobuf/stubs/bytestream.h>
  31. #include <string.h>
  32. #include <algorithm>
  33. namespace google {
  34. namespace protobuf {
  35. namespace strings {
  36. void ByteSource::CopyTo(ByteSink* sink, size_t n) {
  37. while (n > 0) {
  38. StringPiece fragment = Peek();
  39. if (fragment.empty()) {
  40. GOOGLE_LOG(DFATAL) << "ByteSource::CopyTo() overran input.";
  41. break;
  42. }
  43. std::size_t fragment_size = std::min<std::size_t>(n, fragment.size());
  44. sink->Append(fragment.data(), fragment_size);
  45. Skip(fragment_size);
  46. n -= fragment_size;
  47. }
  48. }
  49. void ByteSink::Flush() {}
  50. void UncheckedArrayByteSink::Append(const char* data, size_t n) {
  51. if (data != dest_) {
  52. // Catch cases where the pointer returned by GetAppendBuffer() was modified.
  53. GOOGLE_DCHECK(!(dest_ <= data && data < (dest_ + n)))
  54. << "Append() data[] overlaps with dest_[]";
  55. memcpy(dest_, data, n);
  56. }
  57. dest_ += n;
  58. }
  59. CheckedArrayByteSink::CheckedArrayByteSink(char* outbuf, size_t capacity)
  60. : outbuf_(outbuf), capacity_(capacity), size_(0), overflowed_(false) {
  61. }
  62. void CheckedArrayByteSink::Append(const char* bytes, size_t n) {
  63. size_t available = capacity_ - size_;
  64. if (n > available) {
  65. n = available;
  66. overflowed_ = true;
  67. }
  68. if (n > 0 && bytes != (outbuf_ + size_)) {
  69. // Catch cases where the pointer returned by GetAppendBuffer() was modified.
  70. GOOGLE_DCHECK(!(outbuf_ <= bytes && bytes < (outbuf_ + capacity_)))
  71. << "Append() bytes[] overlaps with outbuf_[]";
  72. memcpy(outbuf_ + size_, bytes, n);
  73. }
  74. size_ += n;
  75. }
  76. GrowingArrayByteSink::GrowingArrayByteSink(size_t estimated_size)
  77. : capacity_(estimated_size),
  78. buf_(new char[estimated_size]),
  79. size_(0) {
  80. }
  81. GrowingArrayByteSink::~GrowingArrayByteSink() {
  82. delete[] buf_; // Just in case the user didn't call GetBuffer.
  83. }
  84. void GrowingArrayByteSink::Append(const char* bytes, size_t n) {
  85. size_t available = capacity_ - size_;
  86. if (bytes != (buf_ + size_)) {
  87. // Catch cases where the pointer returned by GetAppendBuffer() was modified.
  88. // We need to test for this before calling Expand() which may reallocate.
  89. GOOGLE_DCHECK(!(buf_ <= bytes && bytes < (buf_ + capacity_)))
  90. << "Append() bytes[] overlaps with buf_[]";
  91. }
  92. if (n > available) {
  93. Expand(n - available);
  94. }
  95. if (n > 0 && bytes != (buf_ + size_)) {
  96. memcpy(buf_ + size_, bytes, n);
  97. }
  98. size_ += n;
  99. }
  100. char* GrowingArrayByteSink::GetBuffer(size_t* nbytes) {
  101. ShrinkToFit();
  102. char* b = buf_;
  103. *nbytes = size_;
  104. buf_ = NULL;
  105. size_ = capacity_ = 0;
  106. return b;
  107. }
  108. void GrowingArrayByteSink::Expand(size_t amount) { // Expand by at least 50%.
  109. size_t new_capacity = std::max(capacity_ + amount, (3 * capacity_) / 2);
  110. char* bigger = new char[new_capacity];
  111. memcpy(bigger, buf_, size_);
  112. delete[] buf_;
  113. buf_ = bigger;
  114. capacity_ = new_capacity;
  115. }
  116. void GrowingArrayByteSink::ShrinkToFit() {
  117. // Shrink only if the buffer is large and size_ is less than 3/4
  118. // of capacity_.
  119. if (capacity_ > 256 && size_ < (3 * capacity_) / 4) {
  120. char* just_enough = new char[size_];
  121. memcpy(just_enough, buf_, size_);
  122. delete[] buf_;
  123. buf_ = just_enough;
  124. capacity_ = size_;
  125. }
  126. }
  127. void StringByteSink::Append(const char* data, size_t n) {
  128. dest_->append(data, n);
  129. }
  130. size_t ArrayByteSource::Available() const {
  131. return input_.size();
  132. }
  133. StringPiece ArrayByteSource::Peek() {
  134. return input_;
  135. }
  136. void ArrayByteSource::Skip(size_t n) {
  137. GOOGLE_DCHECK_LE(n, input_.size());
  138. input_.remove_prefix(n);
  139. }
  140. LimitByteSource::LimitByteSource(ByteSource *source, size_t limit)
  141. : source_(source),
  142. limit_(limit) {
  143. }
  144. size_t LimitByteSource::Available() const {
  145. size_t available = source_->Available();
  146. if (available > limit_) {
  147. available = limit_;
  148. }
  149. return available;
  150. }
  151. StringPiece LimitByteSource::Peek() {
  152. StringPiece piece(source_->Peek());
  153. if (piece.size() > limit_) {
  154. piece.set(piece.data(), limit_);
  155. }
  156. return piece;
  157. }
  158. void LimitByteSource::Skip(size_t n) {
  159. GOOGLE_DCHECK_LE(n, limit_);
  160. source_->Skip(n);
  161. limit_ -= n;
  162. }
  163. void LimitByteSource::CopyTo(ByteSink *sink, size_t n) {
  164. GOOGLE_DCHECK_LE(n, limit_);
  165. source_->CopyTo(sink, n);
  166. limit_ -= n;
  167. }
  168. } // namespace strings
  169. } // namespace protobuf
  170. } // namespace google