<commit_before>// Copyright 2013 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Unit-tests for the jump table count client.

#include "syzygy/agent/jump_table_count/jump_table_count.h"

#include "gmock/gmock.h"
#include "gtest/gtest.h"

namespace agent {
namespace jump_table_count {

namespace {

const wchar_t kJumpTableCountClientDll[] = L"jump_table_count.dll";

// The test fixture for the jump table count agent.
class JumpTableCountTest : public testing::Test {
 public:
  JumpTableCountTest()
      : agent_module_(NULL) { }

  void LoadDll() {
    ASSERT_EQ(NULL, agent_module_);
    ASSERT_EQ(NULL, jump_table_case_counter_stub_);
    ASSERT_EQ(NULL, ::GetModuleHandle(kJumpTableCountClientDll));

    agent_module_ = ::LoadLibrary(kJumpTableCountClientDll);
    ASSERT_TRUE(agent_module_ != NULL);

    jump_table_case_counter_stub_ =
        ::GetProcAddress(agent_module_, "_jump_table_case_counter");
    ASSERT_TRUE(jump_table_case_counter_stub_ != NULL);

    indirect_penter_dllmain_stub_ =
        ::GetProcAddress(agent_module_, "_indirect_penter_dllmain");
    ASSERT_TRUE(indirect_penter_dllmain_stub_ != NULL);

    indirect_penter_exemain_stub_ =
        ::GetProcAddress(agent_module_, "_indirect_penter_exemain");
    ASSERT_TRUE(indirect_penter_exemain_stub_ != NULL);
  }

  void UnloadDll() {
    if (agent_module_ != NULL) {
      ASSERT_TRUE(::FreeLibrary(agent_module_));
      agent_module_ = NULL;
      jump_table_case_counter_stub_ = NULL;
      indirect_penter_dllmain_stub_ = NULL;
      indirect_penter_exemain_stub_ = NULL;
    }
  }

 protected:
  // The jump table count client module.
  HMODULE agent_module_;

  // The jump table case counter hook.
  static FARPROC jump_table_case_counter_stub_;

  // The DllMain entry stub.
  static FARPROC indirect_penter_dllmain_stub_;

  // The ExeMain entry stub.
  static FARPROC indirect_penter_exemain_stub_;
};

FARPROC JumpTableCountTest::jump_table_case_counter_stub_ = NULL;
FARPROC JumpTableCountTest::indirect_penter_dllmain_stub_ = NULL;
FARPROC JumpTableCountTest::indirect_penter_exemain_stub_ = NULL;

}  // namespace

TEST_F(JumpTableCountTest, LoadUnload) {
  ASSERT_NO_FATAL_FAILURE(LoadDll());
  ASSERT_NO_FATAL_FAILURE(UnloadDll());
}

}  // namespace jump_table_count
}  // namespace agent
<commit_msg>Fix a bug (rename jump_table_count.dll to jump_table_count_client.dll).<commit_after>// Copyright 2013 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Unit-tests for the jump table count client.

#include "syzygy/agent/jump_table_count/jump_table_count.h"

#include "gmock/gmock.h"
#include "gtest/gtest.h"

namespace agent {
namespace jump_table_count {

namespace {

const wchar_t kJumpTableCountClientDll[] = L"jump_table_count_client.dll";

// The test fixture for the jump table count agent.
class JumpTableCountTest : public testing::Test {
 public:
  JumpTableCountTest()
      : agent_module_(NULL) { }

  void LoadDll() {
    ASSERT_EQ(NULL, agent_module_);
    ASSERT_EQ(NULL, jump_table_case_counter_stub_);
    ASSERT_EQ(NULL, ::GetModuleHandle(kJumpTableCountClientDll));

    agent_module_ = ::LoadLibrary(kJumpTableCountClientDll);
    ASSERT_TRUE(agent_module_ != NULL);

    jump_table_case_counter_stub_ =
        ::GetProcAddress(agent_module_, "_jump_table_case_counter");
    ASSERT_TRUE(jump_table_case_counter_stub_ != NULL);

    indirect_penter_dllmain_stub_ =
        ::GetProcAddress(agent_module_, "_indirect_penter_dllmain");
    ASSERT_TRUE(indirect_penter_dllmain_stub_ != NULL);

    indirect_penter_exemain_stub_ =
        ::GetProcAddress(agent_module_, "_indirect_penter_exemain");
    ASSERT_TRUE(indirect_penter_exemain_stub_ != NULL);
  }

  void UnloadDll() {
    if (agent_module_ != NULL) {
      ASSERT_TRUE(::FreeLibrary(agent_module_));
      agent_module_ = NULL;
      jump_table_case_counter_stub_ = NULL;
      indirect_penter_dllmain_stub_ = NULL;
      indirect_penter_exemain_stub_ = NULL;
    }
  }

 protected:
  // The jump table count client module.
  HMODULE agent_module_;

  // The jump table case counter hook.
  static FARPROC jump_table_case_counter_stub_;

  // The DllMain entry stub.
  static FARPROC indirect_penter_dllmain_stub_;

  // The ExeMain entry stub.
  static FARPROC indirect_penter_exemain_stub_;
};

FARPROC JumpTableCountTest::jump_table_case_counter_stub_ = NULL;
FARPROC JumpTableCountTest::indirect_penter_dllmain_stub_ = NULL;
FARPROC JumpTableCountTest::indirect_penter_exemain_stub_ = NULL;

}  // namespace

TEST_F(JumpTableCountTest, LoadUnload) {
  ASSERT_NO_FATAL_FAILURE(LoadDll());
  ASSERT_NO_FATAL_FAILURE(UnloadDll());
}

}  // namespace jump_table_count
}  // namespace agent
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "iree/compiler/Dialect/HAL/Target/LLVM/LinkerTool.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/Support/FormatVariadic.h"

#define DEBUG_TYPE "llvmaot-linker"

namespace mlir {
namespace iree_compiler {
namespace IREE {
namespace HAL {

// Unix linker (ld-like); for ELF files.
class UnixLinkerTool : public LinkerTool {
 public:
  using LinkerTool::LinkerTool;

  std::string getToolPath() const override {
    auto toolPath = LinkerTool::getToolPath();
    if (!toolPath.empty()) return toolPath;

// Attempt to find a linker on the path. Ideally a user specifies the linker so
// they can match whatever they are building with.
//
// TODO(ataei): support discovery of linkers on Windows/etc; popen is
// linux-only. There may be infra in LLVM to do this kind of stuff in a
// cross-platform way.
#if !defined(WIN32)
#define UNIX_SYS_LINKER_PATH_LENGTH 255
    auto sysLinkers = {"ld", "ld.gold", "lld.ld"};
    for (auto syslinker : sysLinkers) {
      FILE *pipe =
          popen(llvm::Twine("which ").concat(syslinker).str().c_str(), "r");
      char linkerPath[UNIX_SYS_LINKER_PATH_LENGTH];
      if (fgets(linkerPath, sizeof(linkerPath), pipe) != NULL) {
        return strtok(linkerPath, "\n");
      }
    }
#undef UNIX_SYS_LINKER_PATH_LENGTH
#endif  // WIN32

    return toolPath;
  }

  LogicalResult configureModule(llvm::Module *llvmModule,
                                ArrayRef<StringRef> entryPointNames) override {
    for (auto &func : *llvmModule) {
      // Enable frame pointers to ensure that stack unwinding works.
      func.addFnAttr("frame-pointer", "all");

      // -ffreestanding-like behavior.
      func.addFnAttr("no-builtins");
    }

    // TODO(benvanik): switch to executable libraries w/ internal functions.
    for (auto entryPointName : entryPointNames) {
      auto *entryPointFn = llvmModule->getFunction(entryPointName);
      entryPointFn->setLinkage(
          llvm::GlobalValue::LinkageTypes::ExternalLinkage);
      entryPointFn->setVisibility(
          llvm::GlobalValue::VisibilityTypes::DefaultVisibility);
    }

    return success();
  }

  Optional<Artifacts> linkDynamicLibrary(
      StringRef libraryName, ArrayRef<Artifact> objectFiles) override {
    Artifacts artifacts;

    // Create the shared object name; if we only have a single input object we
    // can just reuse that.
    if (objectFiles.size() == 1) {
      artifacts.libraryFile =
          Artifact::createVariant(objectFiles.front().path, "so");
    } else {
      artifacts.libraryFile = Artifact::createTemporary(libraryName, "so");
    }
    artifacts.libraryFile.close();

    SmallVector<std::string, 8> flags = {
        getToolPath(),

        // Avoids including any libc/startup files that initialize the CRT as
        // we don't use any of that. Our shared libraries must be freestanding.
        "-nostdlib",  // -nodefaultlibs + -nostartfiles

        // Statically link all dependencies so we don't have any runtime deps.
        // We cannot have any imports in the module we produce.
        // "-static",

        // HACK: we insert mallocs and libm calls. This is *not good*.
        // We need hermetic binaries that pull in no imports; the MLIR LLVM
        // lowering paths introduce a bunch, though, so this is what we are
        // stuck with.
        "-shared",
        "-undefined suppress",

        "-o " + artifacts.libraryFile.path,
    };

    if (targetTriple.isOSDarwin() || targetTriple.isiOS()) {
      flags.push_back("-dylib");
      flags.push_back("-flat_namespace");
    }

    // Strip debug information (only, no relocations) when not requested.
    if (!targetOptions.debugSymbols) {
      flags.push_back("-Wl,--strip-debug");
    }

    // Link all input objects. Note that we are not linking whole-archive as
    // we want to allow dropping of unused codegen outputs.
    for (auto &objectFile : objectFiles) {
      flags.push_back(objectFile.path);
    }

    auto commandLine = llvm::join(flags, " ");
    if (failed(runLinkCommand(commandLine))) return llvm::None;
    return artifacts;
  }
};

std::unique_ptr<LinkerTool> createUnixLinkerTool(
    llvm::Triple &targetTriple, LLVMTargetOptions &targetOptions) {
  return std::make_unique<UnixLinkerTool>(targetTriple, targetOptions);
}

}  // namespace HAL
}  // namespace IREE
}  // namespace iree_compiler
}  // namespace mlir
<commit_msg>Check cwd for Unix linker tools before path. (#4753)<commit_after>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "iree/compiler/Dialect/HAL/Target/LLVM/LinkerTool.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/Process.h"

#define DEBUG_TYPE "llvmaot-linker"

namespace mlir {
namespace iree_compiler {
namespace IREE {
namespace HAL {

// Unix linker (ld-like); for ELF files.
class UnixLinkerTool : public LinkerTool {
 public:
  using LinkerTool::LinkerTool;

  std::string getToolPath() const override {
    // Ideally a user specifies the linker so they can match whatever they are
    // building with.
    auto toolPath = LinkerTool::getToolPath();
    if (!toolPath.empty()) return toolPath;

    // If no linker was specified, attempt to find one.
    auto sysLinkers = {"ld", "ld.gold", "ld.lld"};

    // First search the current directory.
    for (auto sysLinker : sysLinkers) {
      if (llvm::sys::fs::exists(sysLinker)) {
        llvm::SmallString<256> absolutePath(sysLinker);
        llvm::sys::fs::make_absolute(absolutePath);
        return std::string(absolutePath);
      }
    }

    // Next search the environment path.
    for (auto sysLinker : sysLinkers) {
      if (auto result = llvm::sys::Process::FindInEnvPath("PATH", sysLinker)) {
        return *result;
      }
    }

    llvm::errs() << "No Unix linker tool specified or discovered";
    return "";
  }

  LogicalResult configureModule(llvm::Module *llvmModule,
                                ArrayRef<StringRef> entryPointNames) override {
    for (auto &func : *llvmModule) {
      // Enable frame pointers to ensure that stack unwinding works.
      func.addFnAttr("frame-pointer", "all");

      // -ffreestanding-like behavior.
      func.addFnAttr("no-builtins");
    }

    // TODO(benvanik): switch to executable libraries w/ internal functions.
    for (auto entryPointName : entryPointNames) {
      auto *entryPointFn = llvmModule->getFunction(entryPointName);
      entryPointFn->setLinkage(
          llvm::GlobalValue::LinkageTypes::ExternalLinkage);
      entryPointFn->setVisibility(
          llvm::GlobalValue::VisibilityTypes::DefaultVisibility);
    }

    return success();
  }

  Optional<Artifacts> linkDynamicLibrary(
      StringRef libraryName, ArrayRef<Artifact> objectFiles) override {
    Artifacts artifacts;

    // Create the shared object name; if we only have a single input object we
    // can just reuse that.
    if (objectFiles.size() == 1) {
      artifacts.libraryFile =
          Artifact::createVariant(objectFiles.front().path, "so");
    } else {
      artifacts.libraryFile = Artifact::createTemporary(libraryName, "so");
    }
    artifacts.libraryFile.close();

    SmallVector<std::string, 8> flags = {
        getToolPath(),

        // Avoids including any libc/startup files that initialize the CRT as
        // we don't use any of that. Our shared libraries must be freestanding.
        "-nostdlib",  // -nodefaultlibs + -nostartfiles

        // Statically link all dependencies so we don't have any runtime deps.
        // We cannot have any imports in the module we produce.
        // "-static",

        // HACK: we insert mallocs and libm calls. This is *not good*.
        // We need hermetic binaries that pull in no imports; the MLIR LLVM
        // lowering paths introduce a bunch, though, so this is what we are
        // stuck with.
        "-shared",
        "-undefined suppress",

        "-o " + artifacts.libraryFile.path,
    };

    if (targetTriple.isOSDarwin() || targetTriple.isiOS()) {
      flags.push_back("-dylib");
      flags.push_back("-flat_namespace");
    }

    // Strip debug information (only, no relocations) when not requested.
    if (!targetOptions.debugSymbols) {
      flags.push_back("-Wl,--strip-debug");
    }

    // Link all input objects. Note that we are not linking whole-archive as
    // we want to allow dropping of unused codegen outputs.
    for (auto &objectFile : objectFiles) {
      flags.push_back(objectFile.path);
    }

    auto commandLine = llvm::join(flags, " ");
    if (failed(runLinkCommand(commandLine))) return llvm::None;
    return artifacts;
  }
};

std::unique_ptr<LinkerTool> createUnixLinkerTool(
    llvm::Triple &targetTriple, LLVMTargetOptions &targetOptions) {
  return std::make_unique<UnixLinkerTool>(targetTriple, targetOptions);
}

}  // namespace HAL
}  // namespace IREE
}  // namespace iree_compiler
}  // namespace mlir
<|endoftext|>


<commit_before>/* -*- mode: c++; indent-tabs-mode: nil; tab-width: 2 -*-
 *
 *  $Id: expr_test.cpp,v 1.1.1.1 2006/11/06 08:42:18 Paul Pedersen Exp $
 *
 *  Copyright 2006-2007 FLWOR FOundation.
 *
 *	Author: Paul Pedersen
 */

#include "expr.h"
#include "../context/context.h"
#include "../functions/signature.h"
#include "../functions/function.h"
#include "../parser/location.hh"
#include "../parser/symbol_table.h"
#include "../types/sequence_type.h"
#include "../errors/xqp_exception.h"

#include <iostream>

/*
...........................................
:                                         :
: expression tree unit test               :
:.........................................:
*/

using namespace std;
using namespace xqp;

typedef rchandle<expr> exprref_t;

int main(int argc, char* argv[])
{
	//typedef rchandle<expr> exprref_t;
	yy::location loc;
	context ctx;
	symbol_table symtab;

	uint32_t i1 = symtab.put("symbol1", 7);
	uint32_t i2 = symtab.put("symbol2", 7);
	uint32_t i3 = symtab.put("symbol3", 7);

	try {

		rchandle<qname_expr> qnv1_h = new qname_expr("var1");
		rchandle<qname_expr> qnv2_h = new qname_expr("var2");
		rchandle<qname_expr> qnv3_h = new qname_expr("var3");
		rchandle<qname_expr> qna1_h = new qname_expr("attr1");
		rchandle<qname_expr> qna2_h = new qname_expr("attr2");
		rchandle<qname_expr> qna3_h = new qname_expr("attr3");
		rchandle<qname_expr> qne1_h = new qname_expr("elem1");
		rchandle<qname_expr> qne2_h = new qname_expr("elem2");
		rchandle<qname_expr> qne3_h = new qname_expr("elem3");
		rchandle<qname_expr> qnf1_h = new qname_expr("func1");
		rchandle<qname_expr> qnp1_h = new qname_expr("prag1");
		rchandle<qname_expr> qnp2_h = new qname_expr("prag1");

	/*...........................................
		: literal expresions                      :
		:.........................................*/
		cout << "\n>>>literal_expr\n";
		rchandle<literal_expr> lit1_h = new literal_expr(loc, i1, true);
		rchandle<literal_expr> lit2_h = new literal_expr(loc, i2, true);
		rchandle<literal_expr> lit3_h = new literal_expr(loc, i3, true);
		rchandle<literal_expr> lit4_h = new literal_expr(loc, 123);
		rchandle<literal_expr> lit5_h = new literal_expr(loc, 123456);
		rchandle<literal_expr> lit6_h = new literal_expr(loc, 123.456);

		cout << "lit1 [" << literal_expr::decode_type(lit1_h->get_type()) << "] = ";
		lit1_h->put(cout,ctx) << " : " << symtab.get(lit1_h->get_sref()) << endl;
		cout << "lit2 [" << literal_expr::decode_type(lit2_h->get_type()) << "] = ";
		lit2_h->put(cout,ctx) << " : " << symtab.get(lit2_h->get_sref()) << endl;
		cout << "lit3 [" << literal_expr::decode_type(lit3_h->get_type()) << "] = ";
		lit3_h->put(cout,ctx) << " : " << symtab.get(lit3_h->get_sref()) << endl;

		cout << "lit4 [" << literal_expr::decode_type(lit4_h->get_type()) << "] = ";
		lit4_h->put(cout,ctx) << endl;
		cout << "lit5 [" << literal_expr::decode_type(lit5_h->get_type()) << "] = ";
		lit5_h->put(cout,ctx) << endl;
		cout << "lit6 [" << literal_expr::decode_type(lit6_h->get_type()) << "] = ";
		lit6_h->put(cout,ctx) << endl;

	/*...........................................
		: variables                               :
		:.........................................*/
		cout << "\n>>>var_expr\n";
		rchandle<var_expr> var1_h = new var_expr(loc);
	  var1_h->set_varname(&*qnv1_h);
	  var1_h->set_valexpr(&*lit1_h);
		var1_h->set_kind(var_expr::for_var);
	  var1_h->set_type(xs_untypedAtomicValue);

		rchandle<var_expr> var2_h = new var_expr(loc);
	  var2_h->set_varname(&*qnv2_h);
	  var2_h->set_valexpr(&*lit1_h);
		var2_h->set_kind(var_expr::let_var);
	  var2_h->set_type(xs_untypedAtomicValue);

		rchandle<var_expr> var3_h = new var_expr(loc);
	  var3_h->set_varname(&*qnv3_h);
	  var3_h->set_valexpr(&*lit1_h);
		var3_h->set_kind(var_expr::pos_var);
	  var3_h->set_type(xs_untypedAtomicValue);

		var1_h->put(cout,ctx) << endl;
		var2_h->put(cout,ctx) << endl;
		var3_h->put(cout,ctx) << endl;

	/*...........................................
		: expression list                         :
		:.........................................*/
		cout << "\n>>>expr_list\n";
		rchandle<expr_list> exlist1_h = new expr_list(loc);
		exlist1_h->add(&*var1_h);
		exlist1_h->add(&*var2_h);
		exlist1_h->add(&*var3_h);
		exlist1_h->put(cout,ctx);

	/*...........................................
		: constructors                            :
		:.........................................*/
		cout << "\n>>>text_expr\n";
		rchandle<text_expr> text1_h = new text_expr(loc, &*lit4_h);
		rchandle<text_expr> text2_h = new text_expr(loc, &*lit5_h);
		rchandle<text_expr> text3_h = new text_expr(loc, &*lit6_h);

		text1_h->put(cout,ctx) << endl;
		text2_h->put(cout,ctx) << endl;
		text3_h->put(cout,ctx) << endl;

		cout << "\n>>>comment_expr\n";
		rchandle<comment_expr> comment1_h = new comment_expr(loc, &*lit1_h);
		rchandle<comment_expr> comment2_h = new comment_expr(loc, &*lit2_h);
		rchandle<comment_expr> comment3_h = new comment_expr(loc, &*lit3_h);

		comment1_h->put(cout,ctx) << endl;
		comment2_h->put(cout,ctx) << endl;
		comment3_h->put(cout,ctx) << endl;

		cout << "\n>>>pi_expr\n";
		rchandle<pi_expr> pi1_h = new pi_expr(loc, "?PI1", &*lit1_h);
		rchandle<pi_expr> pi2_h = new pi_expr(loc, "?PI2", &*lit2_h);
		rchandle<pi_expr> pi3_h = new pi_expr(loc, "?PI3", &*lit3_h);

		pi1_h->put(cout,ctx) << endl;
		pi2_h->put(cout,ctx) << endl;
		pi3_h->put(cout,ctx) << endl;

		cout << "\n>>>attr_expr\n";
		rchandle<attr_expr> attr1_h = new attr_expr(loc, &*qna1_h, &*lit1_h);
		rchandle<attr_expr> attr2_h = new attr_expr(loc, &*qna2_h, &*lit2_h);
		rchandle<attr_expr> attr3_h = new attr_expr(loc, &*qna3_h, &*lit3_h);

		attr1_h->put(cout,ctx) << endl;
		attr2_h->put(cout,ctx) << endl;
		attr3_h->put(cout,ctx) << endl;

		rchandle<expr_list> exprlist2_h = new expr_list(loc);
		exprlist2_h->add(&*attr1_h);
		exprlist2_h->add(&*attr2_h);
		exprlist2_h->add(&*attr3_h);
		exprlist2_h->add(&*text1_h);
		exprlist2_h->add(&*text2_h);
		exprlist2_h->add(&*text3_h);

		cout << "\n>>>elem_expr\n";
		rchandle<elem_expr> elem1_h = new elem_expr(loc, &*qne1_h, &*exprlist2_h);
		elem_expr::nsbinding ns1("pre1","http://a1.b1.c1");
		elem_expr::nsbinding ns2("pre2","http://a2.b2.c2");
		elem1_h->add(ns1);
		elem1_h->add(ns2);
		elem1_h->put(cout,ctx) << endl;

		rchandle<elem_expr> elem2_h = new elem_expr(loc, &*qne2_h, &*exprlist2_h);
		elem2_h->add(ns1);
		elem2_h->add(ns2);
		elem2_h->put(cout,ctx) << endl;

		cout << "\n>>>doc_expr\n";
		rchandle<doc_expr> doc1_h = new doc_expr(loc, &*elem1_h);
		doc1_h->put(cout,ctx) << endl;

	/*...........................................
		: function call                           :
		:.........................................*/
		cout << "\n>>>funcall_expr\n";
		rchandle<funcall_expr> fun1_h = new funcall_expr(loc, &*qnf1_h);
		fun1_h->add_arg(&*lit1_h);
		fun1_h->add_arg(&*lit2_h);
		fun1_h->add_arg(&*lit3_h);
		fun1_h->put(cout,ctx) << endl;
		for (unsigned i=0; i<fun1_h->arg_count(); ++i) {
			cout << "arg[" << i << "] = ";
			(*fun1_h)[i]->put(cout,ctx) << endl;
		}

	/*...........................................
		: typeswitch expression                   :
		:.........................................*/
		cout << "\n>>>typeswitch_expr\n";
		rchandle<typeswitch_expr> sw1_h = new typeswitch_expr(loc);
		sw1_h->set_switch_expr(&*elem1_h);
		sw1_h->set_default_varname(&*var1_h);
		sw1_h->set_default_clause(&*elem1_h);

		case_clause cc1;
		cc1.var_h = var2_h;
		cc1.case_expr_h = &*lit1_h;
		cc1.type = xs_anyTypeSeq;
		sw1_h->add_clause(&cc1);

		case_clause cc2;
		cc2.var_h = var3_h;
		cc2.case_expr_h = &*lit2_h;
		cc2.type = xs_anyTypeSeq;
		sw1_h->add_clause(&cc2);
		sw1_h->put(cout,ctx);

	/*...........................................
		: conditional expression                  :
		:.........................................*/
		cout << "\n>>>if_expr\n";
		rchandle<if_expr> if1_h = new if_expr(loc, &*lit1_h, &*lit2_h, &*lit3_h);
		if1_h->put(cout,ctx);

	/*...........................................
		: cast-related expressions                :
		:.........................................*/
		cout << "\n>>>instanceof_expr\n";
		rchandle<instanceof_expr> inst1_h =
			new instanceof_expr(loc,&*lit4_h,xs_anyType);
		inst1_h->put(cout,ctx) << endl;

		cout << "\n>>>treat_expr\n";
		rchandle<treat_expr> treat1_h =
			new treat_expr(loc, &*lit5_h, xs_int);
		treat1_h->put(cout,ctx) << endl;

		cout << "\n>>>castable_expr\n";
		rchandle<castable_expr> castable1_h =
			new castable_expr(loc, &*lit6_h, xs_untypedAtomicValue);
		castable1_h->put(cout,ctx) << endl;

		cout << "\n>>>cast_expr\n";
		rchandle<cast_expr> cast1_h =
			new cast_expr(loc, &*lit1_h, xs_untypedAtomicValue);
		cast1_h->put(cout,ctx) << endl;

	/*...........................................
		: validate expression                     :
		:.........................................*/
		cout << "\n>>>validate_expr\n";
		rchandle<validate_expr> val1_h =
			new validate_expr(loc, val_strict, &*elem1_h);
		val1_h->put(cout,ctx) << endl;

	/*...........................................
		: extension expressions                   :
		:.........................................*/
		/*
		cout << "\n>>>extension_expr\n";
		rchandle<extension_expr> ext1_h =
			new extension_expr(loc,&*lit1_h);
		rchandle<pragma> prag1_h = new pragma(&*qnp1_h, "content1");
		ext1_h->add(prag1_h);
		ext1_h->put(cout,ctx) << endl;
		*/

	/*...........................................
		: path expressions                        :
		:.........................................*/
		cout << "\n>>>axis_step_expr\n";
		rchandle<axis_step_expr> ax1_h = new axis_step_expr(loc);
		ax1_h->set_axis(axis_step_expr::child);
		ax1_h->set_test(axis_step_expr::name_test);
		ax1_h->set_name(&*qne1_h);
		ax1_h->add_pred(&*elem1_h);
		ax1_h->put(cout,ctx) << endl;

		rchandle<axis_step_expr> ax2_h = new axis_step_expr(loc);
		ax2_h->set_axis(axis_step_expr::child);
		ax2_h->set_test(axis_step_expr::name_test);
		ax2_h->set_name(&*qne2_h);
		ax2_h->add_pred(&*elem2_h);
		ax2_h->put(cout,ctx) << endl;

		rchandle<relpath_expr> path1_h = new relpath_expr(loc);
		path1_h->add_back(&*ax1_h);
		path1_h->add_back(&*ax2_h);
		path1_h->put(cout,ctx) << endl;

	/*...........................................
		: quantified expressions                  :
		:.........................................*/
		cout << "\n>>>quantified_expr\n";
		rchandle<quantified_expr> quant1_h =
			new quantified_expr(loc,quant_some);
		quant1_h->add(&*var1_h);
		quant1_h->set_sat_expr(&*elem1_h);
		quant1_h->put(cout,ctx) << endl;

		rchandle<quantified_expr> quant2_h =
			new quantified_expr(loc,quant_some);
		quant2_h->add(&*var2_h);
		quant2_h->set_sat_expr(&*elem2_h);
		quant2_h->put(cout,ctx) << endl;

	/*...........................................
		: FO expressions                          :
		:.........................................*/
		cout << "\n>>>fo_expr\n";
		rchandle<signature> sig1_h = new signature(&ctx,"func1",anyNodeSeq);
		sig1_h->add_arg(anyNodeSeq);
		sig1_h->add_arg(anyNodeSeq);
		function func1(*sig1_h);
		rchandle<fo_expr> fo1_h = new fo_expr(loc);
		fo1_h->add(&*lit1_h);
		fo1_h->add(&*lit2_h);
		fo1_h->set_func(&func1);
		fo1_h->put(cout,ctx) << endl;

	/*...........................................
		: FLWOR expressions                       :
		:.........................................*/
		cout << "\n>>>flwor_expr\n";
		rchandle<flwor_expr> flwor1_h = new flwor_expr(loc);
		rchandle<forlet_clause> flc1_h =
			new forlet_clause(forlet_clause::for_clause,&*var1_h,NULL,NULL,&*elem1_h);
		rchandle<forlet_clause> flc2_h =
			new forlet_clause(forlet_clause::let_clause,&*var2_h,NULL,NULL,&*elem2_h);
		flwor1_h->add(&*flc1_h);
		flwor1_h->add(&*flc2_h);
		flwor1_h->set_where(&*var1_h);
		flwor1_h->set_retval(&*var2_h);
		flwor1_h->put(cout,ctx) << endl;

	} catch (null_pointer& e) {
		cout << "Application exception: " << e.get_msg() << endl;
	} catch (xqp_exception& e) {
		cout << "Application exception: " << e.get_msg() << endl;
	} catch (exception& e) {
		cout << "C++ exception: " << e.what() << endl;
	} catch (...) {
		cout << "unrecognized exception" << endl;
	}

};

/*
class ft_contains_expr : public expr
	ft_contains_expr(loc, ctx, exprref_t, exprref_t, exprref_t);
	exprref_t get_range() const { return range_h; }
	exprref_t get_ft_select() const { return ft_select_h; }
	exprref_t get_ignore() const { return ft_ignore_h; }
	virtual std::ostream& put(std::ostream&, ctx) const;
};

class unary_expr : public expr
	unary_expr(loc, ctx, bool neg_b, exprref_t);
	bool is_negative() const { return neg_b; }
	exprref_t get_expr() const { return expr_h; }
	virtual std::ostream& put(std::ostream&,ctx) const;
};

class order_expr : public expr
	enum order_type_t { ordered, unordered };
	order_expr(loc, ctx, order_type_t, exprref_t);
	order_type_t get_type() const { return type; }
	exprref_t get_expr() const { return expr_h; }
	std::ostream& put(std::ostream&, ctx) const;
};
*/

<commit_msg>moved file into src/compiler/expression<commit_after><|endoftext|>


<commit_before><commit_msg>INTEGRATION: CWS sj17 (1.50.22); FILE MERGED 2005/03/21 10:55:54 sj 1.50.22.1: #i37687# now using only one slot id for font work shape types<commit_after><|endoftext|>


<commit_before>#include <SDL2/SDL.h>
#include <engine/input/include/InputController.h>
#include "game/include/Game.h"
#include "engine/input/include/Keyboard.h"
#include "globals.h"
#include "engine/2d_map/include/Map.h"

Game::Game() {
    SDL_Init(SDL_INIT_EVERYTHING);
    this->_eventsManager = new EventsManager();

    this->gameLoop();
}

Game::~Game() {

}

void Game::gameLoop() {
    Graphics graphics = Graphics("Game", globals::SCREEN_WIDTH, globals::SCREEN_HEIGHT);
    Keyboard input;
    SDL_Event event;

    InputController *inputController = new InputController();

    _map = new Map(graphics);
    _map->loadFromJSON("resources/maps", "test.json");

    _player = new Player(graphics, inputController, 0);
    _player->setPosition(120, 200);

    long time_accumulator = 0;
    float game_speed = 1.0f;

    while (true) {
        auto start_time = SDL_GetTicks();

        input.beginNewFrame();

        if (SDL_PollEvent(&event)) {
            if (event.type == SDL_KEYDOWN) {
                if (event.key.repeat == 0) {
                    input.keyDownEvent(event);
                }
            }// if a key was released
            else if (event.type == SDL_KEYUP) {
                input.keyUpEvent(event);
            }//if the user hits the exit button
            else if (event.type == SDL_QUIT) {
                return;
            } else {
                _eventsManager->add_frame_event(event);
            }
        }

        inputController->process_frame_events(_eventsManager->get_frame_events());

        if (input.wasKeyPressed(SDL_SCANCODE_ESCAPE)) {
            return;
        }

        this->update(game_speed);

        long elapsed_time = SDL_GetTicks() - start_time;
        time_accumulator += elapsed_time;
        game_speed = elapsed_time / float(globals::FRAME_TIME);

        if (time_accumulator >= globals::FRAME_TIME) {
            time_accumulator = 0;
            this->draw(graphics);
        }

        this->_eventsManager->clear_events();
    }
}

void Game::draw(Graphics &graphics) {
    graphics.clear(40, 150, 70, 255);
    _map->draw();

    SDL_SetRenderDrawColor(graphics.getRenderer(), 0,0,0,255);
//    SDL_RenderDrawLine(graphics.getRenderer(), 0, 200, 500, 200);
//    SDL_RenderDrawLine(graphics.getRenderer(), 120, 0, 120, 200);

    _player->draw(graphics);

    graphics.flip();
}

static int pos = 0;

void Game::update(float game_speed) {
    _map->setOffset({pos++/1000,0});

    _player->handleInput(game_speed);
    _player->update(game_speed);
}

<commit_msg>Changes to the loop timing<commit_after>#include <SDL2/SDL.h>
#include <engine/input/include/InputController.h>
#include "game/include/Game.h"
#include "engine/input/include/Keyboard.h"
#include "globals.h"
#include "engine/2d_map/include/Map.h"

Game::Game() {
    SDL_Init(SDL_INIT_EVERYTHING);
    this->_eventsManager = new EventsManager();

    this->gameLoop();
}

Game::~Game() {

}

void Game::gameLoop() {
    Graphics graphics = Graphics("Game", globals::SCREEN_WIDTH, globals::SCREEN_HEIGHT);
    Keyboard input;
    SDL_Event event;

    InputController *inputController = new InputController();

    _map = new Map(graphics);
    _map->loadFromJSON("resources/maps", "test.json");

    _player = new Player(graphics, inputController, 0);
    _player->setPosition(120, 200);

    long time_accumulator = 0;
    float game_speed = 1.0f;

    long prev_time = SDL_GetTicks();
    while (true) {
        input.beginNewFrame();

        if (SDL_PollEvent(&event)) {
            if (event.type == SDL_KEYDOWN) {
                if (event.key.repeat == 0) {
                    input.keyDownEvent(event);
                }
            }// if a key was released
            else if (event.type == SDL_KEYUP) {
                input.keyUpEvent(event);
            }//if the user hits the exit button
            else if (event.type == SDL_QUIT) {
                return;
            } else {
                _eventsManager->add_frame_event(event);
            }
        }

        inputController->process_frame_events(_eventsManager->get_frame_events());

        if (input.wasKeyPressed(SDL_SCANCODE_ESCAPE)) {
            return;
        }

        long elapsed_time = SDL_GetTicks() - prev_time;
//        time_accumulator += elapsed_time;
        if (elapsed_time >= globals::FRAME_TIME) {
            game_speed = elapsed_time / float(globals::FRAME_TIME);
            SDL_Log("elapsed:%d speed:%f", elapsed_time, game_speed);
//            time_accumulator -= globals::FRAME_TIME;
            this->update(game_speed);
            this->draw(graphics);
            this->_eventsManager->clear_events();
            prev_time = SDL_GetTicks();
        }
    }
}

void Game::draw(Graphics &graphics) {
    graphics.clear(40, 150, 70, 255);
    _map->draw();

    SDL_SetRenderDrawColor(graphics.getRenderer(), 0,0,0,255);
//    SDL_RenderDrawLine(graphics.getRenderer(), 0, 200, 500, 200);
//    SDL_RenderDrawLine(graphics.getRenderer(), 120, 0, 120, 200);

    _player->draw(graphics);

    graphics.flip();
}

static int pos = 0;

void Game::update(float game_speed) {
    pos += 1 * game_speed;
    _map->setOffset({pos,0});

    _player->handleInput(game_speed);
    _player->update(game_speed);
}

<|endoftext|>


<commit_before><commit_msg>wdr-test: simple cmdline cover wdr feature<commit_after><|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: APNDataObject.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2004-10-22 07:55:39 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

//------------------------------------------------------------------------
// includes
//------------------------------------------------------------------------

#ifndef _APNDATAOBJECT_HXX_
#include "APNDataObject.hxx"
#endif

#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif

#include <systools/win32/comtools.hxx>

//------------------------------------------------------------------------
// defines
//------------------------------------------------------------------------

#define FREE_HGLOB_ON_RELEASE   TRUE
#define KEEP_HGLOB_ON_RELEASE   FALSE

//------------------------------------------------------------------------
// ctor
//------------------------------------------------------------------------

CAPNDataObject::CAPNDataObject( IDataObjectPtr rIDataObject ) :
    m_rIDataObjectOrg( rIDataObject ),
    m_hGlobal( NULL ),
    m_nRefCnt( 0 )
{

    OSL_ENSURE( m_rIDataObjectOrg.get( ), "constructing CAPNDataObject with empty data object" );

    // we marshal the IDataObject interface pointer here so
    // that it can be unmarshaled multiple times when this
    // class will be used from another apartment
    IStreamPtr pStm;
    HRESULT hr = CreateStreamOnHGlobal( 0, KEEP_HGLOB_ON_RELEASE, &pStm );

    OSL_ENSURE( E_INVALIDARG != hr, "invalid args passed to CreateStreamOnHGlobal" );

    if ( SUCCEEDED( hr ) )
    {
        HRESULT hr_marshal = CoMarshalInterface(
            pStm.get(),
            __uuidof(IDataObject),
            static_cast<LPUNKNOWN>(m_rIDataObjectOrg.get()),
            MSHCTX_LOCAL,
            NULL,
            MSHLFLAGS_TABLEWEAK );

        OSL_ENSURE( CO_E_NOTINITIALIZED != hr_marshal, "COM is not initialized" );

        // marshalling may fail if COM is not initialized
        // for the calling thread which is a program time
        // error or because of stream errors which are runtime
        // errors for instance E_OUTOFMEMORY etc.

        hr = GetHGlobalFromStream(pStm.get(), &m_hGlobal );

        OSL_ENSURE( E_INVALIDARG != hr, "invalid stream passed to GetHGlobalFromStream" );

        // if the marshalling failed we free the
        // global memory again and set m_hGlobal
        // to a defined value
        if (FAILED(hr_marshal))
        {
            OSL_ENSURE(sal_False, "marshalling failed");

            HGLOBAL hGlobal = GlobalFree(m_hGlobal);
            OSL_ENSURE(NULL == hGlobal, "GlobalFree failed");
            m_hGlobal = NULL;
        }
    }
}

CAPNDataObject::~CAPNDataObject( )
{
    if (m_hGlobal)
    {
        IStreamPtr pStm;
        HRESULT  hr = CreateStreamOnHGlobal(m_hGlobal, FREE_HGLOB_ON_RELEASE, &pStm);

        OSL_ENSURE( E_INVALIDARG != hr, "invalid args passed to CreateStreamOnHGlobal" );

        if (SUCCEEDED(hr))
        {
            hr = CoReleaseMarshalData(pStm.get());
            OSL_ENSURE(SUCCEEDED(hr), "CoReleaseMarshalData failed");
        }
    }
}

//------------------------------------------------------------------------
// IUnknown->QueryInterface
//------------------------------------------------------------------------

STDMETHODIMP CAPNDataObject::QueryInterface( REFIID iid, LPVOID* ppvObject )
{
    OSL_ASSERT( NULL != ppvObject );

    if ( NULL == ppvObject )
        return E_INVALIDARG;

    HRESULT hr = E_NOINTERFACE;
    *ppvObject = NULL;

    if ( ( __uuidof( IUnknown ) == iid ) || ( __uuidof( IDataObject ) == iid ) )
    {
        *ppvObject = static_cast< IUnknown* >( this );
        ( (LPUNKNOWN)*ppvObject )->AddRef( );
        hr = S_OK;
    }

    return hr;
}

//------------------------------------------------------------------------
// IUnknown->AddRef
//------------------------------------------------------------------------

STDMETHODIMP_(ULONG) CAPNDataObject::AddRef( )
{
    return static_cast< ULONG >( InterlockedIncrement( &m_nRefCnt ) );
}

//------------------------------------------------------------------------
// IUnknown->Release
//------------------------------------------------------------------------

STDMETHODIMP_(ULONG) CAPNDataObject::Release( )
{
    // we need a helper variable because it's not allowed to access
    // a member variable after an object is destroyed
    ULONG nRefCnt = static_cast< ULONG >( InterlockedDecrement( &m_nRefCnt ) );

    if ( 0 == nRefCnt )
        delete this;

    return nRefCnt;
}

//------------------------------------------------------------------------
// IDataObject->GetData
//------------------------------------------------------------------------

STDMETHODIMP CAPNDataObject::GetData( LPFORMATETC pFormatetc, LPSTGMEDIUM pmedium )
{
    HRESULT hr = m_rIDataObjectOrg->GetData( pFormatetc, pmedium );

    if (RPC_E_WRONG_THREAD == hr)
    {
        IDataObjectPtr pIDOTmp;
        hr = MarshalIDataObjectIntoCurrentApartment(&pIDOTmp);

        if (SUCCEEDED(hr))
            hr = pIDOTmp->GetData(pFormatetc, pmedium);
    }
    return hr;
}

//------------------------------------------------------------------------
// IDataObject->EnumFormatEtc
//------------------------------------------------------------------------

STDMETHODIMP CAPNDataObject::EnumFormatEtc( DWORD dwDirection, IEnumFORMATETC** ppenumFormatetc )
{
    HRESULT hr = m_rIDataObjectOrg->EnumFormatEtc(dwDirection, ppenumFormatetc);

    if (RPC_E_WRONG_THREAD == hr)
    {
        IDataObjectPtr pIDOTmp;
        hr = MarshalIDataObjectIntoCurrentApartment(&pIDOTmp);

        if (SUCCEEDED(hr))
            hr = pIDOTmp->EnumFormatEtc(dwDirection, ppenumFormatetc);
    }
    return hr;
}

//------------------------------------------------------------------------
// IDataObject->QueryGetData
//------------------------------------------------------------------------

STDMETHODIMP CAPNDataObject::QueryGetData( LPFORMATETC pFormatetc )
{
    HRESULT hr = m_rIDataObjectOrg->QueryGetData( pFormatetc );

    if (RPC_E_WRONG_THREAD == hr)
    {
        IDataObjectPtr pIDOTmp;
        hr = MarshalIDataObjectIntoCurrentApartment( &pIDOTmp );

        if (SUCCEEDED(hr))
            hr = pIDOTmp->QueryGetData(pFormatetc);
    }
    return hr;
}

//------------------------------------------------------------------------
// IDataObject->GetDataHere
//------------------------------------------------------------------------

STDMETHODIMP CAPNDataObject::GetDataHere( LPFORMATETC pFormatetc, LPSTGMEDIUM pmedium )
{
    HRESULT hr = m_rIDataObjectOrg->GetDataHere(pFormatetc, pmedium);

    if (RPC_E_WRONG_THREAD == hr)
    {
        IDataObjectPtr pIDOTmp;
        hr = MarshalIDataObjectIntoCurrentApartment(&pIDOTmp);

        if (SUCCEEDED(hr))
            hr = pIDOTmp->GetDataHere(pFormatetc, pmedium);
    }
    return hr;
}

//------------------------------------------------------------------------
// IDataObject->GetCanonicalFormatEtc
//------------------------------------------------------------------------

STDMETHODIMP CAPNDataObject::GetCanonicalFormatEtc(LPFORMATETC pFormatectIn, LPFORMATETC pFormatetcOut)
{
    HRESULT hr = m_rIDataObjectOrg->GetCanonicalFormatEtc( pFormatectIn, pFormatetcOut );

    if (RPC_E_WRONG_THREAD == hr)
    {
        IDataObjectPtr pIDOTmp;
        hr = MarshalIDataObjectIntoCurrentApartment(&pIDOTmp);

        if (SUCCEEDED(hr))
            hr = pIDOTmp->GetCanonicalFormatEtc(pFormatectIn, pFormatetcOut);
    }
    return hr;
}

//------------------------------------------------------------------------
// IDataObject->SetData
//------------------------------------------------------------------------

STDMETHODIMP CAPNDataObject::SetData( LPFORMATETC pFormatetc, LPSTGMEDIUM pmedium, BOOL fRelease )
{
    HRESULT hr = m_rIDataObjectOrg->SetData( pFormatetc, pmedium, fRelease );

    if (RPC_E_WRONG_THREAD == hr)
    {
        IDataObjectPtr pIDOTmp;
        hr = MarshalIDataObjectIntoCurrentApartment(&pIDOTmp);

        if (SUCCEEDED(hr))
            hr = pIDOTmp->SetData(pFormatetc, pmedium, fRelease);
    }
    return hr;
}

//------------------------------------------------------------------------
// IDataObject->DAdvise
//------------------------------------------------------------------------

STDMETHODIMP CAPNDataObject::DAdvise( LPFORMATETC pFormatetc, DWORD advf, LPADVISESINK pAdvSink, DWORD * pdwConnection )
{
    HRESULT hr = m_rIDataObjectOrg->DAdvise(pFormatetc, advf, pAdvSink, pdwConnection);

    if (RPC_E_WRONG_THREAD == hr)
    {
        IDataObjectPtr pIDOTmp;
        hr = MarshalIDataObjectIntoCurrentApartment(&pIDOTmp);

        if (SUCCEEDED(hr))
            hr = pIDOTmp->DAdvise(pFormatetc, advf, pAdvSink, pdwConnection);
    }
    return hr;
}

//------------------------------------------------------------------------
// IDataObject->DUnadvise
//------------------------------------------------------------------------

STDMETHODIMP CAPNDataObject::DUnadvise( DWORD dwConnection )
{
    HRESULT hr = m_rIDataObjectOrg->DUnadvise( dwConnection );

    if (RPC_E_WRONG_THREAD == hr)
    {
        IDataObjectPtr pIDOTmp;
        hr = MarshalIDataObjectIntoCurrentApartment(&pIDOTmp);

        if (SUCCEEDED(hr))
            hr = pIDOTmp->DUnadvise(dwConnection);
    }
    return hr;
}

//------------------------------------------------------------------------
// IDataObject->EnumDAdvise
//------------------------------------------------------------------------

STDMETHODIMP CAPNDataObject::EnumDAdvise( LPENUMSTATDATA * ppenumAdvise )
{
    HRESULT hr = m_rIDataObjectOrg->EnumDAdvise(ppenumAdvise);

    if (RPC_E_WRONG_THREAD == hr)
    {
        IDataObjectPtr pIDOTmp;
        hr = MarshalIDataObjectIntoCurrentApartment(&pIDOTmp);

        if (SUCCEEDED(hr))
            hr = pIDOTmp->EnumDAdvise(ppenumAdvise);
    }
    return hr;
}

//------------------------------------------------------------------------
// for our convenience
//------------------------------------------------------------------------

CAPNDataObject::operator IDataObject*( )
{
    return static_cast< IDataObject* >( this );
}

//------------------------------------------------------------------------
// helper function
//------------------------------------------------------------------------

HRESULT CAPNDataObject::MarshalIDataObjectIntoCurrentApartment( IDataObject** ppIDataObj )
{
    OSL_ASSERT(NULL != ppIDataObj);

    *ppIDataObj = NULL;
    HRESULT hr = E_FAIL;

    if (m_hGlobal)
    {
        IStreamPtr pStm;
        hr = CreateStreamOnHGlobal(m_hGlobal, KEEP_HGLOB_ON_RELEASE, &pStm);

        OSL_ENSURE(E_INVALIDARG != hr, "CreateStreamOnHGlobal with invalid args called");

        if (SUCCEEDED(hr))
        {
            hr = CoUnmarshalInterface(pStm.get(), __uuidof(IDataObject), (void**)ppIDataObj);
            OSL_ENSURE(CO_E_NOTINITIALIZED != hr, "COM is not initialized");
        }
    }
    return hr;
}
<commit_msg>INTEGRATION: CWS ooo19126 (1.4.12); FILE MERGED 2005/09/05 18:48:22 rt 1.4.12.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: APNDataObject.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 18:21:07 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

//------------------------------------------------------------------------
// includes
//------------------------------------------------------------------------

#ifndef _APNDATAOBJECT_HXX_
#include "APNDataObject.hxx"
#endif

#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif

#include <systools/win32/comtools.hxx>

//------------------------------------------------------------------------
// defines
//------------------------------------------------------------------------

#define FREE_HGLOB_ON_RELEASE   TRUE
#define KEEP_HGLOB_ON_RELEASE   FALSE

//------------------------------------------------------------------------
// ctor
//------------------------------------------------------------------------

CAPNDataObject::CAPNDataObject( IDataObjectPtr rIDataObject ) :
    m_rIDataObjectOrg( rIDataObject ),
    m_hGlobal( NULL ),
    m_nRefCnt( 0 )
{

    OSL_ENSURE( m_rIDataObjectOrg.get( ), "constructing CAPNDataObject with empty data object" );

    // we marshal the IDataObject interface pointer here so
    // that it can be unmarshaled multiple times when this
    // class will be used from another apartment
    IStreamPtr pStm;
    HRESULT hr = CreateStreamOnHGlobal( 0, KEEP_HGLOB_ON_RELEASE, &pStm );

    OSL_ENSURE( E_INVALIDARG != hr, "invalid args passed to CreateStreamOnHGlobal" );

    if ( SUCCEEDED( hr ) )
    {
        HRESULT hr_marshal = CoMarshalInterface(
            pStm.get(),
            __uuidof(IDataObject),
            static_cast<LPUNKNOWN>(m_rIDataObjectOrg.get()),
            MSHCTX_LOCAL,
            NULL,
            MSHLFLAGS_TABLEWEAK );

        OSL_ENSURE( CO_E_NOTINITIALIZED != hr_marshal, "COM is not initialized" );

        // marshalling may fail if COM is not initialized
        // for the calling thread which is a program time
        // error or because of stream errors which are runtime
        // errors for instance E_OUTOFMEMORY etc.

        hr = GetHGlobalFromStream(pStm.get(), &m_hGlobal );

        OSL_ENSURE( E_INVALIDARG != hr, "invalid stream passed to GetHGlobalFromStream" );

        // if the marshalling failed we free the
        // global memory again and set m_hGlobal
        // to a defined value
        if (FAILED(hr_marshal))
        {
            OSL_ENSURE(sal_False, "marshalling failed");

            HGLOBAL hGlobal = GlobalFree(m_hGlobal);
            OSL_ENSURE(NULL == hGlobal, "GlobalFree failed");
            m_hGlobal = NULL;
        }
    }
}

CAPNDataObject::~CAPNDataObject( )
{
    if (m_hGlobal)
    {
        IStreamPtr pStm;
        HRESULT  hr = CreateStreamOnHGlobal(m_hGlobal, FREE_HGLOB_ON_RELEASE, &pStm);

        OSL_ENSURE( E_INVALIDARG != hr, "invalid args passed to CreateStreamOnHGlobal" );

        if (SUCCEEDED(hr))
        {
            hr = CoReleaseMarshalData(pStm.get());
            OSL_ENSURE(SUCCEEDED(hr), "CoReleaseMarshalData failed");
        }
    }
}

//------------------------------------------------------------------------
// IUnknown->QueryInterface
//------------------------------------------------------------------------

STDMETHODIMP CAPNDataObject::QueryInterface( REFIID iid, LPVOID* ppvObject )
{
    OSL_ASSERT( NULL != ppvObject );

    if ( NULL == ppvObject )
        return E_INVALIDARG;

    HRESULT hr = E_NOINTERFACE;
    *ppvObject = NULL;

    if ( ( __uuidof( IUnknown ) == iid ) || ( __uuidof( IDataObject ) == iid ) )
    {
        *ppvObject = static_cast< IUnknown* >( this );
        ( (LPUNKNOWN)*ppvObject )->AddRef( );
        hr = S_OK;
    }

    return hr;
}

//------------------------------------------------------------------------
// IUnknown->AddRef
//------------------------------------------------------------------------

STDMETHODIMP_(ULONG) CAPNDataObject::AddRef( )
{
    return static_cast< ULONG >( InterlockedIncrement( &m_nRefCnt ) );
}

//------------------------------------------------------------------------
// IUnknown->Release
//------------------------------------------------------------------------

STDMETHODIMP_(ULONG) CAPNDataObject::Release( )
{
    // we need a helper variable because it's not allowed to access
    // a member variable after an object is destroyed
    ULONG nRefCnt = static_cast< ULONG >( InterlockedDecrement( &m_nRefCnt ) );

    if ( 0 == nRefCnt )
        delete this;

    return nRefCnt;
}

//------------------------------------------------------------------------
// IDataObject->GetData
//------------------------------------------------------------------------

STDMETHODIMP CAPNDataObject::GetData( LPFORMATETC pFormatetc, LPSTGMEDIUM pmedium )
{
    HRESULT hr = m_rIDataObjectOrg->GetData( pFormatetc, pmedium );

    if (RPC_E_WRONG_THREAD == hr)
    {
        IDataObjectPtr pIDOTmp;
        hr = MarshalIDataObjectIntoCurrentApartment(&pIDOTmp);

        if (SUCCEEDED(hr))
            hr = pIDOTmp->GetData(pFormatetc, pmedium);
    }
    return hr;
}

//------------------------------------------------------------------------
// IDataObject->EnumFormatEtc
//------------------------------------------------------------------------

STDMETHODIMP CAPNDataObject::EnumFormatEtc( DWORD dwDirection, IEnumFORMATETC** ppenumFormatetc )
{
    HRESULT hr = m_rIDataObjectOrg->EnumFormatEtc(dwDirection, ppenumFormatetc);

    if (RPC_E_WRONG_THREAD == hr)
    {
        IDataObjectPtr pIDOTmp;
        hr = MarshalIDataObjectIntoCurrentApartment(&pIDOTmp);

        if (SUCCEEDED(hr))
            hr = pIDOTmp->EnumFormatEtc(dwDirection, ppenumFormatetc);
    }
    return hr;
}

//------------------------------------------------------------------------
// IDataObject->QueryGetData
//------------------------------------------------------------------------

STDMETHODIMP CAPNDataObject::QueryGetData( LPFORMATETC pFormatetc )
{
    HRESULT hr = m_rIDataObjectOrg->QueryGetData( pFormatetc );

    if (RPC_E_WRONG_THREAD == hr)
    {
        IDataObjectPtr pIDOTmp;
        hr = MarshalIDataObjectIntoCurrentApartment( &pIDOTmp );

        if (SUCCEEDED(hr))
            hr = pIDOTmp->QueryGetData(pFormatetc);
    }
    return hr;
}

//------------------------------------------------------------------------
// IDataObject->GetDataHere
//------------------------------------------------------------------------

STDMETHODIMP CAPNDataObject::GetDataHere( LPFORMATETC pFormatetc, LPSTGMEDIUM pmedium )
{
    HRESULT hr = m_rIDataObjectOrg->GetDataHere(pFormatetc, pmedium);

    if (RPC_E_WRONG_THREAD == hr)
    {
        IDataObjectPtr pIDOTmp;
        hr = MarshalIDataObjectIntoCurrentApartment(&pIDOTmp);

        if (SUCCEEDED(hr))
            hr = pIDOTmp->GetDataHere(pFormatetc, pmedium);
    }
    return hr;
}

//------------------------------------------------------------------------
// IDataObject->GetCanonicalFormatEtc
//------------------------------------------------------------------------

STDMETHODIMP CAPNDataObject::GetCanonicalFormatEtc(LPFORMATETC pFormatectIn, LPFORMATETC pFormatetcOut)
{
    HRESULT hr = m_rIDataObjectOrg->GetCanonicalFormatEtc( pFormatectIn, pFormatetcOut );

    if (RPC_E_WRONG_THREAD == hr)
    {
        IDataObjectPtr pIDOTmp;
        hr = MarshalIDataObjectIntoCurrentApartment(&pIDOTmp);

        if (SUCCEEDED(hr))
            hr = pIDOTmp->GetCanonicalFormatEtc(pFormatectIn, pFormatetcOut);
    }
    return hr;
}

//------------------------------------------------------------------------
// IDataObject->SetData
//------------------------------------------------------------------------

STDMETHODIMP CAPNDataObject::SetData( LPFORMATETC pFormatetc, LPSTGMEDIUM pmedium, BOOL fRelease )
{
    HRESULT hr = m_rIDataObjectOrg->SetData( pFormatetc, pmedium, fRelease );

    if (RPC_E_WRONG_THREAD == hr)
    {
        IDataObjectPtr pIDOTmp;
        hr = MarshalIDataObjectIntoCurrentApartment(&pIDOTmp);

        if (SUCCEEDED(hr))
            hr = pIDOTmp->SetData(pFormatetc, pmedium, fRelease);
    }
    return hr;
}

//------------------------------------------------------------------------
// IDataObject->DAdvise
//------------------------------------------------------------------------

STDMETHODIMP CAPNDataObject::DAdvise( LPFORMATETC pFormatetc, DWORD advf, LPADVISESINK pAdvSink, DWORD * pdwConnection )
{
    HRESULT hr = m_rIDataObjectOrg->DAdvise(pFormatetc, advf, pAdvSink, pdwConnection);

    if (RPC_E_WRONG_THREAD == hr)
    {
        IDataObjectPtr pIDOTmp;
        hr = MarshalIDataObjectIntoCurrentApartment(&pIDOTmp);

        if (SUCCEEDED(hr))
            hr = pIDOTmp->DAdvise(pFormatetc, advf, pAdvSink, pdwConnection);
    }
    return hr;
}

//------------------------------------------------------------------------
// IDataObject->DUnadvise
//------------------------------------------------------------------------

STDMETHODIMP CAPNDataObject::DUnadvise( DWORD dwConnection )
{
    HRESULT hr = m_rIDataObjectOrg->DUnadvise( dwConnection );

    if (RPC_E_WRONG_THREAD == hr)
    {
        IDataObjectPtr pIDOTmp;
        hr = MarshalIDataObjectIntoCurrentApartment(&pIDOTmp);

        if (SUCCEEDED(hr))
            hr = pIDOTmp->DUnadvise(dwConnection);
    }
    return hr;
}

//------------------------------------------------------------------------
// IDataObject->EnumDAdvise
//------------------------------------------------------------------------

STDMETHODIMP CAPNDataObject::EnumDAdvise( LPENUMSTATDATA * ppenumAdvise )
{
    HRESULT hr = m_rIDataObjectOrg->EnumDAdvise(ppenumAdvise);

    if (RPC_E_WRONG_THREAD == hr)
    {
        IDataObjectPtr pIDOTmp;
        hr = MarshalIDataObjectIntoCurrentApartment(&pIDOTmp);

        if (SUCCEEDED(hr))
            hr = pIDOTmp->EnumDAdvise(ppenumAdvise);
    }
    return hr;
}

//------------------------------------------------------------------------
// for our convenience
//------------------------------------------------------------------------

CAPNDataObject::operator IDataObject*( )
{
    return static_cast< IDataObject* >( this );
}

//------------------------------------------------------------------------
// helper function
//------------------------------------------------------------------------

HRESULT CAPNDataObject::MarshalIDataObjectIntoCurrentApartment( IDataObject** ppIDataObj )
{
    OSL_ASSERT(NULL != ppIDataObj);

    *ppIDataObj = NULL;
    HRESULT hr = E_FAIL;

    if (m_hGlobal)
    {
        IStreamPtr pStm;
        hr = CreateStreamOnHGlobal(m_hGlobal, KEEP_HGLOB_ON_RELEASE, &pStm);

        OSL_ENSURE(E_INVALIDARG != hr, "CreateStreamOnHGlobal with invalid args called");

        if (SUCCEEDED(hr))
        {
            hr = CoUnmarshalInterface(pStm.get(), __uuidof(IDataObject), (void**)ppIDataObj);
            OSL_ENSURE(CO_E_NOTINITIALIZED != hr, "COM is not initialized");
        }
    }
    return hr;
}
<|endoftext|>


<commit_before><commit_msg>Added missing header<commit_after><|endoftext|>


<commit_before>/*
 * httpstream.cpp - HTTP stream parser
 * Copyright (C) 2013 Il'inykh Sergey (rion)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 *
 */

#include "httpstream.h"
#include "bsocket.h"
#include "../xmpp/zlib/zlibdecompressor.h"

//------------------------------------------------------------------------------
// LayerStream
//------------------------------------------------------------------------------
// implemented here just in case. usually should be reimplemented or not used
void LayerStream::writeIncoming(const QByteArray &data)
{
	handleOutData(data); // no processing in base class so move data out
}

void LayerStream::handleOutData(const QByteArray &data)
{
	if (_dataOutLayer) {
		_dataOutLayer->writeIncoming(data);
	} else {
		appendRead(data);
		emit readyRead();
	}
}

//--------------------------------------------
// GzipStream
//--------------------------------------------
class GzipStream : public LayerStream
{
	Q_OBJECT

	ZLibDecompressor *zDec;
	QBuffer uncompressed;

public:
	GzipStream(QObject *parent) :
		LayerStream(parent)
	{
		uncompressed.setBuffer(&readBuf());
		zDec = new ZLibDecompressor(&uncompressed);
		connect(&uncompressed, SIGNAL(bytesWritten(qint64)), SLOT(decompressedWritten(qint64)));
	}

	void writeIncoming(const QByteArray &data)
	{
		zDec->write(data);
	}

private slots:
	void decompressedWritten(qint64 size)
	{
		if (size) {
			if (_dataOutLayer) {
				_dataOutLayer->writeIncoming(uncompressed.buffer());
				uncompressed.buffer().clear();
				uncompressed.seek(0);
			} else {
				emit readyRead();
			}
		}
	}
};

//--------------------------------------------
// ChunkedStream
//--------------------------------------------
class ChunkedStream : public LayerStream
{
	Q_OBJECT

	enum State
	{
		Header,
		Body,
		BodyEnd,
		Trailer
	};

	bool sizeParsed;
	State _state;
	quint64 chunkSize;
	quint64 chunkBytesLeft; // bytes left to read for current chunk
	static const quint8 tmpBufSize = 12;
	QByteArray tmpBuffer;

public:
	ChunkedStream(QObject *parent) :
		LayerStream(parent),
		sizeParsed(false),
		_state(Header)
	{
		tmpBuffer.reserve(tmpBufSize);
	}

	void writeIncoming(const QByteArray &data)
	{
		int index;
		QByteArray tail = QByteArray::fromRawData(data.constData(), data.size());
		while (tail.size()) {
			switch (_state) {
			case Header:
			{
				quint8 lastHeaderSize = (quint8)tmpBuffer.size();
				quint8 bufFree = tmpBufSize - lastHeaderSize;
				tmpBuffer += ((int)bufFree > tail.size() ? tail : QByteArray::fromRawData(
														   tail.constData(), bufFree));
				if ((index = tmpBuffer.indexOf("\r\n")) == -1) {
					if (!bufFree) {
						setError(ErrRead, "String for chunk header is too long");
					}
					return;
				}
				tmpBuffer.resize(index);
				int unparsedOffset = tmpBuffer.size() + 2 - lastHeaderSize;
				tail = QByteArray::fromRawData(tail.constData() + unparsedOffset,
											   tail.size() - unparsedOffset);

				chunkSize = tmpBuffer.toInt(&sizeParsed, 16);
				if (!sizeParsed) {
					setError(ErrRead, "chunk size parse failed");
					return;
				}
				chunkBytesLeft = chunkSize;
				tmpBuffer.clear(); // should be clean to make BodyEnd working
				_state = chunkSize? Body : Trailer; // 0 means the end of response
				break;
			}
			case Body:
			{
				QByteArray r = readTail(tail, chunkBytesLeft);
				chunkBytesLeft -= r.size();
				handleOutData(r);
				if (chunkBytesLeft) {
					break; // no enough data to finish chunk read
				}
				_state = BodyEnd;
			}
			case BodyEnd:
				tmpBuffer.append(readTail(tail, 2 - tmpBuffer.size()));
				if (tmpBuffer.size() == 2) {
					if (tmpBuffer[0] != '\r' || tmpBuffer[1] != '\n') {
						setError(ErrRead, "no \r\n at chunk end");
						return;
					}
					_state = Header;
				}
				break;
			case Trailer:
				// TODO
				break;
			}
		}
	}

private:
	QByteArray readTail(QByteArray &tail, int bytes) const
	{
		int rb = qMin<int>(bytes, tail.size());
		QByteArray ret = QByteArray::fromRawData(tail.constData(), rb);
		tail = QByteArray::fromRawData(tail.constData() + rb, tail.size() - rb);
		return ret;
	}
};

//--------------------------------------------
// HttpStream
//
// This layer assumes it receives raw data right from tcp or decoded ssl
// and on out it has some http unrelated data (html for example or contents
// of some file.). Layer internally creates another layers pipeline to handle
// http compression and chunked data (maybe other encodings in the future)
//--------------------------------------------
void HttpStream::writeIncoming(const QByteArray &data)
{
	if (!data.size()) {
		return;
	}
	QByteArray realData;
	if (!headersReady) {
		int parsePos = qMax<int>(headersBuffer.size() - 3, 0);
		headersBuffer += data;
		if (headersBuffer.indexOf("\r\n\r\n", parsePos) == -1) {
			return;
		}
		if (parseHeaders(headersBuffer, parsePos)) {
			parsePos += 2;
			realData = QByteArray::fromRawData(headersBuffer.constData() + parsePos,
											   headersBuffer.size() - parsePos);
			headersReady = true;
			QByteArray header = headers.value("Content-Encoding").toLower();
			if (!header.isEmpty()) {
				QList<QByteArray> tes = header.split(',');
				while (tes.size()) {
					QByteArray lv = tes.takeLast().trimmed().toLower();
					if (lv == "gzip" || lv == "x-gzip" || lv == "deflate") {
						pipeLine.append(new GzipStream(this));
					}
				}
			}
			header = headers.value("Transfer-Encoding");
			if (!header.isEmpty()) {
				QList<QByteArray> tes = header.split(',');
				while (tes.size()) {
					QByteArray lv = tes.takeLast().trimmed().toLower();
					if (lv == "chunked") {
						pipeLine.append(new ChunkedStream(this));
					}
					if (lv == "gzip" || lv == "x-gzip" || lv == "deflate") {
						pipeLine.append(new GzipStream(this));
					}
				}
				headers.remove("Content-Length"); // by rfc2616 we have to ignore this header
			}
			if (pipeLine.count()) { // connect pipes
				for (int i = 0; i < pipeLine.count() - 1; i++) {
					pipeLine[i]->setDataOutLayer(pipeLine[i+1]);
				}
				connect(pipeLine.last(), SIGNAL(readyRead()), SLOT(pipeLine_readyReady()));
			}
			emit metaDataChanged();
		} else {
			qDebug("Invalid header: %s", headersBuffer.mid(
				parsePos, headersBuffer.indexOf("\r\n", parsePos)).data());
			setError(QNetworkReply::ProtocolFailure, "Invalid headers");
		}
	} else {
		realData = data;
	}
	if (realData.size()) {
		if (pipeLine.count()) {
			pipeLine[0]->writeIncoming(realData);
		} else {
			handleOutData(realData);
		}
	}
}

void HttpStream::pipeLine_readyReady()
{
	LayerStream *s = static_cast<LayerStream *>(sender());
	handleOutData(s->readAll());
}

bool HttpStream::parseHeaders(const QByteArray &buffer, int &pos)
{
	bool valid = true;
	bool statusRead = false;
	pos = 0;
	int endPos = 0;
	QByteArray lastKey;
	while ((endPos = buffer.indexOf("\r\n", pos)) != -1 && endPos != pos) {
		if (!statusRead) {
			QRegExp statusRE("^HTTP/(1.[01]) (\\d{3})( .*)?$");
			if (!statusRE.exactMatch(QString::fromLatin1(
								   buffer.constData() + pos, endPos - pos)))
			{
				valid = false;
				break;
			}
			httpVersion = statusRE.cap(1);
			statusCode = statusRE.cap(2).toInt();
			statusText = statusRE.cap(3).trimmed();
			statusRead = true;
		} else {
			QHash<QByteArray, QByteArray>::iterator it;
			if (buffer[pos] == ' ' || buffer[pos] == '\t') { // multiline value
				if (lastKey.isEmpty() || (it = headers.find(lastKey)) == headers.end()) {
					valid = false;
					break;
				}
				*it += ' ';
				*it += buffer.mid(pos, endPos - pos).trimmed();
			} else { // normal header line
				int sPos = buffer.indexOf(':', pos);
				if (sPos == -1 || sPos == pos || sPos > endPos) {
					valid = false;
					break;
				}
				QByteArray newKey = buffer.mid(pos, sPos - pos);
				QByteArray newValue = buffer.mid(sPos + 1, endPos - sPos - 1);
				if ((it = headers.find(newKey)) != headers.end()) { // by rfc we can combine so-named keys
					*it += ',';
					*it += newValue;
				} else {
					headers.insert(newKey, newValue);
					lastKey = newKey;
				}
			}
		}
		pos = endPos + 2;
	}
	return valid;
}

#include "httpstream.moc"
<commit_msg>fixed include path<commit_after>/*
 * httpstream.cpp - HTTP stream parser
 * Copyright (C) 2013 Il'inykh Sergey (rion)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 *
 */

#include "httpstream.h"
#include "bsocket.h"
#include "../../xmpp/zlib/zlibdecompressor.h"

//------------------------------------------------------------------------------
// LayerStream
//------------------------------------------------------------------------------
// implemented here just in case. usually should be reimplemented or not used
void LayerStream::writeIncoming(const QByteArray &data)
{
	handleOutData(data); // no processing in base class so move data out
}

void LayerStream::handleOutData(const QByteArray &data)
{
	if (_dataOutLayer) {
		_dataOutLayer->writeIncoming(data);
	} else {
		appendRead(data);
		emit readyRead();
	}
}

//--------------------------------------------
// GzipStream
//--------------------------------------------
class GzipStream : public LayerStream
{
	Q_OBJECT

	ZLibDecompressor *zDec;
	QBuffer uncompressed;

public:
	GzipStream(QObject *parent) :
		LayerStream(parent)
	{
		uncompressed.setBuffer(&readBuf());
		zDec = new ZLibDecompressor(&uncompressed);
		connect(&uncompressed, SIGNAL(bytesWritten(qint64)), SLOT(decompressedWritten(qint64)));
	}

	void writeIncoming(const QByteArray &data)
	{
		zDec->write(data);
	}

private slots:
	void decompressedWritten(qint64 size)
	{
		if (size) {
			if (_dataOutLayer) {
				_dataOutLayer->writeIncoming(uncompressed.buffer());
				uncompressed.buffer().clear();
				uncompressed.seek(0);
			} else {
				emit readyRead();
			}
		}
	}
};

//--------------------------------------------
// ChunkedStream
//--------------------------------------------
class ChunkedStream : public LayerStream
{
	Q_OBJECT

	enum State
	{
		Header,
		Body,
		BodyEnd,
		Trailer
	};

	bool sizeParsed;
	State _state;
	quint64 chunkSize;
	quint64 chunkBytesLeft; // bytes left to read for current chunk
	static const quint8 tmpBufSize = 12;
	QByteArray tmpBuffer;

public:
	ChunkedStream(QObject *parent) :
		LayerStream(parent),
		sizeParsed(false),
		_state(Header)
	{
		tmpBuffer.reserve(tmpBufSize);
	}

	void writeIncoming(const QByteArray &data)
	{
		int index;
		QByteArray tail = QByteArray::fromRawData(data.constData(), data.size());
		while (tail.size()) {
			switch (_state) {
			case Header:
			{
				quint8 lastHeaderSize = (quint8)tmpBuffer.size();
				quint8 bufFree = tmpBufSize - lastHeaderSize;
				tmpBuffer += ((int)bufFree > tail.size() ? tail : QByteArray::fromRawData(
														   tail.constData(), bufFree));
				if ((index = tmpBuffer.indexOf("\r\n")) == -1) {
					if (!bufFree) {
						setError(ErrRead, "String for chunk header is too long");
					}
					return;
				}
				tmpBuffer.resize(index);
				int unparsedOffset = tmpBuffer.size() + 2 - lastHeaderSize;
				tail = QByteArray::fromRawData(tail.constData() + unparsedOffset,
											   tail.size() - unparsedOffset);

				chunkSize = tmpBuffer.toInt(&sizeParsed, 16);
				if (!sizeParsed) {
					setError(ErrRead, "chunk size parse failed");
					return;
				}
				chunkBytesLeft = chunkSize;
				tmpBuffer.clear(); // should be clean to make BodyEnd working
				_state = chunkSize? Body : Trailer; // 0 means the end of response
				break;
			}
			case Body:
			{
				QByteArray r = readTail(tail, chunkBytesLeft);
				chunkBytesLeft -= r.size();
				handleOutData(r);
				if (chunkBytesLeft) {
					break; // no enough data to finish chunk read
				}
				_state = BodyEnd;
			}
			case BodyEnd:
				tmpBuffer.append(readTail(tail, 2 - tmpBuffer.size()));
				if (tmpBuffer.size() == 2) {
					if (tmpBuffer[0] != '\r' || tmpBuffer[1] != '\n') {
						setError(ErrRead, "no \r\n at chunk end");
						return;
					}
					_state = Header;
				}
				break;
			case Trailer:
				// TODO
				break;
			}
		}
	}

private:
	QByteArray readTail(QByteArray &tail, int bytes) const
	{
		int rb = qMin<int>(bytes, tail.size());
		QByteArray ret = QByteArray::fromRawData(tail.constData(), rb);
		tail = QByteArray::fromRawData(tail.constData() + rb, tail.size() - rb);
		return ret;
	}
};

//--------------------------------------------
// HttpStream
//
// This layer assumes it receives raw data right from tcp or decoded ssl
// and on out it has some http unrelated data (html for example or contents
// of some file.). Layer internally creates another layers pipeline to handle
// http compression and chunked data (maybe other encodings in the future)
//--------------------------------------------
void HttpStream::writeIncoming(const QByteArray &data)
{
	if (!data.size()) {
		return;
	}
	QByteArray realData;
	if (!headersReady) {
		int parsePos = qMax<int>(headersBuffer.size() - 3, 0);
		headersBuffer += data;
		if (headersBuffer.indexOf("\r\n\r\n", parsePos) == -1) {
			return;
		}
		if (parseHeaders(headersBuffer, parsePos)) {
			parsePos += 2;
			realData = QByteArray::fromRawData(headersBuffer.constData() + parsePos,
											   headersBuffer.size() - parsePos);
			headersReady = true;
			QByteArray header = headers.value("Content-Encoding").toLower();
			if (!header.isEmpty()) {
				QList<QByteArray> tes = header.split(',');
				while (tes.size()) {
					QByteArray lv = tes.takeLast().trimmed().toLower();
					if (lv == "gzip" || lv == "x-gzip" || lv == "deflate") {
						pipeLine.append(new GzipStream(this));
					}
				}
			}
			header = headers.value("Transfer-Encoding");
			if (!header.isEmpty()) {
				QList<QByteArray> tes = header.split(',');
				while (tes.size()) {
					QByteArray lv = tes.takeLast().trimmed().toLower();
					if (lv == "chunked") {
						pipeLine.append(new ChunkedStream(this));
					}
					if (lv == "gzip" || lv == "x-gzip" || lv == "deflate") {
						pipeLine.append(new GzipStream(this));
					}
				}
				headers.remove("Content-Length"); // by rfc2616 we have to ignore this header
			}
			if (pipeLine.count()) { // connect pipes
				for (int i = 0; i < pipeLine.count() - 1; i++) {
					pipeLine[i]->setDataOutLayer(pipeLine[i+1]);
				}
				connect(pipeLine.last(), SIGNAL(readyRead()), SLOT(pipeLine_readyReady()));
			}
			emit metaDataChanged();
		} else {
			qDebug("Invalid header: %s", headersBuffer.mid(
				parsePos, headersBuffer.indexOf("\r\n", parsePos)).data());
			setError(QNetworkReply::ProtocolFailure, "Invalid headers");
		}
	} else {
		realData = data;
	}
	if (realData.size()) {
		if (pipeLine.count()) {
			pipeLine[0]->writeIncoming(realData);
		} else {
			handleOutData(realData);
		}
	}
}

void HttpStream::pipeLine_readyReady()
{
	LayerStream *s = static_cast<LayerStream *>(sender());
	handleOutData(s->readAll());
}

bool HttpStream::parseHeaders(const QByteArray &buffer, int &pos)
{
	bool valid = true;
	bool statusRead = false;
	pos = 0;
	int endPos = 0;
	QByteArray lastKey;
	while ((endPos = buffer.indexOf("\r\n", pos)) != -1 && endPos != pos) {
		if (!statusRead) {
			QRegExp statusRE("^HTTP/(1.[01]) (\\d{3})( .*)?$");
			if (!statusRE.exactMatch(QString::fromLatin1(
								   buffer.constData() + pos, endPos - pos)))
			{
				valid = false;
				break;
			}
			httpVersion = statusRE.cap(1);
			statusCode = statusRE.cap(2).toInt();
			statusText = statusRE.cap(3).trimmed();
			statusRead = true;
		} else {
			QHash<QByteArray, QByteArray>::iterator it;
			if (buffer[pos] == ' ' || buffer[pos] == '\t') { // multiline value
				if (lastKey.isEmpty() || (it = headers.find(lastKey)) == headers.end()) {
					valid = false;
					break;
				}
				*it += ' ';
				*it += buffer.mid(pos, endPos - pos).trimmed();
			} else { // normal header line
				int sPos = buffer.indexOf(':', pos);
				if (sPos == -1 || sPos == pos || sPos > endPos) {
					valid = false;
					break;
				}
				QByteArray newKey = buffer.mid(pos, sPos - pos);
				QByteArray newValue = buffer.mid(sPos + 1, endPos - sPos - 1);
				if ((it = headers.find(newKey)) != headers.end()) { // by rfc we can combine so-named keys
					*it += ',';
					*it += newValue;
				} else {
					headers.insert(newKey, newValue);
					lastKey = newKey;
				}
			}
		}
		pos = endPos + 2;
	}
	return valid;
}

#include "httpstream.moc"
<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>

#include <set>
#include <string>
#include <vector>

#include <base/command_line.h>
#include <base/logging.h>
#include <gflags/gflags.h>
#include <glib.h>

#include "update_engine/delta_diff_generator.h"
#include "update_engine/delta_performer.h"
#include "update_engine/payload_signer.h"
#include "update_engine/prefs.h"
#include "update_engine/subprocess.h"
#include "update_engine/terminator.h"
#include "update_engine/update_metadata.pb.h"
#include "update_engine/utils.h"

DEFINE_string(old_dir, "",
              "Directory where the old rootfs is loop mounted read-only");
DEFINE_string(new_dir, "",
              "Directory where the new rootfs is loop mounted read-only");
DEFINE_string(old_image, "", "Path to the old rootfs");
DEFINE_string(new_image, "", "Path to the new rootfs");
DEFINE_string(old_kernel, "", "Path to the old kernel partition image");
DEFINE_string(new_kernel, "", "Path to the new kernel partition image");
DEFINE_string(in_file, "",
              "Path to input delta payload file used to hash/sign payloads "
              "and apply delta over old_image (for debugging)");
DEFINE_string(out_file, "", "Path to output delta payload file");
DEFINE_string(out_hash_file, "", "Path to output hash file");
DEFINE_string(private_key, "", "Path to private key in .pem format");
DEFINE_string(public_key, "", "Path to public key in .pem format");
DEFINE_string(prefs_dir, "/tmp/update_engine_prefs",
              "Preferences directory, used with apply_delta");
DEFINE_int32(signature_size, 0, "Raw signature size used for hash calculation");
DEFINE_string(signature_file, "", "Raw signature file to sign payload with");

// This file contains a simple program that takes an old path, a new path,
// and an output file as arguments and the path to an output file and
// generates a delta that can be sent to Chrome OS clients.

using std::set;
using std::string;
using std::vector;

namespace chromeos_update_engine {

namespace {

bool IsDir(const char* path) {
  struct stat stbuf;
  TEST_AND_RETURN_FALSE_ERRNO(lstat(path, &stbuf) == 0);
  return S_ISDIR(stbuf.st_mode);
}

void CalculatePayloadHashForSigning() {
  LOG(INFO) << "Calculating payload hash for signing.";
  LOG_IF(FATAL, FLAGS_in_file.empty())
      << "Must pass --in_file to calculate hash for signing.";
  LOG_IF(FATAL, FLAGS_out_hash_file.empty())
      << "Must pass --out_hash_file to calculate hash for signing.";
  LOG_IF(FATAL, FLAGS_signature_size <= 0)
      << "Must pass --signature_size to calculate hash for signing.";
  vector<char> hash;
  CHECK(PayloadSigner::HashPayloadForSigning(
      FLAGS_in_file, FLAGS_signature_size, &hash));
  CHECK(utils::WriteFile(
      FLAGS_out_hash_file.c_str(), hash.data(), hash.size()));
  LOG(INFO) << "Done calculating payload hash for signing.";
}

void SignPayload() {
  LOG(INFO) << "Signing payload.";
  LOG_IF(FATAL, FLAGS_in_file.empty())
      << "Must pass --in_file to sign payload.";
  LOG_IF(FATAL, FLAGS_out_file.empty())
      << "Must pass --out_file to sign payload.";
  LOG_IF(FATAL, FLAGS_signature_file.empty())
      << "Must pass --signature_file to sign payload.";
  vector<char> signature;
  CHECK(utils::ReadFile(FLAGS_signature_file, &signature));
  CHECK(PayloadSigner::AddSignatureToPayload(
      FLAGS_in_file, signature, FLAGS_out_file));
  LOG(INFO) << "Done signing payload.";
}

void VerifySignedPayload() {
  LOG(INFO) << "Verifying signed payload.";
  LOG_IF(FATAL, FLAGS_in_file.empty())
      << "Must pass --in_file to verify signed payload.";
  LOG_IF(FATAL, FLAGS_public_key.empty())
      << "Must pass --public_key to verify signed payload.";
  CHECK(PayloadSigner::VerifySignedPayload(FLAGS_in_file, FLAGS_public_key));
  LOG(INFO) << "Done verifying signed payload.";
}

void ApplyDelta() {
  LOG(INFO) << "Applying delta.";
  LOG_IF(FATAL, FLAGS_old_image.empty())
      << "Must pass --old_image to apply delta.";
  Prefs prefs;
  LOG(INFO) << "Setting up preferences under: " << FLAGS_prefs_dir;
  LOG_IF(ERROR, !prefs.Init(FilePath(FLAGS_prefs_dir)))
      << "Failed to initialize preferences.";
  // Get original checksums
  LOG(INFO) << "Calculating original checksums";
  PartitionInfo kern_info, root_info;
  CHECK(DeltaDiffGenerator::InitializePartitionInfo(true,  // is_kernel
                                                    FLAGS_old_kernel,
                                                    &kern_info));
  CHECK(DeltaDiffGenerator::InitializePartitionInfo(false,  // is_kernel
                                                    FLAGS_old_image,
                                                    &root_info));
  vector<char> kern_hash(kern_info.hash().begin(),
                         kern_info.hash().end());
  vector<char> root_hash(root_info.hash().begin(),
                         root_info.hash().end());
  DeltaPerformer performer(&prefs);
  performer.set_current_kernel_hash(kern_hash);
  performer.set_current_rootfs_hash(root_hash);
  CHECK_EQ(performer.Open(FLAGS_old_image.c_str(), 0, 0), 0);
  CHECK(performer.OpenKernel(FLAGS_old_kernel.c_str()));
  vector<char> buf(1024 * 1024);
  int fd = open(FLAGS_in_file.c_str(), O_RDONLY, 0);
  CHECK_GE(fd, 0);
  ScopedFdCloser fd_closer(&fd);
  for (off_t offset = 0;; offset += buf.size()) {
    ssize_t bytes_read;
    CHECK(utils::PReadAll(fd, &buf[0], buf.size(), offset, &bytes_read));
    if (bytes_read == 0)
      break;
    CHECK_EQ(performer.Write(&buf[0], bytes_read), bytes_read);
  }
  CHECK_EQ(performer.Close(), 0);
  DeltaPerformer::ResetUpdateProgress(&prefs, false);
  LOG(INFO) << "Done applying delta.";
}

int Main(int argc, char** argv) {
  g_thread_init(NULL);
  google::ParseCommandLineFlags(&argc, &argv, true);
  CommandLine::Init(argc, argv);
  Terminator::Init();
  Subprocess::Init();
  logging::InitLogging("delta_generator.log",
                       logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG,
                       logging::DONT_LOCK_LOG_FILE,
                       logging::APPEND_TO_OLD_LOG_FILE);
  if (FLAGS_signature_size > 0 || !FLAGS_out_hash_file.empty()) {
    CalculatePayloadHashForSigning();
    return 0;
  }
  if (!FLAGS_signature_file.empty()) {
    SignPayload();
    return 0;
  }
  if (!FLAGS_public_key.empty()) {
    VerifySignedPayload();
    return 0;
  }
  if (!FLAGS_in_file.empty()) {
    ApplyDelta();
    return 0;
  }
  CHECK(!FLAGS_new_image.empty());
  CHECK(!FLAGS_out_file.empty());
  CHECK(!FLAGS_new_kernel.empty());
  if (FLAGS_old_image.empty()) {
    LOG(INFO) << "Generating full update";
  } else {
    LOG(INFO) << "Generating delta update";
    CHECK(!FLAGS_old_dir.empty());
    CHECK(!FLAGS_new_dir.empty());
    if ((!IsDir(FLAGS_old_dir.c_str())) || (!IsDir(FLAGS_new_dir.c_str()))) {
      LOG(FATAL) << "old_dir or new_dir not directory";
    }
  }
  DeltaDiffGenerator::GenerateDeltaUpdateFile(FLAGS_old_dir,
                                              FLAGS_old_image,
                                              FLAGS_new_dir,
                                              FLAGS_new_image,
                                              FLAGS_old_kernel,
                                              FLAGS_new_kernel,
                                              FLAGS_out_file,
                                              FLAGS_private_key);

  return 0;
}

}  // namespace {}

}  // namespace chromeos_update_engine

int main(int argc, char** argv) {
  return chromeos_update_engine::Main(argc, argv);
}
<commit_msg>Return bad exit code when we fail to generate an update.<commit_after>// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>

#include <set>
#include <string>
#include <vector>

#include <base/command_line.h>
#include <base/logging.h>
#include <gflags/gflags.h>
#include <glib.h>

#include "update_engine/delta_diff_generator.h"
#include "update_engine/delta_performer.h"
#include "update_engine/payload_signer.h"
#include "update_engine/prefs.h"
#include "update_engine/subprocess.h"
#include "update_engine/terminator.h"
#include "update_engine/update_metadata.pb.h"
#include "update_engine/utils.h"

DEFINE_string(old_dir, "",
              "Directory where the old rootfs is loop mounted read-only");
DEFINE_string(new_dir, "",
              "Directory where the new rootfs is loop mounted read-only");
DEFINE_string(old_image, "", "Path to the old rootfs");
DEFINE_string(new_image, "", "Path to the new rootfs");
DEFINE_string(old_kernel, "", "Path to the old kernel partition image");
DEFINE_string(new_kernel, "", "Path to the new kernel partition image");
DEFINE_string(in_file, "",
              "Path to input delta payload file used to hash/sign payloads "
              "and apply delta over old_image (for debugging)");
DEFINE_string(out_file, "", "Path to output delta payload file");
DEFINE_string(out_hash_file, "", "Path to output hash file");
DEFINE_string(private_key, "", "Path to private key in .pem format");
DEFINE_string(public_key, "", "Path to public key in .pem format");
DEFINE_string(prefs_dir, "/tmp/update_engine_prefs",
              "Preferences directory, used with apply_delta");
DEFINE_int32(signature_size, 0, "Raw signature size used for hash calculation");
DEFINE_string(signature_file, "", "Raw signature file to sign payload with");

// This file contains a simple program that takes an old path, a new path,
// and an output file as arguments and the path to an output file and
// generates a delta that can be sent to Chrome OS clients.

using std::set;
using std::string;
using std::vector;

namespace chromeos_update_engine {

namespace {

bool IsDir(const char* path) {
  struct stat stbuf;
  TEST_AND_RETURN_FALSE_ERRNO(lstat(path, &stbuf) == 0);
  return S_ISDIR(stbuf.st_mode);
}

void CalculatePayloadHashForSigning() {
  LOG(INFO) << "Calculating payload hash for signing.";
  LOG_IF(FATAL, FLAGS_in_file.empty())
      << "Must pass --in_file to calculate hash for signing.";
  LOG_IF(FATAL, FLAGS_out_hash_file.empty())
      << "Must pass --out_hash_file to calculate hash for signing.";
  LOG_IF(FATAL, FLAGS_signature_size <= 0)
      << "Must pass --signature_size to calculate hash for signing.";
  vector<char> hash;
  CHECK(PayloadSigner::HashPayloadForSigning(
      FLAGS_in_file, FLAGS_signature_size, &hash));
  CHECK(utils::WriteFile(
      FLAGS_out_hash_file.c_str(), hash.data(), hash.size()));
  LOG(INFO) << "Done calculating payload hash for signing.";
}

void SignPayload() {
  LOG(INFO) << "Signing payload.";
  LOG_IF(FATAL, FLAGS_in_file.empty())
      << "Must pass --in_file to sign payload.";
  LOG_IF(FATAL, FLAGS_out_file.empty())
      << "Must pass --out_file to sign payload.";
  LOG_IF(FATAL, FLAGS_signature_file.empty())
      << "Must pass --signature_file to sign payload.";
  vector<char> signature;
  CHECK(utils::ReadFile(FLAGS_signature_file, &signature));
  CHECK(PayloadSigner::AddSignatureToPayload(
      FLAGS_in_file, signature, FLAGS_out_file));
  LOG(INFO) << "Done signing payload.";
}

void VerifySignedPayload() {
  LOG(INFO) << "Verifying signed payload.";
  LOG_IF(FATAL, FLAGS_in_file.empty())
      << "Must pass --in_file to verify signed payload.";
  LOG_IF(FATAL, FLAGS_public_key.empty())
      << "Must pass --public_key to verify signed payload.";
  CHECK(PayloadSigner::VerifySignedPayload(FLAGS_in_file, FLAGS_public_key));
  LOG(INFO) << "Done verifying signed payload.";
}

void ApplyDelta() {
  LOG(INFO) << "Applying delta.";
  LOG_IF(FATAL, FLAGS_old_image.empty())
      << "Must pass --old_image to apply delta.";
  Prefs prefs;
  LOG(INFO) << "Setting up preferences under: " << FLAGS_prefs_dir;
  LOG_IF(ERROR, !prefs.Init(FilePath(FLAGS_prefs_dir)))
      << "Failed to initialize preferences.";
  // Get original checksums
  LOG(INFO) << "Calculating original checksums";
  PartitionInfo kern_info, root_info;
  CHECK(DeltaDiffGenerator::InitializePartitionInfo(true,  // is_kernel
                                                    FLAGS_old_kernel,
                                                    &kern_info));
  CHECK(DeltaDiffGenerator::InitializePartitionInfo(false,  // is_kernel
                                                    FLAGS_old_image,
                                                    &root_info));
  vector<char> kern_hash(kern_info.hash().begin(),
                         kern_info.hash().end());
  vector<char> root_hash(root_info.hash().begin(),
                         root_info.hash().end());
  DeltaPerformer performer(&prefs);
  performer.set_current_kernel_hash(kern_hash);
  performer.set_current_rootfs_hash(root_hash);
  CHECK_EQ(performer.Open(FLAGS_old_image.c_str(), 0, 0), 0);
  CHECK(performer.OpenKernel(FLAGS_old_kernel.c_str()));
  vector<char> buf(1024 * 1024);
  int fd = open(FLAGS_in_file.c_str(), O_RDONLY, 0);
  CHECK_GE(fd, 0);
  ScopedFdCloser fd_closer(&fd);
  for (off_t offset = 0;; offset += buf.size()) {
    ssize_t bytes_read;
    CHECK(utils::PReadAll(fd, &buf[0], buf.size(), offset, &bytes_read));
    if (bytes_read == 0)
      break;
    CHECK_EQ(performer.Write(&buf[0], bytes_read), bytes_read);
  }
  CHECK_EQ(performer.Close(), 0);
  DeltaPerformer::ResetUpdateProgress(&prefs, false);
  LOG(INFO) << "Done applying delta.";
}

int Main(int argc, char** argv) {
  g_thread_init(NULL);
  google::ParseCommandLineFlags(&argc, &argv, true);
  CommandLine::Init(argc, argv);
  Terminator::Init();
  Subprocess::Init();
  logging::InitLogging("delta_generator.log",
                       logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG,
                       logging::DONT_LOCK_LOG_FILE,
                       logging::APPEND_TO_OLD_LOG_FILE);
  if (FLAGS_signature_size > 0 || !FLAGS_out_hash_file.empty()) {
    CalculatePayloadHashForSigning();
    return 0;
  }
  if (!FLAGS_signature_file.empty()) {
    SignPayload();
    return 0;
  }
  if (!FLAGS_public_key.empty()) {
    VerifySignedPayload();
    return 0;
  }
  if (!FLAGS_in_file.empty()) {
    ApplyDelta();
    return 0;
  }
  CHECK(!FLAGS_new_image.empty());
  CHECK(!FLAGS_out_file.empty());
  CHECK(!FLAGS_new_kernel.empty());
  if (FLAGS_old_image.empty()) {
    LOG(INFO) << "Generating full update";
  } else {
    LOG(INFO) << "Generating delta update";
    CHECK(!FLAGS_old_dir.empty());
    CHECK(!FLAGS_new_dir.empty());
    if ((!IsDir(FLAGS_old_dir.c_str())) || (!IsDir(FLAGS_new_dir.c_str()))) {
      LOG(FATAL) << "old_dir or new_dir not directory";
    }
  }
  if (!DeltaDiffGenerator::GenerateDeltaUpdateFile(FLAGS_old_dir,
                                                   FLAGS_old_image,
                                                   FLAGS_new_dir,
                                                   FLAGS_new_image,
                                                   FLAGS_old_kernel,
                                                   FLAGS_new_kernel,
                                                   FLAGS_out_file,
                                                   FLAGS_private_key)) {
    return 1;
  }
  return 0;
}

}  // namespace {}

}  // namespace chromeos_update_engine

int main(int argc, char** argv) {
  return chromeos_update_engine::Main(argc, argv);
}
<|endoftext|>