blob: 4d26076e2487effb144c4541aacd45c627f7a8e7 [file] [log] [blame]
[email protected]93d529ca2011-10-21 22:24:191// Copyright (c) 2011 The Chromium Authors. All rights reserved.
[email protected]04ca1bc2009-05-08 23:00:292// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// The main idea in Courgette is to do patching *under a tranformation*. The
6// input is transformed into a new representation, patching occurs in the new
7// repesentation, and then the tranform is reversed to get the patched data.
8//
9// The idea is applied to pieces (or 'Elements') of the whole (or 'Ensemble').
10// Each of the elements has to go through the same set of steps in lock-step,
11// but there may be many different kinds of elements, which have different
12// transformation.
13//
14// This file declares all the main types involved in creating and applying a
15// patch with this structure.
16
17#ifndef COURGETTE_ENSEMBLE_H_
18#define COURGETTE_ENSEMBLE_H_
19
20#include <vector>
21#include <string>
22
23#include "base/basictypes.h"
24
25#include "courgette/courgette.h"
26#include "courgette/region.h"
27#include "courgette/streams.h"
28
29namespace courgette {
30
31// Forward declarations:
32class Ensemble;
[email protected]04ca1bc2009-05-08 23:00:2933
34// An Element is a region of an Ensemble with an identifyable kind.
35//
36class Element {
37 public:
[email protected]93d529ca2011-10-21 22:24:1938 Element(ExecutableType kind,
39 Ensemble* ensemble,
[email protected]423a3812011-10-26 00:50:2040 const Region& region);
[email protected]04ca1bc2009-05-08 23:00:2941
[email protected]93d529ca2011-10-21 22:24:1942 virtual ~Element();
[email protected]04ca1bc2009-05-08 23:00:2943
[email protected]93d529ca2011-10-21 22:24:1944 ExecutableType kind() const { return kind_; }
[email protected]04ca1bc2009-05-08 23:00:2945 const Region& region() const { return region_; }
46
47 // The name is used only for debugging and logging.
48 virtual std::string Name() const;
49
50 // Returns the byte position of this Element relative to the start of
51 // containing Ensemble.
52 size_t offset_in_ensemble() const;
53
[email protected]04ca1bc2009-05-08 23:00:2954 private:
[email protected]93d529ca2011-10-21 22:24:1955 ExecutableType kind_;
[email protected]04ca1bc2009-05-08 23:00:2956 Ensemble* ensemble_;
57 Region region_;
58
59 DISALLOW_COPY_AND_ASSIGN(Element);
60};
61
62
63class Ensemble {
64 public:
65 Ensemble(const Region& region, const char* name)
66 : region_(region), name_(name) {}
67 ~Ensemble();
68
69 const Region& region() const { return region_; }
70 const std::string& name() const { return name_; }
71
72 // Scans the region to find Elements within the region().
73 Status FindEmbeddedElements();
74
75 // Returns the elements found by 'FindEmbeddedElements'.
76 const std::vector<Element*>& elements() const { return elements_; }
77
78
79 private:
80 Region region_; // The memory, owned by caller, containing the
81 // Ensemble's data.
82 std::string name_; // A debugging/logging name for the Ensemble.
83
84 std::vector<Element*> elements_; // Embedded elements discovered.
85 std::vector<Element*> owned_elements_; // For deallocation.
86
87 DISALLOW_COPY_AND_ASSIGN(Ensemble);
88};
89
90inline size_t Element::offset_in_ensemble() const {
91 return region().start() - ensemble_->region().start();
92}
93
94// The 'CourgettePatchFile' is class is a 'namespace' for the constants that
95// appear in a Courgette patch file.
96struct CourgettePatchFile {
97 //
98 // The Courgette patch format interleaves the data for N embedded Elements.
99 //
100 // Format of a patch file:
101 // header:
102 // magic
103 // version
104 // source-checksum
105 // target-checksum
[email protected]6db3cd4e2011-02-23 21:18:48106 // final-patch-input-size (an allocation hint)
[email protected]04ca1bc2009-05-08 23:00:29107 // multiple-streams:
108 // stream 0:
109 // number-of-transformed-elements (N) - varint32
110 // transformation-1-method-id
111 // transformation-2-method-id
112 // ...
113 // transformation-1-initial-parameters
114 // transformation-2-initial-parameters
115 // ...
116 // stream 1:
117 // correction:
118 // transformation-1-parameters
119 // transformation-2-parameters
120 // ...
121 // stream 2:
122 // correction:
123 // transformed-element-1
124 // transformed-element-2
125 // ...
126 // stream 3:
127 // correction:
128 // base-file
129 // element-1
130 // element-2
131 // ...
132
133 static const uint32 kMagic = 'C' | ('o' << 8) | ('u' << 16);
134
[email protected]6db3cd4e2011-02-23 21:18:48135 static const uint32 kVersion = 20110216;
[email protected]04ca1bc2009-05-08 23:00:29136
[email protected]93d529ca2011-10-21 22:24:19137 // Transformation method IDs. These are embedded in generated files, so
138 // never remove or change an existing id.
[email protected]04ca1bc2009-05-08 23:00:29139 enum TransformationMethodId {
140 T_COURGETTE_WIN32_X86 = 1, // Windows 32 bit 'Portable Executable' x86.
141 };
142};
143
144// For any transform you would implement both a TransformationPatcher and a
145// TransformationPatchGenerator.
146//
147// TransformationPatcher is the interface which abstracts out the actual
148// transformation used on an Element. The patching itself happens outside the
149// actions of a TransformationPatcher. There are four steps.
150//
151// The first step is an Init step. The parameters to the Init step identify the
152// element, for example, range of locations within the original ensemble that
153// correspond to the element.
154//
155// PredictTransformParameters, explained below.
156//
157// The two final steps are 'Transform' - to transform the element into a new
158// representation, and to 'Reform' - to transform from the new representation
159// back to the original form.
160//
161// The Transform step takes some parameters. This allows the transform to be
162// customized to the particular element, or to receive some assistance in the
163// analysis required to perform the transform. The transform parameters might
164// be extensive but mostly predicable, so preceeding Transform is a
165// PredictTransformParameters step.
166//
167class TransformationPatcher {
168 public:
169 virtual ~TransformationPatcher() {}
170
171 // First step: provides parameters for the patching. This would at a minimum
172 // identify the element within the ensemble being patched.
173 virtual Status Init(SourceStream* parameter_stream) = 0;
174
175 // Second step: predicts transform parameters.
176 virtual Status PredictTransformParameters(
177 SinkStreamSet* predicted_parameters) = 0;
178
179 // Third step: transforms element from original representation into alternate
180 // representation.
181 virtual Status Transform(SourceStreamSet* corrected_parameters,
182 SinkStreamSet* transformed_element) = 0;
183
184 // Final step: transforms element back from alternate representation into
185 // original representation.
186 virtual Status Reform(SourceStreamSet* transformed_element,
187 SinkStream* reformed_element) = 0;
188};
189
190// TransformationPatchGenerator is the interface which abstracts out the actual
191// transformation used (and adjustment used) when differentially compressing one
192// Element from the |new_ensemble| against a corresponding element in the
193// |old_ensemble|.
194//
195// This is not a pure interface. There is a small amount of inheritance
196// implementation for the fields and actions common to all
197// TransformationPatchGenerators.
198//
199// When TransformationPatchGenerator is subclassed, there will be a
200// corresponding subclass of TransformationPatcher.
201//
202class TransformationPatchGenerator {
203 public:
204 TransformationPatchGenerator(Element* old_element,
205 Element* new_element,
206 TransformationPatcher* patcher);
207
208 virtual ~TransformationPatchGenerator();
209
210 // Returns the TransformationMethodId that identies this transformation.
211 virtual CourgettePatchFile::TransformationMethodId Kind() = 0;
212
213 // Writes the parameters that will be passed to TransformationPatcher::Init.
214 virtual Status WriteInitialParameters(SinkStream* parameter_stream) = 0;
215
216 // Predicts the transform parameters for the |old_element|. This must match
217 // exactly the output that will be produced by the PredictTransformParameters
218 // method of the corresponding subclass of TransformationPatcher. This method
219 // is not pure. The default implementation delegates to the patcher to
220 // guarantee matching output.
221 virtual Status PredictTransformParameters(SinkStreamSet* prediction);
222
223 // Writes the desired parameters for the transform of the old element from the
224 // file representation to the alternate representation.
225 virtual Status CorrectedTransformParameters(SinkStreamSet* parameters) = 0;
226
227 // Writes both |old_element| and |new_element| in the new representation.
228 // |old_corrected_parameters| will match the |corrected_parameters| passed to
229 // the Transform method of the corresponding sublcass of
230 // TransformationPatcher.
231 //
232 // The output written to |old_transformed_element| must match exactly the
233 // output written by the Transform method of the corresponding subclass of
234 // TransformationPatcher.
235 virtual Status Transform(SourceStreamSet* old_corrected_parameters,
236 SinkStreamSet* old_transformed_element,
237 SinkStreamSet* new_transformed_element) = 0;
238
239 // Transforms the new transformed_element back from the alternate
240 // representation into the original file format. This must match exactly the
241 // output that will be produced by the corresponding subclass of
242 // TransformationPatcher::Reform. This method is not pure. The default
243 // implementation delegates to the patcher.
244 virtual Status Reform(SourceStreamSet* transformed_element,
245 SinkStream* reformed_element);
246
247 protected:
248 Element* old_element_;
249 Element* new_element_;
250 TransformationPatcher* patcher_;
251};
252
253} // namespace
254#endif // COURGETTE_ENSEMBLE_H_