PageRenderTime 51ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/mordor/streams/cat.cpp

http://github.com/mozy/mordor
C++ | 103 lines | 93 code | 9 blank | 1 comment | 28 complexity | 746a23cbb4a72493333e60f63a9ff253 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. // Copyright (c) 2009 - Mozy, Inc.
  2. #include "cat.h"
  3. #include "mordor/assert.h"
  4. namespace Mordor {
  5. CatStream::CatStream(const std::vector<Stream::ptr> &streams)
  6. : m_streams(streams),
  7. m_seekable(true),
  8. m_size(0ll),
  9. m_pos(0ll)
  10. {
  11. m_it = m_streams.begin();
  12. for (std::vector<Stream::ptr>::iterator it = m_streams.begin();
  13. it != m_streams.end();
  14. ++it) {
  15. if (!(*it)->supportsSeek()) {
  16. m_seekable = false;
  17. if (m_size == -1ll)
  18. break;
  19. }
  20. if (!(*it)->supportsSize()) {
  21. m_seekable = false;
  22. m_size = -1ll;
  23. break;
  24. } else {
  25. m_size += (*it)->size();
  26. }
  27. }
  28. }
  29. size_t
  30. CatStream::read(Buffer &buffer, size_t length)
  31. {
  32. MORDOR_ASSERT(length != 0);
  33. if (m_it == m_streams.end())
  34. return 0;
  35. while (true) {
  36. size_t result = (*m_it)->read(buffer, length);
  37. m_pos += result;
  38. if (result == 0) {
  39. if (++m_it == m_streams.end())
  40. return 0;
  41. if ((*m_it)->supportsSeek())
  42. (*m_it)->seek(0);
  43. continue;
  44. }
  45. return result;
  46. }
  47. }
  48. long long
  49. CatStream::seek(long long offset, Anchor anchor)
  50. {
  51. if (offset == 0 && anchor == CURRENT)
  52. return m_pos;
  53. MORDOR_ASSERT(m_seekable);
  54. long long newPos = 0;
  55. switch (anchor) {
  56. case BEGIN:
  57. newPos = offset;
  58. break;
  59. case CURRENT:
  60. newPos = m_pos + offset;
  61. break;
  62. case END:
  63. newPos = m_size + offset;
  64. break;
  65. default:
  66. MORDOR_NOTREACHED();
  67. }
  68. if (newPos < 0) {
  69. MORDOR_THROW_EXCEPTION(std::invalid_argument("Can't seek below 0"));
  70. } else if (newPos >= m_size) {
  71. MORDOR_THROW_EXCEPTION(std::invalid_argument("Can't seek above max size"));
  72. }
  73. long long cursor = 0;
  74. for (std::vector<Stream::ptr>::iterator it = m_streams.begin();
  75. it != m_streams.end();
  76. ++it) {
  77. long long size = (*it)->size();
  78. if (newPos < cursor + size) {
  79. m_it = it;
  80. (*m_it)->seek(newPos - cursor);
  81. break;
  82. }
  83. cursor += size;
  84. }
  85. m_pos = newPos;
  86. return m_pos;
  87. }
  88. long long
  89. CatStream::size()
  90. {
  91. MORDOR_ASSERT(m_size != -1ll);
  92. return m_size;
  93. }
  94. }