PageRenderTime 35ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/thirdparty/breakpad/third_party/protobuf/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.cc

http://github.com/tomahawk-player/tomahawk
C++ | 393 lines | 271 code | 66 blank | 56 comment | 34 complexity | b8139cb4889c1a835835785c3b86240e MD5 | raw file
Possible License(s): LGPL-2.1, BSD-3-Clause, GPL-3.0, GPL-2.0
  1. // Protocol Buffers - Google's data interchange format
  2. // Copyright 2008 Google Inc. All rights reserved.
  3. // http://code.google.com/p/protobuf/
  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. // Author: kenton@google.com (Kenton Varda)
  31. // Based on original Protocol Buffers design by
  32. // Sanjay Ghemawat, Jeff Dean, and others.
  33. #include <google/protobuf/io/zero_copy_stream_impl.h>
  34. #include <google/protobuf/stubs/common.h>
  35. #include <google/protobuf/stubs/stl_util-inl.h>
  36. namespace google {
  37. namespace protobuf {
  38. namespace io {
  39. namespace {
  40. // Default block size for Copying{In,Out}putStreamAdaptor.
  41. static const int kDefaultBlockSize = 8192;
  42. } // namespace
  43. // ===================================================================
  44. ArrayInputStream::ArrayInputStream(const void* data, int size,
  45. int block_size)
  46. : data_(reinterpret_cast<const uint8*>(data)),
  47. size_(size),
  48. block_size_(block_size > 0 ? block_size : size),
  49. position_(0),
  50. last_returned_size_(0) {
  51. }
  52. ArrayInputStream::~ArrayInputStream() {
  53. }
  54. bool ArrayInputStream::Next(const void** data, int* size) {
  55. if (position_ < size_) {
  56. last_returned_size_ = min(block_size_, size_ - position_);
  57. *data = data_ + position_;
  58. *size = last_returned_size_;
  59. position_ += last_returned_size_;
  60. return true;
  61. } else {
  62. // We're at the end of the array.
  63. last_returned_size_ = 0; // Don't let caller back up.
  64. return false;
  65. }
  66. }
  67. void ArrayInputStream::BackUp(int count) {
  68. GOOGLE_CHECK_GT(last_returned_size_, 0)
  69. << "BackUp() can only be called after a successful Next().";
  70. GOOGLE_CHECK_LE(count, last_returned_size_);
  71. GOOGLE_CHECK_GE(count, 0);
  72. position_ -= count;
  73. last_returned_size_ = 0; // Don't let caller back up further.
  74. }
  75. bool ArrayInputStream::Skip(int count) {
  76. GOOGLE_CHECK_GE(count, 0);
  77. last_returned_size_ = 0; // Don't let caller back up.
  78. if (count > size_ - position_) {
  79. position_ = size_;
  80. return false;
  81. } else {
  82. position_ += count;
  83. return true;
  84. }
  85. }
  86. int64 ArrayInputStream::ByteCount() const {
  87. return position_;
  88. }
  89. // ===================================================================
  90. ArrayOutputStream::ArrayOutputStream(void* data, int size, int block_size)
  91. : data_(reinterpret_cast<uint8*>(data)),
  92. size_(size),
  93. block_size_(block_size > 0 ? block_size : size),
  94. position_(0),
  95. last_returned_size_(0) {
  96. }
  97. ArrayOutputStream::~ArrayOutputStream() {
  98. }
  99. bool ArrayOutputStream::Next(void** data, int* size) {
  100. if (position_ < size_) {
  101. last_returned_size_ = min(block_size_, size_ - position_);
  102. *data = data_ + position_;
  103. *size = last_returned_size_;
  104. position_ += last_returned_size_;
  105. return true;
  106. } else {
  107. // We're at the end of the array.
  108. last_returned_size_ = 0; // Don't let caller back up.
  109. return false;
  110. }
  111. }
  112. void ArrayOutputStream::BackUp(int count) {
  113. GOOGLE_CHECK_GT(last_returned_size_, 0)
  114. << "BackUp() can only be called after a successful Next().";
  115. GOOGLE_CHECK_LE(count, last_returned_size_);
  116. GOOGLE_CHECK_GE(count, 0);
  117. position_ -= count;
  118. last_returned_size_ = 0; // Don't let caller back up further.
  119. }
  120. int64 ArrayOutputStream::ByteCount() const {
  121. return position_;
  122. }
  123. // ===================================================================
  124. StringOutputStream::StringOutputStream(string* target)
  125. : target_(target) {
  126. }
  127. StringOutputStream::~StringOutputStream() {
  128. }
  129. bool StringOutputStream::Next(void** data, int* size) {
  130. int old_size = target_->size();
  131. // Grow the string.
  132. if (old_size < target_->capacity()) {
  133. // Resize the string to match its capacity, since we can get away
  134. // without a memory allocation this way.
  135. STLStringResizeUninitialized(target_, target_->capacity());
  136. } else {
  137. // Size has reached capacity, so double the size. Also make sure
  138. // that the new size is at least kMinimumSize.
  139. STLStringResizeUninitialized(
  140. target_,
  141. max(old_size * 2,
  142. kMinimumSize + 0)); // "+ 0" works around GCC4 weirdness.
  143. }
  144. *data = string_as_array(target_) + old_size;
  145. *size = target_->size() - old_size;
  146. return true;
  147. }
  148. void StringOutputStream::BackUp(int count) {
  149. GOOGLE_CHECK_GE(count, 0);
  150. GOOGLE_CHECK_LE(count, target_->size());
  151. target_->resize(target_->size() - count);
  152. }
  153. int64 StringOutputStream::ByteCount() const {
  154. return target_->size();
  155. }
  156. // ===================================================================
  157. CopyingInputStream::~CopyingInputStream() {}
  158. int CopyingInputStream::Skip(int count) {
  159. char junk[4096];
  160. int skipped = 0;
  161. while (skipped < count) {
  162. int bytes = Read(junk, min(count - skipped,
  163. implicit_cast<int>(sizeof(junk))));
  164. if (bytes <= 0) {
  165. // EOF or read error.
  166. return skipped;
  167. }
  168. skipped += bytes;
  169. }
  170. return skipped;
  171. }
  172. CopyingInputStreamAdaptor::CopyingInputStreamAdaptor(
  173. CopyingInputStream* copying_stream, int block_size)
  174. : copying_stream_(copying_stream),
  175. owns_copying_stream_(false),
  176. failed_(false),
  177. position_(0),
  178. buffer_size_(block_size > 0 ? block_size : kDefaultBlockSize),
  179. buffer_used_(0),
  180. backup_bytes_(0) {
  181. }
  182. CopyingInputStreamAdaptor::~CopyingInputStreamAdaptor() {
  183. if (owns_copying_stream_) {
  184. delete copying_stream_;
  185. }
  186. }
  187. bool CopyingInputStreamAdaptor::Next(const void** data, int* size) {
  188. if (failed_) {
  189. // Already failed on a previous read.
  190. return false;
  191. }
  192. AllocateBufferIfNeeded();
  193. if (backup_bytes_ > 0) {
  194. // We have data left over from a previous BackUp(), so just return that.
  195. *data = buffer_.get() + buffer_used_ - backup_bytes_;
  196. *size = backup_bytes_;
  197. backup_bytes_ = 0;
  198. return true;
  199. }
  200. // Read new data into the buffer.
  201. buffer_used_ = copying_stream_->Read(buffer_.get(), buffer_size_);
  202. if (buffer_used_ <= 0) {
  203. // EOF or read error. We don't need the buffer anymore.
  204. if (buffer_used_ < 0) {
  205. // Read error (not EOF).
  206. failed_ = true;
  207. }
  208. FreeBuffer();
  209. return false;
  210. }
  211. position_ += buffer_used_;
  212. *size = buffer_used_;
  213. *data = buffer_.get();
  214. return true;
  215. }
  216. void CopyingInputStreamAdaptor::BackUp(int count) {
  217. GOOGLE_CHECK(backup_bytes_ == 0 && buffer_.get() != NULL)
  218. << " BackUp() can only be called after Next().";
  219. GOOGLE_CHECK_LE(count, buffer_used_)
  220. << " Can't back up over more bytes than were returned by the last call"
  221. " to Next().";
  222. GOOGLE_CHECK_GE(count, 0)
  223. << " Parameter to BackUp() can't be negative.";
  224. backup_bytes_ = count;
  225. }
  226. bool CopyingInputStreamAdaptor::Skip(int count) {
  227. GOOGLE_CHECK_GE(count, 0);
  228. if (failed_) {
  229. // Already failed on a previous read.
  230. return false;
  231. }
  232. // First skip any bytes left over from a previous BackUp().
  233. if (backup_bytes_ >= count) {
  234. // We have more data left over than we're trying to skip. Just chop it.
  235. backup_bytes_ -= count;
  236. return true;
  237. }
  238. count -= backup_bytes_;
  239. backup_bytes_ = 0;
  240. int skipped = copying_stream_->Skip(count);
  241. position_ += skipped;
  242. return skipped == count;
  243. }
  244. int64 CopyingInputStreamAdaptor::ByteCount() const {
  245. return position_ - backup_bytes_;
  246. }
  247. void CopyingInputStreamAdaptor::AllocateBufferIfNeeded() {
  248. if (buffer_.get() == NULL) {
  249. buffer_.reset(new uint8[buffer_size_]);
  250. }
  251. }
  252. void CopyingInputStreamAdaptor::FreeBuffer() {
  253. GOOGLE_CHECK_EQ(backup_bytes_, 0);
  254. buffer_used_ = 0;
  255. buffer_.reset();
  256. }
  257. // ===================================================================
  258. CopyingOutputStream::~CopyingOutputStream() {}
  259. CopyingOutputStreamAdaptor::CopyingOutputStreamAdaptor(
  260. CopyingOutputStream* copying_stream, int block_size)
  261. : copying_stream_(copying_stream),
  262. owns_copying_stream_(false),
  263. failed_(false),
  264. position_(0),
  265. buffer_size_(block_size > 0 ? block_size : kDefaultBlockSize),
  266. buffer_used_(0) {
  267. }
  268. CopyingOutputStreamAdaptor::~CopyingOutputStreamAdaptor() {
  269. WriteBuffer();
  270. if (owns_copying_stream_) {
  271. delete copying_stream_;
  272. }
  273. }
  274. bool CopyingOutputStreamAdaptor::Flush() {
  275. return WriteBuffer();
  276. }
  277. bool CopyingOutputStreamAdaptor::Next(void** data, int* size) {
  278. if (buffer_used_ == buffer_size_) {
  279. if (!WriteBuffer()) return false;
  280. }
  281. AllocateBufferIfNeeded();
  282. *data = buffer_.get() + buffer_used_;
  283. *size = buffer_size_ - buffer_used_;
  284. buffer_used_ = buffer_size_;
  285. return true;
  286. }
  287. void CopyingOutputStreamAdaptor::BackUp(int count) {
  288. GOOGLE_CHECK_GE(count, 0);
  289. GOOGLE_CHECK_EQ(buffer_used_, buffer_size_)
  290. << " BackUp() can only be called after Next().";
  291. GOOGLE_CHECK_LE(count, buffer_used_)
  292. << " Can't back up over more bytes than were returned by the last call"
  293. " to Next().";
  294. buffer_used_ -= count;
  295. }
  296. int64 CopyingOutputStreamAdaptor::ByteCount() const {
  297. return position_ + buffer_used_;
  298. }
  299. bool CopyingOutputStreamAdaptor::WriteBuffer() {
  300. if (failed_) {
  301. // Already failed on a previous write.
  302. return false;
  303. }
  304. if (buffer_used_ == 0) return true;
  305. if (copying_stream_->Write(buffer_.get(), buffer_used_)) {
  306. position_ += buffer_used_;
  307. buffer_used_ = 0;
  308. return true;
  309. } else {
  310. failed_ = true;
  311. FreeBuffer();
  312. return false;
  313. }
  314. }
  315. void CopyingOutputStreamAdaptor::AllocateBufferIfNeeded() {
  316. if (buffer_ == NULL) {
  317. buffer_.reset(new uint8[buffer_size_]);
  318. }
  319. }
  320. void CopyingOutputStreamAdaptor::FreeBuffer() {
  321. buffer_used_ = 0;
  322. buffer_.reset();
  323. }
  324. // ===================================================================
  325. } // namespace io
  326. } // namespace protobuf
  327. } // namespace google