1 // Copyright 2017 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "courgette/courgette_flow.h"
11 #include "base/check.h"
12 #include "base/files/file_path.h"
13 #include "base/memory/ptr_util.h"
14 #include "base/notreached.h"
15 #include "base/strings/stringprintf.h"
16 #include "courgette/assembly_program.h"
17 #include "courgette/disassembler.h"
18 #include "courgette/encoded_program.h"
19 #include "courgette/program_detector.h"
23 /******** CourgetteFlow::Data ********/
25 CourgetteFlow::Data::Data() = default;
27 CourgetteFlow::Data::~Data() = default;
29 /******** CourgetteFlow ********/
31 CourgetteFlow::CourgetteFlow() = default;
33 CourgetteFlow::~CourgetteFlow() = default;
36 const char* CourgetteFlow::name(Group group) {
51 CourgetteFlow::Data* CourgetteFlow::data(Group group) {
66 bool CourgetteFlow::ok() {
67 return status_ == C_OK;
70 bool CourgetteFlow::failed() {
71 return status_ != C_OK;
74 Status CourgetteFlow::status() {
78 const std::string& CourgetteFlow::message() {
82 void CourgetteFlow::ReadSourceStreamSetFromBuffer(Group group,
83 const BasicBuffer& buffer) {
86 Data* d = data(group);
87 if (!check(d->sources.Init(buffer.data(), buffer.length()),
89 setMessage("Cannot read %s as SourceStreamSet.", name(group));
93 void CourgetteFlow::ReadDisassemblerFromBuffer(Group group,
94 const BasicBuffer& buffer) {
97 Data* d = data(group);
98 d->disassembler = DetectDisassembler(buffer.data(), buffer.length());
99 if (!check(d->disassembler.get() != nullptr, C_INPUT_NOT_RECOGNIZED))
100 setMessage("Cannot detect program for %s.", name(group));
103 void CourgetteFlow::ReadEncodedProgramFromSourceStreamSet(
105 SourceStreamSet* opt_sources /* nullptr */) {
108 Data* d = data(group);
109 SourceStreamSet* sources = opt_sources ? opt_sources : &d->sources;
110 if (!check(ReadEncodedProgram(sources, &d->encoded)))
111 setMessage("Cannot read %s as encoded program.", name(group));
114 void CourgetteFlow::CreateAssemblyProgramFromDisassembler(Group group,
118 Data* d = data(group);
119 d->program = d->disassembler->CreateProgram(annotate);
120 if (!check(d->program.get() != nullptr, C_DISASSEMBLY_FAILED))
121 setMessage("Cannot create AssemblyProgram for %s.", name(group));
124 void CourgetteFlow::CreateEncodedProgramFromDisassemblerAndAssemblyProgram(
128 Data* d = data(group);
129 d->encoded = std::make_unique<EncodedProgram>();
130 if (!check(d->disassembler->DisassembleAndEncode(d->program.get(),
131 d->encoded.get()))) {
132 setMessage("Cannot disassemble to form EncodedProgram for %s.",
137 void CourgetteFlow::WriteSinkStreamFromSinkStreamSet(Group group,
142 if (!check(data(group)->sinks.CopyTo(sink), C_GENERAL_ERROR))
143 setMessage("Cannnot combine serialized streams for %s.", name(group));
146 void CourgetteFlow::WriteSinkStreamSetFromEncodedProgram(
148 SinkStreamSet* opt_sinks /* nullptr */) {
151 Data* d = data(group);
152 SinkStreamSet* sinks = opt_sinks ? opt_sinks : &d->sinks;
153 if (!check(WriteEncodedProgram(d->encoded.get(), sinks)))
154 setMessage("Cannot serialize encoded %s.", name(group));
157 void CourgetteFlow::WriteExecutableFromEncodedProgram(Group group,
162 if (!check(Assemble(data(group)->encoded.get(), sink)))
163 setMessage("Cannot assemble %s.", name(group));
166 void CourgetteFlow::AdjustNewAssemblyProgramToMatchOld() {
169 if (!check(Adjust(*data_old_.program, data_new_.program.get())))
170 setMessage("Cannot adjust %s to match %s.", name(OLD), name(NEW));
173 void CourgetteFlow::DestroyDisassembler(Group group) {
176 data(group)->disassembler.reset();
179 void CourgetteFlow::DestroyAssemblyProgram(Group group) {
182 data(group)->program.reset();
185 void CourgetteFlow::DestroyEncodedProgram(Group group) {
188 data(group)->encoded.reset();
191 bool CourgetteFlow::check(Status new_status) {
192 if (new_status == C_OK)
194 status_ = new_status;
198 bool CourgetteFlow::check(bool success, Status failure_mode) {
201 status_ = failure_mode;
205 void CourgetteFlow::setMessage(const char* format, ...) {
207 va_start(args, format);
208 message_ = base::StringPrintV(format, args);
212 } // namespace courgette