Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(360)

Unified Diff: third_party/courgette/ensemble_apply.cc

Issue 113009: Move Courgette from internal depot to third_party. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/courgette/ensemble.cc ('k') | third_party/courgette/ensemble_create.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/courgette/ensemble_apply.cc
===================================================================
--- third_party/courgette/ensemble_apply.cc (revision 0)
+++ third_party/courgette/ensemble_apply.cc (revision 0)
@@ -0,0 +1,412 @@
+// Copyright (c) 2009 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.
+
+// This file contains the code to apply a Courgette patch.
+
+#include "third_party/courgette/ensemble.h"
+
+#include "base/basictypes.h"
+#include "base/file_util.h"
+#include "base/logging.h"
+
+#include "third_party/courgette/crc.h"
+#include "third_party/courgette/image_info.h"
+#include "third_party/courgette/region.h"
+#include "third_party/courgette/streams.h"
+#include "third_party/courgette/simple_delta.h"
+#include "third_party/courgette/win32_x86_patcher.h"
+
+namespace courgette {
+
+// EnsemblePatchApplication is all the logic and data required to apply the
+// multi-stage patch.
+class EnsemblePatchApplication {
+ public:
+ EnsemblePatchApplication();
+ ~EnsemblePatchApplication();
+
+ Status ReadHeader(SourceStream* header_stream);
+
+ Status InitBase(const Region& region);
+
+ Status ValidateBase();
+
+ Status ReadInitialParameters(SourceStream* initial_parameters);
+
+ Status PredictTransformParameters(SinkStreamSet* predicted_parameters);
+
+ Status SubpatchTransformParameters(SinkStreamSet* prediction,
+ SourceStream* correction,
+ SourceStreamSet* corrected_parameters);
+
+ Status TransformUp(SourceStreamSet* parameters,
+ SinkStreamSet* transformed_elements);
+
+ Status SubpatchTransformedElements(SinkStreamSet* elements,
+ SourceStream* correction,
+ SourceStreamSet* corrected_elements);
+
+ Status TransformDown(SourceStreamSet* transformed_elements,
+ SinkStream* basic_elements);
+
+ Status SubpatchFinalOutput(SourceStream* original,
+ SourceStream* correction,
+ SinkStream* corrected_ensemble);
+
+ private:
+ Status SubpatchStreamSets(SinkStreamSet* predicted_items,
+ SourceStream* correction,
+ SourceStreamSet* corrected_items,
+ SinkStream* corrected_items_storage);
+
+ Region base_region_; // Location of in-memory copy of 'old' version.
+
+ uint32 source_checksum_;
+ uint32 target_checksum_;
+
+ std::vector<TransformationPatcher*> patchers_;
+
+ SinkStream corrected_parameters_storage_;
+ SinkStream corrected_elements_storage_;
+
+ DISALLOW_COPY_AND_ASSIGN(EnsemblePatchApplication);
+};
+
+EnsemblePatchApplication::EnsemblePatchApplication()
+ : source_checksum_(0), target_checksum_(0) {
+}
+
+EnsemblePatchApplication::~EnsemblePatchApplication() {
+ for (size_t i = 0; i < patchers_.size(); ++i) {
+ delete patchers_[i];
+ }
+}
+
+Status EnsemblePatchApplication::ReadHeader(SourceStream* header_stream) {
+ uint32 magic;
+ if (!header_stream->ReadVarint32(&magic))
+ return C_BAD_ENSEMBLE_MAGIC;
+
+ if (magic != CourgettePatchFile::kMagic)
+ return C_BAD_ENSEMBLE_MAGIC;
+
+ uint32 version;
+ if (!header_stream->ReadVarint32(&version))
+ return C_BAD_ENSEMBLE_VERSION;
+
+ if (version != CourgettePatchFile::kVersion)
+ return C_BAD_ENSEMBLE_VERSION;
+
+ if (!header_stream->ReadVarint32(&source_checksum_))
+ return C_BAD_ENSEMBLE_HEADER;
+
+ if (!header_stream->ReadVarint32(&target_checksum_))
+ return C_BAD_ENSEMBLE_HEADER;
+
+ return C_OK;
+}
+
+Status EnsemblePatchApplication::InitBase(const Region& region) {
+ base_region_.assign(region);
+ return C_OK;
+}
+
+Status EnsemblePatchApplication::ValidateBase() {
+ uint32 checksum = CalculateCrc(base_region_.start(), base_region_.length());
+ if (source_checksum_ != checksum)
+ return C_BAD_ENSEMBLE_CRC;
+
+ return C_OK;
+}
+
+Status EnsemblePatchApplication::ReadInitialParameters(
+ SourceStream* transformation_parameters) {
+ uint32 number_of_transformations = 0;
+ if (!transformation_parameters->ReadVarint32(&number_of_transformations))
+ return C_BAD_ENSEMBLE_HEADER;
+
+ for (size_t i = 0; i < number_of_transformations; ++i) {
+ uint32 kind;
+ if (!transformation_parameters->ReadVarint32(&kind))
+ return C_BAD_ENSEMBLE_HEADER;
+
+ if (kind == CourgettePatchFile::T_COURGETTE_WIN32_X86) {
+ TransformationPatcher* patcher =
+ new CourgetteWin32X86Patcher(base_region_);
+ patchers_.push_back(patcher);
+ } else {
+ return C_BAD_ENSEMBLE_HEADER;
+ }
+ }
+
+ for (size_t i = 0; i < patchers_.size(); ++i) {
+ Status status = patchers_[i]->Init(transformation_parameters);
+ if (status != C_OK)
+ return status;
+ }
+
+ // All transformation_parameters should have been consumed by the above loop.
+ if (!transformation_parameters->Empty())
+ return C_BAD_ENSEMBLE_HEADER;
+
+ return C_OK;
+}
+
+Status EnsemblePatchApplication::PredictTransformParameters(
+ SinkStreamSet* all_predicted_parameters) {
+ for (size_t i = 0; i < patchers_.size(); ++i) {
+ SinkStreamSet single_predicted_parameters;
+ Status status =
+ patchers_[i]->PredictTransformParameters(&single_predicted_parameters);
+ if (status != C_OK)
+ return status;
+ if (!all_predicted_parameters->WriteSet(&single_predicted_parameters))
+ return C_STREAM_ERROR;
+ }
+ return C_OK;
+}
+
+Status EnsemblePatchApplication::SubpatchTransformParameters(
+ SinkStreamSet* predicted_parameters,
+ SourceStream* correction,
+ SourceStreamSet* corrected_parameters) {
+ return SubpatchStreamSets(predicted_parameters,
+ correction,
+ corrected_parameters,
+ &corrected_parameters_storage_);
+}
+
+Status EnsemblePatchApplication::TransformUp(
+ SourceStreamSet* parameters,
+ SinkStreamSet* transformed_elements) {
+ for (size_t i = 0; i < patchers_.size(); ++i) {
+ SourceStreamSet single_parameters;
+ if (!parameters->ReadSet(&single_parameters))
+ return C_STREAM_ERROR;
+ SinkStreamSet single_transformed_element;
+ Status status = patchers_[i]->Transform(&single_parameters,
+ &single_transformed_element);
+ if (status != C_OK)
+ return status;
+ if (!single_parameters.Empty())
+ return C_STREAM_NOT_CONSUMED;
+ if (!transformed_elements->WriteSet(&single_transformed_element))
+ return C_STREAM_ERROR;
+ }
+
+ if (!parameters->Empty())
+ return C_STREAM_NOT_CONSUMED;
+ return C_OK;
+}
+
+Status EnsemblePatchApplication::SubpatchTransformedElements(
+ SinkStreamSet* predicted_elements,
+ SourceStream* correction,
+ SourceStreamSet* corrected_elements) {
+ return SubpatchStreamSets(predicted_elements,
+ correction,
+ corrected_elements,
+ &corrected_elements_storage_);
+}
+
+Status EnsemblePatchApplication::TransformDown(
+ SourceStreamSet* transformed_elements,
+ SinkStream* basic_elements) {
+ // Construct blob of original input followed by reformed elements.
+
+ // The original input:
+ basic_elements->Write(base_region_.start(), base_region_.length());
+
+ for (size_t i = 0; i < patchers_.size(); ++i) {
+ SourceStreamSet single_corrected_element;
+ if (!transformed_elements->ReadSet(&single_corrected_element))
+ return C_STREAM_ERROR;
+ Status status = patchers_[i]->Reform(&single_corrected_element,
+ basic_elements);
+ if (status != C_OK)
+ return status;
+ if (!single_corrected_element.Empty())
+ return C_STREAM_NOT_CONSUMED;
+ }
+
+ if (!transformed_elements->Empty())
+ return C_STREAM_NOT_CONSUMED;
+
+ return C_OK;
+}
+
+Status EnsemblePatchApplication::SubpatchFinalOutput(
+ SourceStream* original,
+ SourceStream* correction,
+ SinkStream* corrected_ensemble) {
+ Status delta_status = ApplySimpleDelta(original, correction,
+ corrected_ensemble);
+ if (delta_status != C_OK)
+ return delta_status;
+
+ if (CalculateCrc(corrected_ensemble->Buffer(),
+ corrected_ensemble->Length()) != target_checksum_)
+ return C_BAD_ENSEMBLE_CRC;
+
+ return C_OK;
+}
+
+Status EnsemblePatchApplication::SubpatchStreamSets(
+ SinkStreamSet* predicted_items,
+ SourceStream* correction,
+ SourceStreamSet* corrected_items,
+ SinkStream* corrected_items_storage) {
+ SinkStream linearized_predicted_items;
+ if (!predicted_items->CopyTo(&linearized_predicted_items))
+ return C_STREAM_ERROR;
+
+ SourceStream prediction;
+ prediction.Init(linearized_predicted_items);
+
+ Status status = ApplySimpleDelta(&prediction,
+ correction,
+ corrected_items_storage);
+ if (status != C_OK)
+ return status;
+
+ if (!corrected_items->Init(corrected_items_storage->Buffer(),
+ corrected_items_storage->Length()))
+ return C_STREAM_ERROR;
+
+ return C_OK;
+}
+
+Status ApplyEnsemblePatch(SourceStream* base,
+ SourceStream* patch,
+ SinkStream* output) {
+ Status status;
+ EnsemblePatchApplication patch_process;
+
+ status = patch_process.ReadHeader(patch);
+ if (status != C_OK)
+ return status;
+
+ status = patch_process.InitBase(Region(base->Buffer(), base->Remaining()));
+ if (status != C_OK)
+ return status;
+
+ status = patch_process.ValidateBase();
+ if (status != C_OK)
+ return status;
+
+ // The rest of the patch stream is a StreamSet.
+ SourceStreamSet patch_streams;
+ patch_streams.Init(patch);
+
+ SourceStream* transformation_descriptions = patch_streams.stream(0);
+ SourceStream* parameter_correction = patch_streams.stream(1);
+ SourceStream* transformed_elements_correction = patch_streams.stream(2);
+ SourceStream* ensemble_correction = patch_streams.stream(3);
+
+ status = patch_process.ReadInitialParameters(transformation_descriptions);
+ if (status != C_OK)
+ return status;
+
+ SinkStreamSet predicted_parameters;
+ status = patch_process.PredictTransformParameters(&predicted_parameters);
+ if (status != C_OK)
+ return status;
+
+ SourceStreamSet corrected_parameters;
+ status = patch_process.SubpatchTransformParameters(&predicted_parameters,
+ parameter_correction,
+ &corrected_parameters);
+ if (status != C_OK)
+ return status;
+
+ SinkStreamSet transformed_elements;
+ status = patch_process.TransformUp(&corrected_parameters,
+ &transformed_elements);
+ if (status != C_OK)
+ return status;
+
+ SourceStreamSet corrected_transformed_elements;
+ status = patch_process.SubpatchTransformedElements(
+ &transformed_elements,
+ transformed_elements_correction,
+ &corrected_transformed_elements);
+ if (status != C_OK)
+ return status;
+
+ SinkStream original_ensemble_and_corrected_base_elements;
+ status = patch_process.TransformDown(
+ &corrected_transformed_elements,
+ &original_ensemble_and_corrected_base_elements);
+ if (status != C_OK)
+ return status;
+
+ SourceStream final_patch_prediction;
+ final_patch_prediction.Init(original_ensemble_and_corrected_base_elements);
+ status = patch_process.SubpatchFinalOutput(&final_patch_prediction,
+ ensemble_correction, output);
+ if (status != C_OK)
+ return status;
+
+ return C_OK;
+}
+
+Status ApplyEnsemblePatch(const wchar_t* old_file_name,
+ const wchar_t* patch_file_name,
+ const wchar_t* new_file_name) {
+ Status status;
+
+ // First read enough of the patch file to validate the header is well-formed.
+ // A few varint32 numbers should fit in 100.
+ FilePath patch_file_path(patch_file_name);
+ const int BIG_ENOUGH_FOR_HEADER = 100;
+ char buffer[BIG_ENOUGH_FOR_HEADER];
+ int read_count =
+ file_util::ReadFile(patch_file_path, buffer, sizeof(buffer));
+ if (read_count < 0)
+ return C_READ_OPEN_ERROR;
+
+ // 'Dry-run' the first step of the patch process to validate format of header.
+ SourceStream patch_header_stream;
+ patch_header_stream.Init(buffer, read_count);
+ EnsemblePatchApplication patch_process;
+ status = patch_process.ReadHeader(&patch_header_stream);
+ if (status != C_OK)
+ return status;
+
+ // Header smells good so read the whole patch file for real.
+ std::string patch_file_buffer;
+ if (!file_util::ReadFileToString(patch_file_path, &patch_file_buffer))
+ return C_READ_ERROR;
+
+ // Read the old_file.
+ FilePath old_file_path(old_file_name);
+ std::string old_file_buffer;
+ if (!file_util::ReadFileToString(old_file_path, &old_file_buffer))
+ return C_READ_ERROR;
+
+ // Apply patch on streams.
+ SourceStream old_source_stream;
+ SourceStream patch_source_stream;
+ old_source_stream.Init(old_file_buffer);
+ patch_source_stream.Init(patch_file_buffer);
+ SinkStream new_sink_stream;
+ status = ApplyEnsemblePatch(&old_source_stream, &patch_source_stream,
+ &new_sink_stream);
+
+ // Write the patched data to |new_file_name|.
+ FilePath new_file_path(new_file_name);
+ int written =
+ file_util::WriteFile(
+ new_file_path,
+ reinterpret_cast<const char*>(new_sink_stream.Buffer()),
+ new_sink_stream.Length());
+ if (written == -1)
+ return C_WRITE_OPEN_ERROR;
+ if (written != new_sink_stream.Length())
+ return C_WRITE_ERROR;
+
+ return C_OK;
+}
+
+} // namespace
« no previous file with comments | « third_party/courgette/ensemble.cc ('k') | third_party/courgette/ensemble_create.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698