1 // Copyright 2011 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 // 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.
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
14 // This file declares all the main types involved in creating and applying a
15 // patch with this structure.
17 #ifndef COURGETTE_ENSEMBLE_H_
18 #define COURGETTE_ENSEMBLE_H_
26 #include "base/memory/raw_ptr.h"
27 #include "courgette/courgette.h"
28 #include "courgette/region.h"
29 #include "courgette/streams.h"
33 // Forward declarations:
36 // An Element is a region of an Ensemble with an identifyable kind.
40 Element(ExecutableType kind,
42 const Region& region);
44 Element(const Element&) = delete;
45 Element& operator=(const Element&) = delete;
49 ExecutableType kind() const { return kind_; }
50 const Region& region() const { return region_; }
52 // The name is used only for debugging and logging.
53 virtual std::string Name() const;
55 // Returns the byte position of this Element relative to the start of
56 // containing Ensemble.
57 size_t offset_in_ensemble() const;
61 raw_ptr<Ensemble> ensemble_;
68 Ensemble(const Region& region, const char* name)
69 : region_(region), name_(name) {}
71 Ensemble(const Ensemble&) = delete;
72 Ensemble& operator=(const Ensemble&) = delete;
76 const Region& region() const { return region_; }
77 const std::string& name() const { return name_; }
79 // Scans the region to find Elements within the region().
80 Status FindEmbeddedElements();
82 // Returns the elements found by 'FindEmbeddedElements'.
83 const std::vector<Element*>& elements() const { return elements_; }
87 Region region_; // The memory, owned by caller, containing the
89 std::string name_; // A debugging/logging name for the Ensemble.
91 std::vector<Element*> elements_; // Embedded elements discovered.
92 std::vector<Element*> owned_elements_; // For deallocation.
95 inline size_t Element::offset_in_ensemble() const {
96 return region().start() - ensemble_->region().start();
99 // The 'CourgettePatchFile' is class is a 'namespace' for the constants that
100 // appear in a Courgette patch file.
101 struct CourgettePatchFile {
103 // The Courgette patch format interleaves the data for N embedded Elements.
105 // Format of a patch file:
111 // final-patch-input-size (an allocation hint)
114 // number-of-transformed-elements (N) - varint32
115 // transformation-1-method-id
116 // transformation-2-method-id
118 // transformation-1-initial-parameters
119 // transformation-2-initial-parameters
123 // transformation-1-parameters
124 // transformation-2-parameters
128 // transformed-element-1
129 // transformed-element-2
138 static const uint32_t kMagic = 'C' | ('o' << 8) | ('u' << 16);
140 static const uint32_t kVersion = 20110216;
143 // For any transform you would implement both a TransformationPatcher and a
144 // TransformationPatchGenerator.
146 // TransformationPatcher is the interface which abstracts out the actual
147 // transformation used on an Element. The patching itself happens outside the
148 // actions of a TransformationPatcher. There are four steps.
150 // The first step is an Init step. The parameters to the Init step identify the
151 // element, for example, range of locations within the original ensemble that
152 // correspond to the element.
154 // PredictTransformParameters, explained below.
156 // The two final steps are 'Transform' - to transform the element into a new
157 // representation, and to 'Reform' - to transform from the new representation
158 // back to the original form.
160 // The Transform step takes some parameters. This allows the transform to be
161 // customized to the particular element, or to receive some assistance in the
162 // analysis required to perform the transform. The transform parameters might
163 // be extensive but mostly predicable, so preceeding Transform is a
164 // PredictTransformParameters step.
166 class TransformationPatcher {
168 virtual ~TransformationPatcher() {}
170 // First step: provides parameters for the patching. This would at a minimum
171 // identify the element within the ensemble being patched.
172 virtual Status Init(SourceStream* parameter_stream) = 0;
174 // Second step: predicts transform parameters.
175 virtual Status PredictTransformParameters(
176 SinkStreamSet* predicted_parameters) = 0;
178 // Third step: transforms element from original representation into alternate
180 virtual Status Transform(SourceStreamSet* corrected_parameters,
181 SinkStreamSet* transformed_element) = 0;
183 // Final step: transforms element back from alternate representation into
184 // original representation.
185 virtual Status Reform(SourceStreamSet* transformed_element,
186 SinkStream* reformed_element) = 0;
189 // TransformationPatchGenerator is the interface which abstracts out the actual
190 // transformation used (and adjustment used) when differentially compressing one
191 // Element from the |new_ensemble| against a corresponding element in the
194 // This is not a pure interface. There is a small amount of inheritance
195 // implementation for the fields and actions common to all
196 // TransformationPatchGenerators.
198 // When TransformationPatchGenerator is subclassed, there will be a
199 // corresponding subclass of TransformationPatcher.
201 class TransformationPatchGenerator {
203 TransformationPatchGenerator(Element* old_element,
204 Element* new_element,
205 TransformationPatcher* patcher);
207 virtual ~TransformationPatchGenerator();
209 // Returns the TransformationMethodId that identies this transformation.
210 virtual ExecutableType Kind() = 0;
212 // Writes the parameters that will be passed to TransformationPatcher::Init.
213 virtual Status WriteInitialParameters(SinkStream* parameter_stream) = 0;
215 // Predicts the transform parameters for the |old_element|. This must match
216 // exactly the output that will be produced by the PredictTransformParameters
217 // method of the corresponding subclass of TransformationPatcher. This method
218 // is not pure. The default implementation delegates to the patcher to
219 // guarantee matching output.
220 virtual Status PredictTransformParameters(SinkStreamSet* prediction);
222 // Writes the desired parameters for the transform of the old element from the
223 // file representation to the alternate representation.
224 virtual Status CorrectedTransformParameters(SinkStreamSet* parameters) = 0;
226 // Writes both |old_element| and |new_element| in the new representation.
227 // |old_corrected_parameters| will match the |corrected_parameters| passed to
228 // the Transform method of the corresponding sublcass of
229 // TransformationPatcher.
231 // The output written to |old_transformed_element| must match exactly the
232 // output written by the Transform method of the corresponding subclass of
233 // TransformationPatcher.
234 virtual Status Transform(SourceStreamSet* old_corrected_parameters,
235 SinkStreamSet* old_transformed_element,
236 SinkStreamSet* new_transformed_element) = 0;
238 // Transforms the new transformed_element back from the alternate
239 // representation into the original file format. This must match exactly the
240 // output that will be produced by the corresponding subclass of
241 // TransformationPatcher::Reform. This method is not pure. The default
242 // implementation delegates to the patcher.
243 virtual Status Reform(SourceStreamSet* transformed_element,
244 SinkStream* reformed_element);
247 raw_ptr<Element> old_element_;
248 raw_ptr<Element> new_element_;
249 raw_ptr<TransformationPatcher> patcher_;
253 #endif // COURGETTE_ENSEMBLE_H_