PageRenderTime 30ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/mordor/streams/stream.cpp

http://github.com/mozy/mordor
C++ | 168 lines | 142 code | 21 blank | 5 comment | 20 complexity | 0615eda27a1985271f8f151c29132bf0 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. // Copyright (c) 2009 - Mozy, Inc.
  2. #include "stream.h"
  3. #include <boost/scoped_array.hpp>
  4. #include <string.h>
  5. #include "buffer.h"
  6. #include "mordor/assert.h"
  7. namespace Mordor {
  8. size_t
  9. Stream::read(void *buffer, size_t length)
  10. {
  11. MORDOR_ASSERT(supportsRead());
  12. Buffer internalBuffer;
  13. internalBuffer.adopt(buffer, length);
  14. size_t result = read(internalBuffer, length);
  15. MORDOR_ASSERT(result <= length);
  16. MORDOR_ASSERT(internalBuffer.readAvailable() == result);
  17. if (result == 0u)
  18. return 0;
  19. std::vector<iovec> iovs = internalBuffer.readBuffers(result);
  20. MORDOR_ASSERT(!iovs.empty());
  21. // It wrote directly into our buffer
  22. if (iovs.front().iov_base == buffer && iovs.front().iov_len == result)
  23. return result;
  24. bool overlapping = false;
  25. for (std::vector<iovec>::iterator it = iovs.begin();
  26. it != iovs.end();
  27. ++it) {
  28. if (it->iov_base >= buffer || it->iov_base <=
  29. (unsigned char *)buffer + length) {
  30. overlapping = true;
  31. break;
  32. }
  33. }
  34. // It didn't touch our buffer at all; it's safe to just copyOut
  35. if (!overlapping) {
  36. internalBuffer.copyOut(buffer, result);
  37. return result;
  38. }
  39. // We have to allocate *another* buffer so we don't destroy any data while
  40. // copying to our buffer
  41. boost::scoped_array<unsigned char> extraBuffer(new unsigned char[result]);
  42. internalBuffer.copyOut(extraBuffer.get(), result);
  43. memcpy(buffer, extraBuffer.get(), result);
  44. return result;
  45. }
  46. size_t
  47. Stream::read(Buffer &buffer, size_t length)
  48. {
  49. return read(buffer, length, false);
  50. }
  51. size_t
  52. Stream::read(Buffer &buffer, size_t length, bool coalesce)
  53. {
  54. MORDOR_ASSERT(supportsRead());
  55. iovec iov = buffer.writeBuffer(length, coalesce);
  56. size_t result = read(iov.iov_base, iov.iov_len);
  57. buffer.produce(result);
  58. return result;
  59. }
  60. size_t
  61. Stream::write(const char *string)
  62. {
  63. return write(string, strlen(string));
  64. }
  65. size_t
  66. Stream::write(const void *buffer, size_t length)
  67. {
  68. MORDOR_ASSERT(supportsWrite());
  69. Buffer internalBuffer;
  70. internalBuffer.copyIn(buffer, length);
  71. return write(internalBuffer, length);
  72. }
  73. size_t
  74. Stream::write(const Buffer &buffer, size_t length)
  75. {
  76. return write(buffer, length, false);
  77. }
  78. size_t
  79. Stream::write(const Buffer &buffer, size_t length, bool coalesce)
  80. {
  81. MORDOR_ASSERT(supportsWrite());
  82. const iovec iov = buffer.readBuffer(length, coalesce);
  83. return write(iov.iov_base, iov.iov_len);
  84. }
  85. long long
  86. Stream::seek(long long offset, Anchor anchor)
  87. {
  88. MORDOR_NOTREACHED();
  89. }
  90. long long
  91. Stream::size()
  92. {
  93. MORDOR_NOTREACHED();
  94. }
  95. void
  96. Stream::truncate(long long size)
  97. {
  98. MORDOR_NOTREACHED();
  99. }
  100. ptrdiff_t
  101. Stream::find(char delimiter, size_t sanitySize, bool throwIfNotFound)
  102. {
  103. MORDOR_NOTREACHED();
  104. }
  105. ptrdiff_t
  106. Stream::find(const std::string &delimiter, size_t sanitySize,
  107. bool throwIfNotFound)
  108. {
  109. MORDOR_NOTREACHED();
  110. }
  111. std::string
  112. Stream::getDelimited(char delim, bool eofIsDelimiter, bool includeDelimiter)
  113. {
  114. ptrdiff_t offset = find(delim, ~0, !eofIsDelimiter);
  115. eofIsDelimiter = offset < 0;
  116. if (offset < 0)
  117. offset = -offset - 1;
  118. std::string result;
  119. result.resize(offset + (eofIsDelimiter ? 0 : 1));
  120. MORDOR_VERIFY(read((char *)result.c_str(), result.size())
  121. == result.size());
  122. if (!eofIsDelimiter && !includeDelimiter)
  123. result.resize(result.size() - 1);
  124. return result;
  125. }
  126. std::string
  127. Stream::getDelimited(const std::string &delim, bool eofIsDelimiter,
  128. bool includeDelimiter)
  129. {
  130. ptrdiff_t offset = find(delim, ~0, !eofIsDelimiter);
  131. eofIsDelimiter = offset < 0;
  132. if (offset < 0)
  133. offset = -offset - 1;
  134. std::string result;
  135. result.resize(offset + (eofIsDelimiter ? 0 : delim.size()));
  136. MORDOR_VERIFY(read((char *)result.c_str(), result.size())
  137. == result.size());
  138. if (!eofIsDelimiter && !includeDelimiter)
  139. result.resize(result.size() - delim.size());
  140. return result;
  141. }
  142. void
  143. Stream::unread(const Buffer &buffer, size_t length)
  144. {
  145. MORDOR_NOTREACHED();
  146. }
  147. }