123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253 |
- // Copyright (c) 2011 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.
- // The main idea in Courgette is to do patching *under a tranformation*. The
- // input is transformed into a new representation, patching occurs in the new
- // repesentation, and then the tranform is reversed to get the patched data.
- //
- // The idea is applied to pieces (or 'Elements') of the whole (or 'Ensemble').
- // Each of the elements has to go through the same set of steps in lock-step,
- // but there may be many different kinds of elements, which have different
- // transformation.
- //
- // This file declares all the main types involved in creating and applying a
- // patch with this structure.
- #ifndef COURGETTE_ENSEMBLE_H_
- #define COURGETTE_ENSEMBLE_H_
- #include <stddef.h>
- #include <stdint.h>
- #include <string>
- #include <vector>
- #include "base/memory/raw_ptr.h"
- #include "courgette/courgette.h"
- #include "courgette/region.h"
- #include "courgette/streams.h"
- namespace courgette {
- // Forward declarations:
- class Ensemble;
- // An Element is a region of an Ensemble with an identifyable kind.
- //
- class Element {
- public:
- Element(ExecutableType kind,
- Ensemble* ensemble,
- const Region& region);
- Element(const Element&) = delete;
- Element& operator=(const Element&) = delete;
- virtual ~Element();
- ExecutableType kind() const { return kind_; }
- const Region& region() const { return region_; }
- // The name is used only for debugging and logging.
- virtual std::string Name() const;
- // Returns the byte position of this Element relative to the start of
- // containing Ensemble.
- size_t offset_in_ensemble() const;
- private:
- ExecutableType kind_;
- raw_ptr<Ensemble> ensemble_;
- Region region_;
- };
- class Ensemble {
- public:
- Ensemble(const Region& region, const char* name)
- : region_(region), name_(name) {}
- Ensemble(const Ensemble&) = delete;
- Ensemble& operator=(const Ensemble&) = delete;
- ~Ensemble();
- const Region& region() const { return region_; }
- const std::string& name() const { return name_; }
- // Scans the region to find Elements within the region().
- Status FindEmbeddedElements();
- // Returns the elements found by 'FindEmbeddedElements'.
- const std::vector<Element*>& elements() const { return elements_; }
- private:
- Region region_; // The memory, owned by caller, containing the
- // Ensemble's data.
- std::string name_; // A debugging/logging name for the Ensemble.
- std::vector<Element*> elements_; // Embedded elements discovered.
- std::vector<Element*> owned_elements_; // For deallocation.
- };
- inline size_t Element::offset_in_ensemble() const {
- return region().start() - ensemble_->region().start();
- }
- // The 'CourgettePatchFile' is class is a 'namespace' for the constants that
- // appear in a Courgette patch file.
- struct CourgettePatchFile {
- //
- // The Courgette patch format interleaves the data for N embedded Elements.
- //
- // Format of a patch file:
- // header:
- // magic
- // version
- // source-checksum
- // target-checksum
- // final-patch-input-size (an allocation hint)
- // multiple-streams:
- // stream 0:
- // number-of-transformed-elements (N) - varint32
- // transformation-1-method-id
- // transformation-2-method-id
- // ...
- // transformation-1-initial-parameters
- // transformation-2-initial-parameters
- // ...
- // stream 1:
- // correction:
- // transformation-1-parameters
- // transformation-2-parameters
- // ...
- // stream 2:
- // correction:
- // transformed-element-1
- // transformed-element-2
- // ...
- // stream 3:
- // correction:
- // base-file
- // element-1
- // element-2
- // ...
- static const uint32_t kMagic = 'C' | ('o' << 8) | ('u' << 16);
- static const uint32_t kVersion = 20110216;
- };
- // For any transform you would implement both a TransformationPatcher and a
- // TransformationPatchGenerator.
- //
- // TransformationPatcher is the interface which abstracts out the actual
- // transformation used on an Element. The patching itself happens outside the
- // actions of a TransformationPatcher. There are four steps.
- //
- // The first step is an Init step. The parameters to the Init step identify the
- // element, for example, range of locations within the original ensemble that
- // correspond to the element.
- //
- // PredictTransformParameters, explained below.
- //
- // The two final steps are 'Transform' - to transform the element into a new
- // representation, and to 'Reform' - to transform from the new representation
- // back to the original form.
- //
- // The Transform step takes some parameters. This allows the transform to be
- // customized to the particular element, or to receive some assistance in the
- // analysis required to perform the transform. The transform parameters might
- // be extensive but mostly predicable, so preceeding Transform is a
- // PredictTransformParameters step.
- //
- class TransformationPatcher {
- public:
- virtual ~TransformationPatcher() {}
- // First step: provides parameters for the patching. This would at a minimum
- // identify the element within the ensemble being patched.
- virtual Status Init(SourceStream* parameter_stream) = 0;
- // Second step: predicts transform parameters.
- virtual Status PredictTransformParameters(
- SinkStreamSet* predicted_parameters) = 0;
- // Third step: transforms element from original representation into alternate
- // representation.
- virtual Status Transform(SourceStreamSet* corrected_parameters,
- SinkStreamSet* transformed_element) = 0;
- // Final step: transforms element back from alternate representation into
- // original representation.
- virtual Status Reform(SourceStreamSet* transformed_element,
- SinkStream* reformed_element) = 0;
- };
- // TransformationPatchGenerator is the interface which abstracts out the actual
- // transformation used (and adjustment used) when differentially compressing one
- // Element from the |new_ensemble| against a corresponding element in the
- // |old_ensemble|.
- //
- // This is not a pure interface. There is a small amount of inheritance
- // implementation for the fields and actions common to all
- // TransformationPatchGenerators.
- //
- // When TransformationPatchGenerator is subclassed, there will be a
- // corresponding subclass of TransformationPatcher.
- //
- class TransformationPatchGenerator {
- public:
- TransformationPatchGenerator(Element* old_element,
- Element* new_element,
- TransformationPatcher* patcher);
- virtual ~TransformationPatchGenerator();
- // Returns the TransformationMethodId that identies this transformation.
- virtual ExecutableType Kind() = 0;
- // Writes the parameters that will be passed to TransformationPatcher::Init.
- virtual Status WriteInitialParameters(SinkStream* parameter_stream) = 0;
- // Predicts the transform parameters for the |old_element|. This must match
- // exactly the output that will be produced by the PredictTransformParameters
- // method of the corresponding subclass of TransformationPatcher. This method
- // is not pure. The default implementation delegates to the patcher to
- // guarantee matching output.
- virtual Status PredictTransformParameters(SinkStreamSet* prediction);
- // Writes the desired parameters for the transform of the old element from the
- // file representation to the alternate representation.
- virtual Status CorrectedTransformParameters(SinkStreamSet* parameters) = 0;
- // Writes both |old_element| and |new_element| in the new representation.
- // |old_corrected_parameters| will match the |corrected_parameters| passed to
- // the Transform method of the corresponding sublcass of
- // TransformationPatcher.
- //
- // The output written to |old_transformed_element| must match exactly the
- // output written by the Transform method of the corresponding subclass of
- // TransformationPatcher.
- virtual Status Transform(SourceStreamSet* old_corrected_parameters,
- SinkStreamSet* old_transformed_element,
- SinkStreamSet* new_transformed_element) = 0;
- // Transforms the new transformed_element back from the alternate
- // representation into the original file format. This must match exactly the
- // output that will be produced by the corresponding subclass of
- // TransformationPatcher::Reform. This method is not pure. The default
- // implementation delegates to the patcher.
- virtual Status Reform(SourceStreamSet* transformed_element,
- SinkStream* reformed_element);
- protected:
- raw_ptr<Element> old_element_;
- raw_ptr<Element> new_element_;
- raw_ptr<TransformationPatcher> patcher_;
- };
- } // namespace
- #endif // COURGETTE_ENSEMBLE_H_
|