1 : // Copyright 2012 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 : //
15 : // Internal implementation details for msf_file_stream.h. Not meant to be
16 : // included directly.
17 :
18 : #ifndef SYZYGY_MSF_MSF_FILE_STREAM_IMPL_H_
19 : #define SYZYGY_MSF_MSF_FILE_STREAM_IMPL_H_
20 :
21 : #include <algorithm>
22 : #include <cstdio>
23 :
24 : #include "base/logging.h"
25 : #include "syzygy/msf/msf_decl.h"
26 :
27 : namespace msf {
28 : namespace detail {
29 :
30 : template <MsfFileType T>
31 : MsfFileStreamImpl<T>::MsfFileStreamImpl(RefCountedFILE* file,
32 : size_t length,
33 : const uint32_t* pages,
34 : size_t page_size)
35 E : : MsfStreamImpl(length), file_(file), page_size_(page_size) {
36 E : size_t num_pages = (length + page_size - 1) / page_size;
37 E : pages_.assign(pages, pages + num_pages);
38 E : }
39 :
40 : template <MsfFileType T>
41 E : MsfFileStreamImpl<T>::~MsfFileStreamImpl() {
42 E : }
43 :
44 : template <MsfFileType T>
45 E : bool MsfFileStreamImpl<T>::ReadBytesAt(size_t pos, size_t count, void* dest) {
46 E : DCHECK(dest != NULL);
47 :
48 : // Don't read beyond the end of the known stream length.
49 E : if (count > length() - pos)
50 E : return false;
51 :
52 : // Read the stream.
53 E : while (count > 0) {
54 E : size_t page_index = pos / page_size_;
55 E : size_t offset = pos % page_size_;
56 E : size_t chunk_size = std::min(count, page_size_ - (pos % page_size_));
57 E : if (!ReadFromPage(dest, pages_[page_index], offset, chunk_size))
58 i : return false;
59 :
60 E : count -= chunk_size;
61 E : pos += chunk_size;
62 E : dest = reinterpret_cast<uint8_t*>(dest) + chunk_size;
63 E : }
64 :
65 E : return true;
66 E : }
67 :
68 : template <MsfFileType T>
69 : bool MsfFileStreamImpl<T>::ReadFromPage(void* dest,
70 : uint32_t page_num,
71 : size_t offset,
72 E : size_t count) {
73 E : DCHECK(dest != NULL);
74 E : DCHECK(offset + count <= page_size_);
75 :
76 E : size_t page_offset = page_size_ * page_num;
77 : if (fseek(file_->file(),
78 : static_cast<long>(page_offset + offset),
79 E : SEEK_SET) != 0) {
80 i : LOG(ERROR) << "Page seek failed";
81 i : return false;
82 : }
83 :
84 E : if (fread(dest, 1, count, file_->file()) != static_cast<size_t>(count)) {
85 i : LOG(ERROR) << "Page read failed";
86 i : return false;
87 : }
88 :
89 E : return true;
90 E : }
91 :
92 : } // namespace detail
93 : } // namespace msf
94 :
95 : #endif // SYZYGY_MSF_MSF_FILE_STREAM_IMPL_H_
|