Index: courgette/courgette_flow.cc |
diff --git a/courgette/courgette_flow.cc b/courgette/courgette_flow.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..2fa9810379aeab323f05f33b03a576cf5ffdee44 |
--- /dev/null |
+++ b/courgette/courgette_flow.cc |
@@ -0,0 +1,189 @@ |
+// Copyright 2017 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "courgette/courgette_flow.h" |
+ |
+#include <stdarg.h> |
+ |
+#include "base/files/file_path.h" |
+#include "base/logging.h" |
+#include "base/memory/ptr_util.h" |
+#include "base/strings/stringprintf.h" |
+#include "courgette/assembly_program.h" |
+#include "courgette/encoded_program.h" |
+#include "courgette/program_detector.h" |
+ |
+namespace courgette { |
+ |
+/******** CourgetteFlow::Data ********/ |
+ |
+CourgetteFlow::Data::Data() = default; |
+ |
+CourgetteFlow::Data::~Data() = default; |
+ |
+/******** CourgetteFlow ********/ |
+ |
+CourgetteFlow::CourgetteFlow() = default; |
+ |
+CourgetteFlow::~CourgetteFlow() = default; |
+ |
+// static |
+const char* CourgetteFlow::name(Group group) { |
+ switch (group) { |
+ case ONLY: |
+ return "input"; |
+ case OLD: |
+ return "'old' input"; |
+ case NEW: |
+ return "'new' input"; |
+ default: |
+ NOTREACHED(); |
+ break; |
+ } |
+ return nullptr; |
+} |
+ |
+CourgetteFlow::Data* CourgetteFlow::data(Group group) { |
+ switch (group) { |
+ case ONLY: |
+ return &data_only_; |
+ case OLD: |
+ return &data_old_; |
+ case NEW: |
+ return &data_new_; |
+ default: |
+ NOTREACHED(); |
+ break; |
+ } |
+ return nullptr; |
+} |
+ |
+bool CourgetteFlow::ok() { |
+ return status_ == C_OK; |
+} |
+ |
+bool CourgetteFlow::failed() { |
+ return status_ != C_OK; |
+} |
+ |
+Status CourgetteFlow::status() { |
+ return status_; |
+} |
+ |
+const std::string& CourgetteFlow::message() { |
+ return message_; |
+} |
+ |
+void CourgetteFlow::ReadSourceStreamSetFromBuffer(Group group, |
+ const BasicBuffer& buffer) { |
+ if (failed()) |
+ return; |
+ Data* d = data(group); |
+ if (!check(d->sources.Init(buffer.data(), buffer.length()), |
+ C_GENERAL_ERROR)) { |
+ setMessage("Cannot read %s as SourceStreamSet.", name(group)); |
+ } |
+} |
+ |
+void CourgetteFlow::ReadAssemblyProgramFromBuffer(Group group, |
+ const BasicBuffer& buffer, |
+ bool annotate) { |
+ if (failed()) |
+ return; |
+ Data* d = data(group); |
+ auto parser = annotate ? ParseDetectedExecutableWithAnnotation |
+ : ParseDetectedExecutable; |
+ if (!check(parser(buffer.data(), buffer.length(), &d->program))) |
+ setMessage("Cannot parse %s (code = %d).", name(group), status_); |
+} |
+ |
+void CourgetteFlow::ReadEncodedProgramFromSourceStreamSet( |
+ Group group, |
+ SourceStreamSet* opt_sources /* nullptr */) { |
+ if (failed()) |
+ return; |
+ Data* d = data(group); |
+ SourceStreamSet* sources = opt_sources ? opt_sources : &d->sources; |
+ if (!check(ReadEncodedProgram(sources, &d->encoded))) |
+ setMessage("Cannot read %s as encoded program.", name(group)); |
+} |
+ |
+void CourgetteFlow::CreateEncodedProgramFromAssemblyProgram(Group group) { |
+ if (failed()) |
+ return; |
+ Data* d = data(group); |
+ if (!check(Encode(*d->program, &d->encoded))) |
+ setMessage("Cannot encode %s (code = %d).", name(group), status_); |
+} |
+ |
+void CourgetteFlow::WriteSinkStreamFromSinkStreamSet(Group group, |
+ SinkStream* sink) { |
+ DCHECK(sink); |
+ if (failed()) |
+ return; |
+ if (!check(data(group)->sinks.CopyTo(sink), C_GENERAL_ERROR)) |
+ setMessage("Cannnot combine serialized streams for %s.", name(group)); |
+} |
+ |
+void CourgetteFlow::WriteSinkStreamSetFromEncodedProgram( |
+ Group group, |
+ SinkStreamSet* opt_sinks /* nullptr */) { |
+ if (failed()) |
+ return; |
+ Data* d = data(group); |
+ SinkStreamSet* sinks = opt_sinks ? opt_sinks : &d->sinks; |
+ if (!check(WriteEncodedProgram(d->encoded.get(), sinks))) |
+ setMessage("Cannot serialize encoded %s.", name(group)); |
+} |
+ |
+void CourgetteFlow::WriteExecutableFromEncodedProgram(Group group, |
+ SinkStream* sink) { |
+ DCHECK(sink); |
+ if (failed()) |
+ return; |
+ if (!check(Assemble(data(group)->encoded.get(), sink))) |
+ setMessage("Cannot assemble %s.", name(group)); |
+} |
+ |
+void CourgetteFlow::AdjustNewAssemblyProgramToMatchOld() { |
+ if (failed()) |
+ return; |
+ if (!check(Adjust(*data_old_.program, data_new_.program.get()))) |
+ setMessage("Cannot adjust %s to match %s.", name(OLD), name(NEW)); |
+} |
+ |
+void CourgetteFlow::DestroyAssemblyProgram(Group group) { |
+ if (failed()) |
+ return; |
+ data(group)->program.reset(); |
+} |
+ |
+void CourgetteFlow::DestroyEncodedProgram(Group group) { |
+ if (failed()) |
+ return; |
+ data(group)->encoded.reset(); |
+} |
+ |
+bool CourgetteFlow::check(Status new_status) { |
+ if (new_status == C_OK) |
+ return true; |
+ status_ = new_status; |
+ return false; |
+} |
+ |
+bool CourgetteFlow::check(bool success, Status failure_mode) { |
+ if (success) |
+ return true; |
+ status_ = failure_mode; |
+ return false; |
+} |
+ |
+void CourgetteFlow::setMessage(const char* format, ...) { |
+ va_list args; |
+ va_start(args, format); |
+ message_ = base::StringPrintV(format, args); |
+ va_end(args); |
+} |
+ |
+} // namespace courgette |