<commit_before>/*
* Copyright 2016 Nu-book Inc.
* Copyright 2017 Axel Waggershauser
*
* 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 "BlackboxTestRunner.h"
#include "ImageLoader.h"
#include "TestReader.h"
#include "GenericLuminanceSource.h"
#include "HybridBinarizer.h"
#include "TextUtfEncoding.h"
#include "ZXContainerAlgorithms.h"
#include "lodepng.h"

#include <iostream>
#include <set>

#if __has_include(<filesystem>)
#  include <filesystem>
#  ifdef __cpp_lib_filesystem
     namespace fs = std::filesystem;
#    define ZXING_HAS_FILESYSTEM
#  endif
#endif
#if !defined(ZXING_HAS_FILESYSTEM) && __has_include(<experimental/filesystem>)
#  include <experimental/filesystem>
#  ifdef __cpp_lib_experimental_filesystem
     namespace fs = std::experimental::filesystem;
#    define ZXING_HAS_FILESYSTEM
#  endif
#endif
#if defined(__APPLE__) && !defined(__clang__) &&                                                                       \
	__has_include(<dirent.h>) && defined(__SANITIZE_ADDRESS__) && defined(ZXING_HAS_FILESYSTEM)
#  warning detected gcc + macos + <filesystem> + address_sanitizer == bad -> disable <filesystem>
#  undef ZXING_HAS_FILESYSTEM
#endif
#if !defined(ZXING_HAS_FILESYSTEM)
#  if __has_include(<dirent.h>)
#    include <dirent.h>
#  else
#    error need <filesystem> or <dirent.h>
#  endif
#endif

// compiling this with clang (e.g. version 6) might require linking against libc++experimental.a or libc++fs.a.
// E.g.: CMAKE_EXE_LINKER_FLAGS = -L/usr/local/Cellar/llvm/6.0.1/lib -lc++experimental

using namespace ZXing;
using namespace ZXing::Test;

static bool HasSuffix(const std::string& s, const std::string& suffix)
{
	return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin());
}

class GenericImageLoader : public ImageLoader
{
public:
	virtual std::shared_ptr<LuminanceSource> load(const std::wstring& filename) const override
	{
		std::vector<unsigned char> buffer;
		unsigned width, height;
		unsigned error = lodepng::decode(buffer, width, height, TextUtfEncoding::ToUtf8(filename));
		if (error) {
			throw std::runtime_error("Failed to read image");
		}
		return std::make_shared<GenericLuminanceSource>((int)width, (int)height, buffer.data(), width*4, 4, 0, 1, 2);
	}
};

class GenericBlackboxTestRunner : public BlackboxTestRunner
{
public:
	GenericBlackboxTestRunner(const std::wstring& pathPrefix)
		: BlackboxTestRunner(pathPrefix, std::make_shared<GenericImageLoader>())
	{
	}

	virtual std::vector<std::wstring> getImagesInDirectory(const std::wstring& dirPath) override
	{
		std::vector<std::wstring> result;
#ifndef ZXING_HAS_FILESYSTEM
		if (auto dir = opendir(TextUtfEncoding::ToUtf8(pathPrefix() + L"/" + dirPath).c_str())) {
			while (auto entry = readdir(dir)) {
				if (HasSuffix(entry->d_name, ".png")) {
					result.push_back(dirPath + L"/" + TextUtfEncoding::FromUtf8(entry->d_name));
				}
			}
			closedir(dir);
		}
		else {
			std::cerr << "Error open dir " << TextUtfEncoding::ToUtf8(dirPath) << std::endl;
		}
#else
		for (const auto& entry : fs::directory_iterator(fs::path(pathPrefix()) / dirPath))
			if (fs::is_regular_file(entry.status()) && entry.path().extension() == ".png")
				result.push_back(dirPath + L"/" + entry.path().filename().generic_wstring());
#endif
		return result;
	}
};

int main(int argc, char** argv)
{
	if (argc <= 1) {
		std::cout << "Usage: " << argv[0] << " <test_path_prefix>" << std::endl;
		return 0;
	}

	std::string pathPrefix = argv[1];

	GenericBlackboxTestRunner runner(TextUtfEncoding::FromUtf8(pathPrefix));

	if (HasSuffix(pathPrefix, ".png")) {
#if 0
		TestReader reader = runner.createReader(false, false, "QR_CODE");
#else
		TestReader reader = runner.createReader(true, true);
#endif
		bool isPure = getenv("IS_PURE");
		int rotation = getenv("ROTATION") ? atoi(getenv("ROTATION")) : 0;

		for (int i = 1; i < argc; ++i) {
			auto result = reader.read(TextUtfEncoding::FromUtf8(argv[i]), rotation, isPure);
			std::cout << argv[i] << ": ";
			if (result)
				std::cout << result.format << ": " << TextUtfEncoding::ToUtf8(result.text) << "\n";
			else
				std::cout << "FAILED\n";
		}
		return 0;
	}

	std::set<std::string> includedTests;
	for (int i = 2; i < argc; ++i) {
		if (std::strlen(argv[i]) > 2 && argv[i][0] == '-' && argv[i][1] == 't') {
			includedTests.insert(argv[i] + 2);
		}
	}

	runner.run(includedTests);
}
<commit_msg>minor clang-tidy fix in TestReaderMain<commit_after>/*
* Copyright 2016 Nu-book Inc.
* Copyright 2017 Axel Waggershauser
*
* 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 "BlackboxTestRunner.h"
#include "ImageLoader.h"
#include "TestReader.h"
#include "GenericLuminanceSource.h"
#include "HybridBinarizer.h"
#include "TextUtfEncoding.h"
#include "ZXContainerAlgorithms.h"
#include "lodepng.h"

#include <iostream>
#include <set>

#if __has_include(<filesystem>)
#  include <filesystem>
#  ifdef __cpp_lib_filesystem
     namespace fs = std::filesystem;
#    define ZXING_HAS_FILESYSTEM
#  endif
#endif
#if !defined(ZXING_HAS_FILESYSTEM) && __has_include(<experimental/filesystem>)
#  include <experimental/filesystem>
#  ifdef __cpp_lib_experimental_filesystem
     namespace fs = std::experimental::filesystem;
#    define ZXING_HAS_FILESYSTEM
#  endif
#endif
#if defined(__APPLE__) && !defined(__clang__) &&                                                                       \
	__has_include(<dirent.h>) && defined(__SANITIZE_ADDRESS__) && defined(ZXING_HAS_FILESYSTEM)
#  warning detected gcc + macos + <filesystem> + address_sanitizer == bad -> disable <filesystem>
#  undef ZXING_HAS_FILESYSTEM
#endif
#if !defined(ZXING_HAS_FILESYSTEM)
#  if __has_include(<dirent.h>)
#    include <dirent.h>
#  else
#    error need <filesystem> or <dirent.h>
#  endif
#endif

// compiling this with clang (e.g. version 6) might require linking against libc++experimental.a or libc++fs.a.
// E.g.: CMAKE_EXE_LINKER_FLAGS = -L/usr/local/Cellar/llvm/6.0.1/lib -lc++experimental

using namespace ZXing;
using namespace ZXing::Test;

static bool HasSuffix(const std::string& s, const std::string& suffix)
{
	return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin());
}

class GenericImageLoader : public ImageLoader
{
public:
	std::shared_ptr<LuminanceSource> load(const std::wstring& filename) const final
	{
		std::vector<unsigned char> buffer;
		unsigned width, height;
		unsigned error = lodepng::decode(buffer, width, height, TextUtfEncoding::ToUtf8(filename));
		if (error) {
			throw std::runtime_error("Failed to read image");
		}
		return std::make_shared<GenericLuminanceSource>((int)width, (int)height, buffer.data(), width*4, 4, 0, 1, 2);
	}
};

class GenericBlackboxTestRunner : public BlackboxTestRunner
{
public:
	GenericBlackboxTestRunner(const std::wstring& pathPrefix)
		: BlackboxTestRunner(pathPrefix, std::make_shared<GenericImageLoader>())
	{
	}

	std::vector<std::wstring> getImagesInDirectory(const std::wstring& dirPath) final
	{
		std::vector<std::wstring> result;
#ifndef ZXING_HAS_FILESYSTEM
		if (auto dir = opendir(TextUtfEncoding::ToUtf8(pathPrefix() + L"/" + dirPath).c_str())) {
			while (auto entry = readdir(dir)) {
				if (HasSuffix(entry->d_name, ".png")) {
					result.push_back(dirPath + L"/" + TextUtfEncoding::FromUtf8(entry->d_name));
				}
			}
			closedir(dir);
		}
		else {
			std::cerr << "Error open dir " << TextUtfEncoding::ToUtf8(dirPath) << std::endl;
		}
#else
		for (const auto& entry : fs::directory_iterator(fs::path(pathPrefix()) / dirPath))
			if (fs::is_regular_file(entry.status()) && entry.path().extension() == ".png")
				result.push_back(dirPath + L"/" + entry.path().filename().generic_wstring());
#endif
		return result;
	}
};

int main(int argc, char** argv)
{
	if (argc <= 1) {
		std::cout << "Usage: " << argv[0] << " <test_path_prefix>" << std::endl;
		return 0;
	}

	std::string pathPrefix = argv[1];

	GenericBlackboxTestRunner runner(TextUtfEncoding::FromUtf8(pathPrefix));

	if (HasSuffix(pathPrefix, ".png")) {
#if 0
		TestReader reader = runner.createReader(false, false, "QR_CODE");
#else
		TestReader reader = runner.createReader(true, true);
#endif
		bool isPure = getenv("IS_PURE");
		int rotation = getenv("ROTATION") ? atoi(getenv("ROTATION")) : 0;

		for (int i = 1; i < argc; ++i) {
			auto result = reader.read(TextUtfEncoding::FromUtf8(argv[i]), rotation, isPure);
			std::cout << argv[i] << ": ";
			if (result)
				std::cout << result.format << ": " << TextUtfEncoding::ToUtf8(result.text) << "\n";
			else
				std::cout << "FAILED\n";
		}
		return 0;
	}

	std::set<std::string> includedTests;
	for (int i = 2; i < argc; ++i) {
		if (std::strlen(argv[i]) > 2 && argv[i][0] == '-' && argv[i][1] == 't') {
			includedTests.insert(argv[i] + 2);
		}
	}

	runner.run(includedTests);
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svx.hxx"

#include <svx/sdr/contact/viewobjectcontactofpageobj.hxx>
#include <svx/sdr/contact/viewcontactofpageobj.hxx>
#include <svx/svdopage.hxx>
#include <svx/sdr/contact/displayinfo.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
#include <svx/sdr/contact/objectcontactofobjlistpainter.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <svx/svdpage.hxx>
#include <unoapi.hxx>
#include <drawinglayer/primitive2d/pagepreviewprimitive2d.hxx>
#include <drawinglayer/primitive2d/sdrdecompositiontools2d.hxx>

//////////////////////////////////////////////////////////////////////////////

using namespace com::sun::star;

//////////////////////////////////////////////////////////////////////////////

namespace sdr
{
    namespace contact
    {
        class PagePrimitiveExtractor : public ObjectContactOfPagePainter, public Timer
        {
        private:
            // the ViewObjectContactOfPageObj using this painter
            ViewObjectContactOfPageObj&         mrViewObjectContactOfPageObj;

        public:
            // basic constructor/destructor
            PagePrimitiveExtractor(ViewObjectContactOfPageObj& rVOC);
            virtual ~PagePrimitiveExtractor();

            // LazyInvalidate request. Supported here to not automatically
            // invalidate the second interaction state all the time at the
            // original OC
            virtual void setLazyInvalidate(ViewObjectContact& rVOC);

            // From baseclass Timer, the timeout call triggered by te LazyInvalidate mechanism
            virtual void Timeout();

            // get primitive visualization
            drawinglayer::primitive2d::Primitive2DSequence createPrimitive2DSequenceForPage(const DisplayInfo& rDisplayInfo);

            // Own reaction on changes which will be forwarded to the OC of the owner-VOC
            virtual void InvalidatePartOfView(const basegfx::B2DRange& rRange) const;

            // forward access to SdrPageView of ViewObjectContactOfPageObj
            virtual bool isOutputToPrinter() const;
            virtual bool isOutputToWindow() const;
            virtual bool isOutputToVirtualDevice() const;
            virtual bool isOutputToRecordingMetaFile() const;
            virtual bool isOutputToPDFFile() const;
            virtual bool isDrawModeGray() const;
            virtual bool isDrawModeBlackWhite() const;
            virtual bool isDrawModeHighContrast() const;
            virtual SdrPageView* TryToGetSdrPageView() const;
            virtual OutputDevice* TryToGetOutputDevice() const;
        };

        PagePrimitiveExtractor::PagePrimitiveExtractor(
            ViewObjectContactOfPageObj& rVOC)
        :   ObjectContactOfPagePainter(0, rVOC.GetObjectContact()),
            mrViewObjectContactOfPageObj(rVOC)
        {
            // make this renderer a preview renderer
            setPreviewRenderer(true);

            // init timer
            SetTimeout(1);
            Stop();
        }

        PagePrimitiveExtractor::~PagePrimitiveExtractor()
        {
            // execute missing LazyInvalidates and stop timer
            Timeout();
        }

        void PagePrimitiveExtractor::setLazyInvalidate(ViewObjectContact& /*rVOC*/)
        {
            // do NOT call parent, but remember that something is to do by
            // starting the LazyInvalidateTimer
            Start();
        }

        // From baseclass Timer, the timeout call triggered by te LazyInvalidate mechanism
        void PagePrimitiveExtractor::Timeout()
        {
            // stop the timer
            Stop();

            // invalidate all LazyInvalidate VOCs new situations
            const sal_uInt32 nVOCCount(getViewObjectContactCount());

            for(sal_uInt32 a(0); a < nVOCCount; a++)
            {
                ViewObjectContact* pCandidate = getViewObjectContact(a);
                pCandidate->triggerLazyInvalidate();
            }
        }

        drawinglayer::primitive2d::Primitive2DSequence PagePrimitiveExtractor::createPrimitive2DSequenceForPage(const DisplayInfo& /*rDisplayInfo*/)
        {
            drawinglayer::primitive2d::Primitive2DSequence xRetval;
            const SdrPage* pStartPage = GetStartPage();

            if(pStartPage)
            {
                // update own ViewInformation2D for visualized page
                const drawinglayer::geometry::ViewInformation2D& rOriginalViewInformation = mrViewObjectContactOfPageObj.GetObjectContact().getViewInformation2D();
                const drawinglayer::geometry::ViewInformation2D aNewViewInformation2D(
                    rOriginalViewInformation.getObjectTransformation(),
                    rOriginalViewInformation.getViewTransformation(),

                    // #i101075# use empty range for page content here to force
                    // the content not to be physically clipped in any way. This
                    // would be possible, but would require the internal transformation
                    // which maps between the page visualisation object and the page
                    // content, including the aspect ratios (for details see in
                    // PagePreviewPrimitive2D::create2DDecomposition)
                    basegfx::B2DRange(),

                    GetXDrawPageForSdrPage(const_cast< SdrPage* >(pStartPage)),
                    0.0, // no time; page previews are not animated
                    rOriginalViewInformation.getExtendedInformationSequence());
                updateViewInformation2D(aNewViewInformation2D);

                // create copy of DisplayInfo to set PagePainting
                DisplayInfo aDisplayInfo;

                // get page's VOC
                ViewObjectContact& rDrawPageVOContact = pStartPage->GetViewContact().GetViewObjectContact(*this);

                // get whole Primitive2DSequence
                xRetval = rDrawPageVOContact.getPrimitive2DSequenceHierarchy(aDisplayInfo);
            }

            return xRetval;
        }

        void PagePrimitiveExtractor::InvalidatePartOfView(const basegfx::B2DRange& rRange) const
        {
            // an invalidate is called at this view, this needs to be translated to an invalidate
            // for the using VOC. Coordinates are in page coordinate system.
            const SdrPage* pStartPage = GetStartPage();

            if(pStartPage && !rRange.isEmpty())
            {
                const basegfx::B2DRange aPageRange(0.0, 0.0, (double)pStartPage->GetWdt(), (double)pStartPage->GetHgt());

                if(rRange.overlaps(aPageRange))
                {
                    // if object on the page is inside or overlapping with page, create ActionChanged() for
                    // involved VOC
                    mrViewObjectContactOfPageObj.ActionChanged();
                }
            }
        }

        // forward access to SdrPageView to VOCOfPageObj
        bool PagePrimitiveExtractor::isOutputToPrinter() const { return mrViewObjectContactOfPageObj.GetObjectContact().isOutputToPrinter(); }
        bool PagePrimitiveExtractor::isOutputToWindow() const { return mrViewObjectContactOfPageObj.GetObjectContact().isOutputToWindow(); }
        bool PagePrimitiveExtractor::isOutputToVirtualDevice() const { return mrViewObjectContactOfPageObj.GetObjectContact().isOutputToVirtualDevice(); }
        bool PagePrimitiveExtractor::isOutputToRecordingMetaFile() const { return mrViewObjectContactOfPageObj.GetObjectContact().isOutputToRecordingMetaFile(); }
        bool PagePrimitiveExtractor::isOutputToPDFFile() const { return mrViewObjectContactOfPageObj.GetObjectContact().isOutputToPDFFile(); }
        bool PagePrimitiveExtractor::isDrawModeGray() const { return mrViewObjectContactOfPageObj.GetObjectContact().isDrawModeGray(); }
        bool PagePrimitiveExtractor::isDrawModeBlackWhite() const { return mrViewObjectContactOfPageObj.GetObjectContact().isDrawModeBlackWhite(); }
        bool PagePrimitiveExtractor::isDrawModeHighContrast() const { return mrViewObjectContactOfPageObj.GetObjectContact().isDrawModeHighContrast(); }
        SdrPageView* PagePrimitiveExtractor::TryToGetSdrPageView() const { return mrViewObjectContactOfPageObj.GetObjectContact().TryToGetSdrPageView(); }
        OutputDevice* PagePrimitiveExtractor::TryToGetOutputDevice() const { return mrViewObjectContactOfPageObj.GetObjectContact().TryToGetOutputDevice(); }
    } // end of namespace contact
} // end of namespace sdr

//////////////////////////////////////////////////////////////////////////////

namespace sdr
{
    namespace contact
    {
        drawinglayer::primitive2d::Primitive2DSequence ViewObjectContactOfPageObj::createPrimitive2DSequence(const DisplayInfo& rDisplayInfo) const
        {
            drawinglayer::primitive2d::Primitive2DSequence xRetval;
            const SdrPageObj& rPageObject((static_cast< ViewContactOfPageObj& >(GetViewContact())).GetPageObj());
            const SdrPage* pPage = rPageObject.GetReferencedPage();
            const svtools::ColorConfig aColorConfig;

            // get PageObject's geometry
            basegfx::B2DHomMatrix aPageObjectTransform;
            {
                const Rectangle aPageObjectModelData(rPageObject.GetLastBoundRect());
                const basegfx::B2DRange aPageObjectBound(
                    aPageObjectModelData.Left(), aPageObjectModelData.Top(),
                    aPageObjectModelData.Right(), aPageObjectModelData.Bottom());

                aPageObjectTransform.set(0, 0, aPageObjectBound.getWidth());
                aPageObjectTransform.set(1, 1, aPageObjectBound.getHeight());
                aPageObjectTransform.set(0, 2, aPageObjectBound.getMinX());
                aPageObjectTransform.set(1, 2, aPageObjectBound.getMinY());
            }

            // #i102637# add gray frame also when printing and page exists (handout pages)
            const bool bCreateGrayFrame(!GetObjectContact().isOutputToPrinter() || pPage);

            // get displayed page's content. This is the uscaled page content
            if(mpExtractor && pPage)
            {
                // get displayed page's geometry
                   drawinglayer::primitive2d::Primitive2DSequence xPageContent;
                const Size aPageSize(pPage->GetSize());
                const double fPageWidth(aPageSize.getWidth());
                const double fPageHeight(aPageSize.getHeight());

                // The case that a PageObject contains another PageObject which visualizes the
                // same page again would lead to a recursion. Limit that recursion depth to one
                // by using a local static bool
                static bool bInCreatePrimitive2D(false);

                if(bInCreatePrimitive2D)
                {
                    // Recursion is possible. Create a replacement primitive
                    xPageContent.realloc(2);
                    const Color aDocColor(aColorConfig.GetColorValue(svtools::DOCCOLOR).nColor);
                    const Color aBorderColor(aColorConfig.GetColorValue(svtools::DOCBOUNDARIES).nColor);
                    const basegfx::B2DRange aPageBound(0.0, 0.0, fPageWidth, fPageHeight);
                    const basegfx::B2DPolygon aOutline(basegfx::tools::createPolygonFromRect(aPageBound));

                    // add replacement fill
                    xPageContent[0L] = drawinglayer::primitive2d::Primitive2DReference(
                        new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(basegfx::B2DPolyPolygon(aOutline), aDocColor.getBColor()));

                    // add replacement border
                    xPageContent[1L] = drawinglayer::primitive2d::Primitive2DReference(
                        new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(aOutline, aBorderColor.getBColor()));
                }
                else
                {
                    // set recursion flag
                    bInCreatePrimitive2D = true;

                    // init extractor, guarantee existance, set page there
                    mpExtractor->SetStartPage(pPage);

                    // create page content
                    xPageContent = mpExtractor->createPrimitive2DSequenceForPage(rDisplayInfo);

                    // reset recursion flag
                    bInCreatePrimitive2D = false;
                }

                // prepare retval
                if(xPageContent.hasElements())
                {
                    const uno::Reference< drawing::XDrawPage > xDrawPage(GetXDrawPageForSdrPage(const_cast< SdrPage*>(pPage)));
                    const drawinglayer::primitive2d::Primitive2DReference xPagePreview(new drawinglayer::primitive2d::PagePreviewPrimitive2D(
                        xDrawPage, aPageObjectTransform, fPageWidth, fPageHeight, xPageContent, true));
                    xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xPagePreview, 1);
                }
            }
            else if(bCreateGrayFrame)
            {
                // #i105146# no content, but frame display. To make hitting the page preview objects
                // on the handout page more simple, add hidden fill geometry
                const drawinglayer::primitive2d::Primitive2DReference xFrameHit(
                    drawinglayer::primitive2d::createHiddenGeometryPrimitives2D(
                        false,
                        aPageObjectTransform));
                xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xFrameHit, 1);
            }

            // add a gray outline frame, except not when printing
            if(bCreateGrayFrame)
            {
                const Color aFrameColor(aColorConfig.GetColorValue(svtools::OBJECTBOUNDARIES).nColor);
                basegfx::B2DPolygon aOwnOutline(basegfx::tools::createUnitPolygon());
                aOwnOutline.transform(aPageObjectTransform);

                const drawinglayer::primitive2d::Primitive2DReference xGrayFrame(
                    new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(aOwnOutline, aFrameColor.getBColor()));

                drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(xRetval, xGrayFrame);
            }

            return xRetval;
        }

        ViewObjectContactOfPageObj::ViewObjectContactOfPageObj(ObjectContact& rObjectContact, ViewContact& rViewContact)
        :   ViewObjectContactOfSdrObj(rObjectContact, rViewContact),
            mpExtractor(new PagePrimitiveExtractor(*this))
        {
        }

        ViewObjectContactOfPageObj::~ViewObjectContactOfPageObj()
        {
            // delete the helper OC
            if(mpExtractor)
            {
                // remember candidate and reset own pointer to avoid action when createPrimitive2DSequence()
                // would be called for any reason
                PagePrimitiveExtractor* pCandidate = mpExtractor;
                mpExtractor = 0;

                // also reset the StartPage to avoid ActionChanged() forwardings in the
                // PagePrimitiveExtractor::InvalidatePartOfView() implementation
                pCandidate->SetStartPage(0);
                delete pCandidate;
            }
        }
    } // end of namespace contact
} // end of namespace sdr

//////////////////////////////////////////////////////////////////////////////
// eof
<commit_msg>aw083 #i105548# Added using the VOCRedirector inside pageobject content creation<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svx.hxx"

#include <svx/sdr/contact/viewobjectcontactofpageobj.hxx>
#include <svx/sdr/contact/viewcontactofpageobj.hxx>
#include <svx/svdopage.hxx>
#include <svx/sdr/contact/displayinfo.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
#include <svx/sdr/contact/objectcontactofobjlistpainter.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <svx/svdpage.hxx>
#include <unoapi.hxx>
#include <drawinglayer/primitive2d/pagepreviewprimitive2d.hxx>
#include <drawinglayer/primitive2d/sdrdecompositiontools2d.hxx>

//////////////////////////////////////////////////////////////////////////////

using namespace com::sun::star;

//////////////////////////////////////////////////////////////////////////////

namespace sdr
{
    namespace contact
    {
        class PagePrimitiveExtractor : public ObjectContactOfPagePainter, public Timer
        {
        private:
            // the ViewObjectContactOfPageObj using this painter
            ViewObjectContactOfPageObj&         mrViewObjectContactOfPageObj;

        public:
            // basic constructor/destructor
            PagePrimitiveExtractor(ViewObjectContactOfPageObj& rVOC);
            virtual ~PagePrimitiveExtractor();

            // LazyInvalidate request. Supported here to not automatically
            // invalidate the second interaction state all the time at the
            // original OC
            virtual void setLazyInvalidate(ViewObjectContact& rVOC);

            // From baseclass Timer, the timeout call triggered by te LazyInvalidate mechanism
            virtual void Timeout();

            // get primitive visualization
            drawinglayer::primitive2d::Primitive2DSequence createPrimitive2DSequenceForPage(const DisplayInfo& rDisplayInfo);

            // Own reaction on changes which will be forwarded to the OC of the owner-VOC
            virtual void InvalidatePartOfView(const basegfx::B2DRange& rRange) const;

            // forward access to SdrPageView of ViewObjectContactOfPageObj
            virtual bool isOutputToPrinter() const;
            virtual bool isOutputToWindow() const;
            virtual bool isOutputToVirtualDevice() const;
            virtual bool isOutputToRecordingMetaFile() const;
            virtual bool isOutputToPDFFile() const;
            virtual bool isDrawModeGray() const;
            virtual bool isDrawModeBlackWhite() const;
            virtual bool isDrawModeHighContrast() const;
            virtual SdrPageView* TryToGetSdrPageView() const;
            virtual OutputDevice* TryToGetOutputDevice() const;
        };

        PagePrimitiveExtractor::PagePrimitiveExtractor(
            ViewObjectContactOfPageObj& rVOC)
        :   ObjectContactOfPagePainter(0, rVOC.GetObjectContact()),
            mrViewObjectContactOfPageObj(rVOC)
        {
            // make this renderer a preview renderer
            setPreviewRenderer(true);

            // init timer
            SetTimeout(1);
            Stop();
        }

        PagePrimitiveExtractor::~PagePrimitiveExtractor()
        {
            // execute missing LazyInvalidates and stop timer
            Timeout();
        }

        void PagePrimitiveExtractor::setLazyInvalidate(ViewObjectContact& /*rVOC*/)
        {
            // do NOT call parent, but remember that something is to do by
            // starting the LazyInvalidateTimer
            Start();
        }

        // From baseclass Timer, the timeout call triggered by te LazyInvalidate mechanism
        void PagePrimitiveExtractor::Timeout()
        {
            // stop the timer
            Stop();

            // invalidate all LazyInvalidate VOCs new situations
            const sal_uInt32 nVOCCount(getViewObjectContactCount());

            for(sal_uInt32 a(0); a < nVOCCount; a++)
            {
                ViewObjectContact* pCandidate = getViewObjectContact(a);
                pCandidate->triggerLazyInvalidate();
            }
        }

        drawinglayer::primitive2d::Primitive2DSequence PagePrimitiveExtractor::createPrimitive2DSequenceForPage(const DisplayInfo& /*rDisplayInfo*/)
        {
            drawinglayer::primitive2d::Primitive2DSequence xRetval;
            const SdrPage* pStartPage = GetStartPage();

            if(pStartPage)
            {
                // update own ViewInformation2D for visualized page
                const drawinglayer::geometry::ViewInformation2D& rOriginalViewInformation = mrViewObjectContactOfPageObj.GetObjectContact().getViewInformation2D();
                const drawinglayer::geometry::ViewInformation2D aNewViewInformation2D(
                    rOriginalViewInformation.getObjectTransformation(),
                    rOriginalViewInformation.getViewTransformation(),

                    // #i101075# use empty range for page content here to force
                    // the content not to be physically clipped in any way. This
                    // would be possible, but would require the internal transformation
                    // which maps between the page visualisation object and the page
                    // content, including the aspect ratios (for details see in
                    // PagePreviewPrimitive2D::create2DDecomposition)
                    basegfx::B2DRange(),

                    GetXDrawPageForSdrPage(const_cast< SdrPage* >(pStartPage)),
                    0.0, // no time; page previews are not animated
                    rOriginalViewInformation.getExtendedInformationSequence());
                updateViewInformation2D(aNewViewInformation2D);

                // create copy of DisplayInfo to set PagePainting
                DisplayInfo aDisplayInfo;

                // get page's VOC
                ViewObjectContact& rDrawPageVOContact = pStartPage->GetViewContact().GetViewObjectContact(*this);

                // get whole Primitive2DSequence
                xRetval = rDrawPageVOContact.getPrimitive2DSequenceHierarchy(aDisplayInfo);
            }

            return xRetval;
        }

        void PagePrimitiveExtractor::InvalidatePartOfView(const basegfx::B2DRange& rRange) const
        {
            // an invalidate is called at this view, this needs to be translated to an invalidate
            // for the using VOC. Coordinates are in page coordinate system.
            const SdrPage* pStartPage = GetStartPage();

            if(pStartPage && !rRange.isEmpty())
            {
                const basegfx::B2DRange aPageRange(0.0, 0.0, (double)pStartPage->GetWdt(), (double)pStartPage->GetHgt());

                if(rRange.overlaps(aPageRange))
                {
                    // if object on the page is inside or overlapping with page, create ActionChanged() for
                    // involved VOC
                    mrViewObjectContactOfPageObj.ActionChanged();
                }
            }
        }

        // forward access to SdrPageView to VOCOfPageObj
        bool PagePrimitiveExtractor::isOutputToPrinter() const { return mrViewObjectContactOfPageObj.GetObjectContact().isOutputToPrinter(); }
        bool PagePrimitiveExtractor::isOutputToWindow() const { return mrViewObjectContactOfPageObj.GetObjectContact().isOutputToWindow(); }
        bool PagePrimitiveExtractor::isOutputToVirtualDevice() const { return mrViewObjectContactOfPageObj.GetObjectContact().isOutputToVirtualDevice(); }
        bool PagePrimitiveExtractor::isOutputToRecordingMetaFile() const { return mrViewObjectContactOfPageObj.GetObjectContact().isOutputToRecordingMetaFile(); }
        bool PagePrimitiveExtractor::isOutputToPDFFile() const { return mrViewObjectContactOfPageObj.GetObjectContact().isOutputToPDFFile(); }
        bool PagePrimitiveExtractor::isDrawModeGray() const { return mrViewObjectContactOfPageObj.GetObjectContact().isDrawModeGray(); }
        bool PagePrimitiveExtractor::isDrawModeBlackWhite() const { return mrViewObjectContactOfPageObj.GetObjectContact().isDrawModeBlackWhite(); }
        bool PagePrimitiveExtractor::isDrawModeHighContrast() const { return mrViewObjectContactOfPageObj.GetObjectContact().isDrawModeHighContrast(); }
        SdrPageView* PagePrimitiveExtractor::TryToGetSdrPageView() const { return mrViewObjectContactOfPageObj.GetObjectContact().TryToGetSdrPageView(); }
        OutputDevice* PagePrimitiveExtractor::TryToGetOutputDevice() const { return mrViewObjectContactOfPageObj.GetObjectContact().TryToGetOutputDevice(); }
    } // end of namespace contact
} // end of namespace sdr

//////////////////////////////////////////////////////////////////////////////

namespace sdr
{
    namespace contact
    {
        drawinglayer::primitive2d::Primitive2DSequence ViewObjectContactOfPageObj::createPrimitive2DSequence(const DisplayInfo& rDisplayInfo) const
        {
            drawinglayer::primitive2d::Primitive2DSequence xRetval;
            const SdrPageObj& rPageObject((static_cast< ViewContactOfPageObj& >(GetViewContact())).GetPageObj());
            const SdrPage* pPage = rPageObject.GetReferencedPage();
            const svtools::ColorConfig aColorConfig;

            // get PageObject's geometry
            basegfx::B2DHomMatrix aPageObjectTransform;
            {
                const Rectangle aPageObjectModelData(rPageObject.GetLastBoundRect());
                const basegfx::B2DRange aPageObjectBound(
                    aPageObjectModelData.Left(), aPageObjectModelData.Top(),
                    aPageObjectModelData.Right(), aPageObjectModelData.Bottom());

                aPageObjectTransform.set(0, 0, aPageObjectBound.getWidth());
                aPageObjectTransform.set(1, 1, aPageObjectBound.getHeight());
                aPageObjectTransform.set(0, 2, aPageObjectBound.getMinX());
                aPageObjectTransform.set(1, 2, aPageObjectBound.getMinY());
            }

            // #i102637# add gray frame also when printing and page exists (handout pages)
            const bool bCreateGrayFrame(!GetObjectContact().isOutputToPrinter() || pPage);

            // get displayed page's content. This is the uscaled page content
            if(mpExtractor && pPage)
            {
                // get displayed page's geometry
                   drawinglayer::primitive2d::Primitive2DSequence xPageContent;
                const Size aPageSize(pPage->GetSize());
                const double fPageWidth(aPageSize.getWidth());
                const double fPageHeight(aPageSize.getHeight());

                // The case that a PageObject contains another PageObject which visualizes the
                // same page again would lead to a recursion. Limit that recursion depth to one
                // by using a local static bool
                static bool bInCreatePrimitive2D(false);

                if(bInCreatePrimitive2D)
                {
                    // Recursion is possible. Create a replacement primitive
                    xPageContent.realloc(2);
                    const Color aDocColor(aColorConfig.GetColorValue(svtools::DOCCOLOR).nColor);
                    const Color aBorderColor(aColorConfig.GetColorValue(svtools::DOCBOUNDARIES).nColor);
                    const basegfx::B2DRange aPageBound(0.0, 0.0, fPageWidth, fPageHeight);
                    const basegfx::B2DPolygon aOutline(basegfx::tools::createPolygonFromRect(aPageBound));

                    // add replacement fill
                    xPageContent[0L] = drawinglayer::primitive2d::Primitive2DReference(
                        new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(basegfx::B2DPolyPolygon(aOutline), aDocColor.getBColor()));

                    // add replacement border
                    xPageContent[1L] = drawinglayer::primitive2d::Primitive2DReference(
                        new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(aOutline, aBorderColor.getBColor()));
                }
                else
                {
                    // set recursion flag
                    bInCreatePrimitive2D = true;

                    // init extractor, guarantee existance, set page there
                    mpExtractor->SetStartPage(pPage);

                    // #i105548# also need to copy the VOCRedirector for sub-content creation
                    mpExtractor->SetViewObjectContactRedirector(GetObjectContact().GetViewObjectContactRedirector());

                    // create page content
                    xPageContent = mpExtractor->createPrimitive2DSequenceForPage(rDisplayInfo);

                    // #i105548# reset VOCRedirector to not accidentially have a pointer to a
                    // temporary class, so calls to it are avoided safely
                    mpExtractor->SetViewObjectContactRedirector(0);

                    // reset recursion flag
                    bInCreatePrimitive2D = false;
                }

                // prepare retval
                if(xPageContent.hasElements())
                {
                    const uno::Reference< drawing::XDrawPage > xDrawPage(GetXDrawPageForSdrPage(const_cast< SdrPage*>(pPage)));
                    const drawinglayer::primitive2d::Primitive2DReference xPagePreview(new drawinglayer::primitive2d::PagePreviewPrimitive2D(
                        xDrawPage, aPageObjectTransform, fPageWidth, fPageHeight, xPageContent, true));
                    xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xPagePreview, 1);
                }
            }
            else if(bCreateGrayFrame)
            {
                // #i105146# no content, but frame display. To make hitting the page preview objects
                // on the handout page more simple, add hidden fill geometry
                const drawinglayer::primitive2d::Primitive2DReference xFrameHit(
                    drawinglayer::primitive2d::createHiddenGeometryPrimitives2D(
                        false,
                        aPageObjectTransform));
                xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xFrameHit, 1);
            }

            // add a gray outline frame, except not when printing
            if(bCreateGrayFrame)
            {
                const Color aFrameColor(aColorConfig.GetColorValue(svtools::OBJECTBOUNDARIES).nColor);
                basegfx::B2DPolygon aOwnOutline(basegfx::tools::createUnitPolygon());
                aOwnOutline.transform(aPageObjectTransform);

                const drawinglayer::primitive2d::Primitive2DReference xGrayFrame(
                    new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(aOwnOutline, aFrameColor.getBColor()));

                drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(xRetval, xGrayFrame);
            }

            return xRetval;
        }

        ViewObjectContactOfPageObj::ViewObjectContactOfPageObj(ObjectContact& rObjectContact, ViewContact& rViewContact)
        :   ViewObjectContactOfSdrObj(rObjectContact, rViewContact),
            mpExtractor(new PagePrimitiveExtractor(*this))
        {
        }

        ViewObjectContactOfPageObj::~ViewObjectContactOfPageObj()
        {
            // delete the helper OC
            if(mpExtractor)
            {
                // remember candidate and reset own pointer to avoid action when createPrimitive2DSequence()
                // would be called for any reason
                PagePrimitiveExtractor* pCandidate = mpExtractor;
                mpExtractor = 0;

                // also reset the StartPage to avoid ActionChanged() forwardings in the
                // PagePrimitiveExtractor::InvalidatePartOfView() implementation
                pCandidate->SetStartPage(0);
                delete pCandidate;
            }
        }
    } // end of namespace contact
} // end of namespace sdr

//////////////////////////////////////////////////////////////////////////////
// eof
<|endoftext|>


<commit_before>/* Copyright (c) 2012-18, Robert J. Hansen <rob@hansen.engineering>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include "common.hpp"
#include <boost/asio.hpp>
#include <iostream>
#include <regex>
#include <set>

using boost::asio::ip::tcp;
using std::cerr;
using std::regex;
using std::regex_search;
using std::set;
using std::string;
using std::vector;
using boost::asio::streambuf;
using boost::asio::read_until;
using boost::asio::write;
using boost::asio::buffer_cast;
using boost::asio::buffer;

namespace {
std::string readsock(tcp::socket& sock)
{
    streambuf buf;
    read_until(sock, buf, "\n");
    string data = buffer_cast<const char*>(buf.data());
    data.erase(--data.end());
    if (*(data.end() - 1) == '\r') {
        data.erase(--data.end());
    }
    return data;
}

void sendsock(tcp::socket& sock, const string& str)
{
    const string msg {str + "\r\n"};
    write(sock, buffer(msg));
}
}

set<string> query_server(const vector<string>& buffer)
{
    constexpr size_t MAX_SENT = 512;
    set<string> rv;
    auto resprx = regex("^OK [01]+$");
    boost::asio::io_context iocontext;
    tcp::resolver resolver { iocontext };
    tcp::socket sock { iocontext };

    if (buffer.empty())
        return rv;
    try {
        boost::asio::connect(sock, resolver.resolve(SERVER, PORT));
    } catch (boost::system::system_error&) {
        cerr << "Could not connect to " << SERVER << " " << PORT << ".\n";
        bomb(-1);
    }

    try {
        sendsock(sock, "Version: 2.0");
        auto resp = readsock(sock);
        if (resp != "OK") {
            cerr << "0: " << resp << "\n";
            bomb(-1);
        }

        vector<string> queries(MAX_SENT);

        for (auto iter = buffer.cbegin(); iter != buffer.cend();) {
            string q { "query" };
            queries.clear();
            while (iter != buffer.cend() && queries.size() < MAX_SENT) {
                q += " " + *iter;
                queries.emplace_back(*iter);
                ++iter;
            }

            sendsock(sock, q);
            resp = readsock(sock);

            if (!regex_search(resp, resprx) || resp.size() - 3 != queries.size()) {
                cerr << "Error: malformed response from server";
                bomb(-1);
            }

            for (size_t idx = 3; idx < resp.size(); idx += 1) {
                auto scorechar = SCORE_HITS ? '1' : '0';
                if (resp.at(idx) == scorechar) {
                    rv.insert(queries.at(idx - 3));
                }
            }
        }

        sock.close();
        return rv;
    } catch (boost::system::system_error&) {
        cerr << "IO error communicating with " << SERVER << " " << PORT << ".\n";
        bomb(-1);
    }
    return set<string>();
}
<commit_msg>Should now work with Boost 1.65.<commit_after>/* Copyright (c) 2012-18, Robert J. Hansen <rob@hansen.engineering>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include "common.hpp"
#include <boost/asio.hpp>
#include <iostream>
#include <regex>
#include <set>

using boost::asio::ip::tcp;
using std::cerr;
using std::regex;
using std::regex_search;
using std::set;
using std::string;
using std::vector;
using boost::asio::streambuf;
using boost::asio::read_until;
using boost::asio::write;
using boost::asio::buffer_cast;
using boost::asio::buffer;

namespace {
std::string readsock(tcp::socket& sock)
{
    streambuf buf;
    read_until(sock, buf, "\n");
    string data = buffer_cast<const char*>(buf.data());
    data.erase(--data.end());
    if (*(data.end() - 1) == '\r') {
        data.erase(--data.end());
    }
    return data;
}

void sendsock(tcp::socket& sock, const string& str)
{
    const string msg {str + "\r\n"};
    write(sock, buffer(msg));
}
}

set<string> query_server(const vector<string>& buffer)
{
    constexpr size_t MAX_SENT = 512;
    set<string> rv;
    auto resprx = regex("^OK [01]+$");
    boost::asio::io_context iocontext;
    tcp::resolver resolver { iocontext };
    tcp::resolver::query query(SERVER, PORT);
    tcp::socket sock { iocontext };

    if (buffer.empty())
        return rv;
    try {
        boost::asio::connect(sock, resolver.resolve(query));
    } catch (boost::system::system_error&) {
        cerr << "Could not connect to " << SERVER << " " << PORT << ".\n";
        bomb(-1);
    }

    try {
        sendsock(sock, "Version: 2.0");
        auto resp = readsock(sock);
        if (resp != "OK") {
            cerr << "0: " << resp << "\n";
            bomb(-1);
        }

        vector<string> queries(MAX_SENT);

        for (auto iter = buffer.cbegin(); iter != buffer.cend();) {
            string q { "query" };
            queries.clear();
            while (iter != buffer.cend() && queries.size() < MAX_SENT) {
                q += " " + *iter;
                queries.emplace_back(*iter);
                ++iter;
            }

            sendsock(sock, q);
            resp = readsock(sock);

            if (!regex_search(resp, resprx) || resp.size() - 3 != queries.size()) {
                cerr << "Error: malformed response from server";
                bomb(-1);
            }

            for (size_t idx = 3; idx < resp.size(); idx += 1) {
                auto scorechar = SCORE_HITS ? '1' : '0';
                if (resp.at(idx) == scorechar) {
                    rv.insert(queries.at(idx - 3));
                }
            }
        }

        sock.close();
        return rv;
    } catch (boost::system::system_error&) {
        cerr << "IO error communicating with " << SERVER << " " << PORT << ".\n";
        bomb(-1);
    }
    return set<string>();
}
<|endoftext|>


<commit_before>/* Copyright 2017 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/compiler/xla/service/cpu/simple_orc_jit.h"

#include <dlfcn.h>
#include <stdint.h>
#include <algorithm>
#include <list>
#include <utility>

#include "external/llvm/include/llvm/IR/Mangler.h"
#include "external/llvm/include/llvm/Support/CodeGen.h"
#include "external/llvm/include/llvm/Support/Host.h"
#include "tensorflow/compiler/xla/ptr_util.h"
#include "tensorflow/compiler/xla/service/cpu/compiler_functor.h"
#include "tensorflow/compiler/xla/service/cpu/cpu_runtime.h"
#include "tensorflow/compiler/xla/service/cpu/cpu_runtime_avx.h"
#include "tensorflow/compiler/xla/service/cpu/cpu_runtime_sse4_1.h"
#include "tensorflow/compiler/xla/service/cpu/runtime_conv2d.h"
#include "tensorflow/compiler/xla/service/cpu/runtime_matmul.h"
#include "tensorflow/compiler/xla/service/cpu/runtime_single_threaded_conv2d.h"
#include "tensorflow/compiler/xla/service/cpu/runtime_single_threaded_matmul.h"
#include "tensorflow/compiler/xla/types.h"
#include "tensorflow/core/platform/logging.h"

namespace xla {
namespace cpu {
namespace {

// Converts a symbol 'name' into the form expected by dlsym().
std::string CanonicalizeSymbol(const std::string &name) {
#if defined(__APPLE__)
  // On Mac OS X, dlsym() expects names not to be prefixed with a leading
  // underscore.
  if (!name.empty() && name.front() == '_') {
    return name.substr(1);
  }
#endif
  return name;
}

// A simple SymbolResolver that delegates to the host dynamic linker.
struct SimpleResolver : public llvm::JITSymbolResolver {
  llvm::JITSymbol findSymbol(const std::string &name) override {
    void *func_addr = nullptr;

    std::string canonical_name = CanonicalizeSymbol(name);
    if (canonical_name == runtime::kEigenMatmulF32SymbolName) {
      func_addr = reinterpret_cast<void *>(__xla_cpu_runtime_EigenMatMulF32);
    } else if (canonical_name ==
               runtime::kEigenSingleThreadedMatmulF32SymbolName) {
      func_addr = reinterpret_cast<void *>(
          __xla_cpu_runtime_EigenSingleThreadedMatMulF32);
    } else if (canonical_name == runtime::kEigenConvF32SymbolName) {
      func_addr = reinterpret_cast<void *>(__xla_cpu_runtime_EigenConvF32);
    } else if (canonical_name ==
               runtime::kEigenSingleThreadedConvF32SymbolName) {
      func_addr = reinterpret_cast<void *>(
          __xla_cpu_runtime_EigenSingleThreadedConvF32);
    } else if (canonical_name ==
               runtime::kAcquireInfeedBufferForDequeueSymbolName) {
      func_addr = reinterpret_cast<void *>(
          __xla_cpu_runtime_AcquireInfeedBufferForDequeue);
    } else if (canonical_name ==
               runtime::kReleaseInfeedBufferAfterDequeueSymbolName) {
      func_addr = reinterpret_cast<void *>(
          __xla_cpu_runtime_ReleaseInfeedBufferAfterDequeue);
    } else if (canonical_name == runtime::kExpV4F32) {
      func_addr = reinterpret_cast<void *>(runtime::ExpV4F32);
    } else if (canonical_name == runtime::kExpV8F32) {
      func_addr = reinterpret_cast<void *>(runtime::ExpV8F32);
    } else if (canonical_name == runtime::kLogV4F32) {
      func_addr = reinterpret_cast<void *>(runtime::LogV4F32);
    } else if (canonical_name == runtime::kLogV8F32) {
      func_addr = reinterpret_cast<void *>(runtime::LogV8F32);
    } else if (canonical_name == runtime::kTanhV4F32) {
      func_addr = reinterpret_cast<void *>(runtime::TanhV4F32);
    } else if (canonical_name == runtime::kTanhV8F32) {
      func_addr = reinterpret_cast<void *>(runtime::TanhV8F32);
    } else {
      func_addr = dlsym(RTLD_DEFAULT, canonical_name.c_str());
    }

    if (func_addr == nullptr) {
      return nullptr;
    }
    llvm::JITEvaluatedSymbol symbol_info(reinterpret_cast<uint64_t>(func_addr),
                                         llvm::JITSymbolFlags::None);
    return symbol_info;
  }
  llvm::JITSymbol findSymbolInLogicalDylib(const std::string &name) override {
    return nullptr;
  }
};

llvm::SmallVector<std::string, 0> DetectMachineAttributes() {
  llvm::SmallVector<std::string, 0> result;
  llvm::StringMap<bool> host_features;
  if (llvm::sys::getHostCPUFeatures(host_features)) {
    for (auto &feature : host_features) {
      if (feature.second) {
        result.push_back(feature.first());
      }
    }
  }
  return result;
}

CompilerFunctor::VectorIntrinsics GetAvailableIntrinsics() {
  CompilerFunctor::VectorIntrinsics intrinsics;
  intrinsics.sse_intrinsics = (&runtime::ExpV4F32 != nullptr);
  intrinsics.avx_intrinsics = (&runtime::ExpV8F32 != nullptr);
  return intrinsics;
}

}  // namespace

SimpleOrcJIT::SimpleOrcJIT(const llvm::TargetOptions &target_options,
                           llvm::CodeGenOpt::Level opt_level)
    : target_machine_(
          CHECK_NOTNULL(llvm::EngineBuilder()
                            .setTargetOptions(target_options)
                            .setOptLevel(opt_level)
                            .selectTarget(
                                /*TargetTriple=*/llvm::Triple(), /*MArch=*/"",
                                /*MCPU=*/llvm::sys::getHostCPUName(),
                                /*MAttrs=*/DetectMachineAttributes()))),
      disassembler_(*target_machine_),
      data_layout_(target_machine_->createDataLayout()),
      compile_layer_(object_layer_,
                     CompilerFunctor(target_machine_.get(), &disassembler_,
                                     opt_level, GetAvailableIntrinsics())) {}

SimpleOrcJIT::ModuleHandleT SimpleOrcJIT::AddModule(
    std::unique_ptr<llvm::Module> module) {
  // The Orc API adds a whole iterable "set" of modules, so we wrap the module
  // in a vector.
  std::vector<std::unique_ptr<llvm::Module>> module_set;
  module_set.push_back(std::move(module));
  auto handle = compile_layer_.addModuleSet(
      std::move(module_set), MakeUnique<llvm::SectionMemoryManager>(),
      MakeUnique<SimpleResolver>());
  module_handles_.push_back(handle);
  return handle;
}

void SimpleOrcJIT::RemoveModule(SimpleOrcJIT::ModuleHandleT handle) {
  module_handles_.erase(
      std::remove(module_handles_.begin(), module_handles_.end(), handle));
  compile_layer_.removeModuleSet(handle);
}

llvm::JITSymbol SimpleOrcJIT::FindSymbol(const std::string &name) {
  std::string mangled_name;
  {
    llvm::raw_string_ostream mangled_name_stream(mangled_name);
    llvm::Mangler::getNameWithPrefix(mangled_name_stream, name, data_layout_);
  }

  // Resolve symbol from last module to first, allowing later redefinitions of
  // symbols shadow earlier ones.
  for (auto &handle :
       llvm::make_range(module_handles_.rbegin(), module_handles_.rend())) {
    if (auto symbol =
            compile_layer_.findSymbolIn(handle, mangled_name,
                                        /*ExportedSymbolsOnly=*/true)) {
      return symbol;
    }
  }

  return nullptr;
}

}  // namespace cpu
}  // namespace xla
<commit_msg>[XLA:CPU] VLOG(1) the target CPU and its feature in SimpleOrcJIT's constructor. Change: 152802749<commit_after>/* Copyright 2017 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/compiler/xla/service/cpu/simple_orc_jit.h"

#include <dlfcn.h>
#include <stdint.h>
#include <algorithm>
#include <list>
#include <utility>

#include "external/llvm/include/llvm/IR/Mangler.h"
#include "external/llvm/include/llvm/Support/CodeGen.h"
#include "external/llvm/include/llvm/Support/Host.h"
#include "tensorflow/compiler/xla/ptr_util.h"
#include "tensorflow/compiler/xla/service/cpu/compiler_functor.h"
#include "tensorflow/compiler/xla/service/cpu/cpu_runtime.h"
#include "tensorflow/compiler/xla/service/cpu/cpu_runtime_avx.h"
#include "tensorflow/compiler/xla/service/cpu/cpu_runtime_sse4_1.h"
#include "tensorflow/compiler/xla/service/cpu/runtime_conv2d.h"
#include "tensorflow/compiler/xla/service/cpu/runtime_matmul.h"
#include "tensorflow/compiler/xla/service/cpu/runtime_single_threaded_conv2d.h"
#include "tensorflow/compiler/xla/service/cpu/runtime_single_threaded_matmul.h"
#include "tensorflow/compiler/xla/types.h"
#include "tensorflow/core/platform/logging.h"

namespace xla {
namespace cpu {
namespace {

// Converts a symbol 'name' into the form expected by dlsym().
std::string CanonicalizeSymbol(const std::string &name) {
#if defined(__APPLE__)
  // On Mac OS X, dlsym() expects names not to be prefixed with a leading
  // underscore.
  if (!name.empty() && name.front() == '_') {
    return name.substr(1);
  }
#endif
  return name;
}

// A simple SymbolResolver that delegates to the host dynamic linker.
struct SimpleResolver : public llvm::JITSymbolResolver {
  llvm::JITSymbol findSymbol(const std::string &name) override {
    void *func_addr = nullptr;

    std::string canonical_name = CanonicalizeSymbol(name);
    if (canonical_name == runtime::kEigenMatmulF32SymbolName) {
      func_addr = reinterpret_cast<void *>(__xla_cpu_runtime_EigenMatMulF32);
    } else if (canonical_name ==
               runtime::kEigenSingleThreadedMatmulF32SymbolName) {
      func_addr = reinterpret_cast<void *>(
          __xla_cpu_runtime_EigenSingleThreadedMatMulF32);
    } else if (canonical_name == runtime::kEigenConvF32SymbolName) {
      func_addr = reinterpret_cast<void *>(__xla_cpu_runtime_EigenConvF32);
    } else if (canonical_name ==
               runtime::kEigenSingleThreadedConvF32SymbolName) {
      func_addr = reinterpret_cast<void *>(
          __xla_cpu_runtime_EigenSingleThreadedConvF32);
    } else if (canonical_name ==
               runtime::kAcquireInfeedBufferForDequeueSymbolName) {
      func_addr = reinterpret_cast<void *>(
          __xla_cpu_runtime_AcquireInfeedBufferForDequeue);
    } else if (canonical_name ==
               runtime::kReleaseInfeedBufferAfterDequeueSymbolName) {
      func_addr = reinterpret_cast<void *>(
          __xla_cpu_runtime_ReleaseInfeedBufferAfterDequeue);
    } else if (canonical_name == runtime::kExpV4F32) {
      func_addr = reinterpret_cast<void *>(runtime::ExpV4F32);
    } else if (canonical_name == runtime::kExpV8F32) {
      func_addr = reinterpret_cast<void *>(runtime::ExpV8F32);
    } else if (canonical_name == runtime::kLogV4F32) {
      func_addr = reinterpret_cast<void *>(runtime::LogV4F32);
    } else if (canonical_name == runtime::kLogV8F32) {
      func_addr = reinterpret_cast<void *>(runtime::LogV8F32);
    } else if (canonical_name == runtime::kTanhV4F32) {
      func_addr = reinterpret_cast<void *>(runtime::TanhV4F32);
    } else if (canonical_name == runtime::kTanhV8F32) {
      func_addr = reinterpret_cast<void *>(runtime::TanhV8F32);
    } else {
      func_addr = dlsym(RTLD_DEFAULT, canonical_name.c_str());
    }

    if (func_addr == nullptr) {
      return nullptr;
    }
    llvm::JITEvaluatedSymbol symbol_info(reinterpret_cast<uint64_t>(func_addr),
                                         llvm::JITSymbolFlags::None);
    return symbol_info;
  }
  llvm::JITSymbol findSymbolInLogicalDylib(const std::string &name) override {
    return nullptr;
  }
};

llvm::SmallVector<std::string, 0> DetectMachineAttributes() {
  llvm::SmallVector<std::string, 0> result;
  llvm::StringMap<bool> host_features;
  if (llvm::sys::getHostCPUFeatures(host_features)) {
    for (auto &feature : host_features) {
      if (feature.second) {
        result.push_back(feature.first());
      }
    }
  }
  return result;
}

CompilerFunctor::VectorIntrinsics GetAvailableIntrinsics() {
  CompilerFunctor::VectorIntrinsics intrinsics;
  intrinsics.sse_intrinsics = (&runtime::ExpV4F32 != nullptr);
  intrinsics.avx_intrinsics = (&runtime::ExpV8F32 != nullptr);
  return intrinsics;
}

}  // namespace

SimpleOrcJIT::SimpleOrcJIT(const llvm::TargetOptions &target_options,
                           llvm::CodeGenOpt::Level opt_level)
    : target_machine_(
          CHECK_NOTNULL(llvm::EngineBuilder()
                            .setTargetOptions(target_options)
                            .setOptLevel(opt_level)
                            .selectTarget(
                                /*TargetTriple=*/llvm::Triple(), /*MArch=*/"",
                                /*MCPU=*/llvm::sys::getHostCPUName(),
                                /*MAttrs=*/DetectMachineAttributes()))),
      disassembler_(*target_machine_),
      data_layout_(target_machine_->createDataLayout()),
      compile_layer_(object_layer_,
                     CompilerFunctor(target_machine_.get(), &disassembler_,
                                     opt_level, GetAvailableIntrinsics())) {
  VLOG(1) << "CPU target: " << target_machine_->getTargetCPU().str()
          << " features: " << target_machine_->getTargetFeatureString().str();
}

SimpleOrcJIT::ModuleHandleT SimpleOrcJIT::AddModule(
    std::unique_ptr<llvm::Module> module) {
  // The Orc API adds a whole iterable "set" of modules, so we wrap the module
  // in a vector.
  std::vector<std::unique_ptr<llvm::Module>> module_set;
  module_set.push_back(std::move(module));
  auto handle = compile_layer_.addModuleSet(
      std::move(module_set), MakeUnique<llvm::SectionMemoryManager>(),
      MakeUnique<SimpleResolver>());
  module_handles_.push_back(handle);
  return handle;
}

void SimpleOrcJIT::RemoveModule(SimpleOrcJIT::ModuleHandleT handle) {
  module_handles_.erase(
      std::remove(module_handles_.begin(), module_handles_.end(), handle));
  compile_layer_.removeModuleSet(handle);
}

llvm::JITSymbol SimpleOrcJIT::FindSymbol(const std::string &name) {
  std::string mangled_name;
  {
    llvm::raw_string_ostream mangled_name_stream(mangled_name);
    llvm::Mangler::getNameWithPrefix(mangled_name_stream, name, data_layout_);
  }

  // Resolve symbol from last module to first, allowing later redefinitions of
  // symbols shadow earlier ones.
  for (auto &handle :
       llvm::make_range(module_handles_.rbegin(), module_handles_.rend())) {
    if (auto symbol =
            compile_layer_.findSymbolIn(handle, mangled_name,
                                        /*ExportedSymbolsOnly=*/true)) {
      return symbol;
    }
  }

  return nullptr;
}

}  // namespace cpu
}  // namespace xla
<|endoftext|>


<commit_before>#include "ranked_match.hh"

#include "utf8_iterator.hh"
#include "unit_tests.hh"

namespace Kakoune
{

UsedLetters used_letters(StringView str)
{
    UsedLetters res = 0;
    for (auto c : str)
    {
        if (c >= 'a' and c <= 'z')
            res |= 1uL << (c - 'a');
        else if (c >= 'A' and c <= 'Z')
            res |= 1uL << (c - 'A' + 26);
        else if (c == '_')
            res |= 1uL << 53;
        else if (c == '-')
            res |= 1uL << 54;
        else
            res |= 1uL << 63;
    }
    return res;
}

bool matches(UsedLetters query, UsedLetters letters)
{
    return (query & letters) == query;
}

using Utf8It = utf8::iterator<const char*>;

static int count_word_boundaries_match(StringView candidate, StringView query)
{
    int count = 0;
    Utf8It query_it{query.begin(), query};
    Codepoint prev = 0;
    for (Utf8It it{candidate.begin(), candidate}; it != candidate.end(); ++it)
    {
        const Codepoint c = *it;
        const bool is_word_boundary = prev == 0 or
                                      (!iswalnum(prev) and iswalnum(c)) or
                                      (islower(prev) and isupper(c));
        prev = c;

        if (not is_word_boundary)
            continue;

        const Codepoint lc = to_lower(c);
        for (auto qit = query_it; qit != query.end(); ++qit)
        {
            const Codepoint qc = *qit;
            if (qc == (islower(qc) ? lc  : c))
            {
                ++count;
                query_it = qit+1;
                break;
            }
        }
        if (query_it == query.end())
            break;
    }
    return count;
}

static bool smartcase_eq(Codepoint query, Codepoint candidate)
{
    return query == (islower(query) ? to_lower(candidate) : candidate);
}

static bool subsequence_match_smart_case(StringView str, StringView subseq, int& index_sum)
{
    index_sum = 0;
    auto it = str.begin();
    int index = 0;
    for (auto subseq_it = subseq.begin(); subseq_it != subseq.end();)
    {
        if (it == str.end())
            return false;
        const Codepoint c = utf8::read_codepoint(subseq_it, subseq.end());
        while (not smartcase_eq(c, utf8::read_codepoint(it, subseq.end())))
        {
            ++index;
            if (it == str.end())
                return false;
        }
        index_sum += index++;
    }
    return true;
}

template<typename TestFunc>
RankedMatch::RankedMatch(StringView candidate, StringView query, TestFunc func)
{
    if (candidate.empty() or query.length() > candidate.length())
        return;

    if (query.empty())
        m_candidate = candidate;
    else if (func() and  subsequence_match_smart_case(candidate, query, m_match_index_sum))
    {
        m_candidate = candidate;

        m_first_char_match = smartcase_eq(query[0], candidate[0]);
        m_word_boundary_match_count = count_word_boundaries_match(candidate, query);
        m_only_word_boundary = m_word_boundary_match_count == query.length();
        m_prefix = std::equal(query.begin(), query.end(), candidate.begin(), smartcase_eq);
    }
}

RankedMatch::RankedMatch(StringView candidate, UsedLetters candidate_letters,
                         StringView query, UsedLetters query_letters)
    : RankedMatch{candidate, query, [&] {
        return matches(to_lower(query_letters), to_lower(candidate_letters)) and
               matches(query_letters & upper_mask, candidate_letters & upper_mask);
    }} {}

RankedMatch::RankedMatch(StringView candidate, StringView query)
    : RankedMatch{candidate, query, [] { return true; }}
{
}

bool RankedMatch::operator<(const RankedMatch& other) const
{
    kak_assert((bool)*this and (bool)other);

    if (m_prefix != other.m_prefix)
        return m_prefix;

    if (m_first_char_match != other.m_first_char_match)
        return m_first_char_match;

    if (m_only_word_boundary and other.m_only_word_boundary)
    {
        if (m_word_boundary_match_count != other.m_word_boundary_match_count)
            return m_word_boundary_match_count > other.m_word_boundary_match_count;
    }
    else if (m_only_word_boundary or other.m_only_word_boundary)
        return  m_only_word_boundary;

    if (m_word_boundary_match_count != other.m_word_boundary_match_count)
        return m_word_boundary_match_count > other.m_word_boundary_match_count;

    if (m_match_index_sum != other.m_match_index_sum)
        return m_match_index_sum < other.m_match_index_sum;

    for (Utf8It it1{m_candidate.begin(), m_candidate}, it2{other.m_candidate.begin(), other.m_candidate};
         it1 != m_candidate.end() and it2 != other.m_candidate.end(); ++it1, ++it2)
    {
        const auto cp1 = *it1, cp2 = *it2;
        if (cp1 != cp2)
        {
            const bool low1 = islower(cp1), low2 = islower(cp2);
            return low1 == low2 ? cp1 < cp2 : low2;
        }
    }

    return false;
}

UnitTest test_ranked_match{[] {
    kak_assert(count_word_boundaries_match("run_all_tests", "rat") == 3);
    kak_assert(count_word_boundaries_match("run_all_tests", "at") == 2);
    kak_assert(count_word_boundaries_match("countWordBoundariesMatch", "wm") == 2);
    kak_assert(count_word_boundaries_match("countWordBoundariesMatch", "cobm") == 3);
    kak_assert(count_word_boundaries_match("countWordBoundariesMatch", "cWBM") == 4);
}};

UnitTest test_used_letters{[]()
{
    kak_assert(used_letters("abcd") == to_lower(used_letters("abcdABCD")));
}};

}
<commit_msg>Give priority to lower case in RankedMatch<commit_after>#include "ranked_match.hh"

#include "utf8_iterator.hh"
#include "unit_tests.hh"

namespace Kakoune
{

UsedLetters used_letters(StringView str)
{
    UsedLetters res = 0;
    for (auto c : str)
    {
        if (c >= 'a' and c <= 'z')
            res |= 1uL << (c - 'a');
        else if (c >= 'A' and c <= 'Z')
            res |= 1uL << (c - 'A' + 26);
        else if (c == '_')
            res |= 1uL << 53;
        else if (c == '-')
            res |= 1uL << 54;
        else
            res |= 1uL << 63;
    }
    return res;
}

bool matches(UsedLetters query, UsedLetters letters)
{
    return (query & letters) == query;
}

using Utf8It = utf8::iterator<const char*>;

static int count_word_boundaries_match(StringView candidate, StringView query)
{
    int count = 0;
    Utf8It query_it{query.begin(), query};
    Codepoint prev = 0;
    for (Utf8It it{candidate.begin(), candidate}; it != candidate.end(); ++it)
    {
        const Codepoint c = *it;
        const bool is_word_boundary = prev == 0 or
                                      (!iswalnum(prev) and iswalnum(c)) or
                                      (islower(prev) and isupper(c));
        prev = c;

        if (not is_word_boundary)
            continue;

        const Codepoint lc = to_lower(c);
        for (auto qit = query_it; qit != query.end(); ++qit)
        {
            const Codepoint qc = *qit;
            if (qc == (islower(qc) ? lc  : c))
            {
                ++count;
                query_it = qit+1;
                break;
            }
        }
        if (query_it == query.end())
            break;
    }
    return count;
}

static bool smartcase_eq(Codepoint query, Codepoint candidate)
{
    return query == (islower(query) ? to_lower(candidate) : candidate);
}

static bool subsequence_match_smart_case(StringView str, StringView subseq, int& index_sum)
{
    index_sum = 0;
    auto it = str.begin();
    int index = 0;
    for (auto subseq_it = subseq.begin(); subseq_it != subseq.end();)
    {
        if (it == str.end())
            return false;
        const Codepoint c = utf8::read_codepoint(subseq_it, subseq.end());
        while (not smartcase_eq(c, utf8::read_codepoint(it, subseq.end())))
        {
            ++index;
            if (it == str.end())
                return false;
        }
        index_sum += index++;
    }
    return true;
}

template<typename TestFunc>
RankedMatch::RankedMatch(StringView candidate, StringView query, TestFunc func)
{
    if (candidate.empty() or query.length() > candidate.length())
        return;

    if (query.empty())
        m_candidate = candidate;
    else if (func() and  subsequence_match_smart_case(candidate, query, m_match_index_sum))
    {
        m_candidate = candidate;

        m_first_char_match = smartcase_eq(query[0], candidate[0]);
        m_word_boundary_match_count = count_word_boundaries_match(candidate, query);
        m_only_word_boundary = m_word_boundary_match_count == query.length();
        m_prefix = std::equal(query.begin(), query.end(), candidate.begin(), smartcase_eq);
    }
}

RankedMatch::RankedMatch(StringView candidate, UsedLetters candidate_letters,
                         StringView query, UsedLetters query_letters)
    : RankedMatch{candidate, query, [&] {
        return matches(to_lower(query_letters), to_lower(candidate_letters)) and
               matches(query_letters & upper_mask, candidate_letters & upper_mask);
    }} {}

RankedMatch::RankedMatch(StringView candidate, StringView query)
    : RankedMatch{candidate, query, [] { return true; }}
{
}

bool RankedMatch::operator<(const RankedMatch& other) const
{
    kak_assert((bool)*this and (bool)other);

    if (m_prefix != other.m_prefix)
        return m_prefix;

    if (m_first_char_match != other.m_first_char_match)
        return m_first_char_match;

    if (m_only_word_boundary and other.m_only_word_boundary)
    {
        if (m_word_boundary_match_count != other.m_word_boundary_match_count)
            return m_word_boundary_match_count > other.m_word_boundary_match_count;
    }
    else if (m_only_word_boundary or other.m_only_word_boundary)
        return  m_only_word_boundary;

    if (m_word_boundary_match_count != other.m_word_boundary_match_count)
        return m_word_boundary_match_count > other.m_word_boundary_match_count;

    if (m_match_index_sum != other.m_match_index_sum)
        return m_match_index_sum < other.m_match_index_sum;

    for (Utf8It it1{m_candidate.begin(), m_candidate}, it2{other.m_candidate.begin(), other.m_candidate};
         it1 != m_candidate.end() and it2 != other.m_candidate.end(); ++it1, ++it2)
    {
        const auto cp1 = *it1, cp2 = *it2;
        if (cp1 != cp2)
        {
            const bool low1 = islower(cp1), low2 = islower(cp2);
            return low1 == low2 ? cp1 < cp2 : low1;
        }
    }

    return false;
}

UnitTest test_ranked_match{[] {
    kak_assert(count_word_boundaries_match("run_all_tests", "rat") == 3);
    kak_assert(count_word_boundaries_match("run_all_tests", "at") == 2);
    kak_assert(count_word_boundaries_match("countWordBoundariesMatch", "wm") == 2);
    kak_assert(count_word_boundaries_match("countWordBoundariesMatch", "cobm") == 3);
    kak_assert(count_word_boundaries_match("countWordBoundariesMatch", "cWBM") == 4);
}};

UnitTest test_used_letters{[]()
{
    kak_assert(used_letters("abcd") == to_lower(used_letters("abcdABCD")));
}};

}
<|endoftext|>


<commit_before>// RUN: rm -f %t.out && llvm-cov show %S/Inputs/deferred-regions.covmapping -instr-profile %S/Inputs/deferred-regions.profdata -show-line-counts-or-regions -dump -path-equivalence=/Users/vk/src/llvm.org-coverage-braces/llvm/test/tools,%S/.. %s &> %t.out && FileCheck %s -input-file %t.out && FileCheck %s -input-file %t.out -check-prefix=MARKER

void foo(int x) {
  if (x == 0) {
    return; // CHECK: [[@LINE]]|{{ +}}1|
  }

} // CHECK: [[@LINE]]|{{ +}}1|

void bar() {
  return;

} // CHECK: [[@LINE]]|{{ +}}1|

void for_loop() {
  if (false)
    return; // CHECK: [[@LINE]]|{{ +}}0|

  for (int i = 0; i < 10; ++i) { // CHECK: [[@LINE]]|{{ +}}2|
    if (i % 2 == 0)
      continue; // CHECK: [[@LINE]]|{{ +}}1|

    if (i % 5 == 0)
      break; // CHECK: [[@LINE]]|{{ +}}0|

    int x = i;
    return; // CHECK: [[@LINE]]|{{ +}}1|

  } // CHECK: [[@LINE]]|{{ +}}1|
}

struct Error {};

void while_loop() {
  if (false)
    return; // CHECK: [[@LINE]]|{{ +}}0|

  int x = 0;
  while (++x < 10) { // CHECK: [[@LINE]]|{{ +}}3|
    if (x == 1)
      continue; // CHECK: [[@LINE]]|{{ +}}1|

    while (++x < 4) { // CHECK: [[@LINE]]|{{ +}}1|
      if (x == 3)
        break; // CHECK: [[@LINE]]|{{ +}}1|
               // CHECK: [[@LINE]]|{{ +}}0|
      while (++x < 5) {} // CHECK: [[@LINE]]|{{ +}}0|
    } // CHECK: [[@LINE]]|{{ +}}1|

    if (x == 0)
      throw Error(); // CHECK: [[@LINE]]|{{ +}}0|

    while (++x < 9) { // CHECK: [[@LINE]]|{{ +}}6|
      if (x == 0) // CHECK: [[@LINE]]|{{ +}}5|
        break; // CHECK: [[@LINE]]|{{ +}}0|

    }
  }
}

void gotos() {
  if (false)
    goto out; // CHECK: [[@LINE]]|{{ +}}0|

  return;

out: // CHECK: [[@LINE]]|{{ +}}1|
	return;
}

int main() {
  foo(0);
  foo(1);
  bar();
  for_loop();
  while_loop();
  gotos();
  return 0;
}

// MARKER: Marker at 4:7 = 2
// MARKER-NEXT: Highlighted line 17, 5 -> 11
// MARKER-NEXT: Marker at 17:5 = 0
// MARKER-NEXT: Marker at 19:3 = 1
// MARKER-NEXT: Marker at 19:19 = 2
// MARKER-NEXT: Marker at 19:27 = 1
// MARKER-NEXT: Marker at 21:7 = 1
// MARKER-NEXT: Marker at 23:5 = 1
// MARKER-NEXT: Marker at 23:9 = 1
// MARKER-NEXT: Highlighted line 24, 7 -> 12
// MARKER-NEXT: Marker at 24:7 = 0
// MARKER-NEXT: Highlighted line 36, 5 -> 11
// MARKER-NEXT: Marker at 36:5 = 0
// MARKER-NEXT: Marker at 39:10 = 3
// MARKER-NEXT: Marker at 41:7 = 1
// MARKER-NEXT: Marker at 43:5 = 1
// MARKER-NEXT: Marker at 43:12 = 1
// MARKER-NEXT: Highlighted line 45, 14 -> ?
// MARKER-NEXT: Marker at 45:9 = 1
// MARKER-NEXT: Highlighted line 46, 1 -> ?
// MARKER-NEXT: Highlighted line 47, 1 -> 7
// MARKER-NEXT: Highlighted line 47, 7 -> 14
// MARKER-NEXT: Highlighted line 47, 14 -> 21
// MARKER-NEXT: Highlighted line 47, 21 -> 23
// MARKER-NEXT: Highlighted line 47, 23 -> 25
// MARKER-NEXT: Marker at 47:7 = 0
// MARKER-NEXT: Marker at 47:14 = 0
// MARKER-NEXT: Marker at 47:23 = 0
// MARKER-NEXT: Highlighted line 51, 7 -> 20
// MARKER-NEXT: Marker at 51:7 = 0
// MARKER-NEXT: Marker at 53:5 = 1
// MARKER-NEXT: Marker at 53:12 = 6
// MARKER-NEXT: Highlighted line 55, 9 -> 14
// MARKER-NEXT: Highlighted line 63, 5 -> 13
// MARKER-NEXT: Marker at 63:5 = 0
// MARKER-NEXT: Highlighted line 67, 1 -> ?
// MARKER-NEXT: Highlighted line 68, 1 -> 8
// MARKER-NEXT: Highlighted line 68, 8 -> ?
// MARKER-NEXT: Highlighted line 69, 1 -> 2
<commit_msg>[llvm-cov] Use portable output redirection in a test<commit_after>// RUN: llvm-cov show %S/Inputs/deferred-regions.covmapping -instr-profile %S/Inputs/deferred-regions.profdata -show-line-counts-or-regions -dump -path-equivalence=/Users/vk/src/llvm.org-coverage-braces/llvm/test/tools,%S/.. %s 2&>1 > %t.out && FileCheck %s -input-file %t.out && FileCheck %s -input-file %t.out -check-prefix=MARKER

void foo(int x) {
  if (x == 0) {
    return; // CHECK: [[@LINE]]|{{ +}}1|
  }

} // CHECK: [[@LINE]]|{{ +}}1|

void bar() {
  return;

} // CHECK: [[@LINE]]|{{ +}}1|

void for_loop() {
  if (false)
    return; // CHECK: [[@LINE]]|{{ +}}0|

  for (int i = 0; i < 10; ++i) { // CHECK: [[@LINE]]|{{ +}}2|
    if (i % 2 == 0)
      continue; // CHECK: [[@LINE]]|{{ +}}1|

    if (i % 5 == 0)
      break; // CHECK: [[@LINE]]|{{ +}}0|

    int x = i;
    return; // CHECK: [[@LINE]]|{{ +}}1|

  } // CHECK: [[@LINE]]|{{ +}}1|
}

struct Error {};

void while_loop() {
  if (false)
    return; // CHECK: [[@LINE]]|{{ +}}0|

  int x = 0;
  while (++x < 10) { // CHECK: [[@LINE]]|{{ +}}3|
    if (x == 1)
      continue; // CHECK: [[@LINE]]|{{ +}}1|

    while (++x < 4) { // CHECK: [[@LINE]]|{{ +}}1|
      if (x == 3)
        break; // CHECK: [[@LINE]]|{{ +}}1|
               // CHECK: [[@LINE]]|{{ +}}0|
      while (++x < 5) {} // CHECK: [[@LINE]]|{{ +}}0|
    } // CHECK: [[@LINE]]|{{ +}}1|

    if (x == 0)
      throw Error(); // CHECK: [[@LINE]]|{{ +}}0|

    while (++x < 9) { // CHECK: [[@LINE]]|{{ +}}6|
      if (x == 0) // CHECK: [[@LINE]]|{{ +}}5|
        break; // CHECK: [[@LINE]]|{{ +}}0|

    }
  }
}

void gotos() {
  if (false)
    goto out; // CHECK: [[@LINE]]|{{ +}}0|

  return;

out: // CHECK: [[@LINE]]|{{ +}}1|
	return;
}

int main() {
  foo(0);
  foo(1);
  bar();
  for_loop();
  while_loop();
  gotos();
  return 0;
}

// MARKER: Marker at 4:7 = 2
// MARKER-NEXT: Highlighted line 17, 5 -> 11
// MARKER-NEXT: Marker at 17:5 = 0
// MARKER-NEXT: Marker at 19:3 = 1
// MARKER-NEXT: Marker at 19:19 = 2
// MARKER-NEXT: Marker at 19:27 = 1
// MARKER-NEXT: Marker at 21:7 = 1
// MARKER-NEXT: Marker at 23:5 = 1
// MARKER-NEXT: Marker at 23:9 = 1
// MARKER-NEXT: Highlighted line 24, 7 -> 12
// MARKER-NEXT: Marker at 24:7 = 0
// MARKER-NEXT: Highlighted line 36, 5 -> 11
// MARKER-NEXT: Marker at 36:5 = 0
// MARKER-NEXT: Marker at 39:10 = 3
// MARKER-NEXT: Marker at 41:7 = 1
// MARKER-NEXT: Marker at 43:5 = 1
// MARKER-NEXT: Marker at 43:12 = 1
// MARKER-NEXT: Highlighted line 45, 14 -> ?
// MARKER-NEXT: Marker at 45:9 = 1
// MARKER-NEXT: Highlighted line 46, 1 -> ?
// MARKER-NEXT: Highlighted line 47, 1 -> 7
// MARKER-NEXT: Highlighted line 47, 7 -> 14
// MARKER-NEXT: Highlighted line 47, 14 -> 21
// MARKER-NEXT: Highlighted line 47, 21 -> 23
// MARKER-NEXT: Highlighted line 47, 23 -> 25
// MARKER-NEXT: Marker at 47:7 = 0
// MARKER-NEXT: Marker at 47:14 = 0
// MARKER-NEXT: Marker at 47:23 = 0
// MARKER-NEXT: Highlighted line 51, 7 -> 20
// MARKER-NEXT: Marker at 51:7 = 0
// MARKER-NEXT: Marker at 53:5 = 1
// MARKER-NEXT: Marker at 53:12 = 6
// MARKER-NEXT: Highlighted line 55, 9 -> 14
// MARKER-NEXT: Highlighted line 63, 5 -> 13
// MARKER-NEXT: Marker at 63:5 = 0
// MARKER-NEXT: Highlighted line 67, 1 -> ?
// MARKER-NEXT: Highlighted line 68, 1 -> 8
// MARKER-NEXT: Highlighted line 68, 8 -> ?
// MARKER-NEXT: Highlighted line 69, 1 -> 2
<|endoftext|>