1 /**************************************************************************
3 * Copyright 2013-2014 RAD Game Tools and Valve Software
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 **************************************************************************/
26 // File: vogl_trace_file_reader.h
27 #ifndef VOGL_TRACE_FILE_READER_H
28 #define VOGL_TRACE_FILE_READER_H
30 #include "vogl_common.h"
31 #include "vogl_trace_stream_types.h"
32 #include "vogl_trace_packet.h"
33 #include "vogl_cfile_stream.h"
34 #include "vogl_dynamic_stream.h"
35 #include "vogl_json.h"
37 //----------------------------------------------------------------------------------------------------------------------
38 // class vogl_trace_packet_array
39 //----------------------------------------------------------------------------------------------------------------------
40 typedef vogl::vector<uint8_vec> vogl_packet_buf_vec;
42 class vogl_trace_packet_array
45 vogl_trace_packet_array()
54 void resize(uint new_size)
56 m_packets.resize(new_size);
58 void reserve(uint new_capacity)
60 m_packets.reserve(new_capacity);
65 return m_packets.size();
69 return m_packets.is_empty();
72 void push_back(const uint8_vec &packet)
74 m_packets.push_back(packet);
77 void insert(uint index, const uint8_vec &packet)
79 m_packets.insert(index, packet);
82 void erase(uint index)
84 m_packets.erase(index);
87 void swap(vogl_trace_packet_array &other)
89 m_packets.swap(other.m_packets);
92 const vogl_packet_buf_vec &get_vec() const
96 vogl_packet_buf_vec &get_vec()
101 const uint8_vec &get_packet_buf(uint index) const
103 return m_packets[index];
105 uint8_vec &get_packet_buf(uint index)
107 return m_packets[index];
110 template <typename T>
111 inline const T &get_packet(uint index) const
113 VOGL_ASSERT(m_packets[index].size() >= sizeof(T));
114 return *reinterpret_cast<const T *>(m_packets[index].get_ptr());
117 inline const vogl_trace_stream_packet_base &get_base_packet(uint index) const
119 return get_packet<vogl_trace_stream_packet_base>(index);
122 inline vogl_trace_stream_packet_types_t get_packet_type(uint index) const
124 return static_cast<vogl_trace_stream_packet_types_t>(get_base_packet(index).m_type);
126 inline uint get_packet_size(uint index) const
128 return m_packets[index].size();
131 inline bool is_eof_packet(uint index) const
135 return (get_packet_type(index) == cTSPTEOF);
138 inline bool is_swap_buffers_packet(uint index) const
142 if (get_packet_type(index) == cTSPTGLEntrypoint)
144 const vogl_trace_gl_entrypoint_packet &gl_packet = get_packet<vogl_trace_gl_entrypoint_packet>(index);
145 return vogl_is_swap_buffers_entrypoint(static_cast<gl_entrypoint_id_t>(gl_packet.m_entrypoint_id));
151 vogl_packet_buf_vec m_packets;
154 //----------------------------------------------------------------------------------------------------------------------
155 // enum trace_file_reader_type_t
156 //----------------------------------------------------------------------------------------------------------------------
157 enum vogl_trace_file_reader_type_t
159 cINVALID_TRACE_FILE_READER,
160 cBINARY_TRACE_FILE_READER,
161 cJSON_TRACE_FILE_READER,
162 cTOTAL_TRACE_FILE_READERS
165 //----------------------------------------------------------------------------------------------------------------------
166 // class trace_file_reader
167 //----------------------------------------------------------------------------------------------------------------------
168 class vogl_trace_file_reader
170 VOGL_NO_COPY_OR_ASSIGNMENT_OP(vogl_trace_file_reader);
173 vogl_trace_file_reader()
177 utils::zero_object(m_sof_packet);
179 m_multi_blob_manager.init(cBMFReadable | cBMFOpenExisting);
181 m_multi_blob_manager.add_blob_manager(&m_loose_file_blob_manager);
182 m_multi_blob_manager.add_blob_manager(&m_archive_blob_manager);
185 virtual ~vogl_trace_file_reader()
189 virtual bool open(const char *pFilename, const char *pLoose_file_path) = 0;
191 virtual bool is_opened() = 0;
192 virtual const char *get_filename() = 0;
198 utils::zero_object(m_sof_packet);
199 m_packet_buf.clear();
200 m_loose_file_blob_manager.deinit();
201 m_archive_blob_manager.deinit();
204 virtual vogl_trace_file_reader_type_t get_type() const = 0;
206 virtual const vogl_trace_stream_start_of_file_packet &get_sof_packet() const
208 VOGL_FUNC_TRACER return m_sof_packet;
211 virtual bool is_at_eof() = 0;
213 virtual bool can_quickly_seek_forward() const = 0;
215 virtual uint get_cur_frame() const = 0;
217 // Allows random seeking, but it can be very slow to seek forward in binary traces.
218 virtual bool seek_to_frame(uint frame_index) = 0;
220 virtual int64_t get_max_frame_index() = 0;
222 virtual bool push_location() = 0;
223 virtual bool pop_location() = 0;
225 enum trace_file_reader_status_t
232 // Notes: Be careful handling cEOF/eof packets.
233 // The last packet MAY be an EOF packet, or not if the trace terminated before it could be flushed.
234 // So you need to check for both the cEOF return status and if the packet is EOF.
235 // Be sure to test with both JSON and binary readers because with JSON files you'll always just get a cEOF return
236 // status at EOF (and never see an actual EOF packet), while with binary you can get both types of behavior.
237 // Also, for binary traces: just because you get an EOF packet doesn't necessarily mean that cEOF will be returned next (the file could somehow be corrupted).
238 virtual trace_file_reader_status_t read_next_packet() = 0;
240 virtual trace_file_reader_status_t read_frame_packets(uint frame_index, uint num_frames, vogl_trace_packet_array &packets, uint &actual_frames_read);
244 const uint8_vec &get_packet_buf() const
249 template <typename T>
250 inline const T &get_packet() const
252 VOGL_ASSERT(m_packet_buf.size() >= sizeof(T));
253 return *reinterpret_cast<const T *>(m_packet_buf.get_ptr());
256 inline const vogl_trace_stream_packet_base &get_base_packet() const
258 return get_packet<vogl_trace_stream_packet_base>();
261 inline vogl_trace_stream_packet_types_t get_packet_type() const
263 return static_cast<vogl_trace_stream_packet_types_t>(get_base_packet().m_type);
265 inline uint get_packet_size() const
267 return m_packet_buf.size();
270 inline bool is_eof_packet() const
274 return (get_packet_type() == cTSPTEOF);
277 inline bool is_swap_buffers_packet() const
281 if (get_packet_type() == cTSPTGLEntrypoint)
283 const vogl_trace_gl_entrypoint_packet &gl_packet = get_packet<vogl_trace_gl_entrypoint_packet>();
284 return vogl_is_swap_buffers_entrypoint(static_cast<gl_entrypoint_id_t>(gl_packet.m_entrypoint_id));
289 const vogl_multi_blob_manager &get_multi_blob_manager() const
291 return m_multi_blob_manager;
293 vogl_multi_blob_manager &get_multi_blob_manager()
295 return m_multi_blob_manager;
298 const vogl_loose_file_blob_manager &get_loose_file_blob_manager() const
300 return m_loose_file_blob_manager;
302 vogl_loose_file_blob_manager &get_loose_file_blob_manager()
304 return m_loose_file_blob_manager;
307 const vogl_archive_blob_manager &get_archive_blob_manager() const
309 return m_archive_blob_manager;
311 vogl_archive_blob_manager &get_archive_blob_manager()
313 return m_archive_blob_manager;
317 vogl_trace_stream_start_of_file_packet m_sof_packet;
319 uint8_vec m_packet_buf;
321 vogl_loose_file_blob_manager m_loose_file_blob_manager;
322 vogl_archive_blob_manager m_archive_blob_manager;
323 vogl_multi_blob_manager m_multi_blob_manager;
325 void create_eof_packet();
326 bool init_loose_file_blob_manager(const char *pTrace_filename, const char *pLoose_file_path);
329 //----------------------------------------------------------------------------------------------------------------------
330 // class vogl_scoped_location_saver
331 //----------------------------------------------------------------------------------------------------------------------
332 class vogl_scoped_location_saver
334 vogl_trace_file_reader &m_reader;
337 vogl_scoped_location_saver(vogl_trace_file_reader &reader)
340 m_reader.push_location();
342 ~vogl_scoped_location_saver()
344 m_reader.pop_location();
348 //----------------------------------------------------------------------------------------------------------------------
349 // class binary_trace_file_reader
350 //----------------------------------------------------------------------------------------------------------------------
351 class vogl_binary_trace_file_reader : public vogl_trace_file_reader
353 VOGL_NO_COPY_OR_ASSIGNMENT_OP(vogl_binary_trace_file_reader);
356 vogl_binary_trace_file_reader();
358 const data_stream &get_stream() const
360 return m_trace_stream;
362 data_stream &get_stream()
364 return m_trace_stream;
367 virtual ~vogl_binary_trace_file_reader();
369 virtual bool open(const char *pFilename, const char *pLoose_file_path);
371 virtual bool is_opened();
372 virtual const char *get_filename();
374 virtual void close();
376 virtual vogl_trace_file_reader_type_t get_type() const
378 return cBINARY_TRACE_FILE_READER;
381 virtual bool is_at_eof();
383 virtual bool can_quickly_seek_forward() const
385 return m_found_frame_file_offsets_packet;
388 virtual uint get_cur_frame() const
390 return m_cur_frame_index;
393 virtual bool seek_to_frame(uint frame_index);
395 virtual int64_t get_max_frame_index();
397 virtual bool push_location();
398 virtual bool pop_location();
400 uint64_t get_trace_file_size() const
402 return m_trace_file_size;
404 inline uint64_t get_cur_file_ofs()
406 return m_trace_stream.get_ofs();
408 inline bool seek(uint64_t new_ofs)
410 return m_trace_stream.seek(new_ofs, false);
413 virtual trace_file_reader_status_t read_next_packet();
416 cfile_stream m_trace_stream;
417 uint64_t m_trace_file_size;
419 uint m_cur_frame_index;
420 int64_t m_max_frame_index;
421 vogl::vector<uint64_t> m_frame_file_offsets;
423 struct saved_location
425 uint m_cur_frame_index;
429 vogl::vector<saved_location> m_saved_location_stack;
431 bool read_frame_file_offsets();
433 bool m_found_frame_file_offsets_packet;
436 //----------------------------------------------------------------------------------------------------------------------
437 // class json_trace_file_reader
438 //----------------------------------------------------------------------------------------------------------------------
439 class vogl_json_trace_file_reader : public vogl_trace_file_reader
441 VOGL_NO_COPY_OR_ASSIGNMENT_OP(vogl_json_trace_file_reader);
444 vogl_json_trace_file_reader();
446 virtual ~vogl_json_trace_file_reader();
448 virtual bool open(const char *pFilename, const char *pLoose_file_path);
450 virtual bool is_opened();
451 virtual const char *get_filename();
453 virtual void close();
455 virtual vogl_trace_file_reader_type_t get_type() const
457 return cJSON_TRACE_FILE_READER;
460 virtual bool is_at_eof();
462 virtual bool can_quickly_seek_forward() const
467 virtual uint get_cur_frame() const
469 return m_cur_frame_index;
472 virtual int64_t get_max_frame_index()
474 return m_max_frame_index;
477 virtual bool seek_to_frame(uint frame_index);
479 virtual trace_file_reader_status_t read_next_packet();
481 virtual bool push_location();
482 virtual bool pop_location();
485 dynamic_string m_filename;
486 dynamic_string m_base_filename;
487 bool m_filename_exists;
488 bool m_filename_is_in_multiframe_form;
490 dynamic_string m_drive;
491 dynamic_string m_dir;
492 dynamic_string m_fname;
493 dynamic_string m_ext;
495 dynamic_string m_cur_frame_filename;
497 cfile_stream m_trace_stream;
499 uint m_cur_frame_index;
500 uint m_max_frame_index;
502 json_document m_cur_doc;
503 const json_node *m_pPackets_array;
504 uint m_cur_packet_node_index;
505 uint m_packet_node_size;
506 int m_doc_eof_key_value;
510 vogl_ctypes m_trace_ctypes;
511 vogl_trace_packet m_trace_packet;
512 dynamic_stream m_dyn_stream;
514 struct saved_location
516 dynamic_string m_cur_frame_filename;
517 uint m_cur_frame_index;
518 uint m_cur_packet_node_index;
522 vogl::vector<saved_location> m_saved_location_stack;
524 dynamic_string compose_frame_filename();
525 bool read_document(const dynamic_string &filename);
526 bool open_first_document();
529 bool vogl_is_multiframe_json_trace_filename(const char *pFilename);
530 vogl_trace_file_reader_type_t vogl_determine_trace_file_type(const dynamic_string &orig_filename, dynamic_string &filename_to_use);
531 vogl_trace_file_reader *vogl_create_trace_file_reader(vogl_trace_file_reader_type_t trace_type);
532 vogl_trace_file_reader *vogl_open_trace_file(dynamic_string &orig_filename, dynamic_string &actual_filename, const char *pLoose_file_path);
534 #endif // VOGL_TRACE_FILE_READER_H