1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
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_
23 #include "base/basictypes.h"
25 #include "courgette/courgette.h"
26 #include "courgette/region.h"
27 #include "courgette/streams.h"
31 // Forward declarations:
35 // An Element is a region of an Ensemble with an identifyable kind.
39 enum Kind
{ WIN32_X86_WITH_CODE
, WIN32_NOCODE
};
43 Kind
kind() const { return kind_
; }
44 const Region
& region() const { return region_
; }
46 // The name is used only for debugging and logging.
47 virtual std::string
Name() const;
49 // Returns the byte position of this Element relative to the start of
50 // containing Ensemble.
51 size_t offset_in_ensemble() const;
53 // Some subclasses of Element might have a PEInfo.
54 virtual PEInfo
* GetPEInfo() const { return NULL
; }
57 Element(Kind kind
, Ensemble
* ensemble
, const Region
& region
);
64 DISALLOW_COPY_AND_ASSIGN(Element
);
70 Ensemble(const Region
& region
, const char* name
)
71 : region_(region
), name_(name
) {}
74 const Region
& region() const { return region_
; }
75 const std::string
& name() const { return name_
; }
77 // Scans the region to find Elements within the region().
78 Status
FindEmbeddedElements();
80 // Returns the elements found by 'FindEmbeddedElements'.
81 const std::vector
<Element
*>& elements() const { return elements_
; }
85 Region region_
; // The memory, owned by caller, containing the
87 std::string name_
; // A debugging/logging name for the Ensemble.
89 std::vector
<Element
*> elements_
; // Embedded elements discovered.
90 std::vector
<Element
*> owned_elements_
; // For deallocation.
92 DISALLOW_COPY_AND_ASSIGN(Ensemble
);
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 kMagic
= 'C' | ('o' << 8) | ('u' << 16);
140 static const uint32 kVersion
= 20110216;
142 // Transformation method IDs.
143 enum TransformationMethodId
{
144 T_COURGETTE_WIN32_X86
= 1, // Windows 32 bit 'Portable Executable' x86.
148 // For any transform you would implement both a TransformationPatcher and a
149 // TransformationPatchGenerator.
151 // TransformationPatcher is the interface which abstracts out the actual
152 // transformation used on an Element. The patching itself happens outside the
153 // actions of a TransformationPatcher. There are four steps.
155 // The first step is an Init step. The parameters to the Init step identify the
156 // element, for example, range of locations within the original ensemble that
157 // correspond to the element.
159 // PredictTransformParameters, explained below.
161 // The two final steps are 'Transform' - to transform the element into a new
162 // representation, and to 'Reform' - to transform from the new representation
163 // back to the original form.
165 // The Transform step takes some parameters. This allows the transform to be
166 // customized to the particular element, or to receive some assistance in the
167 // analysis required to perform the transform. The transform parameters might
168 // be extensive but mostly predicable, so preceeding Transform is a
169 // PredictTransformParameters step.
171 class TransformationPatcher
{
173 virtual ~TransformationPatcher() {}
175 // First step: provides parameters for the patching. This would at a minimum
176 // identify the element within the ensemble being patched.
177 virtual Status
Init(SourceStream
* parameter_stream
) = 0;
179 // Second step: predicts transform parameters.
180 virtual Status
PredictTransformParameters(
181 SinkStreamSet
* predicted_parameters
) = 0;
183 // Third step: transforms element from original representation into alternate
185 virtual Status
Transform(SourceStreamSet
* corrected_parameters
,
186 SinkStreamSet
* transformed_element
) = 0;
188 // Final step: transforms element back from alternate representation into
189 // original representation.
190 virtual Status
Reform(SourceStreamSet
* transformed_element
,
191 SinkStream
* reformed_element
) = 0;
194 // TransformationPatchGenerator is the interface which abstracts out the actual
195 // transformation used (and adjustment used) when differentially compressing one
196 // Element from the |new_ensemble| against a corresponding element in the
199 // This is not a pure interface. There is a small amount of inheritance
200 // implementation for the fields and actions common to all
201 // TransformationPatchGenerators.
203 // When TransformationPatchGenerator is subclassed, there will be a
204 // corresponding subclass of TransformationPatcher.
206 class TransformationPatchGenerator
{
208 TransformationPatchGenerator(Element
* old_element
,
209 Element
* new_element
,
210 TransformationPatcher
* patcher
);
212 virtual ~TransformationPatchGenerator();
214 // Returns the TransformationMethodId that identies this transformation.
215 virtual CourgettePatchFile::TransformationMethodId
Kind() = 0;
217 // Writes the parameters that will be passed to TransformationPatcher::Init.
218 virtual Status
WriteInitialParameters(SinkStream
* parameter_stream
) = 0;
220 // Predicts the transform parameters for the |old_element|. This must match
221 // exactly the output that will be produced by the PredictTransformParameters
222 // method of the corresponding subclass of TransformationPatcher. This method
223 // is not pure. The default implementation delegates to the patcher to
224 // guarantee matching output.
225 virtual Status
PredictTransformParameters(SinkStreamSet
* prediction
);
227 // Writes the desired parameters for the transform of the old element from the
228 // file representation to the alternate representation.
229 virtual Status
CorrectedTransformParameters(SinkStreamSet
* parameters
) = 0;
231 // Writes both |old_element| and |new_element| in the new representation.
232 // |old_corrected_parameters| will match the |corrected_parameters| passed to
233 // the Transform method of the corresponding sublcass of
234 // TransformationPatcher.
236 // The output written to |old_transformed_element| must match exactly the
237 // output written by the Transform method of the corresponding subclass of
238 // TransformationPatcher.
239 virtual Status
Transform(SourceStreamSet
* old_corrected_parameters
,
240 SinkStreamSet
* old_transformed_element
,
241 SinkStreamSet
* new_transformed_element
) = 0;
243 // Transforms the new transformed_element back from the alternate
244 // representation into the original file format. This must match exactly the
245 // output that will be produced by the corresponding subclass of
246 // TransformationPatcher::Reform. This method is not pure. The default
247 // implementation delegates to the patcher.
248 virtual Status
Reform(SourceStreamSet
* transformed_element
,
249 SinkStream
* reformed_element
);
252 Element
* old_element_
;
253 Element
* new_element_
;
254 TransformationPatcher
* patcher_
;
258 #endif // COURGETTE_ENSEMBLE_H_