Index: courgette/courgette_flow.h |
diff --git a/courgette/courgette_flow.h b/courgette/courgette_flow.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..9b8cb889126fd1e29c4e86a459aa945c84bee781 |
--- /dev/null |
+++ b/courgette/courgette_flow.h |
@@ -0,0 +1,144 @@ |
+// 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. |
+ |
+#ifndef COURGETTE_COURGETTE_FLOW_H_ |
+#define COURGETTE_COURGETTE_FLOW_H_ |
+ |
+#include <memory> |
+#include <string> |
+ |
+#include "base/macros.h" |
+#include "courgette/courgette.h" |
+#include "courgette/region.h" |
+#include "courgette/streams.h" |
+ |
+namespace courgette { |
+ |
+class AssemblyProgram; |
+class EncodedProgram; |
+ |
+// An adaptor for Region as BasicBuffer. |
+class RegionBuffer : public BasicBuffer { |
+ public: |
+ explicit RegionBuffer(const Region& region) : region_(region) {} |
+ ~RegionBuffer() override {} |
+ |
+ // BasicBuffer: |
+ const uint8_t* data() const override { return region_.start(); } |
+ size_t length() const override { return region_.length(); } |
+ |
+ private: |
+ Region region_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(RegionBuffer); |
+}; |
+ |
+// CourgetteFlow stores Courgette data arranged into groups, and exposes |
+// "commands" that operate on them. On the first occurrence of an error, the |
+// Courgette error code is recorded, error messages are generated and stored, |
+// and all subsequent commands become no-op. This allows callers to concisely |
+// specify high-level logic with minimal code for error handling. |
+class CourgetteFlow { |
+ public: |
+ // A group of Courgette data, for a single executable. Takes negligible space |
+ // when unused. |
+ struct Data { |
+ Data(); |
+ ~Data(); |
+ |
+ std::unique_ptr<AssemblyProgram> program; |
+ std::unique_ptr<EncodedProgram> encoded; |
+ SinkStreamSet sinks; |
+ SourceStreamSet sources; |
+ }; |
+ |
+ // Group enumeration into |data_*_| fields. |
+ enum Group { |
+ ONLY, // The only file processed. |
+ OLD, // The "old" file during patching. |
+ NEW, // The "new" file during patching. |
+ }; |
+ |
+ CourgetteFlow(); |
+ ~CourgetteFlow(); |
+ |
+ static const char* name(Group group); |
+ Data* data(Group group); // Allows caller to modify. |
+ bool ok(); |
+ bool failed(); |
+ Status status(); |
+ const std::string& message(); |
+ |
+ // Commands that perform no-op on error. This allows caller to concisely |
+ // specify high-level logic, and perform a single error check at the end. Care |
+ // must be taken w.r.t. error handling if |data()| is harvested between |
+ // commands. |
+ |
+ // Reads |buffer| to initialize |data(group)->sources|. |
+ void ReadSourceStreamSetFromBuffer(Group group, const BasicBuffer& buffer); |
+ |
+ // Reads |buffer| to initialize |data(group)->program|, passing |annotate| as |
+ // initialization parameter (true if AdjustNewAssemblyProgramToMatchOld() gets |
+ // called later). |
+ void ReadAssemblyProgramFromBuffer(Group group, |
+ const BasicBuffer& buffer, |
+ bool annotate); |
+ |
+ // Reads |opt_sources| if given, or else |data(group)->sources| to initialize |
+ // |data(group).encoded|. |
+ void ReadEncodedProgramFromSourceStreamSet( |
+ Group group, |
+ SourceStreamSet* opt_sources = nullptr); |
+ |
+ // Uses |data(group)->program| to initialize |data(group)->encoded|. |
+ void CreateEncodedProgramFromAssemblyProgram(Group group); |
+ |
+ // Serializese |data(group)->sinks| to |sink|. |
+ void WriteSinkStreamFromSinkStreamSet(Group group, SinkStream* sink); |
+ |
+ // Serializes |data(group)->encoded| to |opt_sinks| if given, or else to |
+ // |data(group)->sinks|. |
+ void WriteSinkStreamSetFromEncodedProgram(Group group, |
+ SinkStreamSet* opt_sinks = nullptr); |
+ |
+ // Converts |data(group)->encoded| to an exectuable and writes the result to |
+ // |sink|. |
+ void WriteExecutableFromEncodedProgram(Group group, SinkStream* sink); |
+ |
+ // Adjusts |data(NEW)->program| Labels to match |data(OLD)->program| Labels. |
+ void AdjustNewAssemblyProgramToMatchOld(); |
+ |
+ // Destructor commands to reduce memory usage. |
+ |
+ void DestroyAssemblyProgram(Group group); |
+ |
+ void DestroyEncodedProgram(Group group); |
+ |
+ private: |
+ // Utilities to process return values from Courgette functions, and assign |
+ // |status_| and |message_|. Usage: |
+ // if (!check(some_courgette_function(param1, ...))) |
+ // setMessage("format string %s...", value1, ...); |
+ |
+ // Reassigns |status_|, and returns true if |C_OK|. |
+ bool check(Status new_status); |
+ |
+ // check() alternative for functions that return true on succes. On failure |
+ // assigns |status_| to |failure_mode|. |
+ bool check(bool success, Status failure_mode); |
+ |
+ void setMessage(const char* format, ...); |
+ |
+ Status status_ = C_OK; |
+ std::string message_; |
+ Data data_only_; |
+ Data data_old_; |
+ Data data_new_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(CourgetteFlow); |
+}; |
+ |
+} // namespace courgette |
+ |
+#endif // COURGETTE_COURGETTE_FLOW_H_ |