<commit_before>// Jubatus: Online machine learning framework for distributed environment
// Copyright (C) 2011,2012 Preferred Infrastructure and Nippon Telegraph and Telephone Corporation.
//
// 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#ifndef JUBATUS_CORE_GRAPH_GRAPH_BASE_HPP_
#define JUBATUS_CORE_GRAPH_GRAPH_BASE_HPP_

#include <stdint.h>

#include <map>
#include <string>
#include <vector>

#include "graph_type.hpp"

namespace jubatus {
namespace core {
namespace graph {

class graph_base {
 public:
  graph_base();
  virtual ~graph_base();

  virtual void clear() = 0;
  virtual void create_node(node_id_t id) = 0;
  virtual void create_global_node(node_id_t id) = 0;
  virtual void remove_global_node(node_id_t id) = 0;
  virtual void update_node(node_id_t id, const property& p) = 0;
  virtual void remove_node(node_id_t id) = 0;
  virtual void create_edge(edge_id_t eid, node_id_t src, node_id_t tgt) = 0;
  virtual void update_edge(edge_id_t eid, const property& p) = 0;
  virtual void remove_edge(edge_id_t eid) = 0;

  virtual void add_centrality_query(const preset_query&) = 0;
  virtual void add_shortest_path_query(const preset_query&) = 0;
  virtual void remove_centrality_query(const preset_query&) = 0;
  virtual void remove_shortest_path_query(const preset_query&) = 0;

  virtual double centrality(
      node_id_t id,
      centrality_type ct,
      const preset_query&) const = 0;

  virtual void shortest_path(
      node_id_t src,
      node_id_t tgt,
      uint64_t max_hop,
      std::vector<node_id_t>& ret,
      const preset_query&) const = 0;

  virtual void get_node(node_id_t id, node_info& ret) const = 0;
  virtual void get_edge(edge_id_t id, edge_info& ret) const = 0;

  virtual std::string type() const = 0;

  virtual void get_status(std::map<std::string, std::string>& status) const = 0;
  virtual void update_index() = 0;

  virtual void get_diff(std::string& diff) const = 0;
  virtual void set_mixed_and_clear_diff(const std::string& mixed) = 0;

  void save(std::ostream&);
  void load(std::istream&);

 protected:
  virtual bool save_imp(std::ostream& os) = 0;
  virtual bool load_imp(std::istream& is) = 0;
};

}  // namespace graph
}  // namespace core
}  // namespace jubatus

#endif  // JUBATUS_CORE_GRAPH_GRAPH_BASE_HPP_
<commit_msg>Replaced protected with private in jubatus/core/graph/graph_base.hpp (#347).<commit_after>// Jubatus: Online machine learning framework for distributed environment
// Copyright (C) 2011,2012 Preferred Infrastructure and Nippon Telegraph and Telephone Corporation.
//
// 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#ifndef JUBATUS_CORE_GRAPH_GRAPH_BASE_HPP_
#define JUBATUS_CORE_GRAPH_GRAPH_BASE_HPP_

#include <stdint.h>

#include <map>
#include <string>
#include <vector>

#include "graph_type.hpp"

namespace jubatus {
namespace core {
namespace graph {

class graph_base {
 public:
  graph_base();
  virtual ~graph_base();

  virtual void clear() = 0;
  virtual void create_node(node_id_t id) = 0;
  virtual void create_global_node(node_id_t id) = 0;
  virtual void remove_global_node(node_id_t id) = 0;
  virtual void update_node(node_id_t id, const property& p) = 0;
  virtual void remove_node(node_id_t id) = 0;
  virtual void create_edge(edge_id_t eid, node_id_t src, node_id_t tgt) = 0;
  virtual void update_edge(edge_id_t eid, const property& p) = 0;
  virtual void remove_edge(edge_id_t eid) = 0;

  virtual void add_centrality_query(const preset_query&) = 0;
  virtual void add_shortest_path_query(const preset_query&) = 0;
  virtual void remove_centrality_query(const preset_query&) = 0;
  virtual void remove_shortest_path_query(const preset_query&) = 0;

  virtual double centrality(
      node_id_t id,
      centrality_type ct,
      const preset_query&) const = 0;

  virtual void shortest_path(
      node_id_t src,
      node_id_t tgt,
      uint64_t max_hop,
      std::vector<node_id_t>& ret,
      const preset_query&) const = 0;

  virtual void get_node(node_id_t id, node_info& ret) const = 0;
  virtual void get_edge(edge_id_t id, edge_info& ret) const = 0;

  virtual std::string type() const = 0;

  virtual void get_status(std::map<std::string, std::string>& status) const = 0;
  virtual void update_index() = 0;

  virtual void get_diff(std::string& diff) const = 0;
  virtual void set_mixed_and_clear_diff(const std::string& mixed) = 0;

  void save(std::ostream&);
  void load(std::istream&);

 private:
  virtual bool save_imp(std::ostream& os) = 0;
  virtual bool load_imp(std::istream& is) = 0;
};

}  // namespace graph
}  // namespace core
}  // namespace jubatus

#endif  // JUBATUS_CORE_GRAPH_GRAPH_BASE_HPP_
<|endoftext|>


<commit_before>// ======================================================================== //
// Copyright 2009-2018 Intel Corporation                                    //
//                                                                          //
// 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.                                           //
// ======================================================================== //

#include "scene_instance.h"
#include "scene.h"

namespace embree
{
#if defined(EMBREE_LOWEST_ISA)

  Instance::Instance (Device* device, Accel* object, unsigned int numTimeSteps)
    : Geometry(device,Geometry::GTY_INSTANCE_CHEAP,1,numTimeSteps), object(object), local2world(nullptr)
  {
    if (object) object->refInc();
    world2local0 = one;
    local2world = (AffineSpace3fa*) alignedMalloc(numTimeSteps*sizeof(AffineSpace3fa),16);
    for (size_t i = 0; i < numTimeSteps; i++)
      local2world[i] = one;
  }

  Instance::~Instance()
  {
    alignedFree(local2world);
    if (object) object->refDec();
  }

  void Instance::enabling () {
    if (numTimeSteps == 1) {
      if (this->gtype == Geometry::GTY_INSTANCE_CHEAP) {
        scene->world.numInstancesCheap += numPrimitives;
      } else {
        scene->world.numInstancesExpensive += numPrimitives;
      }
    } else {
      if (this->gtype == Geometry::GTY_INSTANCE_EXPENSIVE) {
        scene->worldMB.numInstancesCheap += numPrimitives;
      } else {
        scene->worldMB.numInstancesExpensive += numPrimitives;
      }
    }
  }

  void Instance::disabling() {
    if (numTimeSteps == 1) {
      if (this->gtype == Geometry::GTY_INSTANCE_CHEAP) {
        scene->world.numInstancesCheap -= numPrimitives;
      } else {
        scene->world.numInstancesExpensive -= numPrimitives;
      }
    } else {
      if (this->gtype == Geometry::GTY_INSTANCE_EXPENSIVE) {
        scene->worldMB.numInstancesCheap -= numPrimitives;
      } else {
        scene->worldMB.numInstancesExpensive -= numPrimitives;
      }
    }
  }

  void Instance::setNumTimeSteps (unsigned int numTimeSteps_in)
  {
    if (numTimeSteps_in == numTimeSteps)
      return;

    AffineSpace3fa* local2world2 = (AffineSpace3fa*) alignedMalloc(numTimeSteps_in*sizeof(AffineSpace3fa),16);

    for (size_t i = 0; i < min(numTimeSteps, numTimeSteps_in); i++)
      local2world2[i] = local2world[i];

    for (size_t i = numTimeSteps; i < numTimeSteps_in; i++)
      local2world2[i] = one;

    alignedFree(local2world);
    local2world = local2world2;

    Geometry::setNumTimeSteps(numTimeSteps_in);
  }

  void Instance::setInstancedScene(const Ref<Scene>& scene)
  {
    if (object) object->refDec();
    object = scene.ptr;
    if (object) object->refInc();
    auto numExpensiveGeo =  scene->getNumPrimitives<CurveGeometry, false>()
                          + scene->getNumPrimitives<CurveGeometry, true>()
                          + scene->getNumPrimitives<UserGeometry, false>()
                          + scene->getNumPrimitives<UserGeometry, true>();
    if (numExpensiveGeo > 0) {
      this->gtype = GTY_INSTANCE_EXPENSIVE;
    }
    Geometry::update();
  }

  void Instance::setTransform(const AffineSpace3fa& xfm, unsigned int timeStep)
  {
    if (timeStep >= numTimeSteps)
      throw_RTCError(RTC_ERROR_INVALID_OPERATION,"invalid timestep");

    local2world[timeStep] = xfm;
    if (timeStep == 0)
      world2local0 = rcp(xfm);
  }

  AffineSpace3fa Instance::getTransform(float time)
  {
    if (likely(numTimeSteps <= 1))
      return getLocal2World();
    else
      return getLocal2World(time);
  }

  void Instance::setMask (unsigned mask)
  {
    this->mask = mask;
    Geometry::update();
  }

#endif

  namespace isa
  {
    Instance* createInstance(Device* device) {
      return new InstanceISA(device);
    }
  }
}
<commit_msg>fix motion blur bug with new instance split<commit_after>// ======================================================================== //
// Copyright 2009-2018 Intel Corporation                                    //
//                                                                          //
// 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.                                           //
// ======================================================================== //

#include "scene_instance.h"
#include "scene.h"

namespace embree
{
#if defined(EMBREE_LOWEST_ISA)

  Instance::Instance (Device* device, Accel* object, unsigned int numTimeSteps)
    : Geometry(device,Geometry::GTY_INSTANCE_CHEAP,1,numTimeSteps), object(object), local2world(nullptr)
  {
    if (object) object->refInc();
    world2local0 = one;
    local2world = (AffineSpace3fa*) alignedMalloc(numTimeSteps*sizeof(AffineSpace3fa),16);
    for (size_t i = 0; i < numTimeSteps; i++)
      local2world[i] = one;
  }

  Instance::~Instance()
  {
    alignedFree(local2world);
    if (object) object->refDec();
  }

  void Instance::enabling () {
    if (numTimeSteps == 1) {
      if (this->gtype == Geometry::GTY_INSTANCE_CHEAP) {
        scene->world.numInstancesCheap += numPrimitives;
      } else {
        scene->world.numInstancesExpensive += numPrimitives;
      }
    } else {
      if (this->gtype == Geometry::GTY_INSTANCE_CHEAP) {
        scene->worldMB.numInstancesCheap += numPrimitives;
      } else {
        scene->worldMB.numInstancesExpensive += numPrimitives;
      }
    }
  }

  void Instance::disabling() {
    if (numTimeSteps == 1) {
      if (this->gtype == Geometry::GTY_INSTANCE_CHEAP) {
        scene->world.numInstancesCheap -= numPrimitives;
      } else {
        scene->world.numInstancesExpensive -= numPrimitives;
      }
    } else {
      if (this->gtype == Geometry::GTY_INSTANCE_CHEAP) {
        scene->worldMB.numInstancesCheap -= numPrimitives;
      } else {
        scene->worldMB.numInstancesExpensive -= numPrimitives;
      }
    }
  }

  void Instance::setNumTimeSteps (unsigned int numTimeSteps_in)
  {
    if (numTimeSteps_in == numTimeSteps)
      return;

    AffineSpace3fa* local2world2 = (AffineSpace3fa*) alignedMalloc(numTimeSteps_in*sizeof(AffineSpace3fa),16);

    for (size_t i = 0; i < min(numTimeSteps, numTimeSteps_in); i++)
      local2world2[i] = local2world[i];

    for (size_t i = numTimeSteps; i < numTimeSteps_in; i++)
      local2world2[i] = one;

    alignedFree(local2world);
    local2world = local2world2;

    Geometry::setNumTimeSteps(numTimeSteps_in);
  }

  void Instance::setInstancedScene(const Ref<Scene>& scene)
  {
    if (object) object->refDec();
    object = scene.ptr;
    if (object) object->refInc();
    auto numExpensiveGeo =  scene->getNumPrimitives<CurveGeometry, false>()
                          + scene->getNumPrimitives<CurveGeometry, true>()
                          + scene->getNumPrimitives<UserGeometry, false>()
                          + scene->getNumPrimitives<UserGeometry, true>();
    if (numExpensiveGeo > 0) {
      this->gtype = GTY_INSTANCE_EXPENSIVE;
    }
    Geometry::update();
  }

  void Instance::setTransform(const AffineSpace3fa& xfm, unsigned int timeStep)
  {
    if (timeStep >= numTimeSteps)
      throw_RTCError(RTC_ERROR_INVALID_OPERATION,"invalid timestep");

    local2world[timeStep] = xfm;
    if (timeStep == 0)
      world2local0 = rcp(xfm);
  }

  AffineSpace3fa Instance::getTransform(float time)
  {
    if (likely(numTimeSteps <= 1))
      return getLocal2World();
    else
      return getLocal2World(time);
  }

  void Instance::setMask (unsigned mask)
  {
    this->mask = mask;
    Geometry::update();
  }

#endif

  namespace isa
  {
    Instance* createInstance(Device* device) {
      return new InstanceISA(device);
    }
  }
}
<|endoftext|>


<commit_before>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	cpp-ethereum 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 General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file dagger.cpp
 * @author Gav Wood <i@gavwood.com>
 * @date 2014
 * Dashimoto test functions.
 */

#include <fstream>
#include <random>
#include "JsonSpiritHeaders.h"
#include <libdevcore/CommonIO.h>
#include <libethcore/ProofOfWork.h>
#include <libethcore/Ethasher.h>
#include <boost/test/unit_test.hpp>
#include "TestHelper.h"

using namespace std;
using namespace dev;
using namespace dev::eth;

namespace js = json_spirit;

using dev::operator <<;

BOOST_AUTO_TEST_SUITE(DashimotoTests)

BOOST_AUTO_TEST_CASE(basic_test)
{
	string testPath = test::getTestPath();

	testPath += "/PoWTests";

	cnote << "Testing Proof of Work...";
	js::mValue v;
	string s = asString(contents(testPath + "/ethash_tests.json"));
	BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of 'ethash_tests.json' is empty. Have you cloned the 'tests' repo branch develop?");
	js::read_string(s, v);
	for (auto& i: v.get_obj())
	{
		cnote << i.first;
		js::mObject& o = i.second.get_obj();
		vector<pair<string, string>> ss;
		BlockInfo header = BlockInfo::fromHeader(fromHex(o["header"].get_str()), CheckNothing);
		h256 headerHash(o["header_hash"].get_str());
		Nonce nonce(o["nonce"].get_str());
		BOOST_REQUIRE_EQUAL(headerHash, header.headerHash(WithoutNonce));
		BOOST_REQUIRE_EQUAL(nonce, header.nonce);

		unsigned cacheSize(o["cache_size"].get_int());
		h256 cacheHash(o["cache_hash"].get_str());
		BOOST_REQUIRE_EQUAL(Ethasher::get()->cache(header).size(), cacheSize);
		BOOST_REQUIRE_EQUAL(sha3(Ethasher::get()->cache(header)), cacheHash);

#if TEST_FULL
		unsigned fullSize(o["full_size"].get_int());
		h256 fullHash(o["full_hash"].get_str());
		BOOST_REQUIRE_EQUAL(Ethasher::get()->full(header).size(), fullSize);
		BOOST_REQUIRE_EQUAL(sha3(Ethasher::get()->full(header)), fullHash);
#endif

		h256 result(o["result"].get_str());
		Ethasher::Result r = Ethasher::eval(header);
		BOOST_REQUIRE_EQUAL(r.value, result);
		BOOST_REQUIRE_EQUAL(r.mixHash, header.mixHash);
	}
}

BOOST_AUTO_TEST_SUITE_END()

<commit_msg>Upgrade to latest ethhash API.<commit_after>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	cpp-ethereum 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 General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file dagger.cpp
 * @author Gav Wood <i@gavwood.com>
 * @date 2014
 * Dashimoto test functions.
 */

#include <fstream>
#include <random>
#include "JsonSpiritHeaders.h"
#include <libdevcore/CommonIO.h>
#include <libethcore/ProofOfWork.h>
#include <libethcore/Ethasher.h>
#include <boost/test/unit_test.hpp>
#include "TestHelper.h"

using namespace std;
using namespace dev;
using namespace dev::eth;

namespace js = json_spirit;

using dev::operator <<;

BOOST_AUTO_TEST_SUITE(DashimotoTests)

BOOST_AUTO_TEST_CASE(basic_test)
{
	string testPath = test::getTestPath();

	testPath += "/PoWTests";

	cnote << "Testing Proof of Work...";
	js::mValue v;
	string s = asString(contents(testPath + "/ethash_tests.json"));
	BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of 'ethash_tests.json' is empty. Have you cloned the 'tests' repo branch develop?");
	js::read_string(s, v);
	for (auto& i: v.get_obj())
	{
		cnote << i.first;
		js::mObject& o = i.second.get_obj();
		vector<pair<string, string>> ss;
		BlockInfo header = BlockInfo::fromHeader(fromHex(o["header"].get_str()), CheckNothing);
		h256 headerHash(o["header_hash"].get_str());
		Nonce nonce(o["nonce"].get_str());
		BOOST_REQUIRE_EQUAL(headerHash, header.headerHash(WithoutNonce));
		BOOST_REQUIRE_EQUAL(nonce, header.nonce);

		unsigned cacheSize(o["cache_size"].get_int());
		h256 cacheHash(o["cache_hash"].get_str());
		BOOST_REQUIRE_EQUAL(Ethasher::get()->params(header).cache_size, cacheSize);
		BOOST_REQUIRE_EQUAL(sha3(bytesConstRef((byte const*)Ethasher::get()->cache(header), cacheSize)), cacheHash);

#if TEST_FULL
		unsigned fullSize(o["full_size"].get_int());
		h256 fullHash(o["full_hash"].get_str());
		BOOST_REQUIRE_EQUAL(Ethasher::get()->full(header).size(), fullSize);
		BOOST_REQUIRE_EQUAL(sha3(Ethasher::get()->full(header)), fullHash);
#endif

		h256 result(o["result"].get_str());
		Ethasher::Result r = Ethasher::eval(header);
		BOOST_REQUIRE_EQUAL(r.value, result);
		BOOST_REQUIRE_EQUAL(r.mixHash, header.mixHash);
	}
}

BOOST_AUTO_TEST_SUITE_END()

<|endoftext|>


<commit_before>// Copyright (c) 2018 The OTS 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 "layout.h"

#include "fvar.h"

// OpenType Variations Common Table Formats

#define TABLE_NAME "Variations" // XXX: use individual table names

namespace {

bool ParseVariationRegionList(const ots::Font* font, const uint8_t* data, const size_t length,
                              uint16_t* regionCount) {
  ots::Buffer subtable(data, length);

  uint16_t axisCount;

  if (!subtable.ReadU16(&axisCount) ||
      !subtable.ReadU16(regionCount)) {
    return OTS_FAILURE_MSG("Failed to read variation region list header");
  }

  if (*regionCount == 0) {
    return true;
  }

  const ots::OpenTypeFVAR* fvar =
    static_cast<ots::OpenTypeFVAR*>(font->GetTypedTable(OTS_TAG_FVAR));
  if (!fvar) {
    return OTS_FAILURE_MSG("Required fvar table is missing");
  }
  if (axisCount != fvar->AxisCount()) {
    return OTS_FAILURE_MSG("Axis count mismatch");
  }

  for (unsigned i = 0; i < *regionCount; i++) {
    for (unsigned j = 0; j < axisCount; j++) {
      int16_t startCoord, peakCoord, endCoord;
      if (!subtable.ReadS16(&startCoord) ||
          !subtable.ReadS16(&peakCoord) ||
          !subtable.ReadS16(&endCoord)) {
        return OTS_FAILURE_MSG("Failed to read region axis coordinates");
      }
      if (startCoord > peakCoord || peakCoord > endCoord) {
        return OTS_FAILURE_MSG("Region axis coordinates out of order");
      }
      if (startCoord < -0x4000 || endCoord > 0x4000) {
        return OTS_FAILURE_MSG("Region axis coordinate out of range");
      }
      if ((peakCoord < 0 && endCoord > 0) ||
          (peakCoord > 0 && startCoord < 0)) {
        return OTS_FAILURE_MSG("Invalid region axis coordinates");
      }
    }
  }

  return true;
}

bool
ParseVariationDataSubtable(const ots::Font* font, const uint8_t* data, const size_t length,
                           const uint16_t regionCount,
                           uint16_t* regionIndexCount) {
  ots::Buffer subtable(data, length);

  uint16_t itemCount;
  uint16_t shortDeltaCount;

  if (!subtable.ReadU16(&itemCount) ||
      !subtable.ReadU16(&shortDeltaCount) ||
      !subtable.ReadU16(regionIndexCount)) {
    return OTS_FAILURE_MSG("Failed to read variation data subtable header");
  }

  for (unsigned i = 0; i < *regionIndexCount; i++) {
    uint16_t regionIndex;
    if (!subtable.ReadU16(&regionIndex) || regionIndex >= regionCount) {
      return OTS_FAILURE_MSG("Bad region index");
    }
  }

  if (!subtable.Skip(size_t(itemCount) * (size_t(shortDeltaCount) + size_t(*regionIndexCount)))) {
    return OTS_FAILURE_MSG("Failed to read delta data");
  }

  return true;
}

} // namespace

namespace ots {

bool
ParseItemVariationStore(const Font* font,
                        const uint8_t* data, const size_t length,
                        std::vector<uint16_t>* regionIndexCounts) {
  Buffer subtable(data, length);

  uint16_t format;
  uint32_t variationRegionListOffset;
  uint16_t itemVariationDataCount;

  if (!subtable.ReadU16(&format) ||
      !subtable.ReadU32(&variationRegionListOffset) ||
      !subtable.ReadU16(&itemVariationDataCount)) {
    return OTS_FAILURE_MSG("Failed to read item variation store header");
  }

  if (format != 1) {
    return OTS_FAILURE_MSG("Unknown item variation store format");
  }

  if (variationRegionListOffset < subtable.offset() + 4 * itemVariationDataCount ||
      variationRegionListOffset > length) {
    return OTS_FAILURE_MSG("Invalid variation region list offset");
  }

  uint16_t regionCount;
  if (!ParseVariationRegionList(font,
                                data + variationRegionListOffset,
                                length - variationRegionListOffset,
                                &regionCount)) {
    return OTS_FAILURE_MSG("Failed to parse variation region list");
  }

  for (unsigned i = 0; i < itemVariationDataCount; i++) {
    uint32_t offset;
    if (!subtable.ReadU32(&offset)) {
      return OTS_FAILURE_MSG("Failed to read variation data subtable offset");
    }
    if (offset >= length) {
      return OTS_FAILURE_MSG("Bad offset to variation data subtable");
    }
    uint16_t regionIndexCount = 0;
    if (!ParseVariationDataSubtable(font, data + offset, length - offset,
                                    regionCount,
                                    &regionIndexCount)) {
      return OTS_FAILURE_MSG("Failed to parse variation data subtable");
    }
    if (regionIndexCounts) {
      regionIndexCounts->push_back(regionIndexCount);
    }
  }

  return true;
}

bool ParseDeltaSetIndexMap(const Font* font, const uint8_t* data, const size_t length) {
  Buffer subtable(data, length);

  uint16_t entryFormat;
  uint16_t mapCount;

  if (!subtable.ReadU16(&entryFormat) ||
      !subtable.ReadU16(&mapCount)) {
    return OTS_FAILURE_MSG("Failed to read delta set index map header");
  }

  const uint16_t MAP_ENTRY_SIZE_MASK = 0x0030;

  const uint16_t entrySize = (((entryFormat & MAP_ENTRY_SIZE_MASK) >> 4) + 1);
  if (!subtable.Skip(entrySize * mapCount)) {
    return OTS_FAILURE_MSG("Failed to read delta set index map data");
  }

  return true;
}

bool ParseVariationData(const Font* font, const uint8_t* data, size_t length,
                        size_t axisCount, size_t sharedTupleCount) {
  Buffer subtable(data, length);

  uint16_t tupleVariationCount;
  uint16_t dataOffset;
  if (!subtable.ReadU16(&tupleVariationCount) ||
      !subtable.ReadU16(&dataOffset)) {
    return OTS_FAILURE_MSG("Failed to read variation data header");
  }

  if (dataOffset > length) {
    return OTS_FAILURE_MSG("Invalid serialized data offset");
  }

  tupleVariationCount &= 0x0FFF; // mask off flags

  const uint16_t EMBEDDED_PEAK_TUPLE = 0x8000;
  const uint16_t INTERMEDIATE_REGION = 0x4000;
  const uint16_t TUPLE_INDEX_MASK    = 0x0FFF;

  for (unsigned i = 0; i < tupleVariationCount; i++) {
    uint16_t variationDataSize;
    uint16_t tupleIndex;

    if (!subtable.ReadU16(&variationDataSize) ||
        !subtable.ReadU16(&tupleIndex)) {
      return OTS_FAILURE_MSG("Failed to read tuple variation header");
    }

    if (tupleIndex & EMBEDDED_PEAK_TUPLE) {
      for (unsigned axis = 0; axis < axisCount; axis++) {
        int16_t coordinate;
        if (!subtable.ReadS16(&coordinate)) {
          return OTS_FAILURE_MSG("Failed to read tuple coordinate");
        }
        if (coordinate < -0x4000 || coordinate > 0x4000) {
          return OTS_FAILURE_MSG("Tuple coordinate not in the range [-1.0, 1.0]: %g", coordinate / 16384.);
        }
      }
    }

    if (tupleIndex & INTERMEDIATE_REGION) {
      std::vector<int16_t> startTuple(axisCount);
      for (unsigned axis = 0; axis < axisCount; axis++) {
        int16_t coordinate;
        if (!subtable.ReadS16(&coordinate)) {
          return OTS_FAILURE_MSG("Failed to read tuple coordinate");
        }
        if (coordinate < -0x4000 || coordinate > 0x4000) {
          return OTS_FAILURE_MSG("Tuple coordinate not in the range [-1.0, 1.0]: %g", coordinate / 16384.);
        }
        startTuple.push_back(coordinate);
      }

      std::vector<int16_t> endTuple(axisCount);
      for (unsigned axis = 0; axis < axisCount; axis++) {
        int16_t coordinate;
        if (!subtable.ReadS16(&coordinate)) {
          return OTS_FAILURE_MSG("Failed to read tuple coordinate");
        }
        if (coordinate < -0x4000 || coordinate > 0x4000) {
          return OTS_FAILURE_MSG("Tuple coordinate not in the range [-1.0, 1.0]: %g", coordinate / 16384.);
        }
        endTuple.push_back(coordinate);
      }

      for (unsigned axis = 0; axis < axisCount; axis++) {
        if (startTuple[axis] > endTuple[axis]) {
          return OTS_FAILURE_MSG("Invalid intermediate range");
        }
      }
    }

    if (!(tupleIndex & EMBEDDED_PEAK_TUPLE)) {
      tupleIndex &= TUPLE_INDEX_MASK;
      if (tupleIndex >= sharedTupleCount) {
        return OTS_FAILURE_MSG("Tuple index out of range");
      }
    }
  }

  // TODO: we don't attempt to interpret the serialized data block

  return true;
}

} // namespace ots

#undef TABLE_NAME
<commit_msg>[variations] Support the LONG_WORDS flag in item variation data (32-bit variable values).<commit_after>// Copyright (c) 2018 The OTS 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 "layout.h"

#include "fvar.h"

// OpenType Variations Common Table Formats

#define TABLE_NAME "Variations" // XXX: use individual table names

namespace {

bool ParseVariationRegionList(const ots::Font* font, const uint8_t* data, const size_t length,
                              uint16_t* regionCount) {
  ots::Buffer subtable(data, length);

  uint16_t axisCount;

  if (!subtable.ReadU16(&axisCount) ||
      !subtable.ReadU16(regionCount)) {
    return OTS_FAILURE_MSG("Failed to read variation region list header");
  }

  if (*regionCount == 0) {
    return true;
  }

  const ots::OpenTypeFVAR* fvar =
    static_cast<ots::OpenTypeFVAR*>(font->GetTypedTable(OTS_TAG_FVAR));
  if (!fvar) {
    return OTS_FAILURE_MSG("Required fvar table is missing");
  }
  if (axisCount != fvar->AxisCount()) {
    return OTS_FAILURE_MSG("Axis count mismatch");
  }

  for (unsigned i = 0; i < *regionCount; i++) {
    for (unsigned j = 0; j < axisCount; j++) {
      int16_t startCoord, peakCoord, endCoord;
      if (!subtable.ReadS16(&startCoord) ||
          !subtable.ReadS16(&peakCoord) ||
          !subtable.ReadS16(&endCoord)) {
        return OTS_FAILURE_MSG("Failed to read region axis coordinates");
      }
      if (startCoord > peakCoord || peakCoord > endCoord) {
        return OTS_FAILURE_MSG("Region axis coordinates out of order");
      }
      if (startCoord < -0x4000 || endCoord > 0x4000) {
        return OTS_FAILURE_MSG("Region axis coordinate out of range");
      }
      if ((peakCoord < 0 && endCoord > 0) ||
          (peakCoord > 0 && startCoord < 0)) {
        return OTS_FAILURE_MSG("Invalid region axis coordinates");
      }
    }
  }

  return true;
}

bool
ParseVariationDataSubtable(const ots::Font* font, const uint8_t* data, const size_t length,
                           const uint16_t regionCount,
                           uint16_t* regionIndexCount) {
  ots::Buffer subtable(data, length);

  uint16_t itemCount;
  uint16_t wordDeltaCount;

  const uint16_t LONG_WORDS	= 0x8000u;
  const uint16_t WORD_DELTA_COUNT_MASK = 0x7FFF;

  if (!subtable.ReadU16(&itemCount) ||
      !subtable.ReadU16(&wordDeltaCount) ||
      !subtable.ReadU16(regionIndexCount)) {
    return OTS_FAILURE_MSG("Failed to read variation data subtable header");
  }

  size_t valueSize = (wordDeltaCount & LONG_WORDS) ? 2 : 1;
  wordDeltaCount &= WORD_DELTA_COUNT_MASK;

  if (wordDeltaCount > *regionIndexCount) {
    return OTS_FAILURE_MSG("Bad word delta count");
  }

  for (unsigned i = 0; i < *regionIndexCount; i++) {
    uint16_t regionIndex;
    if (!subtable.ReadU16(&regionIndex) || regionIndex >= regionCount) {
      return OTS_FAILURE_MSG("Bad region index");
    }
  }

  if (!subtable.Skip(valueSize * size_t(itemCount) * (size_t(wordDeltaCount) + size_t(*regionIndexCount)))) {
    return OTS_FAILURE_MSG("Failed to read delta data");
  }

  return true;
}

} // namespace

namespace ots {

bool
ParseItemVariationStore(const Font* font,
                        const uint8_t* data, const size_t length,
                        std::vector<uint16_t>* regionIndexCounts) {
  Buffer subtable(data, length);

  uint16_t format;
  uint32_t variationRegionListOffset;
  uint16_t itemVariationDataCount;

  if (!subtable.ReadU16(&format) ||
      !subtable.ReadU32(&variationRegionListOffset) ||
      !subtable.ReadU16(&itemVariationDataCount)) {
    return OTS_FAILURE_MSG("Failed to read item variation store header");
  }

  if (format != 1) {
    return OTS_FAILURE_MSG("Unknown item variation store format");
  }

  if (variationRegionListOffset < subtable.offset() + 4 * itemVariationDataCount ||
      variationRegionListOffset > length) {
    return OTS_FAILURE_MSG("Invalid variation region list offset");
  }

  uint16_t regionCount;
  if (!ParseVariationRegionList(font,
                                data + variationRegionListOffset,
                                length - variationRegionListOffset,
                                &regionCount)) {
    return OTS_FAILURE_MSG("Failed to parse variation region list");
  }

  for (unsigned i = 0; i < itemVariationDataCount; i++) {
    uint32_t offset;
    if (!subtable.ReadU32(&offset)) {
      return OTS_FAILURE_MSG("Failed to read variation data subtable offset");
    }
    if (offset >= length) {
      return OTS_FAILURE_MSG("Bad offset to variation data subtable");
    }
    uint16_t regionIndexCount = 0;
    if (!ParseVariationDataSubtable(font, data + offset, length - offset,
                                    regionCount,
                                    &regionIndexCount)) {
      return OTS_FAILURE_MSG("Failed to parse variation data subtable");
    }
    if (regionIndexCounts) {
      regionIndexCounts->push_back(regionIndexCount);
    }
  }

  return true;
}

bool ParseDeltaSetIndexMap(const Font* font, const uint8_t* data, const size_t length) {
  Buffer subtable(data, length);

  uint16_t entryFormat;
  uint16_t mapCount;

  if (!subtable.ReadU16(&entryFormat) ||
      !subtable.ReadU16(&mapCount)) {
    return OTS_FAILURE_MSG("Failed to read delta set index map header");
  }

  const uint16_t MAP_ENTRY_SIZE_MASK = 0x0030;

  const uint16_t entrySize = (((entryFormat & MAP_ENTRY_SIZE_MASK) >> 4) + 1);
  if (!subtable.Skip(entrySize * mapCount)) {
    return OTS_FAILURE_MSG("Failed to read delta set index map data");
  }

  return true;
}

bool ParseVariationData(const Font* font, const uint8_t* data, size_t length,
                        size_t axisCount, size_t sharedTupleCount) {
  Buffer subtable(data, length);

  uint16_t tupleVariationCount;
  uint16_t dataOffset;
  if (!subtable.ReadU16(&tupleVariationCount) ||
      !subtable.ReadU16(&dataOffset)) {
    return OTS_FAILURE_MSG("Failed to read variation data header");
  }

  if (dataOffset > length) {
    return OTS_FAILURE_MSG("Invalid serialized data offset");
  }

  tupleVariationCount &= 0x0FFF; // mask off flags

  const uint16_t EMBEDDED_PEAK_TUPLE = 0x8000;
  const uint16_t INTERMEDIATE_REGION = 0x4000;
  const uint16_t TUPLE_INDEX_MASK    = 0x0FFF;

  for (unsigned i = 0; i < tupleVariationCount; i++) {
    uint16_t variationDataSize;
    uint16_t tupleIndex;

    if (!subtable.ReadU16(&variationDataSize) ||
        !subtable.ReadU16(&tupleIndex)) {
      return OTS_FAILURE_MSG("Failed to read tuple variation header");
    }

    if (tupleIndex & EMBEDDED_PEAK_TUPLE) {
      for (unsigned axis = 0; axis < axisCount; axis++) {
        int16_t coordinate;
        if (!subtable.ReadS16(&coordinate)) {
          return OTS_FAILURE_MSG("Failed to read tuple coordinate");
        }
        if (coordinate < -0x4000 || coordinate > 0x4000) {
          return OTS_FAILURE_MSG("Tuple coordinate not in the range [-1.0, 1.0]: %g", coordinate / 16384.);
        }
      }
    }

    if (tupleIndex & INTERMEDIATE_REGION) {
      std::vector<int16_t> startTuple(axisCount);
      for (unsigned axis = 0; axis < axisCount; axis++) {
        int16_t coordinate;
        if (!subtable.ReadS16(&coordinate)) {
          return OTS_FAILURE_MSG("Failed to read tuple coordinate");
        }
        if (coordinate < -0x4000 || coordinate > 0x4000) {
          return OTS_FAILURE_MSG("Tuple coordinate not in the range [-1.0, 1.0]: %g", coordinate / 16384.);
        }
        startTuple.push_back(coordinate);
      }

      std::vector<int16_t> endTuple(axisCount);
      for (unsigned axis = 0; axis < axisCount; axis++) {
        int16_t coordinate;
        if (!subtable.ReadS16(&coordinate)) {
          return OTS_FAILURE_MSG("Failed to read tuple coordinate");
        }
        if (coordinate < -0x4000 || coordinate > 0x4000) {
          return OTS_FAILURE_MSG("Tuple coordinate not in the range [-1.0, 1.0]: %g", coordinate / 16384.);
        }
        endTuple.push_back(coordinate);
      }

      for (unsigned axis = 0; axis < axisCount; axis++) {
        if (startTuple[axis] > endTuple[axis]) {
          return OTS_FAILURE_MSG("Invalid intermediate range");
        }
      }
    }

    if (!(tupleIndex & EMBEDDED_PEAK_TUPLE)) {
      tupleIndex &= TUPLE_INDEX_MASK;
      if (tupleIndex >= sharedTupleCount) {
        return OTS_FAILURE_MSG("Tuple index out of range");
      }
    }
  }

  // TODO: we don't attempt to interpret the serialized data block

  return true;
}

} // namespace ots

#undef TABLE_NAME
<|endoftext|>


<commit_before>/*
 ***********************************************************************************************************************
 *
 *  Copyright (c) 2017-2020 Advanced Micro Devices, Inc. All Rights Reserved.
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 *
 **********************************************************************************************************************/
/**
 ***********************************************************************************************************************
 * @file  PatchLoadScalarizer.cpp
 * @brief LLPC source file: contains implementation of class lgc::PatchLoadScalarizer.
 ***********************************************************************************************************************
 */
#include "PatchLoadScalarizer.h"
#include "lgc/state/PipelineShaders.h"
#include "lgc/state/PipelineState.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Instructions.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"

#define DEBUG_TYPE "lgc-patch-load-scalarizer"

using namespace lgc;
using namespace llvm;

namespace lgc {

// =====================================================================================================================
// Define static members (no initializer needed as LLVM only cares about the address of ID, never its value).
char PatchLoadScalarizer::ID;

// =====================================================================================================================
// Pass creator, creates the pass of LLVM patching operations for load scalarizer optimizations.
FunctionPass *createPatchLoadScalarizer() {
  return new PatchLoadScalarizer();
}

// =====================================================================================================================
PatchLoadScalarizer::PatchLoadScalarizer() : FunctionPass(ID) {
  m_scalarThreshold = 0;
}

// =====================================================================================================================
// Get the analysis usage of this pass.
//
// @param [out] analysisUsage : The analysis usage.
void PatchLoadScalarizer::getAnalysisUsage(AnalysisUsage &analysisUsage) const {
  analysisUsage.addRequired<PipelineStateWrapper>();
  analysisUsage.addRequired<PipelineShaders>();
  analysisUsage.addPreserved<PipelineShaders>();
}

// =====================================================================================================================
// Executes this LLVM pass on the specified LLVM function.
//
// @param [in,out] function : Function that will run this optimization.
bool PatchLoadScalarizer::runOnFunction(Function &function) {
  LLVM_DEBUG(dbgs() << "Run the pass Patch-Load-Scalarizer-Opt\n");

  auto pipelineState = getAnalysis<PipelineStateWrapper>().getPipelineState(function.getParent());
  auto pipelineShaders = &getAnalysis<PipelineShaders>();
  auto shaderStage = pipelineShaders->getShaderStage(&function);

  // If the function is not a valid shader stage, or the optimization is disabled, bail.
  m_scalarThreshold = 0;
  if (shaderStage != ShaderStageInvalid)
    m_scalarThreshold = pipelineState->getShaderOptions(shaderStage).loadScalarizerThreshold;
  if (m_scalarThreshold == 0)
    return false;

  m_builder.reset(new IRBuilder<>(function.getContext()));

  visit(function);

  const bool changed = (!m_instsToErase.empty());

  for (Instruction *const inst : m_instsToErase) {
    // Lastly delete any instructions we replaced.
    inst->eraseFromParent();
  }
  m_instsToErase.clear();

  return changed;
}

// =====================================================================================================================
// Visits "load" instruction.
//
// @param loadInst : The instruction
void PatchLoadScalarizer::visitLoadInst(LoadInst &loadInst) {
  const unsigned addrSpace = loadInst.getPointerAddressSpace();
  auto loadTy = dyn_cast<VectorType>(loadInst.getType());

  if (loadTy) {
    // This optimization will try to scalarize the load inst. The pattern is like:
    //    %loadValue = load <4 x float>, <4 x float> addrspace(7)* %loadPtr, align 16
    // will be converted to:
    //    %newloadPtr = bitcast <4 x float> addrspace(7)* %loadPtr to float addrspace(7)*
    //    %loadCompPtr.i0 = getelementptr float, float addrspace(7)* %newloadPtr, i32 0
    //    %loadComp.i0 = load float, float addrspace(7)* %loadCompPtr.i0, align 16
    //    %loadCompPtr.i1 = getelementptr float, float addrspace(7)* %newloadPtr, i32 1
    //    %loadComp.i1 = load float, float addrspace(7)* %loadCompPtr.i1, align 4
    //    %loadCompPtr.i2 = getelementptr float, float addrspace(7)* %newloadPtr, i32 2
    //    %loadComp.i2 = load float, float addrspace(7)* %loadCompPtr.i2, align 8
    //    %loadCompPtr.i3 = getelementptr float, float addrspace(7)* %newloadPtr, i32 3
    //    %loadComp.i3 = load float, float addrspace(7)* %loadCompPtr.i3, align 4
    //    %loadValue.i0 = insertelement <4 x float> undef, float %loadComp.i0, i32 0
    //    %loadValue.i01 = insertelement <4 x float> %loadValue.i0, float %loadComp.i1, i32 1
    //    %loadValue.i012 = insertelement <4 x float> %loadValue.i01, float %loadComp.i2, i32 2
    //    %loadValue = insertelement <4 x float> %loadValue.i012, float %loadComp.i3, i32 3

    unsigned compCount = loadTy->getNumElements();

    if (compCount > m_scalarThreshold)
      return;

    Type *compTy = cast<VectorType>(loadTy)->getElementType();
    uint64_t compSize = loadInst.getModule()->getDataLayout().getTypeStoreSize(compTy);

    Value *loadValue = UndefValue::get(loadTy);
    Type *newLoadPtrTy = PointerType::get(compTy, addrSpace);
    SmallVector<Value *, 4> loadComps;

    loadComps.resize(compCount);

    // Get all the metadata
    SmallVector<std::pair<unsigned, MDNode *>, 8> allMetaNodes;
    loadInst.getAllMetadata(allMetaNodes);

    m_builder->SetInsertPoint(&loadInst);
    Value *newLoadPtr = m_builder->CreateBitCast(loadInst.getPointerOperand(), newLoadPtrTy,
                                                 loadInst.getPointerOperand()->getName() + ".i0");

    for (unsigned i = 0; i < compCount; i++) {
      Value *loadCompPtr = m_builder->CreateConstGEP1_32(compTy, newLoadPtr, i,
                                                         loadInst.getPointerOperand()->getName() + ".i" + Twine(i));
      // Calculate the alignment of component i
      uint64_t compAlignment = MinAlign(loadInst.getAlignment(), i * compSize);

      loadComps[i] = m_builder->CreateAlignedLoad(compTy, loadCompPtr, Align(compAlignment),
                                                  loadInst.getName() + ".ii" + Twine(i));

      for (auto metaNode : allMetaNodes)
        dyn_cast<Instruction>(loadComps[i])->setMetadata(metaNode.first, metaNode.second);
    }

    for (unsigned i = 0; i < compCount; i++) {
      loadValue = m_builder->CreateInsertElement(loadValue, loadComps[i], m_builder->getInt32(i),
                                                 loadInst.getName() + ".u" + Twine(i));
    }

    loadValue->takeName(&loadInst);
    loadInst.replaceAllUsesWith(loadValue);
    m_instsToErase.push_back(&loadInst);
  }
}

} // namespace lgc

// =====================================================================================================================
// Initializes the pass of LLVM patching operations for load scarlarizer optimization.
INITIALIZE_PASS(PatchLoadScalarizer, DEBUG_TYPE, "Patch LLVM for load scarlarizer optimization", false, false)
<commit_msg>Fix typo in pass description<commit_after>/*
 ***********************************************************************************************************************
 *
 *  Copyright (c) 2017-2020 Advanced Micro Devices, Inc. All Rights Reserved.
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 *
 **********************************************************************************************************************/
/**
 ***********************************************************************************************************************
 * @file  PatchLoadScalarizer.cpp
 * @brief LLPC source file: contains implementation of class lgc::PatchLoadScalarizer.
 ***********************************************************************************************************************
 */
#include "PatchLoadScalarizer.h"
#include "lgc/state/PipelineShaders.h"
#include "lgc/state/PipelineState.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Instructions.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"

#define DEBUG_TYPE "lgc-patch-load-scalarizer"

using namespace lgc;
using namespace llvm;

namespace lgc {

// =====================================================================================================================
// Define static members (no initializer needed as LLVM only cares about the address of ID, never its value).
char PatchLoadScalarizer::ID;

// =====================================================================================================================
// Pass creator, creates the pass of LLVM patching operations for load scalarizer optimizations.
FunctionPass *createPatchLoadScalarizer() {
  return new PatchLoadScalarizer();
}

// =====================================================================================================================
PatchLoadScalarizer::PatchLoadScalarizer() : FunctionPass(ID) {
  m_scalarThreshold = 0;
}

// =====================================================================================================================
// Get the analysis usage of this pass.
//
// @param [out] analysisUsage : The analysis usage.
void PatchLoadScalarizer::getAnalysisUsage(AnalysisUsage &analysisUsage) const {
  analysisUsage.addRequired<PipelineStateWrapper>();
  analysisUsage.addRequired<PipelineShaders>();
  analysisUsage.addPreserved<PipelineShaders>();
}

// =====================================================================================================================
// Executes this LLVM pass on the specified LLVM function.
//
// @param [in,out] function : Function that will run this optimization.
bool PatchLoadScalarizer::runOnFunction(Function &function) {
  LLVM_DEBUG(dbgs() << "Run the pass Patch-Load-Scalarizer-Opt\n");

  auto pipelineState = getAnalysis<PipelineStateWrapper>().getPipelineState(function.getParent());
  auto pipelineShaders = &getAnalysis<PipelineShaders>();
  auto shaderStage = pipelineShaders->getShaderStage(&function);

  // If the function is not a valid shader stage, or the optimization is disabled, bail.
  m_scalarThreshold = 0;
  if (shaderStage != ShaderStageInvalid)
    m_scalarThreshold = pipelineState->getShaderOptions(shaderStage).loadScalarizerThreshold;
  if (m_scalarThreshold == 0)
    return false;

  m_builder.reset(new IRBuilder<>(function.getContext()));

  visit(function);

  const bool changed = (!m_instsToErase.empty());

  for (Instruction *const inst : m_instsToErase) {
    // Lastly delete any instructions we replaced.
    inst->eraseFromParent();
  }
  m_instsToErase.clear();

  return changed;
}

// =====================================================================================================================
// Visits "load" instruction.
//
// @param loadInst : The instruction
void PatchLoadScalarizer::visitLoadInst(LoadInst &loadInst) {
  const unsigned addrSpace = loadInst.getPointerAddressSpace();
  auto loadTy = dyn_cast<VectorType>(loadInst.getType());

  if (loadTy) {
    // This optimization will try to scalarize the load inst. The pattern is like:
    //    %loadValue = load <4 x float>, <4 x float> addrspace(7)* %loadPtr, align 16
    // will be converted to:
    //    %newloadPtr = bitcast <4 x float> addrspace(7)* %loadPtr to float addrspace(7)*
    //    %loadCompPtr.i0 = getelementptr float, float addrspace(7)* %newloadPtr, i32 0
    //    %loadComp.i0 = load float, float addrspace(7)* %loadCompPtr.i0, align 16
    //    %loadCompPtr.i1 = getelementptr float, float addrspace(7)* %newloadPtr, i32 1
    //    %loadComp.i1 = load float, float addrspace(7)* %loadCompPtr.i1, align 4
    //    %loadCompPtr.i2 = getelementptr float, float addrspace(7)* %newloadPtr, i32 2
    //    %loadComp.i2 = load float, float addrspace(7)* %loadCompPtr.i2, align 8
    //    %loadCompPtr.i3 = getelementptr float, float addrspace(7)* %newloadPtr, i32 3
    //    %loadComp.i3 = load float, float addrspace(7)* %loadCompPtr.i3, align 4
    //    %loadValue.i0 = insertelement <4 x float> undef, float %loadComp.i0, i32 0
    //    %loadValue.i01 = insertelement <4 x float> %loadValue.i0, float %loadComp.i1, i32 1
    //    %loadValue.i012 = insertelement <4 x float> %loadValue.i01, float %loadComp.i2, i32 2
    //    %loadValue = insertelement <4 x float> %loadValue.i012, float %loadComp.i3, i32 3

    unsigned compCount = loadTy->getNumElements();

    if (compCount > m_scalarThreshold)
      return;

    Type *compTy = cast<VectorType>(loadTy)->getElementType();
    uint64_t compSize = loadInst.getModule()->getDataLayout().getTypeStoreSize(compTy);

    Value *loadValue = UndefValue::get(loadTy);
    Type *newLoadPtrTy = PointerType::get(compTy, addrSpace);
    SmallVector<Value *, 4> loadComps;

    loadComps.resize(compCount);

    // Get all the metadata
    SmallVector<std::pair<unsigned, MDNode *>, 8> allMetaNodes;
    loadInst.getAllMetadata(allMetaNodes);

    m_builder->SetInsertPoint(&loadInst);
    Value *newLoadPtr = m_builder->CreateBitCast(loadInst.getPointerOperand(), newLoadPtrTy,
                                                 loadInst.getPointerOperand()->getName() + ".i0");

    for (unsigned i = 0; i < compCount; i++) {
      Value *loadCompPtr = m_builder->CreateConstGEP1_32(compTy, newLoadPtr, i,
                                                         loadInst.getPointerOperand()->getName() + ".i" + Twine(i));
      // Calculate the alignment of component i
      uint64_t compAlignment = MinAlign(loadInst.getAlignment(), i * compSize);

      loadComps[i] = m_builder->CreateAlignedLoad(compTy, loadCompPtr, Align(compAlignment),
                                                  loadInst.getName() + ".ii" + Twine(i));

      for (auto metaNode : allMetaNodes)
        dyn_cast<Instruction>(loadComps[i])->setMetadata(metaNode.first, metaNode.second);
    }

    for (unsigned i = 0; i < compCount; i++) {
      loadValue = m_builder->CreateInsertElement(loadValue, loadComps[i], m_builder->getInt32(i),
                                                 loadInst.getName() + ".u" + Twine(i));
    }

    loadValue->takeName(&loadInst);
    loadInst.replaceAllUsesWith(loadValue);
    m_instsToErase.push_back(&loadInst);
  }
}

} // namespace lgc

// =====================================================================================================================
// Initializes the pass of LLVM patching operations for load scalarizer optimization.
INITIALIZE_PASS(PatchLoadScalarizer, DEBUG_TYPE, "Patch LLVM for load scalarizer optimization", false, false)
<|endoftext|>


<commit_before>//===- CocoaConventions.h - Special handling of Cocoa conventions -*- C++ -*--//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements cocoa naming convention analysis.
//
//===----------------------------------------------------------------------===//

#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
#include "clang/AST/Type.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/ErrorHandling.h"

using namespace clang;
using namespace ento;

using llvm::StringRef;

// The "fundamental rule" for naming conventions of methods:
//  (url broken into two lines)
//  http://developer.apple.com/documentation/Cocoa/Conceptual/
//     MemoryMgmt/Tasks/MemoryManagementRules.html
//
// "You take ownership of an object if you create it using a method whose name
//  begins with "alloc" or "new" or contains "copy" (for example, alloc,
//  newObject, or mutableCopy), or if you send it a retain message. You are
//  responsible for relinquishing ownership of objects you own using release
//  or autorelease. Any other time you receive an object, you must
//  not release it."
//

cocoa::NamingConvention cocoa::deriveNamingConvention(Selector S) {
  switch (S.getMethodFamily()) {
  case OMF_None:
  case OMF_autorelease:
  case OMF_dealloc:
  case OMF_release:
  case OMF_retain:
  case OMF_retainCount:
  case OMF_self:
    return NoConvention;

  case OMF_init:
    return InitRule;

  case OMF_alloc:
  case OMF_copy:
  case OMF_mutableCopy:
  case OMF_new:
    return CreateRule;
  }
  llvm_unreachable("unexpected naming convention");
  return NoConvention;
}

bool cocoa::isRefType(QualType RetTy, llvm::StringRef Prefix,
                      llvm::StringRef Name) {
  // Recursively walk the typedef stack, allowing typedefs of reference types.
  while (const TypedefType *TD = dyn_cast<TypedefType>(RetTy.getTypePtr())) {
    llvm::StringRef TDName = TD->getDecl()->getIdentifier()->getName();
    if (TDName.startswith(Prefix) && TDName.endswith("Ref"))
      return true;

    RetTy = TD->getDecl()->getUnderlyingType();
  }

  if (Name.empty())
    return false;

  // Is the type void*?
  const PointerType* PT = RetTy->getAs<PointerType>();
  if (!(PT->getPointeeType().getUnqualifiedType()->isVoidType()))
    return false;

  // Does the name start with the prefix?
  return Name.startswith(Prefix);
}

bool cocoa::isCFObjectRef(QualType T) {
  return isRefType(T, "CF") || // Core Foundation.
         isRefType(T, "CG") || // Core Graphics.
         isRefType(T, "DADisk") || // Disk Arbitration API.
         isRefType(T, "DADissenter") ||
         isRefType(T, "DASessionRef");
}

bool cocoa::isCocoaObjectRef(QualType Ty) {
  if (!Ty->isObjCObjectPointerType())
    return false;

  const ObjCObjectPointerType *PT = Ty->getAs<ObjCObjectPointerType>();

  // Can be true for objects with the 'NSObject' attribute.
  if (!PT)
    return true;

  // We assume that id<..>, id, Class, and Class<..> all represent tracked
  // objects.
  if (PT->isObjCIdType() || PT->isObjCQualifiedIdType() ||
      PT->isObjCClassType() || PT->isObjCQualifiedClassType())
    return true;

  // Does the interface subclass NSObject?
  // FIXME: We can memoize here if this gets too expensive.
  const ObjCInterfaceDecl *ID = PT->getInterfaceDecl();

  // Assume that anything declared with a forward declaration and no
  // @interface subclasses NSObject.
  if (ID->isForwardDecl())
    return true;

  for ( ; ID ; ID = ID->getSuperClass())
    if (ID->getIdentifier()->getName() == "NSObject")
      return true;

  return false;
}
<commit_msg>Added a missing case  label.<commit_after>//===- CocoaConventions.h - Special handling of Cocoa conventions -*- C++ -*--//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements cocoa naming convention analysis.
//
//===----------------------------------------------------------------------===//

#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
#include "clang/AST/Type.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/ErrorHandling.h"

using namespace clang;
using namespace ento;

using llvm::StringRef;

// The "fundamental rule" for naming conventions of methods:
//  (url broken into two lines)
//  http://developer.apple.com/documentation/Cocoa/Conceptual/
//     MemoryMgmt/Tasks/MemoryManagementRules.html
//
// "You take ownership of an object if you create it using a method whose name
//  begins with "alloc" or "new" or contains "copy" (for example, alloc,
//  newObject, or mutableCopy), or if you send it a retain message. You are
//  responsible for relinquishing ownership of objects you own using release
//  or autorelease. Any other time you receive an object, you must
//  not release it."
//

cocoa::NamingConvention cocoa::deriveNamingConvention(Selector S) {
  switch (S.getMethodFamily()) {
  case OMF_None:
  case OMF_autorelease:
  case OMF_dealloc:
  case OMF_release:
  case OMF_retain:
  case OMF_retainCount:
  case OMF_self:
  case OMF_performSelector:
    return NoConvention;

  case OMF_init:
    return InitRule;

  case OMF_alloc:
  case OMF_copy:
  case OMF_mutableCopy:
  case OMF_new:
    return CreateRule;
  }
  llvm_unreachable("unexpected naming convention");
  return NoConvention;
}

bool cocoa::isRefType(QualType RetTy, llvm::StringRef Prefix,
                      llvm::StringRef Name) {
  // Recursively walk the typedef stack, allowing typedefs of reference types.
  while (const TypedefType *TD = dyn_cast<TypedefType>(RetTy.getTypePtr())) {
    llvm::StringRef TDName = TD->getDecl()->getIdentifier()->getName();
    if (TDName.startswith(Prefix) && TDName.endswith("Ref"))
      return true;

    RetTy = TD->getDecl()->getUnderlyingType();
  }

  if (Name.empty())
    return false;

  // Is the type void*?
  const PointerType* PT = RetTy->getAs<PointerType>();
  if (!(PT->getPointeeType().getUnqualifiedType()->isVoidType()))
    return false;

  // Does the name start with the prefix?
  return Name.startswith(Prefix);
}

bool cocoa::isCFObjectRef(QualType T) {
  return isRefType(T, "CF") || // Core Foundation.
         isRefType(T, "CG") || // Core Graphics.
         isRefType(T, "DADisk") || // Disk Arbitration API.
         isRefType(T, "DADissenter") ||
         isRefType(T, "DASessionRef");
}

bool cocoa::isCocoaObjectRef(QualType Ty) {
  if (!Ty->isObjCObjectPointerType())
    return false;

  const ObjCObjectPointerType *PT = Ty->getAs<ObjCObjectPointerType>();

  // Can be true for objects with the 'NSObject' attribute.
  if (!PT)
    return true;

  // We assume that id<..>, id, Class, and Class<..> all represent tracked
  // objects.
  if (PT->isObjCIdType() || PT->isObjCQualifiedIdType() ||
      PT->isObjCClassType() || PT->isObjCQualifiedClassType())
    return true;

  // Does the interface subclass NSObject?
  // FIXME: We can memoize here if this gets too expensive.
  const ObjCInterfaceDecl *ID = PT->getInterfaceDecl();

  // Assume that anything declared with a forward declaration and no
  // @interface subclasses NSObject.
  if (ID->isForwardDecl())
    return true;

  for ( ; ID ; ID = ID->getSuperClass())
    if (ID->getIdentifier()->getName() == "NSObject")
      return true;

  return false;
}
<|endoftext|>


<commit_before>#include "qquickgridstar.h"

QQuickRowDefinition::QQuickRowDefinition(QQuickItem *parent) :
    QQuickItem(parent),
    m_weight(1.0f)
{
}

QQuickColumnDefinition::QQuickColumnDefinition(QQuickItem *parent) :
    QQuickItem(parent),
    m_weight(1.0f)
{
}

QQuickGridStarAttached::QQuickGridStarAttached(QObject *object) :
    QObject(object),
    m_ignore(false),
    m_dirty(true),
    m_row(0),
    m_column(0),
    m_rowSpan(1),
    m_columnSpan(1),
    m_rowSpanActual(1),
    m_columnSpanActual(1)
{
}

bool QQuickGridStarAttached::getIgnore()
{
    return m_ignore;
}

qint32 QQuickGridStarAttached::getRow()
{
    return m_row;
}

qint32 QQuickGridStarAttached::getColumn()
{
    return m_column;
}

qint32 QQuickGridStarAttached::getRowSpan()
{
    return m_rowSpan;
}

qint32 QQuickGridStarAttached::getColumnSpan()
{
    return m_columnSpan;
}

void QQuickGridStarAttached::setIgnore(bool ignore)
{
    m_ignore = ignore;

    m_dirty = true;
}

void QQuickGridStarAttached::setRow(qint32 row)
{
    m_row = row;

    m_dirty = true;
}

void QQuickGridStarAttached::setColumn(qint32 column)
{
    m_column = column;

    m_dirty = true;
}

void QQuickGridStarAttached::setRowSpan(qint32 rowSpan)
{
    m_rowSpan = rowSpan;

    m_dirty = true;
}

void QQuickGridStarAttached::setColumnSpan(qint32 columnSpan)
{
    m_columnSpan = columnSpan;

    m_dirty = true;
}

QQuickGridStar::QQuickGridStar(QQuickItem *parent) :
    QQuickItem(parent)
{
}

QQuickGridStar::~QQuickGridStar()
{
}

qint32 QQuickGridStar::rowCount()
{
    return m_gridDefinition.rowCount();
}

qint32 QQuickGridStar::columnCount()
{
    return m_gridDefinition.columnCount();
}

QVariant QQuickGridStar::itemsAt(qint32 row, qint32 column)
{
    QVariantList
            quickItems;

    for(QQuickItem *item : m_items)
    {
        QQuickGridStarAttached
            *attached = qobject_cast<QQuickGridStarAttached *>(qmlAttachedPropertiesObject<QQuickGridStar>(item));

        if(attached->m_row == row && attached->m_column == column)
        {
            quickItems << QVariant::fromValue(item);
        }
    }

    return quickItems;
}

void QQuickGridStar::addRowDefinition(qreal weight, qint32 row)
{
    for(QQuickItem *item : m_items)
    {
        QQuickGridStarAttached
            *attached = qobject_cast<QQuickGridStarAttached *>(qmlAttachedPropertiesObject<QQuickGridStar>(item));

        if(attached->m_row >= row)
        {
            attached->m_row++;
        }

        attached->m_dirty = true;
    }

    m_gridDefinition.addRowDefinition(weight, row);

    polish();
}

void QQuickGridStar::addColumnDefinition(qreal weight, qint32 column)
{
    for(QQuickItem *item : m_items)
    {
        QQuickGridStarAttached
            *attached = qobject_cast<QQuickGridStarAttached *>(qmlAttachedPropertiesObject<QQuickGridStar>(item));

        if(attached->m_column >= column)
        {
            attached->m_column++;
        }

        attached->m_dirty = true;
    }

    m_gridDefinition.addColumnDefinition(weight, column);

    polish();
}

void QQuickGridStar::removeRowDefinition(qint32 row)
{
    for(QQuickItem *item : m_items)
    {
        QQuickGridStarAttached
            *attached = qobject_cast<QQuickGridStarAttached *>(qmlAttachedPropertiesObject<QQuickGridStar>(item));

        if(attached->m_row >= row)
        {
            attached->m_row--;
        }

        attached->m_dirty = true;
    }

    m_gridDefinition.removeRowDefinition(row);

    polish();
}

void QQuickGridStar::removeColumnDefinition(qint32 column)
{
    for(QQuickItem *item : m_items)
    {
        QQuickGridStarAttached
            *attached = qobject_cast<QQuickGridStarAttached *>(qmlAttachedPropertiesObject<QQuickGridStar>(item));

        if(attached->m_column >= column)
        {
            attached->m_column--;
        }

        attached->m_dirty = true;
    }

    m_gridDefinition.removeColumnDefinition(column);

    polish();
}

void QQuickGridStar::componentComplete()
{
    QSizeF
        size = QSizeF(width(), height());

    if(size.isEmpty())
    {
        QObject
            *parentObject = parent();

        if(parentObject->isWindowType())
        {
            QQuickWindow
                *quickWindow = qobject_cast<QQuickWindow *>(parentObject);

            size = QSizeF(quickWindow->width(), quickWindow->height());
        }
        else
        {
            QQuickItem
                *quickItem = qobject_cast<QQuickItem *>(parentObject);

            size = QSizeF(quickItem->width(), quickItem->height());
        }

        setSize(size);
    }

    QQuickItem::componentComplete();
}

void QQuickGridStar::itemChange(ItemChange change, const ItemChangeData &value)
{
    if(change == ItemChildAddedChange)
    {
        QQuickItem
            *item = value.item;

        QString
            className(item->metaObject()->className());

        if(!className.compare("QQuickRowDefinition"))
        {
            QQuickRowDefinition
                *definition = qobject_cast<QQuickRowDefinition *>(item);

            m_gridDefinition.addRowDefinition(definition->m_weight);
        }
        else if(!className.compare("QQuickColumnDefinition"))
        {
            QQuickColumnDefinition
                *definition = qobject_cast<QQuickColumnDefinition *>(item);

            m_gridDefinition.addColumnDefinition(definition->m_weight);
        }
        else
        {
            m_items << item;
        }
    }
    else if(change == ItemChildRemovedChange)
    {
        QQuickItem
            *item = value.item;

        m_items.removeOne(item);
    }

    polish();

    QQuickItem::itemChange(change, value);
}

void QQuickGridStar::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
{
    polish();

    QQuickItem::geometryChanged(newGeometry, oldGeometry);
}

void QQuickGridStar::updatePolish()
{
    QSizeF
        size(width(), height());

    QRectF
        rect(QPointF(0.0f, 0.0f), size);

    for(QQuickItem *item : m_items)
    {
        QQuickGridStarAttached
            *attached = qobject_cast<QQuickGridStarAttached *>(qmlAttachedPropertiesObject<QQuickGridStar>(item));

        if(!attached->m_ignore)
        {
            if(attached->m_dirty)
            {
                attached->m_rowSpanActual = attached->m_rowSpan;
                attached->m_columnSpanActual = attached->m_columnSpan;

                m_gridDefinition.calculateBounds(attached->m_row, attached->m_column, attached->m_rowSpanActual, attached->m_columnSpanActual);

                attached->m_dirty = false;
            }

            QRectF
                cellRect(m_gridDefinition.cellRect(rect, attached->m_row, attached->m_column, attached->m_rowSpanActual, attached->m_columnSpanActual));

            item->setPosition(cellRect.topLeft());
            item->setSize(cellRect.size());
        }
    }
}

QQuickGridStarAttached *QQuickGridStar::qmlAttachedProperties(QObject *object)
{
    return new QQuickGridStarAttached(object);
}

void registerQuickGridStarTypes()
{
    qmlRegisterType<QQuickGridStar>("QuickGridStar", 1, 0, "GridStar");
    qmlRegisterType<QQuickRowDefinition>("QuickGridStar", 1, 0, "RowDefinition");
    qmlRegisterType<QQuickColumnDefinition>("QuickGridStar", 1, 0, "ColumnDefinition");
}

Q_COREAPP_STARTUP_FUNCTION(registerQuickGridStarTypes)
<commit_msg>Update qquickgridstar.cpp<commit_after>#include "qquickgridstar.h"

QQuickRowDefinition::QQuickRowDefinition(QQuickItem *parent) :
    QQuickItem(parent),
    m_weight(1.0)
{
}

QQuickColumnDefinition::QQuickColumnDefinition(QQuickItem *parent) :
    QQuickItem(parent),
    m_weight(1.0)
{
}

QQuickGridStarAttached::QQuickGridStarAttached(QObject *object) :
    QObject(object),
    m_ignore(false),
    m_dirty(true),
    m_row(0),
    m_column(0),
    m_rowSpan(1),
    m_columnSpan(1),
    m_rowSpanActual(1),
    m_columnSpanActual(1)
{
}

bool QQuickGridStarAttached::getIgnore()
{
    return m_ignore;
}

qint32 QQuickGridStarAttached::getRow()
{
    return m_row;
}

qint32 QQuickGridStarAttached::getColumn()
{
    return m_column;
}

qint32 QQuickGridStarAttached::getRowSpan()
{
    return m_rowSpan;
}

qint32 QQuickGridStarAttached::getColumnSpan()
{
    return m_columnSpan;
}

void QQuickGridStarAttached::setIgnore(bool ignore)
{
    m_ignore = ignore;

    m_dirty = true;
}

void QQuickGridStarAttached::setRow(qint32 row)
{
    m_row = row;

    m_dirty = true;
}

void QQuickGridStarAttached::setColumn(qint32 column)
{
    m_column = column;

    m_dirty = true;
}

void QQuickGridStarAttached::setRowSpan(qint32 rowSpan)
{
    m_rowSpan = rowSpan;

    m_dirty = true;
}

void QQuickGridStarAttached::setColumnSpan(qint32 columnSpan)
{
    m_columnSpan = columnSpan;

    m_dirty = true;
}

QQuickGridStar::QQuickGridStar(QQuickItem *parent) :
    QQuickItem(parent)
{
}

QQuickGridStar::~QQuickGridStar()
{
}

qint32 QQuickGridStar::rowCount()
{
    return m_gridDefinition.rowCount();
}

qint32 QQuickGridStar::columnCount()
{
    return m_gridDefinition.columnCount();
}

QVariant QQuickGridStar::itemsAt(qint32 row, qint32 column)
{
    QVariantList
            quickItems;

    for(QQuickItem *item : m_items)
    {
        QQuickGridStarAttached
            *attached = qobject_cast<QQuickGridStarAttached *>(qmlAttachedPropertiesObject<QQuickGridStar>(item));

        if(attached->m_row == row && attached->m_column == column)
        {
            quickItems << QVariant::fromValue(item);
        }
    }

    return quickItems;
}

void QQuickGridStar::addRowDefinition(qreal weight, qint32 row)
{
    for(QQuickItem *item : m_items)
    {
        QQuickGridStarAttached
            *attached = qobject_cast<QQuickGridStarAttached *>(qmlAttachedPropertiesObject<QQuickGridStar>(item));

        if(attached->m_row >= row)
        {
            attached->m_row++;
        }

        attached->m_dirty = true;
    }

    m_gridDefinition.addRowDefinition(weight, row);

    polish();
}

void QQuickGridStar::addColumnDefinition(qreal weight, qint32 column)
{
    for(QQuickItem *item : m_items)
    {
        QQuickGridStarAttached
            *attached = qobject_cast<QQuickGridStarAttached *>(qmlAttachedPropertiesObject<QQuickGridStar>(item));

        if(attached->m_column >= column)
        {
            attached->m_column++;
        }

        attached->m_dirty = true;
    }

    m_gridDefinition.addColumnDefinition(weight, column);

    polish();
}

void QQuickGridStar::removeRowDefinition(qint32 row)
{
    for(QQuickItem *item : m_items)
    {
        QQuickGridStarAttached
            *attached = qobject_cast<QQuickGridStarAttached *>(qmlAttachedPropertiesObject<QQuickGridStar>(item));

        if(attached->m_row >= row)
        {
            attached->m_row--;
        }

        attached->m_dirty = true;
    }

    m_gridDefinition.removeRowDefinition(row);

    polish();
}

void QQuickGridStar::removeColumnDefinition(qint32 column)
{
    for(QQuickItem *item : m_items)
    {
        QQuickGridStarAttached
            *attached = qobject_cast<QQuickGridStarAttached *>(qmlAttachedPropertiesObject<QQuickGridStar>(item));

        if(attached->m_column >= column)
        {
            attached->m_column--;
        }

        attached->m_dirty = true;
    }

    m_gridDefinition.removeColumnDefinition(column);

    polish();
}

qreal QQuickGridStar::getRowSpacing()
{
    return m_rowSpacing;
}

qreal QQuickGridStar::getColumnSpacing()
{
    return m_columnSpacing;
}

void QQuickGridStar::setRowSpacing(qreal rowSpacing)
{
    m_rowSpacing = rowSpacing;
}

void QQuickGridStar::setColumnSpacing(qreal columnSpacing)
{
    m_columnSpacing = columnSpacing;
}

void QQuickGridStar::componentComplete()
{
    QSizeF
        size = QSizeF(width(), height());

    if(size.isEmpty())
    {
        QObject
            *parentObject = parent();

        if(parentObject->isWindowType())
        {
            QQuickWindow
                *quickWindow = qobject_cast<QQuickWindow *>(parentObject);

            size = QSizeF(quickWindow->width(), quickWindow->height());
        }
        else
        {
            QQuickItem
                *quickItem = qobject_cast<QQuickItem *>(parentObject);

            size = QSizeF(quickItem->width(), quickItem->height());
        }

        setSize(size);
    }

    if(m_rowSpacing > 0.0)
    {
        qreal
            weight = m_rowSpacing / size.height();

        for(qint32 i = 0, rows = rowCount() - 1; i < rows; i++)
        {
            addRowDefinition(weight, i * 2 + 1);
        }
    }

    if(m_columnSpacing > 0.0)
    {
        qreal
            weight = m_columnSpacing / size.height();

        for(qint32 i = 0, columns = columnCount() - 1; i < columns; i++)
        {
            addColumnDefinition(weight, i * 2 + 1);
        }
    }

    QQuickItem::componentComplete();
}

void QQuickGridStar::itemChange(ItemChange change, const ItemChangeData &value)
{
    if(change == ItemChildAddedChange)
    {
        QQuickItem
            *item = value.item;

        QString
            className(item->metaObject()->className());

        if(!className.compare("QQuickRowDefinition"))
        {
            QQuickRowDefinition
                *definition = qobject_cast<QQuickRowDefinition *>(item);

            m_gridDefinition.addRowDefinition(definition->m_weight);
        }
        else if(!className.compare("QQuickColumnDefinition"))
        {
            QQuickColumnDefinition
                *definition = qobject_cast<QQuickColumnDefinition *>(item);

            m_gridDefinition.addColumnDefinition(definition->m_weight);
        }
        else
        {
            m_items << item;
        }
    }
    else if(change == ItemChildRemovedChange)
    {
        QQuickItem
            *item = value.item;

        m_items.removeOne(item);
    }

    polish();

    QQuickItem::itemChange(change, value);
}

void QQuickGridStar::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
{
    polish();

    QQuickItem::geometryChanged(newGeometry, oldGeometry);
}

void QQuickGridStar::updatePolish()
{
    QSizeF
        size(width(), height());

    QRectF
        rect(QPointF(0.0, 0.0), size);

    for(QQuickItem *item : m_items)
    {
        QQuickGridStarAttached
            *attached = qobject_cast<QQuickGridStarAttached *>(qmlAttachedPropertiesObject<QQuickGridStar>(item));

        if(!attached->m_ignore)
        {
            if(attached->m_dirty)
            {
                attached->m_rowSpanActual = attached->m_rowSpan;
                attached->m_columnSpanActual = attached->m_columnSpan;

                m_gridDefinition.calculateBounds(attached->m_row, attached->m_column, attached->m_rowSpanActual, attached->m_columnSpanActual);

                attached->m_dirty = false;
            }

            QRectF
                cellRect(m_gridDefinition.cellRect(rect, attached->m_row, attached->m_column, attached->m_rowSpanActual, attached->m_columnSpanActual));

            item->setPosition(cellRect.topLeft());
            item->setSize(cellRect.size());

            emit attached->layout();
        }
    }
}

QQuickGridStarAttached *QQuickGridStar::qmlAttachedProperties(QObject *object)
{
    return new QQuickGridStarAttached(object);
}

void registerQuickGridStarTypes()
{
    qmlRegisterType<QQuickGridStar>("QuickGridStar", 1, 0, "GridStar");
    qmlRegisterType<QQuickRowDefinition>("QuickGridStar", 1, 0, "RowDefinition");
    qmlRegisterType<QQuickColumnDefinition>("QuickGridStar", 1, 0, "ColumnDefinition");
}

Q_COREAPP_STARTUP_FUNCTION(registerQuickGridStarTypes)
<|endoftext|>


<commit_before>#include "QFileEdit.h"

#include <QBoxLayout>
#include <QFileDialog>
#include <QToolButton>

QFileEdit::QFileEdit( QWidget* parent, Mode m, const QString& f ) :
	QWidget( parent ),
	mode( m ),
	filter( f )
{
	auto* l = new QHBoxLayout( this );
	l->setSpacing( 2 );
	l->setMargin( 0 );
	setLayout( l );

	lineEdit = new QLineEdit( this );
	l->addWidget( lineEdit );

	browseButton = new QToolButton( this );
	browseButton->setText( "..." );
	browseButton->setContentsMargins( 0, 0, 0, 0 );
	l->addWidget( browseButton );

	connect( browseButton, &QPushButton::released, this, &QFileEdit::browse );
}

void QFileEdit::browse()
{
	QFileInfo fi = lineEdit->text();

	QString result;

	switch ( mode )
	{
	case QFileEdit::OpenFile:
		result = QFileDialog::getOpenFileName( this, "Open File", fi.path(), filter, nullptr );
		break;
	case QFileEdit::SaveFile:
		result = QFileDialog::getSaveFileName( this, "Save File", fi.path(), filter, nullptr );
		break;
	case QFileEdit::Directory:
		result = QFileDialog::getExistingDirectory( this, "Select Directory", fi.path(), nullptr );
		break;
	default:
		break;
	}

	if ( !result.isEmpty() )
		lineEdit->setText( result );
}

void QFileEdit::setText( const QString& s )
{
	lineEdit->setText( s );
}

void QFileEdit::setText( const QString& s, Mode m, const QString& f )
{
	setText( s );
	setMode( m );
	setFilter( f );
}

QString QFileEdit::text() const
{
	return lineEdit->text();
}

void QFileEdit::setFilter( const QString& f )
{
	filter = f;
}

void QFileEdit::setMode( Mode m )
{
	mode = m;
}
<commit_msg>F: QFileEdit connect<commit_after>#include "QFileEdit.h"

#include <QBoxLayout>
#include <QFileDialog>
#include <QToolButton>

QFileEdit::QFileEdit( QWidget* parent, Mode m, const QString& f ) :
	QWidget( parent ),
	mode( m ),
	filter( f )
{
	auto* l = new QHBoxLayout( this );
	l->setSpacing( 2 );
	l->setMargin( 0 );
	setLayout( l );

	lineEdit = new QLineEdit( this );
	l->addWidget( lineEdit );

	browseButton = new QToolButton( this );
	browseButton->setText( "..." );
	browseButton->setContentsMargins( 0, 0, 0, 0 );
	l->addWidget( browseButton );

	connect( browseButton, &QAbstractButton::released, this, &QFileEdit::browse );
}

void QFileEdit::browse()
{
	QFileInfo fi = lineEdit->text();
	QString result;

	switch ( mode )
	{
	case QFileEdit::OpenFile:
		result = QFileDialog::getOpenFileName( this, "Open File", fi.path(), filter, nullptr );
		break;
	case QFileEdit::SaveFile:
		result = QFileDialog::getSaveFileName( this, "Save File", fi.path(), filter, nullptr );
		break;
	case QFileEdit::Directory:
		result = QFileDialog::getExistingDirectory( this, "Select Directory", fi.path(), nullptr );
		break;
	default:
		break;
	}

	if ( !result.isEmpty() )
		lineEdit->setText( result );
}

void QFileEdit::setText( const QString& s )
{
	lineEdit->setText( s );
}

void QFileEdit::setText( const QString& s, Mode m, const QString& f )
{
	setText( s );
	setMode( m );
	setFilter( f );
}

QString QFileEdit::text() const
{
	return lineEdit->text();
}

void QFileEdit::setFilter( const QString& f )
{
	filter = f;
}

void QFileEdit::setMode( Mode m )
{
	mode = m;
}
<|endoftext|>


<commit_before>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <chainparams.h>
#include <fs.h>
#include <logging.h>
#include <wallet/db.h>

#include <string>

std::vector<fs::path> ListDatabases(const fs::path& wallet_dir)
{
    const size_t offset = wallet_dir.native().size() + (wallet_dir == wallet_dir.root_name() ? 0 : 1);
    std::vector<fs::path> paths;
    boost::system::error_code ec;

    for (auto it = fs::recursive_directory_iterator(wallet_dir, ec); it != fs::recursive_directory_iterator(); it.increment(ec)) {
        if (ec) {
            if (fs::is_directory(*it)) {
                it.no_push();
                LogPrintf("%s: %s %s -- skipping.\n", __func__, ec.message(), fs::PathToString(it->path()));
            } else {
                LogPrintf("%s: %s %s\n", __func__, ec.message(), fs::PathToString(it->path()));
            }
            continue;
        }

        try {
            // Get wallet path relative to walletdir by removing walletdir from the wallet path.
            // This can be replaced by boost::filesystem::lexically_relative once boost is bumped to 1.60.
            const auto path_str = it->path().native().substr(offset);
            const fs::path path{path_str.begin(), path_str.end()};

            if (it->status().type() == fs::directory_file &&
                (IsBDBFile(BDBDataFile(it->path())) || IsSQLiteFile(SQLiteDataFile(it->path())))) {
                // Found a directory which contains wallet.dat btree file, add it as a wallet.
                paths.emplace_back(path);
            } else if (it.level() == 0 && it->symlink_status().type() == fs::regular_file && IsBDBFile(it->path())) {
                if (it->path().filename() == "wallet.dat") {
                    // Found top-level wallet.dat btree file, add top level directory ""
                    // as a wallet.
                    paths.emplace_back();
                } else {
                    // Found top-level btree file not called wallet.dat. Current bitcoin
                    // software will never create these files but will allow them to be
                    // opened in a shared database environment for backwards compatibility.
                    // Add it to the list of available wallets.
                    paths.emplace_back(path);
                }
            }
        } catch (const std::exception& e) {
            LogPrintf("%s: Error scanning %s: %s\n", __func__, fs::PathToString(it->path()), e.what());
            it.no_push();
        }
    }

    return paths;
}

fs::path BDBDataFile(const fs::path& wallet_path)
{
    if (fs::is_regular_file(wallet_path)) {
        // Special case for backwards compatibility: if wallet path points to an
        // existing file, treat it as the path to a BDB data file in a parent
        // directory that also contains BDB log files.
        return wallet_path;
    } else {
        // Normal case: Interpret wallet path as a directory path containing
        // data and log files.
        return wallet_path / "wallet.dat";
    }
}

fs::path SQLiteDataFile(const fs::path& path)
{
    return path / "wallet.dat";
}

bool IsBDBFile(const fs::path& path)
{
    if (!fs::exists(path)) return false;

    // A Berkeley DB Btree file has at least 4K.
    // This check also prevents opening lock files.
    boost::system::error_code ec;
    auto size = fs::file_size(path, ec);
    if (ec) LogPrintf("%s: %s %s\n", __func__, ec.message(), fs::PathToString(path));
    if (size < 4096) return false;

    fsbridge::ifstream file(path, std::ios::binary);
    if (!file.is_open()) return false;

    file.seekg(12, std::ios::beg); // Magic bytes start at offset 12
    uint32_t data = 0;
    file.read((char*) &data, sizeof(data)); // Read 4 bytes of file to compare against magic

    // Berkeley DB Btree magic bytes, from:
    //  https://github.com/file/file/blob/5824af38469ec1ca9ac3ffd251e7afe9dc11e227/magic/Magdir/database#L74-L75
    //  - big endian systems - 00 05 31 62
    //  - little endian systems - 62 31 05 00
    return data == 0x00053162 || data == 0x62310500;
}

bool IsSQLiteFile(const fs::path& path)
{
    if (!fs::exists(path)) return false;

    // A SQLite Database file is at least 512 bytes.
    boost::system::error_code ec;
    auto size = fs::file_size(path, ec);
    if (ec) LogPrintf("%s: %s %s\n", __func__, ec.message(), fs::PathToString(path));
    if (size < 512) return false;

    fsbridge::ifstream file(path, std::ios::binary);
    if (!file.is_open()) return false;

    // Magic is at beginning and is 16 bytes long
    char magic[16];
    file.read(magic, 16);

    // Application id is at offset 68 and 4 bytes long
    file.seekg(68, std::ios::beg);
    char app_id[4];
    file.read(app_id, 4);

    file.close();

    // Check the magic, see https://sqlite.org/fileformat2.html
    std::string magic_str(magic, 16);
    if (magic_str != std::string("SQLite format 3", 16)) {
        return false;
    }

    // Check the application id matches our network magic
    return memcmp(Params().MessageStart(), app_id, 4) == 0;
}
<commit_msg>refactor: get wallet path relative to wallet_dir<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <chainparams.h>
#include <fs.h>
#include <logging.h>
#include <wallet/db.h>

#include <string>

std::vector<fs::path> ListDatabases(const fs::path& wallet_dir)
{
    std::vector<fs::path> paths;
    boost::system::error_code ec;

    for (auto it = fs::recursive_directory_iterator(wallet_dir, ec); it != fs::recursive_directory_iterator(); it.increment(ec)) {
        if (ec) {
            if (fs::is_directory(*it)) {
                it.no_push();
                LogPrintf("%s: %s %s -- skipping.\n", __func__, ec.message(), fs::PathToString(it->path()));
            } else {
                LogPrintf("%s: %s %s\n", __func__, ec.message(), fs::PathToString(it->path()));
            }
            continue;
        }

        try {
            const fs::path path{it->path().lexically_relative(wallet_dir)};

            if (it->status().type() == fs::directory_file &&
                (IsBDBFile(BDBDataFile(it->path())) || IsSQLiteFile(SQLiteDataFile(it->path())))) {
                // Found a directory which contains wallet.dat btree file, add it as a wallet.
                paths.emplace_back(path);
            } else if (it.level() == 0 && it->symlink_status().type() == fs::regular_file && IsBDBFile(it->path())) {
                if (it->path().filename() == "wallet.dat") {
                    // Found top-level wallet.dat btree file, add top level directory ""
                    // as a wallet.
                    paths.emplace_back();
                } else {
                    // Found top-level btree file not called wallet.dat. Current bitcoin
                    // software will never create these files but will allow them to be
                    // opened in a shared database environment for backwards compatibility.
                    // Add it to the list of available wallets.
                    paths.emplace_back(path);
                }
            }
        } catch (const std::exception& e) {
            LogPrintf("%s: Error scanning %s: %s\n", __func__, fs::PathToString(it->path()), e.what());
            it.no_push();
        }
    }

    return paths;
}

fs::path BDBDataFile(const fs::path& wallet_path)
{
    if (fs::is_regular_file(wallet_path)) {
        // Special case for backwards compatibility: if wallet path points to an
        // existing file, treat it as the path to a BDB data file in a parent
        // directory that also contains BDB log files.
        return wallet_path;
    } else {
        // Normal case: Interpret wallet path as a directory path containing
        // data and log files.
        return wallet_path / "wallet.dat";
    }
}

fs::path SQLiteDataFile(const fs::path& path)
{
    return path / "wallet.dat";
}

bool IsBDBFile(const fs::path& path)
{
    if (!fs::exists(path)) return false;

    // A Berkeley DB Btree file has at least 4K.
    // This check also prevents opening lock files.
    boost::system::error_code ec;
    auto size = fs::file_size(path, ec);
    if (ec) LogPrintf("%s: %s %s\n", __func__, ec.message(), fs::PathToString(path));
    if (size < 4096) return false;

    fsbridge::ifstream file(path, std::ios::binary);
    if (!file.is_open()) return false;

    file.seekg(12, std::ios::beg); // Magic bytes start at offset 12
    uint32_t data = 0;
    file.read((char*) &data, sizeof(data)); // Read 4 bytes of file to compare against magic

    // Berkeley DB Btree magic bytes, from:
    //  https://github.com/file/file/blob/5824af38469ec1ca9ac3ffd251e7afe9dc11e227/magic/Magdir/database#L74-L75
    //  - big endian systems - 00 05 31 62
    //  - little endian systems - 62 31 05 00
    return data == 0x00053162 || data == 0x62310500;
}

bool IsSQLiteFile(const fs::path& path)
{
    if (!fs::exists(path)) return false;

    // A SQLite Database file is at least 512 bytes.
    boost::system::error_code ec;
    auto size = fs::file_size(path, ec);
    if (ec) LogPrintf("%s: %s %s\n", __func__, ec.message(), fs::PathToString(path));
    if (size < 512) return false;

    fsbridge::ifstream file(path, std::ios::binary);
    if (!file.is_open()) return false;

    // Magic is at beginning and is 16 bytes long
    char magic[16];
    file.read(magic, 16);

    // Application id is at offset 68 and 4 bytes long
    file.seekg(68, std::ios::beg);
    char app_id[4];
    file.read(app_id, 4);

    file.close();

    // Check the magic, see https://sqlite.org/fileformat2.html
    std::string magic_str(magic, 16);
    if (magic_str != std::string("SQLite format 3", 16)) {
        return false;
    }

    // Check the application id matches our network magic
    return memcmp(Params().MessageStart(), app_id, 4) == 0;
}
<|endoftext|>