1 /* 2 mkvmerge -- utility for splicing together matroska files 3 from component media subtypes 4 5 Distributed under the GPL v2 6 see the file COPYING for details 7 or visit https://www.gnu.org/licenses/old-licenses/gpl-2.0.html 8 9 class definition for a memory slice cursor 10 11 Written by Moritz Bunkus <moritz@bunkus.org>. 12 */ 13 14 #pragma once 15 16 #include "common/common_pch.h" 17 18 namespace mtx::mem { 19 20 class slice_cursor_c { 21 protected: 22 std::size_t m_pos{}, m_pos_in_slice{}, m_size{}, m_current_slice_num{}, m_current_slice_size{}; 23 unsigned char *m_current_slice_buffer{}; 24 std::vector<memory_cptr> m_slices; 25 26 public: slice_cursor_c()27 slice_cursor_c() 28 { 29 } 30 ~slice_cursor_c()31 ~slice_cursor_c() { 32 } 33 34 slice_cursor_c(slice_cursor_c const &) = delete; 35 init_slice_variables()36 void init_slice_variables() { 37 if (m_current_slice_num < m_slices.size()) { 38 auto &slice = *m_slices[m_current_slice_num]; 39 m_current_slice_buffer = slice.get_buffer(); 40 m_current_slice_size = slice.get_size(); 41 } else { 42 m_current_slice_buffer = nullptr; 43 m_current_slice_size = 0; 44 } 45 } 46 add_slice(memory_cptr const & slice)47 void add_slice(memory_cptr const &slice) { 48 if (slice->get_size() == 0) 49 return; 50 51 m_slices.emplace_back(slice); 52 m_size += slice->get_size(); 53 54 if (!m_current_slice_buffer) 55 init_slice_variables(); 56 } 57 add_slice(unsigned char * buffer,std::size_t size)58 void add_slice(unsigned char *buffer, std::size_t size) { 59 if (0 == size) 60 return; 61 62 add_slice(memory_c::borrow(buffer, size)); 63 } 64 get_char()65 inline unsigned char get_char() { 66 assert(m_current_slice_buffer && (m_pos < m_size)); 67 68 auto c = m_current_slice_buffer[m_pos_in_slice]; 69 70 ++m_pos_in_slice; 71 ++m_pos; 72 73 if (m_pos_in_slice < m_current_slice_size) 74 return c; 75 76 ++m_current_slice_num; 77 m_pos_in_slice = 0; 78 79 init_slice_variables(); 80 81 return c; 82 } 83 char_available()84 inline bool char_available() { 85 return m_pos < m_size; 86 } 87 get_remaining_size()88 inline std::size_t get_remaining_size() { 89 return m_size - m_pos; 90 } 91 get_size()92 inline std::size_t get_size() { 93 return m_size; 94 } 95 get_position()96 inline std::size_t get_position() { 97 return m_pos; 98 } 99 100 void reset(bool clear_slices = false) { 101 if (clear_slices) { 102 m_slices.clear(); 103 m_size = 0; 104 } 105 106 m_pos = 0; 107 m_pos_in_slice = 0; 108 m_current_slice_num = 0; 109 110 init_slice_variables(); 111 } 112 copy(unsigned char * dest,std::size_t start,std::size_t size)113 void copy(unsigned char *dest, std::size_t start, std::size_t size) { 114 assert((start + size) <= m_size); 115 116 auto curr = m_slices.begin(); 117 auto offset = 0u; 118 119 while (start > ((*curr)->get_size() + offset)) { 120 offset += (*curr)->get_size(); 121 ++curr; 122 assert(m_slices.end() != curr); 123 } 124 offset = start - offset; 125 126 while (0 < size) { 127 auto num_bytes = (*curr)->get_size() - offset; 128 if (num_bytes > size) 129 num_bytes = size; 130 131 std::memcpy(dest, (*curr)->get_buffer() + offset, num_bytes); 132 133 size -= num_bytes; 134 dest += num_bytes; 135 offset = 0; 136 ++curr; 137 } 138 } 139 }; 140 141 } 142