1 // Copyright 2020 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://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, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 //==============================================================================
15 //
16 
17 #pragma once
18 
19 #include <stdio.h>
20 
21 #include <fstream>
22 
23 #include "pw_trace_tokenized/trace_callback.h"
24 
25 namespace pw {
26 namespace trace {
27 
28 class TraceToFile {
29  public:
TraceToFile(Callbacks & callbacks,const char * file_name)30   TraceToFile(Callbacks& callbacks, const char* file_name)
31       : callbacks_(callbacks) {
32     callbacks_
33         .RegisterSink(TraceSinkStartBlock,
34                       TraceSinkAddBytes,
35                       TraceSinkEndBlock,
36                       &out_,
37                       &sink_handle_)
38         .IgnoreError();  // TODO: b/242598609 - Handle Status properly
39     out_.open(file_name, std::ios::out | std::ios::binary);
40   }
41 
~TraceToFile()42   ~TraceToFile() {
43     callbacks_.UnregisterSink(sink_handle_)
44         .IgnoreError();  // TODO: b/242598609 - Handle Status properly
45     out_.close();
46   }
47 
TraceSinkStartBlock(void * user_data,size_t size)48   static void TraceSinkStartBlock(void* user_data, size_t size) {
49     std::ofstream* out = reinterpret_cast<std::ofstream*>(user_data);
50     uint8_t b = static_cast<uint8_t>(size);
51     out->write(reinterpret_cast<const char*>(&b), sizeof(b));
52   }
53 
TraceSinkAddBytes(void * user_data,const void * bytes,size_t size)54   static void TraceSinkAddBytes(void* user_data,
55                                 const void* bytes,
56                                 size_t size) {
57     std::ofstream* out = reinterpret_cast<std::ofstream*>(user_data);
58     out->write(reinterpret_cast<const char*>(bytes), size);
59   }
60 
TraceSinkEndBlock(void * user_data)61   static void TraceSinkEndBlock(void* user_data) {
62     std::ofstream* out = reinterpret_cast<std::ofstream*>(user_data);
63     out->flush();
64   }
65 
66  private:
67   Callbacks& callbacks_;
68   std::ofstream out_;
69   Callbacks::SinkHandle sink_handle_;
70 };
71 
72 }  // namespace trace
73 }  // namespace pw
74