4 * Redistribution and use in source and binary forms, with or without modification,
5 * are permitted provided that the following conditions are met:
7 * Redistributions of source code must retain the above copyright notice, this
8 * list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright notice, this
11 * list of conditions and the following disclaimer in the documentation and/or
12 * other materials provided with the distribution.
14 * Neither the name of the NXP Semiconductor nor the names of its
15 * contributors may be used to endorse or promote products derived from this
16 * software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
36 #include <condition_variable>
59 int file_overwrite_monitor(std::string filename
, FileBuffer
*p
);
63 //bit 1, data total size known
64 #define FILEBUFFER_FLAG_LOADED_BIT 0x1
65 #define FILEBUFFER_FLAG_KNOWN_SIZE_BIT 0x2
66 #define FILEBUFFER_FLAG_ERROR_BIT 0x4
67 #define FILEBUFFER_FLAG_NEVER_FREE 0x8
68 #define FILEBUFFER_FLAG_PARTIAL_RELOADABLE 0x10
69 #define FILEBUFFER_FLAG_SEG_DONE 0x20
71 #define FILEBUFFER_FLAG_LOADED (FILEBUFFER_FLAG_LOADED_BIT|FILEBUFFER_FLAG_KNOWN_SIZE_BIT) // LOADED must be known size
72 #define FILEBUFFER_FLAG_KNOWN_SIZE FILEBUFFER_FLAG_KNOWN_SIZE_BIT
85 CONVERT_PARTIAL
= 0x8,
87 size_t m_input_offset
= 0;
88 size_t m_input_sz
= 0;
89 std::shared_ptr
<FileBuffer
> m_input
;
91 size_t m_actual_size
= 0;
92 size_t m_output_size
= 0;
93 size_t m_output_offset
= 0;
94 virtual int DataConvert() { return -1; };
95 std::vector
<uint8_t> m_data
;
97 std::atomic_int m_dataflags
{0};
98 uint8_t* m_pData
= NULL
;
103 return m_data
.data();
106 virtual ~FragmentBlock() {}
110 class DataBuffer
: public std::enable_shared_from_this
<DataBuffer
>
112 enum class ALLOCATION_WAYS
120 ALLOCATION_WAYS
get_m_allocate_way() const noexcept
{ return m_allocate_way
; }
121 uint8_t* m_pDatabuffer
= NULL
;
122 size_t m_DataSize
= 0;
123 size_t m_MemSize
= 0;
124 std::shared_ptr
<FileBuffer
> m_ref
;
125 ALLOCATION_WAYS m_allocate_way
= ALLOCATION_WAYS::MALLOC
;
130 m_allocate_way
= ALLOCATION_WAYS::MALLOC
;
132 DataBuffer(void* p
, size_t sz
)
134 m_allocate_way
= ALLOCATION_WAYS::MALLOC
;
136 memcpy(data(), p
, sz
);
138 uint8_t* data() { return m_pDatabuffer
; }
139 size_t size() { return m_DataSize
; }
140 int resize(size_t sz
);
141 int ref_other_buffer(std::shared_ptr
<FileBuffer
> p
, size_t offset
, size_t size
);
142 uint8_t& operator[] (size_t index
)
144 assert(m_pDatabuffer
);
145 assert(index
< m_DataSize
);
147 return *(m_pDatabuffer
+ index
);
149 uint8_t& at(size_t index
)
151 return (*this)[index
];
153 virtual ~DataBuffer()
155 if (m_allocate_way
== ALLOCATION_WAYS::MALLOC
)
160 friend class FileBuffer
;
163 class FileBuffer
: public std::enable_shared_from_this
<FileBuffer
>
166 friend class DataBuffer
;
169 friend class FSHttps
;
173 friend class FSCompressStream
;
177 friend class Zip_file_Info
;
178 enum class ALLOCATION_WAYS
187 std::mutex m_data_mutex
;
189 uint8_t *m_pDatabuffer
;
193 std::shared_ptr
<FileBuffer
> m_ref
;
195 int ref_other_buffer(std::shared_ptr
<FileBuffer
> p
, size_t offset
, size_t size
);
197 std::mutex m_async_mutex
;
199 std::map
<size_t, std::shared_ptr
<FragmentBlock
>, std::greater
<size_t>> m_seg_map
;
200 std::mutex m_seg_map_mutex
;
201 std::queue
<size_t> m_offset_request
;
202 size_t m_last_request_offset
= 0;
203 std::condition_variable m_pool_load_cv
;
204 std::mutex m_pool_load_cv_mutex
;
205 std::shared_ptr
<FragmentBlock
> m_last_db
;
206 size_t m_seg_blk_size
= 0x800000;
207 size_t m_total_buffer_size
= 8 * m_seg_blk_size
;
208 std::atomic_bool m_reset_stream
{ false };
210 //used for continue decompress\loading only
211 std::shared_ptr
<FragmentBlock
> request_new_blk();
212 bool check_offset_in_seg(size_t offset
, std::shared_ptr
<FragmentBlock
> blk
)
214 if (offset
>= blk
->m_output_offset
215 && offset
< blk
->m_output_offset
+ blk
->m_output_size
)
220 std::shared_ptr
<FragmentBlock
> get_map_it(size_t offset
, bool alloc
= false)
223 std::lock_guard
<std::mutex
> lock(m_seg_map_mutex
);
224 auto it
= m_seg_map
.lower_bound(offset
);
225 if ( it
== m_seg_map
.end())
228 auto blk
= it
->second
;
229 if (check_offset_in_seg(offset
, blk
))
233 std::lock_guard
<std::mutex
> lck(blk
->m_mutex
);
234 blk
->m_data
.resize(blk
->m_output_size
);
241 void truncate_old_data_in_pool();
243 std::atomic_int m_dataflags
;
245 std::thread m_async_thread
;
247 std::atomic_size_t m_available_size
;
248 std::condition_variable m_request_cv
;
249 std::mutex m_request_cv_mutex
;
252 OVERLAPPED m_OverLapped
;
253 REQUEST_OPLOCK_INPUT_BUFFER m_Request
;
254 HANDLE m_file_handle
;
256 std::thread m_file_monitor
;
259 uint64_t m_timesample
;
262 FileBuffer(void*p
, size_t sz
);
265 ALLOCATION_WAYS
get_m_allocate_way() const noexcept
{ return m_allocate_way
; }
267 int64_t request_data(void * data
, size_t offset
, size_t sz
);
268 int request_data(std::vector
<uint8_t> &data
, size_t offset
, size_t sz
);
269 std::shared_ptr
<DataBuffer
> request_data(size_t offset
, size_t sz
);
271 bool IsLoaded() const noexcept
273 return m_dataflags
& FILEBUFFER_FLAG_LOADED_BIT
;
276 bool IsRefable() const noexcept
278 return m_dataflags
& FILEBUFFER_FLAG_NEVER_FREE
;
281 bool IsKnownSize() const noexcept
283 return m_dataflags
& FILEBUFFER_FLAG_KNOWN_SIZE_BIT
;
286 bool IsError() const noexcept
288 return m_dataflags
& FILEBUFFER_FLAG_ERROR_BIT
;
291 int reload(std::string filename
, bool async
= false);
298 std::unique_lock
<std::mutex
> lck(m_request_cv_mutex
);
299 while (!(m_dataflags
& FILEBUFFER_FLAG_KNOWN_SIZE_BIT
))
300 m_request_cv
.wait(lck
);
306 uint8_t * data() noexcept
308 return m_pDatabuffer
;
311 uint8_t & operator[] (size_t index
)
313 assert(m_pDatabuffer
);
314 assert(index
< m_DataSize
);
316 return *(m_pDatabuffer
+ index
);
319 uint8_t & at(size_t index
)
321 return (*this)[index
];
323 int resize(size_t sz
);
325 int reserve(size_t sz
);
327 int swap(FileBuffer
& a
);
329 int mapfile(const std::string
&filename
, size_t sz
);
335 int64_t request_data_from_segment(void* data
, size_t offset
, size_t sz
);
336 int m_pool_size
= 10;
337 std::string m_filename
;
339 ALLOCATION_WAYS m_allocate_way
= ALLOCATION_WAYS::MALLOC
;
342 std::shared_ptr
<FileBuffer
> get_file_buffer(std::string filename
, bool async
=false);
343 bool check_file_exist(std::string filename
, bool start_async_load
=true);
345 void set_current_dir(const std::string
&dir
);
347 bool IsMBR(std::shared_ptr
<DataBuffer
> p
);
348 size_t ScanTerm(std::shared_ptr
<DataBuffer
> p
, size_t& pos
, size_t offset
= 512, size_t limited
= 0x800000);
349 void clean_up_filemap();