<commit_before>/**
 * This file is part of the "FnordMetric" project
 *   Copyright (c) 2011-2014 Paul Asmuth, Google Inc.
 *
 * FnordMetric is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License v3.0. You should have received a
 * copy of the GNU General Public License along with this program. If not, see
 * <http://www.gnu.org/licenses/>.
 */
#include <chartsql/runtime/orderby.h>
#include <chartsql/expressions/boolean.h>
#include <algorithm>
#include <fnord/inspect.h>

namespace csql {

OrderBy::OrderBy(
    Vector<OrderByNode::SortSpec> sort_specs,
    size_t max_output_column_index,
    ScopedPtr<TableExpression> child) :
    sort_specs_(sort_specs),
    max_output_column_index_(max_output_column_index),
    child_(std::move(child)) {
  if (sort_specs_.size() == 0) {
    RAISE(kIllegalArgumentError, "can't execute ORDER BY: no sort specs");
  }

  size_t max_sort_idx = 0;
  for (const auto& sspec : sort_specs_) {
    if (sspec.column > max_sort_idx) {
      max_sort_idx = sspec.column;
    }
  }

  const auto& child_columns = child_->numColumns();
  if (child_columns <= max_sort_idx) {
    RAISE(
        kRuntimeError,
        "can't execute ORDER BY: not enough columns in virtual table");
  }
}

// FIXPAUL this should mergesort while inserting...
void OrderBy::execute(
    ExecutionContext* context,
    Function<bool (int argc, const SValue* argv)> fn) {
  Vector<Vector<SValue>> rows;

  child_->execute(context, [&rows] (int argc, const SValue* argv) -> bool {
    Vector<SValue> row;
    for (int i = 0; i < argc; i++) {
      row.emplace_back(argv[i]);
    }

    rows.emplace_back(row);
    return true;
  });

  std::sort(
      rows.begin(),
      rows.end(),
      [this] (const Vector<SValue>& left, const Vector<SValue>& right) -> bool {
    for (const auto& sort : sort_specs_) {
      SValue args[2];
      SValue res(false);
      args[0] = left[sort.column];
      args[1] = right[sort.column];

      expressions::eqExpr(2, args, &res);
      if (res.getBool()) {
        continue;
      }

      if (sort.descending) {
        expressions::gtExpr(2, args, &res);
      } else {
        expressions::ltExpr(2, args, &res);
      }

      return res.getBool();
    }

    /* all dimensions equal */
    return false;
  });

  for (auto& row : rows) {
    if (!fn(std::min(row.size(), max_output_column_index_), row.data())) {
      return;
    }
  }
}

Vector<String> OrderBy::columnNames() const {
  return child_->columnNames();
}

size_t OrderBy::numColumns() const {
  return child_->numColumns();
}

} // namespace csql
<commit_msg>proper order by output colunn names<commit_after>/**
 * This file is part of the "FnordMetric" project
 *   Copyright (c) 2011-2014 Paul Asmuth, Google Inc.
 *
 * FnordMetric is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License v3.0. You should have received a
 * copy of the GNU General Public License along with this program. If not, see
 * <http://www.gnu.org/licenses/>.
 */
#include <chartsql/runtime/orderby.h>
#include <chartsql/expressions/boolean.h>
#include <algorithm>
#include <fnord/inspect.h>

namespace csql {

OrderBy::OrderBy(
    Vector<OrderByNode::SortSpec> sort_specs,
    size_t max_output_column_index,
    ScopedPtr<TableExpression> child) :
    sort_specs_(sort_specs),
    max_output_column_index_(max_output_column_index),
    child_(std::move(child)) {
  if (sort_specs_.size() == 0) {
    RAISE(kIllegalArgumentError, "can't execute ORDER BY: no sort specs");
  }

  size_t max_sort_idx = 0;
  for (const auto& sspec : sort_specs_) {
    if (sspec.column > max_sort_idx) {
      max_sort_idx = sspec.column;
    }
  }

  const auto& child_columns = child_->numColumns();
  if (child_columns <= max_sort_idx) {
    RAISE(
        kRuntimeError,
        "can't execute ORDER BY: not enough columns in virtual table");
  }
}

// FIXPAUL this should mergesort while inserting...
void OrderBy::execute(
    ExecutionContext* context,
    Function<bool (int argc, const SValue* argv)> fn) {
  Vector<Vector<SValue>> rows;

  child_->execute(context, [&rows] (int argc, const SValue* argv) -> bool {
    Vector<SValue> row;
    for (int i = 0; i < argc; i++) {
      row.emplace_back(argv[i]);
    }

    rows.emplace_back(row);
    return true;
  });

  std::sort(
      rows.begin(),
      rows.end(),
      [this] (const Vector<SValue>& left, const Vector<SValue>& right) -> bool {
    for (const auto& sort : sort_specs_) {
      SValue args[2];
      SValue res(false);
      args[0] = left[sort.column];
      args[1] = right[sort.column];

      expressions::eqExpr(2, args, &res);
      if (res.getBool()) {
        continue;
      }

      if (sort.descending) {
        expressions::gtExpr(2, args, &res);
      } else {
        expressions::ltExpr(2, args, &res);
      }

      return res.getBool();
    }

    /* all dimensions equal */
    return false;
  });

  for (auto& row : rows) {
    if (!fn(std::min(row.size(), max_output_column_index_), row.data())) {
      return;
    }
  }
}

Vector<String> OrderBy::columnNames() const {
  auto col_names = child_->columnNames();

  if (col_names.size() > max_output_column_index_) {
    col_names.erase(
        col_names.begin() + max_output_column_index_,
        col_names.end());
  }

  return col_names;
}

size_t OrderBy::numColumns() const {
  return std::min(child_->numColumns(), max_output_column_index_);
}

} // namespace csql
<|endoftext|>


<commit_before><commit_msg>IQA-490: Dummy out calls to LLTrans::getString() in linux_updater.cpp. It appears that the LLTrans machinery, or at least the way it's used in this program, is buggy: linux-updater.bin has been crashing. Tracebacks and experimentation identify LLTrans as the culprit, so replace it with baked-in string constants copied from strings.xml. (linux-updater.bin was already producing English-only messages because the update_install shell script that calls it was specifically passing the English version of strings.xml.)<commit_after><|endoftext|>


<commit_before>/***********************************************************************
 *    filename:   Window.cpp
 *    created:    11/6/2011
 *    author:     Martin Preisler
 *************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2011 Paul D Turner & The CEGUI Development Team
 *
 *   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 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.
 ***************************************************************************/

#include "CEGUI/Window.h"
#include "CEGUI/WindowManager.h"

#include <boost/test/unit_test.hpp>
#include <boost/timer.hpp>

/*
 * Used to bring some Windows up for testing
 *
 * This is for exception safety, no matter what happens in the tests,
 * its destructor will be called
 */
struct LayoutSetupFixture
{
    LayoutSetupFixture()
    {
        d_root = CEGUI::WindowManager::getSingleton().createWindow("DefaultWindow");
        d_root->setPosition(CEGUI::UVector2(CEGUI::UDim(0, 0), CEGUI::UDim(0, 0)));
        d_root->setSize(CEGUI::USize(CEGUI::UDim(1, 0), CEGUI::UDim(1, 0)));

        d_insideRoot = CEGUI::WindowManager::getSingleton().createWindow("DefaultWindow");
        d_insideRoot->setPosition(CEGUI::UVector2(CEGUI::UDim(0, 100), CEGUI::UDim(0, 50)));
        d_insideRoot->setSize(CEGUI::USize(CEGUI::UDim(0.5f, 0), CEGUI::UDim(0.5f, 0)));
        d_root->addChild(d_insideRoot);

        d_insideInsideRoot = CEGUI::WindowManager::getSingleton().createWindow("DefaultWindow");
        d_insideInsideRoot->setPosition(CEGUI::UVector2(CEGUI::UDim(0, 100), CEGUI::UDim(0, 50)));
        d_insideInsideRoot->setSize(CEGUI::USize(CEGUI::UDim(0.5f, 0), CEGUI::UDim(0.5f, 0)));
        d_insideRoot->addChild(d_insideInsideRoot);

        CEGUI::System::getSingleton().setGUISheet(d_root);
        CEGUI::System::getSingleton().notifyDisplaySizeChanged(CEGUI::Sizef(800, 600));
    }

    ~LayoutSetupFixture()
    {
        CEGUI::System::getSingleton().setGUISheet(0);

        CEGUI::WindowManager::getSingleton().destroyWindow(d_root);
    }

    CEGUI::Window* d_root;
    CEGUI::Window* d_insideRoot;
    CEGUI::Window* d_insideInsideRoot;
};

BOOST_FIXTURE_TEST_SUITE(Window, LayoutSetupFixture)

BOOST_AUTO_TEST_CASE(Defaults)
{
    /*
     * We check these to ensure we don't change them between releases, as people very likely depend on them!
     */

    BOOST_CHECK(!d_root->isActive());

    BOOST_CHECK(!d_root->isDisabled());
    BOOST_CHECK(!d_root->isEffectiveDisabled());

    BOOST_CHECK(d_root->isVisible());
    BOOST_CHECK(d_root->isEffectiveVisible());
}

BOOST_AUTO_TEST_CASE(PropertyInheritance)
{
    /*
     * Alpha and Disabled state should get "inherited"/propagated to children via effective alpha/disabled
     */

    d_root->setAlpha(0.5f);
    d_insideRoot->setAlpha(0.5f);

    BOOST_CHECK_EQUAL(d_insideInsideRoot->getEffectiveAlpha(), 0.25f);

    d_root->setAlpha(1.0f);
    d_insideRoot->setAlpha(1.0f);

    d_root->setDisabled(true);

    BOOST_CHECK_EQUAL(d_insideRoot->isEffectiveDisabled(), true);
    BOOST_CHECK_EQUAL(d_insideInsideRoot->isEffectiveDisabled(), true);

    d_root->setDisabled(false);

    BOOST_CHECK_EQUAL(d_insideRoot->isEffectiveDisabled(), false);
    BOOST_CHECK_EQUAL(d_insideInsideRoot->isEffectiveDisabled(), false);
}

BOOST_AUTO_TEST_CASE(UnifiedDimensions)
{
    /*
     * Basic relative UDim tests
     */
    BOOST_CHECK_EQUAL(d_insideInsideRoot->getPixelSize(), CEGUI::Sizef(200, 150));
    BOOST_CHECK_EQUAL(d_insideInsideRoot->getUnclippedOuterRect().get(), CEGUI::Rectf(200, 100, 400, 250));
}

BOOST_AUTO_TEST_CASE(HitTesting)
{
    /*
     * We know where the windows are so lets check whether CEGUI reports correct hits for them
     */

    BOOST_CHECK(d_insideInsideRoot->isHit(CEGUI::Vector2f(300, 150)));

    d_insideInsideRoot->setDisabled(true);
    BOOST_CHECK(!d_insideInsideRoot->isHit(CEGUI::Vector2f(300, 150), false));
    BOOST_CHECK(d_insideInsideRoot->isHit(CEGUI::Vector2f(300, 150), true));
    d_insideInsideRoot->setDisabled(false);

    d_root->setDisabled(true);
    BOOST_CHECK(!d_insideInsideRoot->isHit(CEGUI::Vector2f(300, 150), false));
    BOOST_CHECK(d_insideInsideRoot->isHit(CEGUI::Vector2f(300, 150), true));
    d_root->setDisabled(false);
}

BOOST_AUTO_TEST_CASE(Hierarchy)
{
    CEGUI::Window* child = d_insideInsideRoot->createChild("DefaultWindow");
    BOOST_CHECK(d_insideInsideRoot->isChild(child));
    d_insideInsideRoot->destroyChild(child);

    child = d_insideInsideRoot->createChild("DefaultWindow");
    child->setDestroyedByParent(false);
    d_insideInsideRoot->removeChild(child);
    BOOST_CHECK(!d_insideInsideRoot->isChild(child));
    CEGUI::WindowManager::getSingleton().destroyWindow(child);
}

struct DrawListPerformanceFixture
{
    DrawListPerformanceFixture()
    {
        d_root = CEGUI::WindowManager::getSingleton().createWindow("DefaultWindow");
        d_root->setPosition(CEGUI::UVector2(CEGUI::UDim(0, 0), CEGUI::UDim(0, 0)));
        d_root->setSize(CEGUI::USize(CEGUI::UDim(1, 0), CEGUI::UDim(1, 0)));

        for (unsigned int i = 0; i < 100; ++i)
        {
            d_windows.push_back(d_root->createChild("DefaultWindow"));
        }
    }

    ~DrawListPerformanceFixture()
    {
        CEGUI::WindowManager::getSingleton().destroyWindow(d_root);
    }

    CEGUI::Window* d_root;
    std::vector<CEGUI::Window*> d_windows;
};
/*
BOOST_AUTO_TEST_CASE(DrawListPerformance)
{
    DrawListPerformanceFixture fixture;

    {
        boost::timer timer;
        for (unsigned int i = 0; i < 1000; ++i)
        {

            // first, we are trying to measure the hit we get when we have to move a window to the back of the draw list
            for (unsigned int i = 0; i < 100; ++i)
            {
                fixture.d_windows[i]->moveToBack();
            }
        }

        BOOST_TEST_MESSAGE("Time taken, 1000x 100 windows moved back (100 windows total): " << timer.elapsed());
    }

    {
        boost::timer timer;
        for (unsigned int i = 0; i < 1000; ++i)
        {

            // secondly, we are trying to measure the hit we get when we have to move a window to the front of the draw list
            for (unsigned int i = 0; i < 100; ++i)
            {
                fixture.d_windows[i]->moveToFront();
            }
        }

        BOOST_TEST_MESSAGE("Time taken, 1000x 100 windows moved front (100 windows total): " << timer.elapsed());
    }
}
*/
BOOST_AUTO_TEST_SUITE_END()
<commit_msg>Fix tests so they at least build (yes, this is totally backwards :( )<commit_after>/***********************************************************************
 *    filename:   Window.cpp
 *    created:    11/6/2011
 *    author:     Martin Preisler
 *************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2011 Paul D Turner & The CEGUI Development Team
 *
 *   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 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.
 ***************************************************************************/

#include "CEGUI/Window.h"
#include "CEGUI/WindowManager.h"

#include <boost/test/unit_test.hpp>
#include <boost/timer.hpp>

/*
 * Used to bring some Windows up for testing
 *
 * This is for exception safety, no matter what happens in the tests,
 * its destructor will be called
 */
struct LayoutSetupFixture
{
    LayoutSetupFixture()
    {
        d_root = CEGUI::WindowManager::getSingleton().createWindow("DefaultWindow");
        d_root->setPosition(CEGUI::UVector2(CEGUI::UDim(0, 0), CEGUI::UDim(0, 0)));
        d_root->setSize(CEGUI::USize(CEGUI::UDim(1, 0), CEGUI::UDim(1, 0)));

        d_insideRoot = CEGUI::WindowManager::getSingleton().createWindow("DefaultWindow");
        d_insideRoot->setPosition(CEGUI::UVector2(CEGUI::UDim(0, 100), CEGUI::UDim(0, 50)));
        d_insideRoot->setSize(CEGUI::USize(CEGUI::UDim(0.5f, 0), CEGUI::UDim(0.5f, 0)));
        d_root->addChild(d_insideRoot);

        d_insideInsideRoot = CEGUI::WindowManager::getSingleton().createWindow("DefaultWindow");
        d_insideInsideRoot->setPosition(CEGUI::UVector2(CEGUI::UDim(0, 100), CEGUI::UDim(0, 50)));
        d_insideInsideRoot->setSize(CEGUI::USize(CEGUI::UDim(0.5f, 0), CEGUI::UDim(0.5f, 0)));
        d_insideRoot->addChild(d_insideInsideRoot);

        CEGUI::System::getSingleton().getDefaultGUIContext().setRootWindow(d_root);
        CEGUI::System::getSingleton().notifyDisplaySizeChanged(CEGUI::Sizef(800, 600));
    }

    ~LayoutSetupFixture()
    {
        CEGUI::System::getSingleton().getDefaultGUIContext().setRootWindow(0);

        CEGUI::WindowManager::getSingleton().destroyWindow(d_root);
    }

    CEGUI::Window* d_root;
    CEGUI::Window* d_insideRoot;
    CEGUI::Window* d_insideInsideRoot;
};

BOOST_FIXTURE_TEST_SUITE(Window, LayoutSetupFixture)

BOOST_AUTO_TEST_CASE(Defaults)
{
    /*
     * We check these to ensure we don't change them between releases, as people very likely depend on them!
     */

    BOOST_CHECK(!d_root->isActive());

    BOOST_CHECK(!d_root->isDisabled());
    BOOST_CHECK(!d_root->isEffectiveDisabled());

    BOOST_CHECK(d_root->isVisible());
    BOOST_CHECK(d_root->isEffectiveVisible());
}

BOOST_AUTO_TEST_CASE(PropertyInheritance)
{
    /*
     * Alpha and Disabled state should get "inherited"/propagated to children via effective alpha/disabled
     */

    d_root->setAlpha(0.5f);
    d_insideRoot->setAlpha(0.5f);

    BOOST_CHECK_EQUAL(d_insideInsideRoot->getEffectiveAlpha(), 0.25f);

    d_root->setAlpha(1.0f);
    d_insideRoot->setAlpha(1.0f);

    d_root->setDisabled(true);

    BOOST_CHECK_EQUAL(d_insideRoot->isEffectiveDisabled(), true);
    BOOST_CHECK_EQUAL(d_insideInsideRoot->isEffectiveDisabled(), true);

    d_root->setDisabled(false);

    BOOST_CHECK_EQUAL(d_insideRoot->isEffectiveDisabled(), false);
    BOOST_CHECK_EQUAL(d_insideInsideRoot->isEffectiveDisabled(), false);
}

BOOST_AUTO_TEST_CASE(UnifiedDimensions)
{
    /*
     * Basic relative UDim tests
     */
    BOOST_CHECK_EQUAL(d_insideInsideRoot->getPixelSize(), CEGUI::Sizef(200, 150));
    BOOST_CHECK_EQUAL(d_insideInsideRoot->getUnclippedOuterRect().get(), CEGUI::Rectf(200, 100, 400, 250));
}

BOOST_AUTO_TEST_CASE(HitTesting)
{
    /*
     * We know where the windows are so lets check whether CEGUI reports correct hits for them
     */

    BOOST_CHECK(d_insideInsideRoot->isHit(CEGUI::Vector2f(300, 150)));

    d_insideInsideRoot->setDisabled(true);
    BOOST_CHECK(!d_insideInsideRoot->isHit(CEGUI::Vector2f(300, 150), false));
    BOOST_CHECK(d_insideInsideRoot->isHit(CEGUI::Vector2f(300, 150), true));
    d_insideInsideRoot->setDisabled(false);

    d_root->setDisabled(true);
    BOOST_CHECK(!d_insideInsideRoot->isHit(CEGUI::Vector2f(300, 150), false));
    BOOST_CHECK(d_insideInsideRoot->isHit(CEGUI::Vector2f(300, 150), true));
    d_root->setDisabled(false);
}

BOOST_AUTO_TEST_CASE(Hierarchy)
{
    CEGUI::Window* child = d_insideInsideRoot->createChild("DefaultWindow");
    BOOST_CHECK(d_insideInsideRoot->isChild(child));
    d_insideInsideRoot->destroyChild(child);

    child = d_insideInsideRoot->createChild("DefaultWindow");
    child->setDestroyedByParent(false);
    d_insideInsideRoot->removeChild(child);
    BOOST_CHECK(!d_insideInsideRoot->isChild(child));
    CEGUI::WindowManager::getSingleton().destroyWindow(child);
}

struct DrawListPerformanceFixture
{
    DrawListPerformanceFixture()
    {
        d_root = CEGUI::WindowManager::getSingleton().createWindow("DefaultWindow");
        d_root->setPosition(CEGUI::UVector2(CEGUI::UDim(0, 0), CEGUI::UDim(0, 0)));
        d_root->setSize(CEGUI::USize(CEGUI::UDim(1, 0), CEGUI::UDim(1, 0)));

        for (unsigned int i = 0; i < 100; ++i)
        {
            d_windows.push_back(d_root->createChild("DefaultWindow"));
        }
    }

    ~DrawListPerformanceFixture()
    {
        CEGUI::WindowManager::getSingleton().destroyWindow(d_root);
    }

    CEGUI::Window* d_root;
    std::vector<CEGUI::Window*> d_windows;
};
/*
BOOST_AUTO_TEST_CASE(DrawListPerformance)
{
    DrawListPerformanceFixture fixture;

    {
        boost::timer timer;
        for (unsigned int i = 0; i < 1000; ++i)
        {

            // first, we are trying to measure the hit we get when we have to move a window to the back of the draw list
            for (unsigned int i = 0; i < 100; ++i)
            {
                fixture.d_windows[i]->moveToBack();
            }
        }

        BOOST_TEST_MESSAGE("Time taken, 1000x 100 windows moved back (100 windows total): " << timer.elapsed());
    }

    {
        boost::timer timer;
        for (unsigned int i = 0; i < 1000; ++i)
        {

            // secondly, we are trying to measure the hit we get when we have to move a window to the front of the draw list
            for (unsigned int i = 0; i < 100; ++i)
            {
                fixture.d_windows[i]->moveToFront();
            }
        }

        BOOST_TEST_MESSAGE("Time taken, 1000x 100 windows moved front (100 windows total): " << timer.elapsed());
    }
}
*/
BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>/*
 * Convert_hapcut2.cpp
 *
 *  Created on: Mar 14, 2018
 *      Author: sedlazec
 */

#include "Convert_hapcut2.h"

map<std::string, bool> parse_hapcut(std::string hapcut2, std::string target_chr) {
	std::string buffer;
	std::ifstream myfile;

	map<std::string, bool> hapcut;

	myfile.open(hapcut2.c_str(), std::ifstream::in);
	if (!myfile.good()) {
		std::cout << "Hapcut2 Parser: could not open file: " << hapcut2.c_str() << std::endl;
		exit(0);
	}

	getline(myfile, buffer);
	while (!myfile.eof()) {
		if (buffer[0] != 'B' && buffer[0] != '*') { //avoid headers!
			int count = 0;
			std::string chr = "";
			int pos = -1;
			bool first_gt = true;
			bool second_gt = true; //not needed but good to check!
			for (size_t i = 0; i < buffer.size(); i++) {
				if (count == 1 && buffer[i - 1] == '\t') {
					first_gt = (bool) (buffer[i] != '0');
				}
				if (count == 2 && buffer[i - 1] == '\t') {
					second_gt = (bool) (buffer[i] != '0');
				}

				if (count == 3 && buffer[i] != '\t') {
					chr += buffer[i];
				}
				if (count == 4 && buffer[i - 1] == '\t') {
					pos = atoi(&buffer[i]);
					break;
				}

				if (buffer[i] == '\t') {
					count++;
				}
			}
			if (strcmp(chr.c_str(), target_chr.c_str()) == 0) {
				if ((first_gt && !second_gt) || (!first_gt && second_gt)) {
					std::stringstream ss;
					ss << chr;
					ss << "_";
					ss << pos;

					if (hapcut.find(ss.str()) == hapcut.end()) {
						hapcut[ss.str()] = first_gt;
					} else {
						cerr << "A position was found twice: " << ss.str() << endl;
					}
				}
			}
		}
		getline(myfile, buffer);
	}
	myfile.close();
	return hapcut;
}

void process_hapcut(std::string orig_snp, std::string hapcut2, std::string output) {

	//parse VCF file. just if we dected a 0/1 we check the hapcut results.
	std::string buffer;
	std::ifstream myfile;

	myfile.open(orig_snp.c_str(), std::ifstream::in);
	if (!myfile.good()) {
		std::cout << "SNP Parser: could not open file: " << orig_snp.c_str() << std::endl;
		exit(0);
	}
	FILE * file = fopen(output.c_str(), "w");
	map<std::string, bool> hapcut_res;
	std::string old_chr;
	getline(myfile, buffer);
	//int num = 0;
	while (!myfile.eof()) {
		if (buffer[0] == '#') {
			fprintf(file, "%s", buffer.c_str());
			fprintf(file, "%c", '\n');
		} else {
		//	num++;

			std::size_t found = buffer.find_last_of('\t');
			//check found + 1 if '1' && if found+3 !='0' ->
			if (buffer[found + 1] == '0' && buffer[found + 3] == '1') {
				//search pos and replace 3 chars.
				int count = 0;
				std::string chr;
				int pos = 0;
				for (size_t i = 0; i < buffer.size(); i++) {
					if (count == 0 && buffer[i] != '\t') {
						chr += buffer[i];
					}
					if (count == 1 && buffer[i - 1] == '\t') {
						pos = atoi(&buffer[i]);
						break;
					}
					if (buffer[i] == '\t') {
						count++;
					}
				}
				if (strcmp(chr.c_str(), old_chr.c_str()) != 0) {
					//load new chr set:
					cout<<"Parsing hapcut2 output for "<<chr;
					hapcut_res = parse_hapcut(hapcut2, chr);
					cout<<" SNPs parsed "<<hapcut_res.size()<<endl;
					old_chr=chr;

				}

				if (!chr.empty()) {
					std::stringstream ss;
					ss << chr;
					ss << "_";
					ss << pos;
					if (hapcut_res.find(ss.str()) != hapcut_res.end()) {
						if (hapcut_res[ss.str()]) {
							buffer[found + 1] = '1';
							buffer[found + 2] = '|';
							buffer[found + 3] = '0';
						} else {
							buffer[found + 1] = '0';
							buffer[found + 2] = '|';
							buffer[found + 3] = '1';
						}
					}
				}
			}
			fprintf(file, "%s", buffer.c_str());
			fprintf(file, "%c", '\n');
		}

		getline(myfile, buffer);
	}
	myfile.close();
	fclose(file);
}
<commit_msg>Fixed bug in hapcut2 parser<commit_after>/*
 * Convert_hapcut2.cpp
 *
 *  Created on: Mar 14, 2018
 *      Author: sedlazec
 */

#include "Convert_hapcut2.h"

map<std::string, bool> parse_hapcut(std::string hapcut2, std::string target_chr) {
	std::string buffer;
	std::ifstream myfile;

	map<std::string, bool> hapcut;

	myfile.open(hapcut2.c_str(), std::ifstream::in);
	if (!myfile.good()) {
		std::cout << "Hapcut2 Parser: could not open file: " << hapcut2.c_str() << std::endl;
		exit(0);
	}

	getline(myfile, buffer);
	while (!myfile.eof()) {
		if (buffer[0] != 'B' && buffer[0] != '*') { //avoid headers!
			int count = 0;
			std::string chr = "";
			int pos = -1;
			bool first_gt = true;
			bool second_gt = true; //not needed but good to check!
			for (size_t i = 0; i < buffer.size(); i++) {
				if (count == 1 && buffer[i - 1] == '\t') {
					first_gt = (bool) (buffer[i] != '0');
				}
				if (count == 2 && buffer[i - 1] == '\t') {
					second_gt = (bool) (buffer[i] != '0');
				}

				if (count == 3 && buffer[i] != '\t') {
					chr += buffer[i];
				}
				if (count == 4 && buffer[i - 1] == '\t') {
					pos = atoi(&buffer[i]);
					break;
				}

				if (buffer[i] == '\t') {
					count++;
				}
			}
			if (strcmp(chr.c_str(), target_chr.c_str()) == 0) {
				if ((first_gt && !second_gt) || (!first_gt && second_gt)) {
					std::stringstream ss;
					ss << chr;
					ss << "_";
					ss << pos;

					if (hapcut.find(ss.str()) == hapcut.end()) {
						hapcut[ss.str()] = first_gt;
					} else {
						cerr << "A position was found twice: " << ss.str() << endl;
					}
				}
			}
		}
		getline(myfile, buffer);
	}
	myfile.close();
	return hapcut;
}

void process_hapcut(std::string orig_snp, std::string hapcut2, std::string output) {

	//parse VCF file. just if we dected a 0/1 we check the hapcut results.
	std::string buffer;
	std::ifstream myfile;

	myfile.open(orig_snp.c_str(), std::ifstream::in);
	if (!myfile.good()) {
		std::cout << "SNP Parser: could not open file: " << orig_snp.c_str() << std::endl;
		exit(0);
	}
	FILE * file = fopen(output.c_str(), "w");
	map<std::string, bool> hapcut_res;
	std::string old_chr;
	getline(myfile, buffer);
	//int num = 0;
	while (!myfile.eof()) {
		if (buffer[0] == '#') {
			fprintf(file, "%s", buffer.c_str());
			fprintf(file, "%c", '\n');
		} else {
			//	num++;

			std::size_t found = buffer.find_last_of('\t');
			//check found + 1 if '1' && if found+3 !='0' ->
			if ((buffer[found + 1] == '0' && buffer[found + 3] == '1') ||( buffer[found + 1] == '1' && buffer[found + 3] == '0') ) {
				//search pos and replace 3 chars.
				int count = 0;
				std::string chr;
				int pos = 0;
				for (size_t i = 0; i < buffer.size(); i++) {
					if (count == 0 && buffer[i] != '\t') {
						chr += buffer[i];
					}
					if (count == 1 && buffer[i - 1] == '\t') {
						pos = atoi(&buffer[i]);
						break;
					}
					if (buffer[i] == '\t') {
						count++;
					}
				}
				if (strcmp(chr.c_str(), old_chr.c_str()) != 0) {
					//load new chr set:
					cout << "Parsing hapcut2 output for " << chr;
					hapcut_res = parse_hapcut(hapcut2, chr);
					cout << " SNPs parsed " << hapcut_res.size() << endl;
					old_chr = chr;

				}

				if (!chr.empty()) {
					std::stringstream ss;
					ss << chr;
					ss << "_";
					ss << pos;
					if (hapcut_res.find(ss.str()) != hapcut_res.end()) {
			//			cout << "MATCH: " << ss.str() << endl;
						if (hapcut_res[ss.str()]) {
							buffer[found + 1] = '1';
							buffer[found + 2] = '|';
							buffer[found + 3] = '0';
						} else {
							buffer[found + 1] = '0';
							buffer[found + 2] = '|';
							buffer[found + 3] = '1';
						}

					}
				}

			}
			fprintf(file, "%s", buffer.c_str());
			fprintf(file, "%c", '\n');

		}

		getline(myfile, buffer);
	}
	myfile.close();
	fclose(file);
}
<|endoftext|>


<commit_before>/*
 * Copyright 2021 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "src/core/SkBlendModeBlender.h"
#include "src/core/SkReadBuffer.h"
#include "src/core/SkWriteBuffer.h"

#if SK_SUPPORT_GPU
#include "src/gpu/GrFragmentProcessor.h"
#endif

sk_sp<SkBlender> SkBlenders::Mode(SkBlendMode mode) {
#define RETURN_SINGLETON_BLENDER(m)                        \
    case m: {                                              \
        static auto* sBlender = new SkBlendModeBlender{m}; \
        return sk_ref_sp(sBlender);                        \
    }

    switch (mode) {
        RETURN_SINGLETON_BLENDER(SkBlendMode::kClear)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kSrc)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kDst)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kSrcOver)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kDstOver)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kSrcIn)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kDstIn)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kSrcOut)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kDstOut)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kSrcATop)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kDstATop)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kXor)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kPlus)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kModulate)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kScreen)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kOverlay)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kDarken)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kLighten)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kColorDodge)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kColorBurn)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kHardLight)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kSoftLight)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kDifference)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kExclusion)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kMultiply)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kHue)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kSaturation)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kColor)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kLuminosity)
    }

    SkDEBUGFAILF("invalid blend mode %d", mode);
    return nullptr;

#undef RETURN_SINGLETON_BLENDER
}

sk_sp<SkFlattenable> SkBlendModeBlender::CreateProc(SkReadBuffer& buffer) {
    SkBlendMode mode = buffer.read32LE(SkBlendMode::kLastMode);
    return SkBlenders::Mode(mode);
}

void SkBlendModeBlender::flatten(SkWriteBuffer& buffer) const {
    buffer.writeInt((int)fMode);
}

#if SK_SUPPORT_GPU
std::unique_ptr<GrFragmentProcessor> SkBlendModeBlender::asFragmentProcessor(
        std::unique_ptr<GrFragmentProcessor> inputFP, const GrFPArgs& fpArgs) const {
    // Using a SkBlendModeBlender on the GPU side isn't supported; we should use GrXferProcessor to
    // perform this blend instead. The Xfer processor is able to perform coefficient-based blends
    // without readback, so it's more efficient.
    SkDEBUGFAIL("SkBuiltInBlender::asFragmentProcessor is not supported");
    return nullptr;
}
#endif

skvm::Color SkBlendModeBlender::onProgram(skvm::Builder* p, skvm::Color src, skvm::Color dst,
                                          const SkColorInfo& colorInfo, skvm::Uniforms* uniforms,
                                          SkArenaAlloc* alloc) const {
    return p->blend(fMode, src, dst);
}
<commit_msg>Fix class name in debug message.<commit_after>/*
 * Copyright 2021 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "src/core/SkBlendModeBlender.h"
#include "src/core/SkReadBuffer.h"
#include "src/core/SkWriteBuffer.h"

#if SK_SUPPORT_GPU
#include "src/gpu/GrFragmentProcessor.h"
#endif

sk_sp<SkBlender> SkBlenders::Mode(SkBlendMode mode) {
#define RETURN_SINGLETON_BLENDER(m)                        \
    case m: {                                              \
        static auto* sBlender = new SkBlendModeBlender{m}; \
        return sk_ref_sp(sBlender);                        \
    }

    switch (mode) {
        RETURN_SINGLETON_BLENDER(SkBlendMode::kClear)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kSrc)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kDst)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kSrcOver)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kDstOver)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kSrcIn)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kDstIn)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kSrcOut)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kDstOut)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kSrcATop)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kDstATop)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kXor)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kPlus)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kModulate)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kScreen)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kOverlay)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kDarken)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kLighten)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kColorDodge)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kColorBurn)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kHardLight)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kSoftLight)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kDifference)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kExclusion)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kMultiply)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kHue)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kSaturation)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kColor)
        RETURN_SINGLETON_BLENDER(SkBlendMode::kLuminosity)
    }

    SkDEBUGFAILF("invalid blend mode %d", mode);
    return nullptr;

#undef RETURN_SINGLETON_BLENDER
}

sk_sp<SkFlattenable> SkBlendModeBlender::CreateProc(SkReadBuffer& buffer) {
    SkBlendMode mode = buffer.read32LE(SkBlendMode::kLastMode);
    return SkBlenders::Mode(mode);
}

void SkBlendModeBlender::flatten(SkWriteBuffer& buffer) const {
    buffer.writeInt((int)fMode);
}

#if SK_SUPPORT_GPU
std::unique_ptr<GrFragmentProcessor> SkBlendModeBlender::asFragmentProcessor(
        std::unique_ptr<GrFragmentProcessor> inputFP, const GrFPArgs& fpArgs) const {
    // Using a SkBlendModeBlender on the GPU side isn't supported; we should use GrXferProcessor to
    // perform this blend instead. The Xfer processor is able to perform coefficient-based blends
    // without readback, so it's more efficient.
    SkDEBUGFAIL("SkBlendModeBlender::asFragmentProcessor is not supported");
    return nullptr;
}
#endif

skvm::Color SkBlendModeBlender::onProgram(skvm::Builder* p, skvm::Color src, skvm::Color dst,
                                          const SkColorInfo& colorInfo, skvm::Uniforms* uniforms,
                                          SkArenaAlloc* alloc) const {
    return p->blend(fMode, src, dst);
}
<|endoftext|>


<commit_before>#include "catch.hpp"
#include "expected.hpp"

#include <string>

using std::string;

tl::expected<int, string> getInt3(int val) { return val; }

tl::expected<int, string> getInt2(int val) { return val; }

tl::expected<int, string> getInt1() { return getInt2(5).and_then(getInt3); }

TEST_CASE("Issue 1", "[issues.1]") { getInt1(); }

tl::expected<int, int> operation1() { return 42; }

tl::expected<std::string, int> operation2(int const val) { return "Bananas"; }

TEST_CASE("Issue 17", "[issues.17]") {
  auto const intermediate_result = operation1();

  intermediate_result.and_then(operation2);
}

struct a{};
struct b:a{};

TEST_CASE("Issue 26", "[issues.26]") {
    tl::expected<a, int> exp = tl::expected<b,int>(tl::unexpect, 0);
    REQUIRE(!exp.has_value());
}

struct foo {
  foo() = default;
  foo(foo&) = delete;
  foo(foo&&) {};
};

TEST_CASE("Issue 29", "[issues.29]") {
  std::vector<foo> v;
  v.emplace_back();
  tl::expected<std::vector<foo>, int> ov = std::move(v);
  REQUIRE(ov->size() == 1);
}
<commit_msg>Add issue 30 test<commit_after>#include "catch.hpp"
#include "expected.hpp"

#include <string>

using std::string;

tl::expected<int, string> getInt3(int val) { return val; }

tl::expected<int, string> getInt2(int val) { return val; }

tl::expected<int, string> getInt1() { return getInt2(5).and_then(getInt3); }

TEST_CASE("Issue 1", "[issues.1]") { getInt1(); }

tl::expected<int, int> operation1() { return 42; }

tl::expected<std::string, int> operation2(int const val) { return "Bananas"; }

TEST_CASE("Issue 17", "[issues.17]") {
  auto const intermediate_result = operation1();

  intermediate_result.and_then(operation2);
}

struct a {};
struct b : a {};

TEST_CASE("Issue 26", "[issues.26]") {
  tl::expected<a, int> exp = tl::expected<b, int>(tl::unexpect, 0);
  REQUIRE(!exp.has_value());
}

struct foo {
  foo() = default;
  foo(foo &) = delete;
  foo(foo &&){};
};

TEST_CASE("Issue 29", "[issues.29]") {
  std::vector<foo> v;
  v.emplace_back();
  tl::expected<std::vector<foo>, int> ov = std::move(v);
  REQUIRE(ov->size() == 1);
}

tl::expected<int, std::string> error() {
  return tl::make_unexpected(std::string("error1 "));
}
std::string maperror(std::string s) { return s + "maperror "; }

TEST_CASE("Issue 30", "[issues.30]") {
  error().map_error(maperror);
}
<|endoftext|>


<commit_before>/*****************************************************************************

YASK: Yet Another Stencil Kernel
Copyright (c) 2014-2019, Intel Corporation

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.

*****************************************************************************/

#pragma once

namespace yask {

    // Classes that support evaluation of one stencil bundle
    // and a 'pack' of bundles.
    // A stencil context contains one or more packs.

    // A pure-virtual class base for a stencil bundle.
    class StencilBundleBase :
        public ContextLinker {

    protected:
        std::string _name;
        int _scalar_fp_ops = 0;
        int _scalar_points_read = 0;
        int _scalar_points_written = 0;

        // Other bundles that this one depends on.
        StencilBundleSet _depends_on;

        // List of scratch-grid bundles that need to be evaluated
        // before this bundle. Listed in eval order first-to-last.
        StencilBundleList _scratch_children;

        // Whether this updates scratch grid(s);
        bool _is_scratch = false;

        // Overall bounding box for the bundle.
        // This may or may not be solid, i.e., it
        // may contain some invalid points.
        // This must fit inside the extended BB for this rank.
        BoundingBox _bundle_bb;

	// Bounding box(es) that indicate where this bundle is valid.
	// These must be non-overlapping. These do NOT contain
        // any invalid points. These will all be inside '_bundle_bb'.
	BBList _bb_list;

        // Normalize the indices, i.e., divide by vector len in each dim.
        // Ranks offsets must already be subtracted.
        // Each dim in 'orig' must be a multiple of corresponding vec len.
        void normalize_indices(const Indices& orig, Indices& norm) const {
            STATE_VARS(this);
            assert(orig.getNumDims() == nsdims);
            assert(norm.getNumDims() == nsdims);

            // i: index for stencil dims, j: index for domain dims.
            DOMAIN_VAR_LOOP(i, j) {

                // Divide indices by fold lengths as needed by
                // read/writeVecNorm().  Use idiv_flr() instead of '/'
                // because begin/end vars may be negative (if in halo).
                norm[i] = idiv_flr<idx_t>(orig[i], fold_pts[j]);

                // Check for no remainder.
                assert(imod_flr<idx_t>(orig[i], fold_pts[j]) == 0);
            }
        }

    public:

        // Grids that are written to by these stencils.
        GridPtrs outputGridPtrs;

        // Grids that are read by these stencils (not necessarify
        // read-only, i.e., a grid can be input and output).
        GridPtrs inputGridPtrs;

        // Vectors of scratch grids that are written to/read from.
        ScratchVecs outputScratchVecs;
        ScratchVecs inputScratchVecs;

        // ctor, dtor.
        StencilBundleBase(StencilContext* context) :
            ContextLinker(context) { }
        virtual ~StencilBundleBase() { }

        // Get name of this bundle.
        const std::string& get_name() const { return _name; }

        // Get estimated number of FP ops done for one scalar eval.
        virtual int get_scalar_fp_ops() const { return _scalar_fp_ops; }

        // Get number of points read and written for one scalar eval.
        virtual int get_scalar_points_read() const { return _scalar_points_read; }
        virtual int get_scalar_points_written() const { return _scalar_points_written; }

        // Scratch accessors.
        bool is_scratch() const { return _is_scratch; }
        void set_scratch(bool is_scratch) { _is_scratch = is_scratch; }

        // Access to BBs.
        BoundingBox& getBB() { return _bundle_bb; }
        BBList& getBBs() { return _bb_list; }

        // Add dependency.
        virtual void add_dep(StencilBundleBase* eg) {
            _depends_on.insert(eg);
        }

        // Get dependencies.
        virtual const StencilBundleSet& get_deps() const {
            return _depends_on;
        }

        // Add needed scratch-bundle.
        virtual void add_scratch_child(StencilBundleBase* eg) {
            _scratch_children.push_back(eg);
        }

        // Get needed scratch-bundle(s).
        const StencilBundleList& get_scratch_children() const {
            return _scratch_children;
        }

        // Get scratch children plus self.
        StencilBundleList get_reqd_bundles() {
            auto sg_list = get_scratch_children(); // Do children first.
            sg_list.push_back(this); // Do self last.
            return sg_list;
        }

        // If this bundle is updating scratch grid(s),
        // expand indices to calculate values in halo.
        // Adjust offsets in grids based on original idxs.
        // Return adjusted indices.
        ScanIndices adjust_span(int thread_idx, const ScanIndices& idxs) const;

        // Set the bounding-box vars for this bundle in this rank.
        void find_bounding_box();

        // Copy BB vars from another.
        void copy_bounding_box(const StencilBundleBase* src);

        // Determine whether indices are in [sub-]domain.
        virtual bool
        is_in_valid_domain(const Indices& idxs) const =0;

        // Return true if there is a non-default conditions.
        virtual bool
        is_sub_domain_expr() const { return false; }
        virtual bool
        is_step_cond_expr() const { return false; }

        // Return human-readable description of conditions.
        virtual std::string
        get_domain_description() const =0;
        virtual std::string
        get_step_cond_description() const =0;

        // Determine whether step index is enabled.
        virtual bool
        is_in_valid_step(idx_t input_step_index) const =0;

        // If bundle updates grid(s) with the step index,
        // set 'output_step_index' to the step that an update
        // occurs when calling one of the calc_*() methods with
        // 'input_step_index' and return 'true'.
        // Else, return 'false';
        virtual bool
        get_output_step_index(idx_t input_step_index,
                              idx_t& output_step_index) const =0;

        // Calculate one scalar result.
        virtual void
        calc_scalar(int thread_idx, const Indices& idxs) =0;

        // Calculate results within a mini-block.
        void
        calc_mini_block(int region_thread_idx,
                        KernelSettings& settings,
                        const ScanIndices& mini_block_idxs);

        // Calculate results within a sub-block.
        void
        calc_sub_block_vec(int region_thread_idx,
                           int block_thread_idx,
                           KernelSettings& settings,
                           const ScanIndices& mini_block_idxs);
        void
        calc_sub_block_scalar(int region_thread_idx,
                              int block_thread_idx,
                              KernelSettings& settings,
                              const ScanIndices& mini_block_idxs);
        inline void
        calc_sub_block(int region_thread_idx,
                       int block_thread_idx,
                       KernelSettings& settings,
                       const ScanIndices& mini_block_idxs) {
            if (settings.force_scalar)
                calc_sub_block_scalar(region_thread_idx, block_thread_idx,
                                      settings, mini_block_idxs);
            else
                calc_sub_block_vec(region_thread_idx, block_thread_idx,
                                   settings, mini_block_idxs);
        }

        // Calculate a series of cluster results within an inner loop.
        // All indices start at 'start_idxs'. Inner loop iterates to
        // 'stop_inner' by 'step_inner'.
        // Indices must be rank-relative.
        // Indices must be normalized, i.e., already divided by VLEN_*.
        virtual void
        calc_loop_of_clusters(int region_thread_idx,
                              int block_thread_idx,
                              const Indices& start_idxs,
                              idx_t stop_inner) =0;

        // Calculate a series of cluster results within an inner loop.
        // The 'loop_idxs' must specify a range only in the inner dim.
        // Indices must be rank-relative.
        // Indices must be normalized, i.e., already divided by VLEN_*.
        void
        calc_loop_of_clusters(int region_thread_idx,
                              int block_thread_idx,
                              const ScanIndices& loop_idxs);

        // Calculate a series of vector results within an inner loop.
        // All indices start at 'start_idxs'. Inner loop iterates to
        // 'stop_inner' by 'step_inner'.
        // Indices must be rank-relative.
        // Indices must be normalized, i.e., already divided by VLEN_*.
        // Each vector write is masked by 'write_mask'.
        virtual void
        calc_loop_of_vectors(int region_thread_idx,
                             int block_thread_idx,
                             const Indices& start_idxs,
                             idx_t stop_inner,
                             idx_t write_mask) =0;

        // Calculate a series of vector results within an inner loop.
        // The 'loop_idxs' must specify a range only in the inner dim.
        // Indices must be rank-relative.
        // Indices must be normalized, i.e., already divided by VLEN_*.
        // Each vector write is masked by 'write_mask'.
        void
        calc_loop_of_vectors(int region_thread_idx,
                             int block_thread_idx,
                             const ScanIndices& loop_idxs,
                             idx_t write_mask);

    };                          // StencilBundleBase.

    // A collection of independent stencil bundles.
    // "Independent" implies that they may be evaluated
    // in any order.
    class BundlePack :
        public ContextLinker,
        public std::vector<StencilBundleBase*> {

    protected:
        std::string _name;

        // Union of bounding boxes for all bundles in this pack.
        BoundingBox _pack_bb;

        // Local pack settings.
        // Only some of these will be used.
        KernelSettings _pack_opts;

        // Auto-tuner for pack settings.
        AutoTuner _at;

    public:

        // Perf stats for this pack.
        YaskTimer timer;
        idx_t steps_done = 0;
        Stats stats;

        // Work needed across points in this rank.
        idx_t num_reads_per_step = 0;
        idx_t num_writes_per_step = 0;
        idx_t num_fpops_per_step = 0;

        // Work done across all ranks.
        idx_t tot_reads_per_step = 0;
        idx_t tot_writes_per_step = 0;
        idx_t tot_fpops_per_step = 0;

        BundlePack(StencilContext* context,
                   const std::string& name) :
            ContextLinker(context),
            _name(name),
            _pack_opts(*context->get_state()->_opts), // init w/a copy of the base settings.
            _at(context, &_pack_opts, name) { }
        virtual ~BundlePack() { }

        const std::string& get_name() {
            return _name;
        }

        // Update the amount of work stats.
        // Print to current debug stream.
        void init_work_stats();

        // Determine whether step index is enabled.
        bool
        is_in_valid_step(idx_t input_step_index) const {
            if (!size())
                return false;

            // All step conditions must be the same, so
            // we call first one.
            return front()->is_in_valid_step(input_step_index);
        }

        // Accessors.
        BoundingBox& getBB() { return _pack_bb; }
        AutoTuner& getAT() { return _at; }
        KernelSettings& getLocalSettings() { return _pack_opts; }

        // If using separate pack tuners, return local settings.
        // Otherwise, return one in context.
        KernelSettings& getActiveSettings() {
            STATE_VARS(this);
            return use_pack_tuners() ? _pack_opts : *opts;
        }

        // Perf-tracking methods.
        void start_timers();
        void stop_timers();
        void add_steps(idx_t num_steps);

    }; // BundlePack.

} // yask namespace.
<commit_msg>Set block-thread id if needed.<commit_after>/*****************************************************************************

YASK: Yet Another Stencil Kernel
Copyright (c) 2014-2019, Intel Corporation

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.

*****************************************************************************/

#pragma once

namespace yask {

    // Classes that support evaluation of one stencil bundle
    // and a 'pack' of bundles.
    // A stencil context contains one or more packs.

    // A pure-virtual class base for a stencil bundle.
    class StencilBundleBase :
        public ContextLinker {

    protected:
        std::string _name;
        int _scalar_fp_ops = 0;
        int _scalar_points_read = 0;
        int _scalar_points_written = 0;

        // Other bundles that this one depends on.
        StencilBundleSet _depends_on;

        // List of scratch-grid bundles that need to be evaluated
        // before this bundle. Listed in eval order first-to-last.
        StencilBundleList _scratch_children;

        // Whether this updates scratch grid(s);
        bool _is_scratch = false;

        // Overall bounding box for the bundle.
        // This may or may not be solid, i.e., it
        // may contain some invalid points.
        // This must fit inside the extended BB for this rank.
        BoundingBox _bundle_bb;

	// Bounding box(es) that indicate where this bundle is valid.
	// These must be non-overlapping. These do NOT contain
        // any invalid points. These will all be inside '_bundle_bb'.
	BBList _bb_list;

        // Normalize the indices, i.e., divide by vector len in each dim.
        // Ranks offsets must already be subtracted.
        // Each dim in 'orig' must be a multiple of corresponding vec len.
        void normalize_indices(const Indices& orig, Indices& norm) const {
            STATE_VARS(this);
            assert(orig.getNumDims() == nsdims);
            assert(norm.getNumDims() == nsdims);

            // i: index for stencil dims, j: index for domain dims.
            DOMAIN_VAR_LOOP(i, j) {

                // Divide indices by fold lengths as needed by
                // read/writeVecNorm().  Use idiv_flr() instead of '/'
                // because begin/end vars may be negative (if in halo).
                norm[i] = idiv_flr<idx_t>(orig[i], fold_pts[j]);

                // Check for no remainder.
                assert(imod_flr<idx_t>(orig[i], fold_pts[j]) == 0);
            }
        }

    public:

        // Grids that are written to by these stencils.
        GridPtrs outputGridPtrs;

        // Grids that are read by these stencils (not necessarify
        // read-only, i.e., a grid can be input and output).
        GridPtrs inputGridPtrs;

        // Vectors of scratch grids that are written to/read from.
        ScratchVecs outputScratchVecs;
        ScratchVecs inputScratchVecs;

        // ctor, dtor.
        StencilBundleBase(StencilContext* context) :
            ContextLinker(context) { }
        virtual ~StencilBundleBase() { }

        // Get name of this bundle.
        const std::string& get_name() const { return _name; }

        // Get estimated number of FP ops done for one scalar eval.
        virtual int get_scalar_fp_ops() const { return _scalar_fp_ops; }

        // Get number of points read and written for one scalar eval.
        virtual int get_scalar_points_read() const { return _scalar_points_read; }
        virtual int get_scalar_points_written() const { return _scalar_points_written; }

        // Scratch accessors.
        bool is_scratch() const { return _is_scratch; }
        void set_scratch(bool is_scratch) { _is_scratch = is_scratch; }

        // Access to BBs.
        BoundingBox& getBB() { return _bundle_bb; }
        BBList& getBBs() { return _bb_list; }

        // Add dependency.
        virtual void add_dep(StencilBundleBase* eg) {
            _depends_on.insert(eg);
        }

        // Get dependencies.
        virtual const StencilBundleSet& get_deps() const {
            return _depends_on;
        }

        // Add needed scratch-bundle.
        virtual void add_scratch_child(StencilBundleBase* eg) {
            _scratch_children.push_back(eg);
        }

        // Get needed scratch-bundle(s).
        const StencilBundleList& get_scratch_children() const {
            return _scratch_children;
        }

        // Get scratch children plus self.
        StencilBundleList get_reqd_bundles() {
            auto sg_list = get_scratch_children(); // Do children first.
            sg_list.push_back(this); // Do self last.
            return sg_list;
        }

        // If this bundle is updating scratch grid(s),
        // expand indices to calculate values in halo.
        // Adjust offsets in grids based on original idxs.
        // Return adjusted indices.
        ScanIndices adjust_span(int thread_idx, const ScanIndices& idxs) const;

        // Set the bounding-box vars for this bundle in this rank.
        void find_bounding_box();

        // Copy BB vars from another.
        void copy_bounding_box(const StencilBundleBase* src);

        // Determine whether indices are in [sub-]domain.
        virtual bool
        is_in_valid_domain(const Indices& idxs) const =0;

        // Return true if there is a non-default conditions.
        virtual bool
        is_sub_domain_expr() const { return false; }
        virtual bool
        is_step_cond_expr() const { return false; }

        // Return human-readable description of conditions.
        virtual std::string
        get_domain_description() const =0;
        virtual std::string
        get_step_cond_description() const =0;

        // Determine whether step index is enabled.
        virtual bool
        is_in_valid_step(idx_t input_step_index) const =0;

        // If bundle updates grid(s) with the step index,
        // set 'output_step_index' to the step that an update
        // occurs when calling one of the calc_*() methods with
        // 'input_step_index' and return 'true'.
        // Else, return 'false';
        virtual bool
        get_output_step_index(idx_t input_step_index,
                              idx_t& output_step_index) const =0;

        // Calculate one scalar result.
        virtual void
        calc_scalar(int thread_idx, const Indices& idxs) =0;

        // Calculate results within a mini-block.
        void
        calc_mini_block(int region_thread_idx,
                        KernelSettings& settings,
                        const ScanIndices& mini_block_idxs);

        // Calculate results within a sub-block.
        void
        calc_sub_block_vec(int region_thread_idx,
                           int block_thread_idx,
                           KernelSettings& settings,
                           const ScanIndices& mini_block_idxs);
        void
        calc_sub_block_scalar(int region_thread_idx,
                              int block_thread_idx,
                              KernelSettings& settings,
                              const ScanIndices& mini_block_idxs);
        inline void
        calc_sub_block(int region_thread_idx,
                       int block_thread_idx,
                       KernelSettings& settings,
                       const ScanIndices& mini_block_idxs) {
            if (block_thread_idx < 0)
                block_thread_idx = omp_get_thread_num();
            if (settings.force_scalar)
                calc_sub_block_scalar(region_thread_idx, block_thread_idx,
                                      settings, mini_block_idxs);
            else
                calc_sub_block_vec(region_thread_idx, block_thread_idx,
                                   settings, mini_block_idxs);
        }

        // Calculate a series of cluster results within an inner loop.
        // All indices start at 'start_idxs'. Inner loop iterates to
        // 'stop_inner' by 'step_inner'.
        // Indices must be rank-relative.
        // Indices must be normalized, i.e., already divided by VLEN_*.
        virtual void
        calc_loop_of_clusters(int region_thread_idx,
                              int block_thread_idx,
                              const Indices& start_idxs,
                              idx_t stop_inner) =0;

        // Calculate a series of cluster results within an inner loop.
        // The 'loop_idxs' must specify a range only in the inner dim.
        // Indices must be rank-relative.
        // Indices must be normalized, i.e., already divided by VLEN_*.
        void
        calc_loop_of_clusters(int region_thread_idx,
                              int block_thread_idx,
                              const ScanIndices& loop_idxs);

        // Calculate a series of vector results within an inner loop.
        // All indices start at 'start_idxs'. Inner loop iterates to
        // 'stop_inner' by 'step_inner'.
        // Indices must be rank-relative.
        // Indices must be normalized, i.e., already divided by VLEN_*.
        // Each vector write is masked by 'write_mask'.
        virtual void
        calc_loop_of_vectors(int region_thread_idx,
                             int block_thread_idx,
                             const Indices& start_idxs,
                             idx_t stop_inner,
                             idx_t write_mask) =0;

        // Calculate a series of vector results within an inner loop.
        // The 'loop_idxs' must specify a range only in the inner dim.
        // Indices must be rank-relative.
        // Indices must be normalized, i.e., already divided by VLEN_*.
        // Each vector write is masked by 'write_mask'.
        void
        calc_loop_of_vectors(int region_thread_idx,
                             int block_thread_idx,
                             const ScanIndices& loop_idxs,
                             idx_t write_mask);

    };                          // StencilBundleBase.

    // A collection of independent stencil bundles.
    // "Independent" implies that they may be evaluated
    // in any order.
    class BundlePack :
        public ContextLinker,
        public std::vector<StencilBundleBase*> {

    protected:
        std::string _name;

        // Union of bounding boxes for all bundles in this pack.
        BoundingBox _pack_bb;

        // Local pack settings.
        // Only some of these will be used.
        KernelSettings _pack_opts;

        // Auto-tuner for pack settings.
        AutoTuner _at;

    public:

        // Perf stats for this pack.
        YaskTimer timer;
        idx_t steps_done = 0;
        Stats stats;

        // Work needed across points in this rank.
        idx_t num_reads_per_step = 0;
        idx_t num_writes_per_step = 0;
        idx_t num_fpops_per_step = 0;

        // Work done across all ranks.
        idx_t tot_reads_per_step = 0;
        idx_t tot_writes_per_step = 0;
        idx_t tot_fpops_per_step = 0;

        BundlePack(StencilContext* context,
                   const std::string& name) :
            ContextLinker(context),
            _name(name),
            _pack_opts(*context->get_state()->_opts), // init w/a copy of the base settings.
            _at(context, &_pack_opts, name) { }
        virtual ~BundlePack() { }

        const std::string& get_name() {
            return _name;
        }

        // Update the amount of work stats.
        // Print to current debug stream.
        void init_work_stats();

        // Determine whether step index is enabled.
        bool
        is_in_valid_step(idx_t input_step_index) const {
            if (!size())
                return false;

            // All step conditions must be the same, so
            // we call first one.
            return front()->is_in_valid_step(input_step_index);
        }

        // Accessors.
        BoundingBox& getBB() { return _pack_bb; }
        AutoTuner& getAT() { return _at; }
        KernelSettings& getLocalSettings() { return _pack_opts; }

        // If using separate pack tuners, return local settings.
        // Otherwise, return one in context.
        KernelSettings& getActiveSettings() {
            STATE_VARS(this);
            return use_pack_tuners() ? _pack_opts : *opts;
        }

        // Perf-tracking methods.
        void start_timers();
        void stop_timers();
        void add_steps(idx_t num_steps);

    }; // BundlePack.

} // yask namespace.
<|endoftext|>


<commit_before>#include <filesystem>
#include <vector>
#include <mutex>
#include <iostream>

#include <ogr_api.h>
#include <ogr_spatialref.h>

#pragma warning (push)
#pragma warning (disable:4251)
#include <gdal_priv.h>
#pragma warning (pop)
#include <cpl_vsi.h>

#include <ZFXMath.h>

#include "../WebMapService.h"

using namespace std;
using namespace std::experimental::filesystem::v1;
using namespace dw;
using namespace ZFXMath;

namespace dw
{
namespace Layers
{
	const astring LayerName = "QualityElevation";
	const string LayerTitle = dwTEXT("ASTER + SRTMv3 High Quality Elevation Service");

	class QualityElevation : public WebMapService::Layer
	{
		struct SrcDestTransfromId
		{
			const OGRSpatialReference* src;
			const OGRSpatialReference* dst;

			bool operator< (const QualityElevation::SrcDestTransfromId& other) const
			{
				return memcmp(this, &other, sizeof(QualityElevation::SrcDestTransfromId)) < 0;
			}
		};

		struct ASTERTile
		{
			int longitude;
			int latitude;
			astring filename_dem;
			astring filename_num;
		};

		struct ASTERTileContent
		{
			s16* elevation;
			s16* quality;

			int width;
			int height;

			double geoTransform[6];

			~ASTERTileContent()
			{
				delete[] elevation;
				delete[] quality;
			}
		};

		map<astring, OGRSpatialReference*> supportedCRS;
		OGRSpatialReference* ASTER_EPSG;
		map<SrcDestTransfromId, OGRCoordinateTransformation*> srsTransforms;

		ASTERTile* asterTiles;
		int asterTileStartLatitude;
		int asterTileEndLatitude;
		const int AsterTileStartLongitude = -180;
		const int AsterTileEndLongitude = 179;
		const int NumASTERTilesX = AsterTileEndLongitude - AsterTileStartLongitude + 1;
		const int MissingTileCoordinate = -1000;

	public:

		virtual bool Init(/* layerconfig */) override
		{
			GDALRegister_GTiff();

			supportedCRS =
			{
				//pair<astring, OGRSpatialReference*>("EPSG:3857", new OGRSpatialReference()),
				pair<astring, OGRSpatialReference*>("EPSG:4326", new OGRSpatialReference())
			};

			for (auto it = supportedCRS.begin(); it != supportedCRS.end(); it++)
			{
				int epsgCode = atoi(it->first.c_str() + 5);
				OGRErr err = it->second->importFromEPSG(epsgCode);
				if (err == OGRERR_UNSUPPORTED_SRS)
				{
					return false;
				}
			}

			ASTER_EPSG = supportedCRS["EPSG:4326"];

			// create all possible SRS transformation permutations
			for (auto it1 = supportedCRS.begin(); it1 != supportedCRS.end(); it1++)
			{
				for (auto it2 = it1; it2 != supportedCRS.end(); it2++)
				{
					if (it2 == supportedCRS.end()) break;

					CreateTransform(it1->second, it2->second);
					CreateTransform(it2->second, it1->second);
				}
			}

			// load TOC from disk
			//const path ASTERSourceDir("D:/ASTER/");
			const path ASTERSourceDir("C:/Dev/temp/ASTER/");

			asterTileStartLatitude = 90;
			asterTileEndLatitude = -90;
			for (directory_iterator di(ASTERSourceDir); di != end(di); di++)
			{
				const auto& entity = *di;
				const auto extension = entity.path().extension();
				if (is_regular_file(entity.status()) && entity.path().extension().generic_string() == ".zip")
				{
					astring filepath = entity.path().string();
					int latitudeSign = 1;
					size_t offset = filepath.find_last_of('N');
					if (offset == std::string::npos)
					{
						offset = filepath.find_last_of('S');
						latitudeSign = -1;
					}
					if (offset != std::string::npos)
					{
						int latitude = atoi(filepath.c_str() + offset + 1) * latitudeSign;
						asterTileStartLatitude = min(asterTileStartLatitude, latitude);
						asterTileEndLatitude = max(asterTileEndLatitude, latitude);
					}
				}
			}

			const int NumASTERTilesX = 360;
			const int NumASTERTilesY = max(0, asterTileEndLatitude - asterTileStartLatitude + 1);

			if (NumASTERTilesY == 0)
			{
				cout << "ASTER data not found" << endl;
				return false;
			}

			asterTiles = new ASTERTile[NumASTERTilesX * NumASTERTilesY];
			memset(asterTiles, 0, sizeof(ASTERTile) * NumASTERTilesX * NumASTERTilesY);
			for (int y = asterTileStartLatitude; y <= asterTileEndLatitude; y++)
			{
				for (int x = AsterTileStartLongitude; x <= AsterTileEndLongitude; x++)
				{
					auto& tile = asterTiles[(y - asterTileStartLatitude) * NumASTERTilesX + (x - AsterTileStartLongitude)];
					tile.longitude = x;
					tile.latitude = y;

					int absX = abs(x);
					int absY = abs(y);

					astring filename = ((y < 0) ? "S" : "N");
					if (absY < 10) filename += "0";
					filename += to_string(absY) + ((x < 0) ? "W" : "E");
					if (absX < 10) filename += "00";
					else if (absX < 100) filename += "0";
					filename += to_string(absX);

					astring zipFilename = ASTERSourceDir.string() + "ASTGTM2_" + filename + ".zip";

					if (exists(zipFilename))
					{
						tile.filename_dem = "/vsizip/" + zipFilename + "/ASTGTM2_" + filename + "_dem.tif";
						tile.filename_num = "/vsizip/" + zipFilename + "/ASTGTM2_" + filename + "_num.tif";
					}
					else
					{
						tile.latitude = MissingTileCoordinate;
						tile.longitude = MissingTileCoordinate;
					}
				}
			}

			return true;
		}

		virtual const char* GetName() const override
		{
			return LayerName.c_str();
		}

		virtual const char_t* GetTitle() const override
		{
			return LayerTitle.c_str();
		}

		virtual const int GetFixedWidth() const override
		{
			return 3600 * 360; // number of arc seconds around longitude
		}

		virtual const int GetFixedHeight() const override
		{
			return 3600 * 180; // number of arc seconds around latitude
		}

		virtual HandleGetMapRequestResult HandleGetMapRequest(const WebMapService::GetMapRequest& gmr, u8* data) override
		{
			auto crs = supportedCRS.find(gmr.crs);
			if (crs == supportedCRS.end())
			{
				return HGMRR_InvalidSRS;
			}

			switch (gmr.valueFormat)
			{
			case WebMapService::CF_UINT32:
				return HandleGetMapRequest<u32>(gmr, crs->second, (u32*)data);
			default:
				return HGMRR_InvalidFormat;
			}
		}

	private:

		virtual ~QualityElevation() override
		{
			delete[] asterTiles;

			for each (auto crs in supportedCRS)
			{
				delete crs.second;
			}

			for each (auto trans in srsTransforms)
			{
				OGRCoordinateTransformation::DestroyCT(trans.second);
			}
		}

		bool LoadASTERTileContent(const ASTERTile* tile, ASTERTileContent& content)
		{
			content.elevation = NULL;
			content.quality = NULL;

			GDALDataset* demDS = NULL;
			GDALDataset* numDS = NULL;

			demDS = (GDALDataset*)GDALOpen(tile->filename_dem.c_str(), GA_ReadOnly);
			if (!demDS) goto err;

			numDS = (GDALDataset*)GDALOpen(tile->filename_num.c_str(), GA_ReadOnly);
			if (!numDS) goto err;

			if (demDS->GetGeoTransform(content.geoTransform) != CE_None) goto err;

			auto demRasterBand = demDS->GetRasterBand(1);
			if (!demRasterBand || demRasterBand->GetRasterDataType() != GDT_Int16) goto err;

			content.width = demRasterBand->GetXSize();
			content.height = demRasterBand->GetYSize();

			content.elevation = new s16[content.width * content.height];
			content.quality = new s16[content.width * content.height];

			if (demRasterBand->RasterIO(GF_Read, 0, 0, content.width, 1, content.elevation, content.width, 1, GDT_Int16, 0, 0) != CE_None)
			{
				goto err;
			}

			auto numRasterBand = numDS->GetRasterBand(1);
			if (!numRasterBand || numRasterBand->GetRasterDataType() != GDT_Int16) goto err;

			if (numRasterBand->RasterIO(GF_Read, 0, 0, content.width, 1, content.quality, content.width, 1, GDT_Int16, 0, 0) != CE_None)
			{
				goto err;
			}

			return true;
		err:
			GDALClose(demDS);
			GDALClose(numDS);
			return false;
		}

		template<typename T>
		HandleGetMapRequestResult HandleGetMapRequest(const WebMapService::GetMapRequest& gmr, const OGRSpatialReference* requestSRS, T* data)
		{
			WebMapService::GetMapRequest::BBox asterBBox;
			if (!TransformBBox(gmr.bbox, asterBBox, requestSRS, ASTER_EPSG))
			{
				return HGMRR_InvalidBBox; // TODO: according to WMS specs bbox may lay outside of valid areas (e.g. latitudes greater than 90 degrees in CRS:84)
			}

			vector<ASTERTile*> asterTilesTouched;
			GetASTERTiles(asterTilesTouched, asterBBox);

			for each (const auto& tile in asterTilesTouched)
			{
				ASTERTileContent tileContent;

				if (!LoadASTERTileContent(tile, tileContent))
				{
					return HGMRR_InternalError;
				}

			}

			const int numPixels = gmr.width * gmr.height;
			for (size_t p = 0; p < numPixels; p++)
			{
				data[p] = 0xFF0000FF;
			}

			return HGMRR_OK;
		}

		bool TransformBBox(
			const WebMapService::GetMapRequest::BBox& srcBBox, WebMapService::GetMapRequest::BBox& dstBBox,
			const OGRSpatialReference* srcSRS, const OGRSpatialReference* dstSRS) const
		{
			bool success = true;
			auto transform = GetTransform(srcSRS, dstSRS);
			if (transform)
			{
				double x[2] = { srcBBox.minX, srcBBox.maxX };
				double y[2] = { srcBBox.minY, srcBBox.maxY };
				success = transform->Transform(2, x, y) == TRUE;
				dstBBox.minX = x[0];
				dstBBox.minY = y[0];
				dstBBox.maxX = x[1];
				dstBBox.maxY = y[1];
			}
			else
			{
				memcpy(&dstBBox, &srcBBox, sizeof(WebMapService::GetMapRequest::BBox));
			}
			return success;
		}

		OGRCoordinateTransformation* GetTransform(const OGRSpatialReference* src, const OGRSpatialReference* dst) const
		{
			SrcDestTransfromId transId;
			transId.src = src;
			transId.dst = dst;

			auto transform = srsTransforms.find(transId);
			return transform->second;
		}

		void CreateTransform(OGRSpatialReference* src, OGRSpatialReference* dst)
		{
			SrcDestTransfromId transId;
			transId.src = src;
			transId.dst = dst;

			auto existingTransform = srsTransforms.find(transId);
			if (existingTransform != srsTransforms.end()) return;

			srsTransforms[transId] = (src == dst) ? NULL : OGRCreateCoordinateTransformation(src, dst);
		}

		void GetASTERTiles(vector<ASTERTile*>& asterTilesTouched, const WebMapService::GetMapRequest::BBox& asterBBox)
		{
			int startX = Clamp((int)floor(asterBBox.minX), AsterTileStartLongitude, AsterTileEndLongitude) - AsterTileStartLongitude;
			int startY = Clamp((int)floor(asterBBox.minY), asterTileStartLatitude, asterTileEndLatitude) - asterTileStartLatitude;
			int endX = Clamp((int)floor(asterBBox.maxX - 0.000001), AsterTileStartLongitude, AsterTileEndLongitude) - AsterTileStartLongitude; // we fudge the max values because each
			int endY = Clamp((int)floor(asterBBox.maxY - 0.000001), asterTileStartLatitude, asterTileEndLatitude) - asterTileStartLatitude; // tile overlaps by one pixel with next tile

			for (int y = startY; y <= endY; y++)
			{
				int vIndex = y * NumASTERTilesX;
				ASTERTile* asterTile = &asterTiles[vIndex + startX];
				for (int x = startX; x <= endX; x++)
				{
					if (asterTile->latitude != MissingTileCoordinate)
					{
						asterTilesTouched.push_back(asterTile);
					}

					asterTile++;
				}
			}
		}
	};

	IMPLEMENT_WEBMAPSERVICE_LAYER(QualityElevation, LayerName, LayerTitle);
	}
}<commit_msg>implemented 16 bit to greyscale color conversion for elevation layer<commit_after>#include <filesystem>
#include <vector>
#include <mutex>
#include <iostream>

#include <ogr_api.h>
#include <ogr_spatialref.h>

#pragma warning (push)
#pragma warning (disable:4251)
#include <gdal_priv.h>
#pragma warning (pop)
#include <cpl_vsi.h>

#include <ZFXMath.h>

#include "../WebMapService.h"

using namespace std;
using namespace std::experimental::filesystem::v1;
using namespace dw;
using namespace ZFXMath;

namespace dw
{
namespace Layers
{
	const astring LayerName = "QualityElevation";
	const string LayerTitle = dwTEXT("ASTER + SRTMv3 High Quality Elevation Service");

	class QualityElevation : public WebMapService::Layer
	{
		struct SrcDestTransfromId
		{
			const OGRSpatialReference* src;
			const OGRSpatialReference* dst;

			bool operator< (const QualityElevation::SrcDestTransfromId& other) const
			{
				return memcmp(this, &other, sizeof(QualityElevation::SrcDestTransfromId)) < 0;
			}
		};

		struct ASTERTile
		{
			int longitude;
			int latitude;
			astring filename_dem;
			astring filename_num;
		};

		struct ASTERTileContent
		{
			s16* elevation;
			s16* quality;

			int width;
			int height;

			double geoTransform[6];

			~ASTERTileContent()
			{
				delete[] elevation;
				delete[] quality;
			}
		};

		map<astring, OGRSpatialReference*> supportedCRS;
		OGRSpatialReference* ASTER_EPSG;
		map<SrcDestTransfromId, OGRCoordinateTransformation*> srsTransforms;

		ASTERTile* asterTiles;
		int asterTileStartLatitude;
		int asterTileEndLatitude;
		const int AsterTileStartLongitude = -180;
		const int AsterTileEndLongitude = 179;
		const int NumASTERTilesX = AsterTileEndLongitude - AsterTileStartLongitude + 1;
		const int MissingTileCoordinate = -1000;

	public:

		virtual bool Init(/* layerconfig */) override
		{
			GDALRegister_GTiff();

			supportedCRS =
			{
				//pair<astring, OGRSpatialReference*>("EPSG:3857", new OGRSpatialReference()),
				pair<astring, OGRSpatialReference*>("EPSG:4326", new OGRSpatialReference())
			};

			for (auto it = supportedCRS.begin(); it != supportedCRS.end(); it++)
			{
				int epsgCode = atoi(it->first.c_str() + 5);
				OGRErr err = it->second->importFromEPSG(epsgCode);
				if (err == OGRERR_UNSUPPORTED_SRS)
				{
					return false;
				}
			}

			ASTER_EPSG = supportedCRS["EPSG:4326"];

			// create all possible SRS transformation permutations
			for (auto it1 = supportedCRS.begin(); it1 != supportedCRS.end(); it1++)
			{
				for (auto it2 = it1; it2 != supportedCRS.end(); it2++)
				{
					if (it2 == supportedCRS.end()) break;

					CreateTransform(it1->second, it2->second);
					CreateTransform(it2->second, it1->second);
				}
			}

			// load TOC from disk
			//const path ASTERSourceDir("D:/ASTER/");
			const path ASTERSourceDir("C:/Dev/temp/ASTER/");

			asterTileStartLatitude = 90;
			asterTileEndLatitude = -90;
			for (directory_iterator di(ASTERSourceDir); di != end(di); di++)
			{
				const auto& entity = *di;
				const auto extension = entity.path().extension();
				if (is_regular_file(entity.status()) && entity.path().extension().generic_string() == ".zip")
				{
					astring filepath = entity.path().string();
					int latitudeSign = 1;
					size_t offset = filepath.find_last_of('N');
					if (offset == std::string::npos)
					{
						offset = filepath.find_last_of('S');
						latitudeSign = -1;
					}
					if (offset != std::string::npos)
					{
						int latitude = atoi(filepath.c_str() + offset + 1) * latitudeSign;
						asterTileStartLatitude = min(asterTileStartLatitude, latitude);
						asterTileEndLatitude = max(asterTileEndLatitude, latitude);
					}
				}
			}

			const int NumASTERTilesX = 360;
			const int NumASTERTilesY = max(0, asterTileEndLatitude - asterTileStartLatitude + 1);

			if (NumASTERTilesY == 0)
			{
				cout << "ASTER data not found" << endl;
				return false;
			}

			asterTiles = new ASTERTile[NumASTERTilesX * NumASTERTilesY];
			memset(asterTiles, 0, sizeof(ASTERTile) * NumASTERTilesX * NumASTERTilesY);
			for (int y = asterTileStartLatitude; y <= asterTileEndLatitude; y++)
			{
				for (int x = AsterTileStartLongitude; x <= AsterTileEndLongitude; x++)
				{
					auto& tile = asterTiles[(y - asterTileStartLatitude) * NumASTERTilesX + (x - AsterTileStartLongitude)];
					tile.longitude = x;
					tile.latitude = y;

					int absX = abs(x);
					int absY = abs(y);

					astring filename = ((y < 0) ? "S" : "N");
					if (absY < 10) filename += "0";
					filename += to_string(absY) + ((x < 0) ? "W" : "E");
					if (absX < 10) filename += "00";
					else if (absX < 100) filename += "0";
					filename += to_string(absX);

					astring zipFilename = ASTERSourceDir.string() + "ASTGTM2_" + filename + ".zip";

					if (exists(zipFilename))
					{
						tile.filename_dem = "/vsizip/" + zipFilename + "/ASTGTM2_" + filename + "_dem.tif";
						tile.filename_num = "/vsizip/" + zipFilename + "/ASTGTM2_" + filename + "_num.tif";
					}
					else
					{
						tile.latitude = MissingTileCoordinate;
						tile.longitude = MissingTileCoordinate;
					}
				}
			}

			return true;
		}

		virtual const char* GetName() const override
		{
			return LayerName.c_str();
		}

		virtual const char_t* GetTitle() const override
		{
			return LayerTitle.c_str();
		}

		virtual const int GetFixedWidth() const override
		{
			return 3600 * 360; // number of arc seconds around longitude
		}

		virtual const int GetFixedHeight() const override
		{
			return 3600 * 180; // number of arc seconds around latitude
		}

		virtual HandleGetMapRequestResult HandleGetMapRequest(const WebMapService::GetMapRequest& gmr, u8* data) override
		{
			auto crs = supportedCRS.find(gmr.crs);
			if (crs == supportedCRS.end())
			{
				return HGMRR_InvalidSRS;
			}

			switch (gmr.valueFormat)
			{
			case WebMapService::CF_INT16:
			{
				return HandleGetMapRequest(gmr, crs->second, (s16*)data);
			}
			case WebMapService::CF_UINT32:
			{
				auto result = HandleGetMapRequest(gmr, crs->second, (s16*)data);
				if (result != HGMRR_OK) return result;
				u32* dstColorStart = (u32*)data;
				u32* dstColor = ((u32*)data) + gmr.width * gmr.height - 1;
				s16* elevation = ((s16*)data) + gmr.width * gmr.height - 1;
				while(dstColor >= dstColorStart) // convert elevation data to visual greyscale inplace
				{
					u32 elevationAsGrayScale = (u32)max(0, min(255, (((s32)(*elevation)) * 255) / 8800));

					*dstColor = 0xFF000000 | (elevationAsGrayScale << 16) | (elevationAsGrayScale << 8) | (elevationAsGrayScale << 0);

					elevation--;
					dstColor--;
				}
				return result;
			}
			default:
				return HGMRR_InvalidFormat;
			}
		}

	private:

		virtual ~QualityElevation() override
		{
			delete[] asterTiles;

			for each (auto crs in supportedCRS)
			{
				delete crs.second;
			}

			for each (auto trans in srsTransforms)
			{
				OGRCoordinateTransformation::DestroyCT(trans.second);
			}
		}

		bool LoadASTERTileContent(const ASTERTile* tile, ASTERTileContent& content)
		{
			content.elevation = NULL;
			content.quality = NULL;

			GDALDataset* demDS = NULL;
			GDALDataset* numDS = NULL;

			demDS = (GDALDataset*)GDALOpen(tile->filename_dem.c_str(), GA_ReadOnly);
			if (!demDS) goto err;

			numDS = (GDALDataset*)GDALOpen(tile->filename_num.c_str(), GA_ReadOnly);
			if (!numDS) goto err;

			if (demDS->GetGeoTransform(content.geoTransform) != CE_None) goto err;

			auto demRasterBand = demDS->GetRasterBand(1);
			if (!demRasterBand || demRasterBand->GetRasterDataType() != GDT_Int16) goto err;

			content.width = demRasterBand->GetXSize();
			content.height = demRasterBand->GetYSize();

			content.elevation = new s16[content.width * content.height];
			content.quality = new s16[content.width * content.height];

			if (demRasterBand->RasterIO(GF_Read, 0, 0, content.width, 1, content.elevation, content.width, 1, GDT_Int16, 0, 0) != CE_None)
			{
				goto err;
			}

			auto numRasterBand = numDS->GetRasterBand(1);
			if (!numRasterBand || numRasterBand->GetRasterDataType() != GDT_Int16) goto err;

			if (numRasterBand->RasterIO(GF_Read, 0, 0, content.width, 1, content.quality, content.width, 1, GDT_Int16, 0, 0) != CE_None)
			{
				goto err;
			}

			return true;
		err:
			GDALClose(demDS);
			GDALClose(numDS);
			return false;
		}

		HandleGetMapRequestResult HandleGetMapRequest(const WebMapService::GetMapRequest& gmr, const OGRSpatialReference* requestSRS, s16* data)
		{
			WebMapService::GetMapRequest::BBox asterBBox;
			if (!TransformBBox(gmr.bbox, asterBBox, requestSRS, ASTER_EPSG))
			{
				return HGMRR_InvalidBBox; // TODO: according to WMS specs bbox may lay outside of valid areas (e.g. latitudes greater than 90 degrees in CRS:84)
			}

			vector<ASTERTile*> asterTilesTouched;
			GetASTERTiles(asterTilesTouched, asterBBox);

			for each (const auto& tile in asterTilesTouched)
			{
				ASTERTileContent tileContent;

				if (!LoadASTERTileContent(tile, tileContent))
				{
					return HGMRR_InternalError;
				}

				data[0] = 0;
			}

			return HGMRR_OK;
		}

		bool TransformBBox(
			const WebMapService::GetMapRequest::BBox& srcBBox, WebMapService::GetMapRequest::BBox& dstBBox,
			const OGRSpatialReference* srcSRS, const OGRSpatialReference* dstSRS) const
		{
			bool success = true;
			auto transform = GetTransform(srcSRS, dstSRS);
			if (transform)
			{
				double x[2] = { srcBBox.minX, srcBBox.maxX };
				double y[2] = { srcBBox.minY, srcBBox.maxY };
				success = transform->Transform(2, x, y) == TRUE;
				dstBBox.minX = x[0];
				dstBBox.minY = y[0];
				dstBBox.maxX = x[1];
				dstBBox.maxY = y[1];
			}
			else
			{
				memcpy(&dstBBox, &srcBBox, sizeof(WebMapService::GetMapRequest::BBox));
			}
			return success;
		}

		OGRCoordinateTransformation* GetTransform(const OGRSpatialReference* src, const OGRSpatialReference* dst) const
		{
			SrcDestTransfromId transId;
			transId.src = src;
			transId.dst = dst;

			auto transform = srsTransforms.find(transId);
			return transform->second;
		}

		void CreateTransform(OGRSpatialReference* src, OGRSpatialReference* dst)
		{
			SrcDestTransfromId transId;
			transId.src = src;
			transId.dst = dst;

			auto existingTransform = srsTransforms.find(transId);
			if (existingTransform != srsTransforms.end()) return;

			srsTransforms[transId] = (src == dst) ? NULL : OGRCreateCoordinateTransformation(src, dst);
		}

		void GetASTERTiles(vector<ASTERTile*>& asterTilesTouched, const WebMapService::GetMapRequest::BBox& asterBBox)
		{
			int startX = Clamp((int)floor(asterBBox.minX), AsterTileStartLongitude, AsterTileEndLongitude) - AsterTileStartLongitude;
			int startY = Clamp((int)floor(asterBBox.minY), asterTileStartLatitude, asterTileEndLatitude) - asterTileStartLatitude;
			int endX = Clamp((int)floor(asterBBox.maxX - 0.000001), AsterTileStartLongitude, AsterTileEndLongitude) - AsterTileStartLongitude; // we fudge the max values because each
			int endY = Clamp((int)floor(asterBBox.maxY - 0.000001), asterTileStartLatitude, asterTileEndLatitude) - asterTileStartLatitude; // tile overlaps by one pixel with next tile

			for (int y = startY; y <= endY; y++)
			{
				int vIndex = y * NumASTERTilesX;
				ASTERTile* asterTile = &asterTiles[vIndex + startX];
				for (int x = startX; x <= endX; x++)
				{
					if (asterTile->latitude != MissingTileCoordinate)
					{
						asterTilesTouched.push_back(asterTile);
					}

					asterTile++;
				}
			}
		}
	};

	IMPLEMENT_WEBMAPSERVICE_LAYER(QualityElevation, LayerName, LayerTitle);
	}
}<|endoftext|>