<commit_before>/************************************************************************
	filename: 	CEGUIWindowManager.cpp
	created:	21/2/2004
	author:		Paul D Turner

	purpose:	Implements the WindowManager class
*************************************************************************/
/*************************************************************************
    Crazy Eddie's GUI System (http://www.cegui.org.uk)
    Copyright (C)2004 - 2005 Paul D Turner (paul@cegui.org.uk)

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*************************************************************************/
#include "CEGUIWindowManager.h"
#include "CEGUIWindowFactoryManager.h"
#include "CEGUIWindowFactory.h"
#include "CEGUIWindow.h"
#include "CEGUIExceptions.h"
#include "CEGUIGUILayout_xmlHandler.h"

#include <xercesc/sax2/SAX2XMLReader.hpp>
#include <xercesc/sax2/XMLReaderFactory.hpp>
#include "xercesc/framework/MemBufInputSource.hpp"

// Start of CEGUI namespace section
namespace CEGUI
{
/*************************************************************************
	Static Data Definitions
*************************************************************************/
// singleton instance pointer
template<> WindowManager* Singleton<WindowManager>::ms_Singleton	= NULL;

/*************************************************************************
	Definition of constant data for WindowManager
*************************************************************************/
// Declared in WindowManager
const char	WindowManager::GUILayoutSchemaName[]	= "GUILayout.xsd";

/*************************************************************************
	Destructor
*************************************************************************/
WindowManager::~WindowManager(void)
{
	destroyAllWindows();

	Logger::getSingleton().logEvent((utf8*)"CEGUI::WindowManager singleton destroyed");
}

/*************************************************************************
	Create a new window of the specified type
*************************************************************************/
Window* WindowManager::createWindow(const String& type, const String& name)
{
	if (isWindowPresent(name))
	{
		throw AlreadyExistsException("WindowManager::createWindow - A Window object with the name '" + name +"' already exists within the system.");
	}

	WindowFactory* factory = WindowFactoryManager::getSingleton().getFactory(type);

	Window* newWindow = factory->createWindow(name);
	d_windowRegistry[name] = newWindow;

	Logger::getSingleton().logEvent((utf8*)"Window '" + name +"' of type '" + type + "' has been created.", Informative);

	return newWindow;
}

/*************************************************************************
	Destroy the given window by pointer
*************************************************************************/
void WindowManager::destroyWindow(Window* window)
{
	if (window != NULL)
	{
		// this is done because the name is used for the log after the window is destroyed,
		// if we just did getName() we would get a const ref to the Window's internal name
		// string which is destroyed along with the window so wouldn't exist when the log tried
		// to use it (as I soon discovered).
		String name = window->getName();

		destroyWindow(name);
	}

}

/*************************************************************************
	Destroy the given window by name
*************************************************************************/
void WindowManager::destroyWindow(const String& window)
{
	WindowRegistry::iterator wndpos = d_windowRegistry.find(window);

	if (wndpos != d_windowRegistry.end())
	{
		WindowFactory* factory = WindowFactoryManager::getSingleton().getFactory(wndpos->second->getType());
		factory->destroyWindow(wndpos->second);

		// notify system object of the window destruction
		System::getSingleton().notifyWindowDestroyed(wndpos->second);

		// remove entry from the WindowRegistry.
		d_windowRegistry.erase(wndpos);

		Logger::getSingleton().logEvent((utf8*)"Window '" + window + "' has been destroyed.", Informative);
	}

}

/*************************************************************************
	Return a pointer to the named window
*************************************************************************/
Window* WindowManager::getWindow(const String& name) const
{
	WindowRegistry::const_iterator pos = d_windowRegistry.find(name);

	if (pos == d_windowRegistry.end())
	{
		throw UnknownObjectException("WindowManager::getWindow - A Window object with the name '" + name +"' does not exist within the system");
	}

	return pos->second;
}

/*************************************************************************
	Return true if a window with the given name is present
*************************************************************************/
bool WindowManager::isWindowPresent(const String& name) const
{
	return (d_windowRegistry.find(name) != d_windowRegistry.end());
}

/*************************************************************************
	Destroy all Window objects
*************************************************************************/
void WindowManager::destroyAllWindows(void)
{
	String window_name;
	while (!d_windowRegistry.empty())
	{
		window_name = d_windowRegistry.begin()->first;
		destroyWindow(window_name);
	}

}

/*************************************************************************
	Creates a set of windows (a Gui layout) from the information in the
	specified XML file.
*************************************************************************/
Window* WindowManager::loadWindowLayout(const String& filename, const String& name_prefix, PropertyCallback* callback, void* userdata)
{
	XERCES_CPP_NAMESPACE_USE

	if (filename.empty() || (filename == (utf8*)""))
	{
		throw InvalidRequestException((utf8*)"WindowManager::loadWindowLayout - Filename supplied for gui-layout loading must be valid.");
	}

	// log the fact we are about to load a layout
	Logger::getSingleton().logEvent((utf8*)"---- Beginning loading of GUI layout from '" + filename + "' ----", Informative);

	SAX2XMLReader* parser = XMLReaderFactory::createXMLReader();

	// set basic settings we want from parser
	parser->setFeature(XMLUni::fgSAX2CoreValidation, true);
	parser->setFeature(XMLUni::fgSAX2CoreNameSpaces, true);
	parser->setFeature(XMLUni::fgXercesSchema, true);
	parser->setFeature(XMLUni::fgXercesValidationErrorAsFatal, true);

//    InputSourceContainer layoutSchemaData;
//    System::getSingleton().getResourceProvider()->loadInputSourceContainer(GUILayoutSchemaName, layoutSchemaData);
//    parser->loadGrammar(*(layoutSchemaData.getDataPtr()), Grammar::SchemaGrammarType, true);

    RawDataContainer rawSchemaData;
    System::getSingleton().getResourceProvider()->loadRawDataContainer(GUILayoutSchemaName, rawSchemaData);
    MemBufInputSource  layoutSchemaData(rawSchemaData.getDataPtr(), rawSchemaData.getSize(), GUILayoutSchemaName, false);
    parser->loadGrammar(layoutSchemaData, Grammar::SchemaGrammarType, true);

    // enable grammar reuse
    parser->setFeature(XMLUni::fgXercesUseCachedGrammarInParse, true);

	// setup schema for gui-layout data
	XMLCh* pval = XMLString::transcode(GUILayoutSchemaName);
	parser->setProperty(XMLUni::fgXercesSchemaExternalNoNameSpaceSchemaLocation, pval);
	XMLString::release(&pval);

	// setup handler object
	GUILayout_xmlHandler handler(name_prefix, callback, userdata);
	parser->setContentHandler(&handler);
	parser->setErrorHandler(&handler);

//    InputSourceContainer layoutData;
//    System::getSingleton().getResourceProvider()->loadInputSourceContainer(filename, layoutData);

    RawDataContainer rawXMLData;
    System::getSingleton().getResourceProvider()->loadRawDataContainer(filename, rawXMLData);
    MemBufInputSource  layoutData(rawXMLData.getDataPtr(), rawXMLData.getSize(), filename.c_str(), false);

	// do parse (which uses handler to create actual data)
	try
	{
//        parser->parse(*(layoutData.getDataPtr()));
        parser->parse(layoutData);

		// log the completion of loading
		Logger::getSingleton().logEvent((utf8*)"---- Successfully completed loading of GUI layout from '" + filename + "' ----", Standard);
	}
	catch(const XMLException& exc)
	{
		if (exc.getCode() != XMLExcepts::NoError)
		{
			delete parser;

			char* excmsg = XMLString::transcode(exc.getMessage());
			String message((utf8*)"WindowManager::loadWindowLayout - An error occurred while parsing gui-layout file '" + filename + "'.  Additional information: ");
			message += (utf8*)excmsg;
			XMLString::release(&excmsg);

			throw FileIOException(message);
		}

	}
	catch(const SAXParseException& exc)
	{
		delete parser;

		char* excmsg = XMLString::transcode(exc.getMessage());
		String message((utf8*)"WindowManager::loadWindowLayout - An error occurred while parsing gui-layout file '" + filename + "'.  Additional information: ");
		message += (utf8*)excmsg;
		XMLString::release(&excmsg);

		throw FileIOException(message);
	}
	catch(...)
	{
		delete parser;

		throw FileIOException((utf8*)"WindowManager::loadWindowLayout - An unexpected error occurred while parsing gui-layout file '" + filename + "'.");
	}

	// cleanup
	delete parser;

	return handler.getLayoutRootWindow();
}

WindowManager& WindowManager::getSingleton(void)
{
	return Singleton<WindowManager>::getSingleton();
}

WindowManager* WindowManager::getSingletonPtr(void)
{
	return Singleton<WindowManager>::getSingletonPtr();
}

/*************************************************************************
	Return a WindowManager::WindowIterator object to iterate over the
	currently defined Windows.
*************************************************************************/
WindowManager::WindowIterator WindowManager::getIterator(void) const
{
	return WindowIterator(d_windowRegistry.begin(), d_windowRegistry.end());
}
} // End of  CEGUI namespace section
<commit_msg>Patch #1112329: Throw CEGUI layout loading errors out of xercesc parser.<commit_after>/************************************************************************
	filename: 	CEGUIWindowManager.cpp
	created:	21/2/2004
	author:		Paul D Turner

	purpose:	Implements the WindowManager class
*************************************************************************/
/*************************************************************************
    Crazy Eddie's GUI System (http://www.cegui.org.uk)
    Copyright (C)2004 - 2005 Paul D Turner (paul@cegui.org.uk)

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*************************************************************************/
#include "CEGUIWindowManager.h"
#include "CEGUIWindowFactoryManager.h"
#include "CEGUIWindowFactory.h"
#include "CEGUIWindow.h"
#include "CEGUIExceptions.h"
#include "CEGUIGUILayout_xmlHandler.h"

#include <xercesc/sax2/SAX2XMLReader.hpp>
#include <xercesc/sax2/XMLReaderFactory.hpp>
#include "xercesc/framework/MemBufInputSource.hpp"

// Start of CEGUI namespace section
namespace CEGUI
{
/*************************************************************************
	Static Data Definitions
*************************************************************************/
// singleton instance pointer
template<> WindowManager* Singleton<WindowManager>::ms_Singleton	= NULL;

/*************************************************************************
	Definition of constant data for WindowManager
*************************************************************************/
// Declared in WindowManager
const char	WindowManager::GUILayoutSchemaName[]	= "GUILayout.xsd";

/*************************************************************************
	Destructor
*************************************************************************/
WindowManager::~WindowManager(void)
{
	destroyAllWindows();

	Logger::getSingleton().logEvent((utf8*)"CEGUI::WindowManager singleton destroyed");
}

/*************************************************************************
	Create a new window of the specified type
*************************************************************************/
Window* WindowManager::createWindow(const String& type, const String& name)
{
	if (isWindowPresent(name))
	{
		throw AlreadyExistsException("WindowManager::createWindow - A Window object with the name '" + name +"' already exists within the system.");
	}

	WindowFactory* factory = WindowFactoryManager::getSingleton().getFactory(type);

	Window* newWindow = factory->createWindow(name);
	d_windowRegistry[name] = newWindow;

	Logger::getSingleton().logEvent((utf8*)"Window '" + name +"' of type '" + type + "' has been created.", Informative);

	return newWindow;
}

/*************************************************************************
	Destroy the given window by pointer
*************************************************************************/
void WindowManager::destroyWindow(Window* window)
{
	if (window != NULL)
	{
		// this is done because the name is used for the log after the window is destroyed,
		// if we just did getName() we would get a const ref to the Window's internal name
		// string which is destroyed along with the window so wouldn't exist when the log tried
		// to use it (as I soon discovered).
		String name = window->getName();

		destroyWindow(name);
	}

}

/*************************************************************************
	Destroy the given window by name
*************************************************************************/
void WindowManager::destroyWindow(const String& window)
{
	WindowRegistry::iterator wndpos = d_windowRegistry.find(window);

	if (wndpos != d_windowRegistry.end())
	{
		WindowFactory* factory = WindowFactoryManager::getSingleton().getFactory(wndpos->second->getType());
		factory->destroyWindow(wndpos->second);

		// notify system object of the window destruction
		System::getSingleton().notifyWindowDestroyed(wndpos->second);

		// remove entry from the WindowRegistry.
		d_windowRegistry.erase(wndpos);

		Logger::getSingleton().logEvent((utf8*)"Window '" + window + "' has been destroyed.", Informative);
	}

}

/*************************************************************************
	Return a pointer to the named window
*************************************************************************/
Window* WindowManager::getWindow(const String& name) const
{
	WindowRegistry::const_iterator pos = d_windowRegistry.find(name);

	if (pos == d_windowRegistry.end())
	{
		throw UnknownObjectException("WindowManager::getWindow - A Window object with the name '" + name +"' does not exist within the system");
	}

	return pos->second;
}

/*************************************************************************
	Return true if a window with the given name is present
*************************************************************************/
bool WindowManager::isWindowPresent(const String& name) const
{
	return (d_windowRegistry.find(name) != d_windowRegistry.end());
}

/*************************************************************************
	Destroy all Window objects
*************************************************************************/
void WindowManager::destroyAllWindows(void)
{
	String window_name;
	while (!d_windowRegistry.empty())
	{
		window_name = d_windowRegistry.begin()->first;
		destroyWindow(window_name);
	}

}

/*************************************************************************
	Creates a set of windows (a Gui layout) from the information in the
	specified XML file.
*************************************************************************/
Window* WindowManager::loadWindowLayout(const String& filename, const String& name_prefix, PropertyCallback* callback, void* userdata)
{
	XERCES_CPP_NAMESPACE_USE

	if (filename.empty() || (filename == (utf8*)""))
	{
		throw InvalidRequestException((utf8*)"WindowManager::loadWindowLayout - Filename supplied for gui-layout loading must be valid.");
	}

	// log the fact we are about to load a layout
	Logger::getSingleton().logEvent((utf8*)"---- Beginning loading of GUI layout from '" + filename + "' ----", Informative);

	SAX2XMLReader* parser = XMLReaderFactory::createXMLReader();

	// set basic settings we want from parser
	parser->setFeature(XMLUni::fgSAX2CoreValidation, true);
	parser->setFeature(XMLUni::fgSAX2CoreNameSpaces, true);
	parser->setFeature(XMLUni::fgXercesSchema, true);
	parser->setFeature(XMLUni::fgXercesValidationErrorAsFatal, true);

//    InputSourceContainer layoutSchemaData;
//    System::getSingleton().getResourceProvider()->loadInputSourceContainer(GUILayoutSchemaName, layoutSchemaData);
//    parser->loadGrammar(*(layoutSchemaData.getDataPtr()), Grammar::SchemaGrammarType, true);

    RawDataContainer rawSchemaData;
    System::getSingleton().getResourceProvider()->loadRawDataContainer(GUILayoutSchemaName, rawSchemaData);
    MemBufInputSource  layoutSchemaData(rawSchemaData.getDataPtr(), rawSchemaData.getSize(), GUILayoutSchemaName, false);
    parser->loadGrammar(layoutSchemaData, Grammar::SchemaGrammarType, true);

    // enable grammar reuse
    parser->setFeature(XMLUni::fgXercesUseCachedGrammarInParse, true);

	// setup schema for gui-layout data
	XMLCh* pval = XMLString::transcode(GUILayoutSchemaName);
	parser->setProperty(XMLUni::fgXercesSchemaExternalNoNameSpaceSchemaLocation, pval);
	XMLString::release(&pval);

	// setup handler object
	GUILayout_xmlHandler handler(name_prefix, callback, userdata);
	parser->setContentHandler(&handler);
	parser->setErrorHandler(&handler);

//    InputSourceContainer layoutData;
//    System::getSingleton().getResourceProvider()->loadInputSourceContainer(filename, layoutData);

    RawDataContainer rawXMLData;
    System::getSingleton().getResourceProvider()->loadRawDataContainer(filename, rawXMLData);
    MemBufInputSource  layoutData(rawXMLData.getDataPtr(), rawXMLData.getSize(), filename.c_str(), false);

	// do parse (which uses handler to create actual data)
	try
	{
//        parser->parse(*(layoutData.getDataPtr()));
        parser->parse(layoutData);

		// log the completion of loading
		Logger::getSingleton().logEvent((utf8*)"---- Successfully completed loading of GUI layout from '" + filename + "' ----", Standard);
	}
	catch(const XMLException& exc)
	{
		if (exc.getCode() != XMLExcepts::NoError)
		{
			delete parser;

			char* excmsg = XMLString::transcode(exc.getMessage());
			String message((utf8*)"WindowManager::loadWindowLayout - An error occurred while parsing gui-layout file '" + filename + "'.  Additional information: ");
			message += (utf8*)excmsg;
			XMLString::release(&excmsg);

			throw FileIOException(message);
		}

	}
	catch(const SAXParseException& exc)
	{
		delete parser;

		char* excmsg = XMLString::transcode(exc.getMessage());
		String message((utf8*)"WindowManager::loadWindowLayout - An error occurred while parsing gui-layout file '" + filename + "'.  Additional information: ");
		message += (utf8*)excmsg;
		XMLString::release(&excmsg);

		throw FileIOException(message);
	}
	catch(const CEGUI::Exception&)
	{
		delete parser;
		throw;
	}
	catch(...)
	{
		delete parser;

		throw FileIOException((utf8*)"WindowManager::loadWindowLayout - An unexpected error occurred while parsing gui-layout file '" + filename + "'.");
	}

	// cleanup
	delete parser;

	return handler.getLayoutRootWindow();
}

WindowManager& WindowManager::getSingleton(void)
{
	return Singleton<WindowManager>::getSingleton();
}

WindowManager* WindowManager::getSingletonPtr(void)
{
	return Singleton<WindowManager>::getSingletonPtr();
}

/*************************************************************************
	Return a WindowManager::WindowIterator object to iterate over the
	currently defined Windows.
*************************************************************************/
WindowManager::WindowIterator WindowManager::getIterator(void) const
{
	return WindowIterator(d_windowRegistry.begin(), d_windowRegistry.end());
}
} // End of  CEGUI namespace section
<|endoftext|>


<commit_before>#include "OutputPrinter.h"

OutputPrinter::OutputPrinter(const std::string& outputFileName)
    : m_outputFileName(outputFileName)
{
    TiXmlDeclaration* decl = new TiXmlDeclaration("1.0", "", "");
    m_document.LinkEndChild(decl);

    m_resultsElement = new TiXmlElement("results");
}

void OutputPrinter::Save()
{
    m_document.LinkEndChild(m_resultsElement);
    m_document.SaveFile(m_outputFileName);
}

void OutputPrinter::PrintRuleViolation(const std::string& ruleName,
                                       Severity severity,
                                       const std::string& description,
                                       const clang::SourceLocation& location,
                                       clang::SourceManager& sourceManager)
{
    TiXmlElement* errorElement = new TiXmlElement("error");

    errorElement->SetAttribute("file", sourceManager.getFilename(location).str());
    errorElement->SetAttribute("line", std::to_string(sourceManager.getSpellingLineNumber(location)));
    errorElement->SetAttribute("id", ruleName);
    errorElement->SetAttribute("severity", GetSeverityString(severity));
    errorElement->SetAttribute("message", description);

    m_resultsElement->LinkEndChild(errorElement);
}

std::string OutputPrinter::GetSeverityString(Severity severity)
{
    std::string str;

    switch (severity)
    {
        case Severity::Style:
            str = "style";
            break;

        case Severity::Error:
            str = "error";
            break;

        case Severity::Warning:
            str = "warning";
            break;

        case Severity::Information:
            str = "information";
            break;
    }

    return str;
}

<commit_msg>Fix XML output<commit_after>#include "OutputPrinter.h"

OutputPrinter::OutputPrinter(const std::string& outputFileName)
    : m_outputFileName(outputFileName)
{
    TiXmlDeclaration* decl = new TiXmlDeclaration("1.0", "", "");
    m_document.LinkEndChild(decl);

    m_resultsElement = new TiXmlElement("results");
}

void OutputPrinter::Save()
{
    m_document.LinkEndChild(m_resultsElement);
    m_document.SaveFile(m_outputFileName);
}

void OutputPrinter::PrintRuleViolation(const std::string& ruleName,
                                       Severity severity,
                                       const std::string& description,
                                       const clang::SourceLocation& location,
                                       clang::SourceManager& sourceManager)
{
    TiXmlElement* errorElement = new TiXmlElement("error");

    errorElement->SetAttribute("file", sourceManager.getFilename(location).str());
    errorElement->SetAttribute("line", std::to_string(sourceManager.getSpellingLineNumber(location)));
    errorElement->SetAttribute("id", ruleName);
    errorElement->SetAttribute("severity", GetSeverityString(severity));
    errorElement->SetAttribute("msg", description);

    m_resultsElement->LinkEndChild(errorElement);
}

std::string OutputPrinter::GetSeverityString(Severity severity)
{
    std::string str;

    switch (severity)
    {
        case Severity::Style:
            str = "style";
            break;

        case Severity::Error:
            str = "error";
            break;

        case Severity::Warning:
            str = "warning";
            break;

        case Severity::Information:
            str = "information";
            break;
    }

    return str;
}

<|endoftext|>


<commit_before>/* mbed Microcontroller Library
 * Copyright (c) 2017 ARM Limited
 *
 * 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.
 */

#if !DEVICE_SLEEP
#error [NOT_SUPPORTED] sleep not supported for this target
#endif

#include "mbed.h"

#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"

#include "sleep_api_tests.h"

#define US_PER_S 1000000

using namespace utest::v1;

/* The following ticker frequencies are possible:
 * high frequency ticker: 250 KHz (1 tick per 4 us) - 8 Mhz (1 tick per 1/8 us)
 * low power ticker: 8 KHz (1 tick per 125 us) - 64 KHz (1 tick per ~15.6 us)
 */

/* Used for regular sleep mode, a target should be awake within 10 us. Define us delta value as follows:
 * delta = default 10 us + worst ticker resolution + extra time for code execution */
static const uint32_t sleep_mode_delta_us = (10 + 4 + 5);

/* Used for deep-sleep mode, a target should be awake within 10 ms. Define us delta value as follows:
 * delta = default 10 ms + worst ticker resolution + extra time for code execution */
static const uint32_t deepsleep_mode_delta_us = (10000 + 125 + 5);

unsigned int ticks_to_us(unsigned int ticks, unsigned int freq)
{
    return (unsigned int)((unsigned long long)ticks * US_PER_S / freq);
}

unsigned int us_to_ticks(unsigned int us, unsigned int freq)
{
    return (unsigned int)((unsigned long long)us * freq / US_PER_S);
}

unsigned int overflow_protect(unsigned int timestamp, unsigned int ticker_width)
{
    unsigned int counter_mask = ((1 << ticker_width) - 1);

    return (timestamp & counter_mask);
}

bool compare_timestamps(unsigned int delta_ticks, unsigned int ticker_width, unsigned int expected, unsigned int actual)
{
    const unsigned int counter_mask = ((1 << ticker_width) - 1);

    const unsigned int lower_bound = ((expected - delta_ticks) & counter_mask);
    const unsigned int upper_bound = ((expected + delta_ticks) & counter_mask);

    if(lower_bound < upper_bound) {
        if (actual >= lower_bound && actual <= upper_bound) {
            return true;
        } else {
            return false;
        }
    } else {
        if ((actual >= lower_bound && actual <= counter_mask) ||
            (actual >= 0 && actual <= upper_bound)) {
            return true;
        } else {
            return false;
        }
    }
}

void us_ticker_isr(const ticker_data_t *const ticker_data)
{
    us_ticker_clear_interrupt();
}

#ifdef DEVICE_LOWPOWERTIMER
void lp_ticker_isr(const ticker_data_t *const ticker_data)
{
    lp_ticker_clear_interrupt();
}
#endif

/* Test that wake-up time from sleep should be less than 10 us and
 * high frequency ticker interrupt can wake-up target from sleep. */
void sleep_usticker_test()
{
    Timeout timeout;
    const ticker_data_t * ticker = get_us_ticker_data();
    const unsigned int ticker_freq = ticker->interface->get_info()->frequency;
    const unsigned int ticker_width = ticker->interface->get_info()->bits;

    const ticker_irq_handler_type  us_ticker_irq_handler_org = set_us_ticker_irq_handler(us_ticker_isr);

    /* Test only sleep functionality. */
    sleep_manager_lock_deep_sleep();
    TEST_ASSERT_FALSE_MESSAGE(sleep_manager_can_deep_sleep(), "deep sleep should be locked");

    /* Testing wake-up time 10 us. */
    for (timestamp_t i = 100; i < 1000; i += 100) {
        /* note: us_ticker_read() operates on ticks. */
        const timestamp_t next_match_timestamp = overflow_protect(us_ticker_read() + us_to_ticks(i, ticker_freq),
                ticker_width);

        us_ticker_set_interrupt(next_match_timestamp);

        sleep();

        const unsigned int wakeup_timestamp = us_ticker_read();

        TEST_ASSERT(
                compare_timestamps(us_to_ticks(sleep_mode_delta_us, ticker_freq), ticker_width, next_match_timestamp,
                        wakeup_timestamp));
    }

    set_us_ticker_irq_handler(us_ticker_irq_handler_org);

    sleep_manager_unlock_deep_sleep();
    TEST_ASSERT_TRUE(sleep_manager_can_deep_sleep());
}

#ifdef DEVICE_LOWPOWERTIMER

/* Test that wake-up time from sleep should be less than 10 ms and
 * low power ticker interrupt can wake-up target from sleep. */
void deepsleep_lpticker_test()
{
    const ticker_data_t * ticker = get_us_ticker_data();
    const unsigned int ticker_freq = ticker->interface->get_info()->frequency;
    const unsigned int ticker_width = ticker->interface->get_info()->bits;

    const ticker_irq_handler_type  lp_ticker_irq_handler_org = set_lp_ticker_irq_handler(lp_ticker_isr);

    /* Give some time Green Tea to finish UART transmission before entering
     * deep-sleep mode.
     */
    wait_ms(10);

    TEST_ASSERT_TRUE_MESSAGE(sleep_manager_can_deep_sleep(), "deep sleep should not be locked");

    /* Testing wake-up time 10 ms. */
    for (timestamp_t i = 20000; i < 200000; i += 20000) {
        /* note: lp_ticker_read() operates on ticks. */
        const timestamp_t next_match_timestamp = overflow_protect(lp_ticker_read() + us_to_ticks(i, ticker_freq), ticker_width);

        lp_ticker_set_interrupt(next_match_timestamp);

        sleep();

        const timestamp_t wakeup_timestamp = lp_ticker_read();

        TEST_ASSERT(compare_timestamps(us_to_ticks(deepsleep_mode_delta_us, ticker_freq), ticker_width, next_match_timestamp, wakeup_timestamp));
    }

    set_lp_ticker_irq_handler(lp_ticker_irq_handler_org);

}

void deepsleep_high_speed_clocks_turned_off_test()
{
    const ticker_data_t * us_ticker = get_us_ticker_data();
    const ticker_data_t * lp_ticker = get_lp_ticker_data();
    const unsigned int us_ticker_freq = us_ticker->interface->get_info()->frequency;
    const unsigned int lp_ticker_freq = lp_ticker->interface->get_info()->frequency;
    const unsigned int us_ticker_width = us_ticker->interface->get_info()->bits;
    const unsigned int lp_ticker_width = lp_ticker->interface->get_info()->bits;
    const unsigned int us_ticker_mask = ((1 << us_ticker_width) - 1);

    /* Give some time Green Tea to finish UART transmission before entering
     * deep-sleep mode.
     */
    wait_ms(10);

    TEST_ASSERT_TRUE_MESSAGE(sleep_manager_can_deep_sleep(), "deep sleep should not be locked");

    const unsigned int us_ticks_before_sleep = us_ticker_read();

    const timestamp_t wakeup_time = lp_ticker_read() + us_to_ticks(200000, lp_ticker_freq);
    lp_ticker_set_interrupt(wakeup_time);

    sleep();

    const unsigned int us_ticks_after_sleep = us_ticker_read();
    const unsigned int lp_ticks_after_sleep = lp_ticker_read();

    /* High freqency ticker should be disabled in deep-sleep mode. We expect that time difference between
     * ticker reads before and after the sleep represents only code execution time between calls.
     * Since we went to sleep for about 200 ms check if time counted by high frequency timer does not
     * exceed 1 ms.
     */
    const unsigned int us_ticks_diff = (us_ticks_before_sleep <= us_ticks_after_sleep) ? (us_ticks_after_sleep - us_ticks_before_sleep) : (us_ticker_mask - us_ticks_before_sleep + us_ticks_after_sleep + 1);

    TEST_ASSERT_UINT32_WITHIN(1000, 0, ticks_to_us(us_ticks_diff, us_ticker_freq));

    /* Check if we have woken-up after expected time. */
    TEST_ASSERT(compare_timestamps(us_to_ticks(deepsleep_mode_delta_us, lp_ticker_freq), lp_ticker_width, wakeup_time, lp_ticks_after_sleep));
}

#endif

utest::v1::status_t greentea_failure_handler(const Case * const source, const failure_t reason)
{
    greentea_case_failure_abort_handler(source, reason);
    return STATUS_CONTINUE;
}

utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
{
    GREENTEA_SETUP(60, "default_auto");
    us_ticker_init();
#if DEVICE_LOWPOWERTIMER
    lp_ticker_init();
#endif
    /* Suspend RTOS Kernel to enable sleep modes. */
    osKernelSuspend();
    return greentea_test_setup_handler(number_of_cases);
}

Case cases[] = {
    Case("sleep - source of wake-up - us ticker", sleep_usticker_test, greentea_failure_handler),
#if DEVICE_LOWPOWERTIMER
    Case("deep-sleep - source of wake-up - lp ticker",deepsleep_lpticker_test, greentea_failure_handler),
    Case("deep-sleep - high-speed clocks are turned off",deepsleep_high_speed_clocks_turned_off_test, greentea_failure_handler),
#endif
};

Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);

int main() {
    Harness::run(specification);
}
<commit_msg>tests-mbed_hal-sleep: use lp ticker data while testing deepsleep.<commit_after>/* mbed Microcontroller Library
 * Copyright (c) 2017 ARM Limited
 *
 * 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.
 */

#if !DEVICE_SLEEP
#error [NOT_SUPPORTED] sleep not supported for this target
#endif

#include "mbed.h"

#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"

#include "sleep_api_tests.h"

#define US_PER_S 1000000

using namespace utest::v1;

/* The following ticker frequencies are possible:
 * high frequency ticker: 250 KHz (1 tick per 4 us) - 8 Mhz (1 tick per 1/8 us)
 * low power ticker: 8 KHz (1 tick per 125 us) - 64 KHz (1 tick per ~15.6 us)
 */

/* Used for regular sleep mode, a target should be awake within 10 us. Define us delta value as follows:
 * delta = default 10 us + worst ticker resolution + extra time for code execution */
static const uint32_t sleep_mode_delta_us = (10 + 4 + 5);

/* Used for deep-sleep mode, a target should be awake within 10 ms. Define us delta value as follows:
 * delta = default 10 ms + worst ticker resolution + extra time for code execution */
static const uint32_t deepsleep_mode_delta_us = (10000 + 125 + 5);

unsigned int ticks_to_us(unsigned int ticks, unsigned int freq)
{
    return (unsigned int)((unsigned long long)ticks * US_PER_S / freq);
}

unsigned int us_to_ticks(unsigned int us, unsigned int freq)
{
    return (unsigned int)((unsigned long long)us * freq / US_PER_S);
}

unsigned int overflow_protect(unsigned int timestamp, unsigned int ticker_width)
{
    unsigned int counter_mask = ((1 << ticker_width) - 1);

    return (timestamp & counter_mask);
}

bool compare_timestamps(unsigned int delta_ticks, unsigned int ticker_width, unsigned int expected, unsigned int actual)
{
    const unsigned int counter_mask = ((1 << ticker_width) - 1);

    const unsigned int lower_bound = ((expected - delta_ticks) & counter_mask);
    const unsigned int upper_bound = ((expected + delta_ticks) & counter_mask);

    if(lower_bound < upper_bound) {
        if (actual >= lower_bound && actual <= upper_bound) {
            return true;
        } else {
            return false;
        }
    } else {
        if ((actual >= lower_bound && actual <= counter_mask) ||
            (actual >= 0 && actual <= upper_bound)) {
            return true;
        } else {
            return false;
        }
    }
}

void us_ticker_isr(const ticker_data_t *const ticker_data)
{
    us_ticker_clear_interrupt();
}

#ifdef DEVICE_LOWPOWERTIMER
void lp_ticker_isr(const ticker_data_t *const ticker_data)
{
    lp_ticker_clear_interrupt();
}
#endif

/* Test that wake-up time from sleep should be less than 10 us and
 * high frequency ticker interrupt can wake-up target from sleep. */
void sleep_usticker_test()
{
    Timeout timeout;
    const ticker_data_t * ticker = get_us_ticker_data();
    const unsigned int ticker_freq = ticker->interface->get_info()->frequency;
    const unsigned int ticker_width = ticker->interface->get_info()->bits;

    const ticker_irq_handler_type  us_ticker_irq_handler_org = set_us_ticker_irq_handler(us_ticker_isr);

    /* Test only sleep functionality. */
    sleep_manager_lock_deep_sleep();
    TEST_ASSERT_FALSE_MESSAGE(sleep_manager_can_deep_sleep(), "deep sleep should be locked");

    /* Testing wake-up time 10 us. */
    for (timestamp_t i = 100; i < 1000; i += 100) {
        /* note: us_ticker_read() operates on ticks. */
        const timestamp_t next_match_timestamp = overflow_protect(us_ticker_read() + us_to_ticks(i, ticker_freq),
                ticker_width);

        us_ticker_set_interrupt(next_match_timestamp);

        sleep();

        const unsigned int wakeup_timestamp = us_ticker_read();

        TEST_ASSERT(
                compare_timestamps(us_to_ticks(sleep_mode_delta_us, ticker_freq), ticker_width, next_match_timestamp,
                        wakeup_timestamp));
    }

    set_us_ticker_irq_handler(us_ticker_irq_handler_org);

    sleep_manager_unlock_deep_sleep();
    TEST_ASSERT_TRUE(sleep_manager_can_deep_sleep());
}

#ifdef DEVICE_LOWPOWERTIMER

/* Test that wake-up time from sleep should be less than 10 ms and
 * low power ticker interrupt can wake-up target from sleep. */
void deepsleep_lpticker_test()
{
    const ticker_data_t * ticker = get_lp_ticker_data();
    const unsigned int ticker_freq = ticker->interface->get_info()->frequency;
    const unsigned int ticker_width = ticker->interface->get_info()->bits;

    const ticker_irq_handler_type  lp_ticker_irq_handler_org = set_lp_ticker_irq_handler(lp_ticker_isr);

    /* Give some time Green Tea to finish UART transmission before entering
     * deep-sleep mode.
     */
    wait_ms(10);

    TEST_ASSERT_TRUE_MESSAGE(sleep_manager_can_deep_sleep(), "deep sleep should not be locked");

    /* Testing wake-up time 10 ms. */
    for (timestamp_t i = 20000; i < 200000; i += 20000) {
        /* note: lp_ticker_read() operates on ticks. */
        const timestamp_t next_match_timestamp = overflow_protect(lp_ticker_read() + us_to_ticks(i, ticker_freq), ticker_width);

        lp_ticker_set_interrupt(next_match_timestamp);

        sleep();

        const timestamp_t wakeup_timestamp = lp_ticker_read();

        TEST_ASSERT(compare_timestamps(us_to_ticks(deepsleep_mode_delta_us, ticker_freq), ticker_width, next_match_timestamp, wakeup_timestamp));
    }

    set_lp_ticker_irq_handler(lp_ticker_irq_handler_org);

}

void deepsleep_high_speed_clocks_turned_off_test()
{
    const ticker_data_t * us_ticker = get_us_ticker_data();
    const ticker_data_t * lp_ticker = get_lp_ticker_data();
    const unsigned int us_ticker_freq = us_ticker->interface->get_info()->frequency;
    const unsigned int lp_ticker_freq = lp_ticker->interface->get_info()->frequency;
    const unsigned int us_ticker_width = us_ticker->interface->get_info()->bits;
    const unsigned int lp_ticker_width = lp_ticker->interface->get_info()->bits;
    const unsigned int us_ticker_mask = ((1 << us_ticker_width) - 1);

    /* Give some time Green Tea to finish UART transmission before entering
     * deep-sleep mode.
     */
    wait_ms(10);

    TEST_ASSERT_TRUE_MESSAGE(sleep_manager_can_deep_sleep(), "deep sleep should not be locked");

    const unsigned int us_ticks_before_sleep = us_ticker_read();

    const timestamp_t wakeup_time = lp_ticker_read() + us_to_ticks(200000, lp_ticker_freq);
    lp_ticker_set_interrupt(wakeup_time);

    sleep();

    const unsigned int us_ticks_after_sleep = us_ticker_read();
    const unsigned int lp_ticks_after_sleep = lp_ticker_read();

    /* High freqency ticker should be disabled in deep-sleep mode. We expect that time difference between
     * ticker reads before and after the sleep represents only code execution time between calls.
     * Since we went to sleep for about 200 ms check if time counted by high frequency timer does not
     * exceed 1 ms.
     */
    const unsigned int us_ticks_diff = (us_ticks_before_sleep <= us_ticks_after_sleep) ? (us_ticks_after_sleep - us_ticks_before_sleep) : (us_ticker_mask - us_ticks_before_sleep + us_ticks_after_sleep + 1);

    TEST_ASSERT_UINT32_WITHIN(1000, 0, ticks_to_us(us_ticks_diff, us_ticker_freq));

    /* Check if we have woken-up after expected time. */
    TEST_ASSERT(compare_timestamps(us_to_ticks(deepsleep_mode_delta_us, lp_ticker_freq), lp_ticker_width, wakeup_time, lp_ticks_after_sleep));
}

#endif

utest::v1::status_t greentea_failure_handler(const Case * const source, const failure_t reason)
{
    greentea_case_failure_abort_handler(source, reason);
    return STATUS_CONTINUE;
}

utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
{
    GREENTEA_SETUP(60, "default_auto");
    us_ticker_init();
#if DEVICE_LOWPOWERTIMER
    lp_ticker_init();
#endif
    /* Suspend RTOS Kernel to enable sleep modes. */
    osKernelSuspend();
    return greentea_test_setup_handler(number_of_cases);
}

Case cases[] = {
    Case("sleep - source of wake-up - us ticker", sleep_usticker_test, greentea_failure_handler),
#if DEVICE_LOWPOWERTIMER
    Case("deep-sleep - source of wake-up - lp ticker",deepsleep_lpticker_test, greentea_failure_handler),
    Case("deep-sleep - high-speed clocks are turned off",deepsleep_high_speed_clocks_turned_off_test, greentea_failure_handler),
#endif
};

Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);

int main() {
    Harness::run(specification);
}
<|endoftext|>


<commit_before>//===- InstrInfoEmitter.cpp - Generate a Instruction Set Desc. ------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This tablegen backend is responsible for emitting a description of the target
// instruction set for the code generator.
//
//===----------------------------------------------------------------------===//

#include "InstrInfoEmitter.h"
#include "CodeGenTarget.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "Record.h"
#include <algorithm>
using namespace llvm;

// runEnums - Print out enum values for all of the instructions.
void InstrInfoEmitter::runEnums(std::ostream &OS) {
  EmitSourceFileHeader("Target Instruction Enum Values", OS);
  OS << "namespace llvm {\n\n";

  CodeGenTarget Target;

  // We must emit the PHI opcode first...
  std::string Namespace;
  for (CodeGenTarget::inst_iterator II = Target.inst_begin(),
       E = Target.inst_end(); II != E; ++II) {
    if (II->second.Namespace != "TargetInstrInfo") {
      Namespace = II->second.Namespace;
      break;
    }
  }

  if (Namespace.empty()) {
    cerr << "No instructions defined!\n";
    exit(1);
  }

  std::vector<const CodeGenInstruction*> NumberedInstructions;
  Target.getInstructionsByEnumValue(NumberedInstructions);

  OS << "namespace " << Namespace << " {\n";
  OS << "  enum {\n";
  for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
    OS << "    " << NumberedInstructions[i]->TheDef->getName()
       << "\t= " << i << ",\n";
  }
  OS << "    INSTRUCTION_LIST_END = " << NumberedInstructions.size() << "\n";
  OS << "  };\n}\n";
  OS << "} // End llvm namespace \n";
}

void InstrInfoEmitter::printDefList(const std::vector<Record*> &Uses,
                                    unsigned Num, std::ostream &OS) const {
  OS << "static const unsigned ImplicitList" << Num << "[] = { ";
  for (unsigned i = 0, e = Uses.size(); i != e; ++i)
    OS << getQualifiedName(Uses[i]) << ", ";
  OS << "0 };\n";
}

std::vector<std::string>
InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
  std::vector<std::string> Result;

  for (unsigned i = 0, e = Inst.OperandList.size(); i != e; ++i) {
    // Handle aggregate operands and normal operands the same way by expanding
    // either case into a list of operands for this op.
    std::vector<CodeGenInstruction::OperandInfo> OperandList;

    // This might be a multiple operand thing.  Targets like X86 have
    // registers in their multi-operand operands.  It may also be an anonymous
    // operand, which has a single operand, but no declared class for the
    // operand.
    DagInit *MIOI = Inst.OperandList[i].MIOperandInfo;

    if (!MIOI || MIOI->getNumArgs() == 0) {
      // Single, anonymous, operand.
      OperandList.push_back(Inst.OperandList[i]);
    } else {
      for (unsigned j = 0, e = Inst.OperandList[i].MINumOperands; j != e; ++j) {
        OperandList.push_back(Inst.OperandList[i]);

        Record *OpR = dynamic_cast<DefInit*>(MIOI->getArg(j))->getDef();
        OperandList.back().Rec = OpR;
      }
    }

    for (unsigned j = 0, e = OperandList.size(); j != e; ++j) {
      Record *OpR = OperandList[j].Rec;
      std::string Res;

      if (OpR->isSubClassOf("RegisterClass"))
        Res += getQualifiedName(OpR) + "RegClassID, ";
      else
        Res += "0, ";
      // Fill in applicable flags.
      Res += "0";

      // Ptr value whose register class is resolved via callback.
      if (OpR->getName() == "ptr_rc")
        Res += "|M_LOOK_UP_PTR_REG_CLASS";

      // Predicate operands.  Check to see if the original unexpanded operand
      // was of type PredicateOperand.
      if (Inst.OperandList[i].Rec->isSubClassOf("PredicateOperand"))
        Res += "|M_PREDICATE_OPERAND";

      // Optional def operands.  Check to see if the original unexpanded operand
      // was of type OptionalDefOperand.
      if (Inst.OperandList[i].Rec->isSubClassOf("OptionalDefOperand"))
        Res += "|M_OPTIONAL_DEF_OPERAND";

      // Fill in constraint info.
      Res += ", " + Inst.OperandList[i].Constraints[j];
      Result.push_back(Res);
    }
  }

  return Result;
}

// run - Emit the main instruction description records for the target...
void InstrInfoEmitter::run(std::ostream &OS) {
  GatherItinClasses();

  EmitSourceFileHeader("Target Instruction Descriptors", OS);
  OS << "namespace llvm {\n\n";

  CodeGenTarget Target;
  const std::string &TargetName = Target.getName();
  Record *InstrInfo = Target.getInstructionSet();

  // Keep track of all of the def lists we have emitted already.
  std::map<std::vector<Record*>, unsigned> EmittedLists;
  unsigned ListNumber = 0;

  // Emit all of the instruction's implicit uses and defs.
  for (CodeGenTarget::inst_iterator II = Target.inst_begin(),
         E = Target.inst_end(); II != E; ++II) {
    Record *Inst = II->second.TheDef;
    std::vector<Record*> Uses = Inst->getValueAsListOfDefs("Uses");
    if (!Uses.empty()) {
      unsigned &IL = EmittedLists[Uses];
      if (!IL) printDefList(Uses, IL = ++ListNumber, OS);
    }
    std::vector<Record*> Defs = Inst->getValueAsListOfDefs("Defs");
    if (!Defs.empty()) {
      unsigned &IL = EmittedLists[Defs];
      if (!IL) printDefList(Defs, IL = ++ListNumber, OS);
    }
  }

  std::map<std::vector<std::string>, unsigned> OperandInfosEmitted;
  unsigned OperandListNum = 0;
  OperandInfosEmitted[std::vector<std::string>()] = ++OperandListNum;

  // Emit all of the operand info records.
  OS << "\n";
  for (CodeGenTarget::inst_iterator II = Target.inst_begin(),
       E = Target.inst_end(); II != E; ++II) {
    std::vector<std::string> OperandInfo = GetOperandInfo(II->second);
    unsigned &N = OperandInfosEmitted[OperandInfo];
    if (N == 0) {
      N = ++OperandListNum;
      OS << "static const TargetOperandInfo OperandInfo" << N << "[] = { ";
      for (unsigned i = 0, e = OperandInfo.size(); i != e; ++i)
        OS << "{ " << OperandInfo[i] << " }, ";
      OS << "};\n";
    }
  }

  // Emit all of the TargetInstrDescriptor records in their ENUM ordering.
  //
  OS << "\nstatic const TargetInstrDescriptor " << TargetName
     << "Insts[] = {\n";
  std::vector<const CodeGenInstruction*> NumberedInstructions;
  Target.getInstructionsByEnumValue(NumberedInstructions);

  for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i)
    emitRecord(*NumberedInstructions[i], i, InstrInfo, EmittedLists,
               OperandInfosEmitted, OS);
  OS << "};\n";
  OS << "} // End llvm namespace \n";
}

void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
                                  Record *InstrInfo,
                         std::map<std::vector<Record*>, unsigned> &EmittedLists,
                           std::map<std::vector<std::string>, unsigned> &OpInfo,
                                  std::ostream &OS) {
  int MinOperands;
  if (!Inst.OperandList.empty())
    // Each logical operand can be multiple MI operands.
    MinOperands = Inst.OperandList.back().MIOperandNo +
                  Inst.OperandList.back().MINumOperands;
  else
    MinOperands = 0;

  OS << "  { ";
  OS << Num << ",\t" << MinOperands << ",\t"
     << Inst.NumDefs << ",\t\"";

  if (Inst.Name.empty())
    OS << Inst.TheDef->getName();
  else
    OS << Inst.Name;

  unsigned ItinClass = !IsItineraries ? 0 :
            ItinClassNumber(Inst.TheDef->getValueAsDef("Itinerary")->getName());

  OS << "\",\t" << ItinClass << ", 0";

  // Try to determine (from the pattern), if the instruction is a store.
  bool isStore = false;
  if (dynamic_cast<ListInit*>(Inst.TheDef->getValueInit("Pattern"))) {
    ListInit *LI = Inst.TheDef->getValueAsListInit("Pattern");
    if (LI && LI->getSize() > 0) {
      DagInit *Dag = (DagInit *)LI->getElement(0);
      DefInit *OpDef = dynamic_cast<DefInit*>(Dag->getOperator());
      if (OpDef) {
        Record *Operator = OpDef->getDef();
        if (Operator->isSubClassOf("SDNode")) {
          const std::string Opcode = Operator->getValueAsString("Opcode");
          if (Opcode == "ISD::STORE" || Opcode == "ISD::TRUNCSTORE")
            isStore = true;
        }
      }
    }
  }

  // Emit all of the target indepedent flags...
  if (Inst.isReturn)     OS << "|M_RET_FLAG";
  if (Inst.isBranch)     OS << "|M_BRANCH_FLAG";
  if (Inst.isIndirectBranch) OS << "|M_INDIRECT_FLAG";
  if (Inst.isBarrier)    OS << "|M_BARRIER_FLAG";
  if (Inst.hasDelaySlot) OS << "|M_DELAY_SLOT_FLAG";
  if (Inst.isCall)       OS << "|M_CALL_FLAG";
  if (Inst.isLoad)       OS << "|M_LOAD_FLAG";
  if (Inst.isStore || isStore) OS << "|M_STORE_FLAG";
  if (Inst.isImplicitDef)OS << "|M_IMPLICIT_DEF_FLAG";
  if (Inst.isPredicable) OS << "|M_PREDICABLE";
  if (Inst.isConvertibleToThreeAddress) OS << "|M_CONVERTIBLE_TO_3_ADDR";
  if (Inst.isCommutable) OS << "|M_COMMUTABLE";
  if (Inst.isTerminator) OS << "|M_TERMINATOR_FLAG";
  if (Inst.isReMaterializable) OS << "|M_REMATERIALIZIBLE";
  if (Inst.isNotDuplicable) OS << "|M_NOT_DUPLICABLE";
  if (Inst.hasOptionalDef) OS << "|M_HAS_OPTIONAL_DEF";
  if (Inst.usesCustomDAGSchedInserter)
    OS << "|M_USES_CUSTOM_DAG_SCHED_INSERTION";
  if (Inst.hasVariableNumberOfOperands) OS << "|M_VARIABLE_OPS";
  if (Inst.mayHaveSideEffects) OS << "|M_MAY_HAVE_SIDE_EFFECTS";
  if (Inst.neverHasSideEffects) OS << "|M_NEVER_HAS_SIDE_EFFECTS";
  OS << ", 0";

  // Emit all of the target-specific flags...
  ListInit *LI    = InstrInfo->getValueAsListInit("TSFlagsFields");
  ListInit *Shift = InstrInfo->getValueAsListInit("TSFlagsShifts");
  if (LI->getSize() != Shift->getSize())
    throw "Lengths of " + InstrInfo->getName() +
          ":(TargetInfoFields, TargetInfoPositions) must be equal!";

  for (unsigned i = 0, e = LI->getSize(); i != e; ++i)
    emitShiftedValue(Inst.TheDef, dynamic_cast<StringInit*>(LI->getElement(i)),
                     dynamic_cast<IntInit*>(Shift->getElement(i)), OS);

  OS << ", ";

  // Emit the implicit uses and defs lists...
  std::vector<Record*> UseList = Inst.TheDef->getValueAsListOfDefs("Uses");
  if (UseList.empty())
    OS << "NULL, ";
  else
    OS << "ImplicitList" << EmittedLists[UseList] << ", ";

  std::vector<Record*> DefList = Inst.TheDef->getValueAsListOfDefs("Defs");
  if (DefList.empty())
    OS << "NULL, ";
  else
    OS << "ImplicitList" << EmittedLists[DefList] << ", ";

  // Emit the operand info.
  std::vector<std::string> OperandInfo = GetOperandInfo(Inst);
  if (OperandInfo.empty())
    OS << "0";
  else
    OS << "OperandInfo" << OpInfo[OperandInfo];

  OS << " },  // Inst #" << Num << " = " << Inst.TheDef->getName() << "\n";
}

struct LessRecord {
  bool operator()(const Record *Rec1, const Record *Rec2) const {
    return Rec1->getName() < Rec2->getName();
  }
};
void InstrInfoEmitter::GatherItinClasses() {
  std::vector<Record*> DefList =
                          Records.getAllDerivedDefinitions("InstrItinClass");
  IsItineraries = !DefList.empty();

  if (!IsItineraries) return;

  std::sort(DefList.begin(), DefList.end(), LessRecord());

  for (unsigned i = 0, N = DefList.size(); i < N; i++) {
    Record *Def = DefList[i];
    ItinClassMap[Def->getName()] = i;
  }
}

unsigned InstrInfoEmitter::ItinClassNumber(std::string ItinName) {
  return ItinClassMap[ItinName];
}

void InstrInfoEmitter::emitShiftedValue(Record *R, StringInit *Val,
                                        IntInit *ShiftInt, std::ostream &OS) {
  if (Val == 0 || ShiftInt == 0)
    throw std::string("Illegal value or shift amount in TargetInfo*!");
  RecordVal *RV = R->getValue(Val->getValue());
  int Shift = ShiftInt->getValue();

  if (RV == 0 || RV->getValue() == 0) {
    // This isn't an error if this is a builtin instruction.
    if (R->getName() != "PHI" &&
        R->getName() != "INLINEASM" &&
        R->getName() != "LABEL" &&
        R->getName() != "EXTRACT_SUBREG" &&
        R->getName() != "INSERT_SUBREG")
      throw R->getName() + " doesn't have a field named '" +
            Val->getValue() + "'!";
    return;
  }

  Init *Value = RV->getValue();
  if (BitInit *BI = dynamic_cast<BitInit*>(Value)) {
    if (BI->getValue()) OS << "|(1<<" << Shift << ")";
    return;
  } else if (BitsInit *BI = dynamic_cast<BitsInit*>(Value)) {
    // Convert the Bits to an integer to print...
    Init *I = BI->convertInitializerTo(new IntRecTy());
    if (I)
      if (IntInit *II = dynamic_cast<IntInit*>(I)) {
        if (II->getValue()) {
          if (Shift)
            OS << "|(" << II->getValue() << "<<" << Shift << ")";
          else
            OS << "|" << II->getValue();
        }
        return;
      }

  } else if (IntInit *II = dynamic_cast<IntInit*>(Value)) {
    if (II->getValue()) {
      if (Shift)
        OS << "|(" << II->getValue() << "<<" << Shift << ")";
      else
        OS << II->getValue();
    }
    return;
  }

  cerr << "Unhandled initializer: " << *Val << "\n";
  throw "In record '" + R->getName() + "' for TSFlag emission.";
}

<commit_msg>tblgen shouldn't include headers from llvm codegen.<commit_after>//===- InstrInfoEmitter.cpp - Generate a Instruction Set Desc. ------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This tablegen backend is responsible for emitting a description of the target
// instruction set for the code generator.
//
//===----------------------------------------------------------------------===//

#include "InstrInfoEmitter.h"
#include "CodeGenTarget.h"
#include "Record.h"
#include <algorithm>
#include <iostream>
using namespace llvm;

// runEnums - Print out enum values for all of the instructions.
void InstrInfoEmitter::runEnums(std::ostream &OS) {
  EmitSourceFileHeader("Target Instruction Enum Values", OS);
  OS << "namespace llvm {\n\n";

  CodeGenTarget Target;

  // We must emit the PHI opcode first...
  std::string Namespace;
  for (CodeGenTarget::inst_iterator II = Target.inst_begin(),
       E = Target.inst_end(); II != E; ++II) {
    if (II->second.Namespace != "TargetInstrInfo") {
      Namespace = II->second.Namespace;
      break;
    }
  }

  if (Namespace.empty()) {
    std::cerr << "No instructions defined!\n";
    exit(1);
  }

  std::vector<const CodeGenInstruction*> NumberedInstructions;
  Target.getInstructionsByEnumValue(NumberedInstructions);

  OS << "namespace " << Namespace << " {\n";
  OS << "  enum {\n";
  for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
    OS << "    " << NumberedInstructions[i]->TheDef->getName()
       << "\t= " << i << ",\n";
  }
  OS << "    INSTRUCTION_LIST_END = " << NumberedInstructions.size() << "\n";
  OS << "  };\n}\n";
  OS << "} // End llvm namespace \n";
}

void InstrInfoEmitter::printDefList(const std::vector<Record*> &Uses,
                                    unsigned Num, std::ostream &OS) const {
  OS << "static const unsigned ImplicitList" << Num << "[] = { ";
  for (unsigned i = 0, e = Uses.size(); i != e; ++i)
    OS << getQualifiedName(Uses[i]) << ", ";
  OS << "0 };\n";
}

std::vector<std::string>
InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
  std::vector<std::string> Result;

  for (unsigned i = 0, e = Inst.OperandList.size(); i != e; ++i) {
    // Handle aggregate operands and normal operands the same way by expanding
    // either case into a list of operands for this op.
    std::vector<CodeGenInstruction::OperandInfo> OperandList;

    // This might be a multiple operand thing.  Targets like X86 have
    // registers in their multi-operand operands.  It may also be an anonymous
    // operand, which has a single operand, but no declared class for the
    // operand.
    DagInit *MIOI = Inst.OperandList[i].MIOperandInfo;

    if (!MIOI || MIOI->getNumArgs() == 0) {
      // Single, anonymous, operand.
      OperandList.push_back(Inst.OperandList[i]);
    } else {
      for (unsigned j = 0, e = Inst.OperandList[i].MINumOperands; j != e; ++j) {
        OperandList.push_back(Inst.OperandList[i]);

        Record *OpR = dynamic_cast<DefInit*>(MIOI->getArg(j))->getDef();
        OperandList.back().Rec = OpR;
      }
    }

    for (unsigned j = 0, e = OperandList.size(); j != e; ++j) {
      Record *OpR = OperandList[j].Rec;
      std::string Res;

      if (OpR->isSubClassOf("RegisterClass"))
        Res += getQualifiedName(OpR) + "RegClassID, ";
      else
        Res += "0, ";
      // Fill in applicable flags.
      Res += "0";

      // Ptr value whose register class is resolved via callback.
      if (OpR->getName() == "ptr_rc")
        Res += "|M_LOOK_UP_PTR_REG_CLASS";

      // Predicate operands.  Check to see if the original unexpanded operand
      // was of type PredicateOperand.
      if (Inst.OperandList[i].Rec->isSubClassOf("PredicateOperand"))
        Res += "|M_PREDICATE_OPERAND";

      // Optional def operands.  Check to see if the original unexpanded operand
      // was of type OptionalDefOperand.
      if (Inst.OperandList[i].Rec->isSubClassOf("OptionalDefOperand"))
        Res += "|M_OPTIONAL_DEF_OPERAND";

      // Fill in constraint info.
      Res += ", " + Inst.OperandList[i].Constraints[j];
      Result.push_back(Res);
    }
  }

  return Result;
}

// run - Emit the main instruction description records for the target...
void InstrInfoEmitter::run(std::ostream &OS) {
  GatherItinClasses();

  EmitSourceFileHeader("Target Instruction Descriptors", OS);
  OS << "namespace llvm {\n\n";

  CodeGenTarget Target;
  const std::string &TargetName = Target.getName();
  Record *InstrInfo = Target.getInstructionSet();

  // Keep track of all of the def lists we have emitted already.
  std::map<std::vector<Record*>, unsigned> EmittedLists;
  unsigned ListNumber = 0;

  // Emit all of the instruction's implicit uses and defs.
  for (CodeGenTarget::inst_iterator II = Target.inst_begin(),
         E = Target.inst_end(); II != E; ++II) {
    Record *Inst = II->second.TheDef;
    std::vector<Record*> Uses = Inst->getValueAsListOfDefs("Uses");
    if (!Uses.empty()) {
      unsigned &IL = EmittedLists[Uses];
      if (!IL) printDefList(Uses, IL = ++ListNumber, OS);
    }
    std::vector<Record*> Defs = Inst->getValueAsListOfDefs("Defs");
    if (!Defs.empty()) {
      unsigned &IL = EmittedLists[Defs];
      if (!IL) printDefList(Defs, IL = ++ListNumber, OS);
    }
  }

  std::map<std::vector<std::string>, unsigned> OperandInfosEmitted;
  unsigned OperandListNum = 0;
  OperandInfosEmitted[std::vector<std::string>()] = ++OperandListNum;

  // Emit all of the operand info records.
  OS << "\n";
  for (CodeGenTarget::inst_iterator II = Target.inst_begin(),
       E = Target.inst_end(); II != E; ++II) {
    std::vector<std::string> OperandInfo = GetOperandInfo(II->second);
    unsigned &N = OperandInfosEmitted[OperandInfo];
    if (N == 0) {
      N = ++OperandListNum;
      OS << "static const TargetOperandInfo OperandInfo" << N << "[] = { ";
      for (unsigned i = 0, e = OperandInfo.size(); i != e; ++i)
        OS << "{ " << OperandInfo[i] << " }, ";
      OS << "};\n";
    }
  }

  // Emit all of the TargetInstrDescriptor records in their ENUM ordering.
  //
  OS << "\nstatic const TargetInstrDescriptor " << TargetName
     << "Insts[] = {\n";
  std::vector<const CodeGenInstruction*> NumberedInstructions;
  Target.getInstructionsByEnumValue(NumberedInstructions);

  for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i)
    emitRecord(*NumberedInstructions[i], i, InstrInfo, EmittedLists,
               OperandInfosEmitted, OS);
  OS << "};\n";
  OS << "} // End llvm namespace \n";
}

void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
                                  Record *InstrInfo,
                         std::map<std::vector<Record*>, unsigned> &EmittedLists,
                           std::map<std::vector<std::string>, unsigned> &OpInfo,
                                  std::ostream &OS) {
  int MinOperands;
  if (!Inst.OperandList.empty())
    // Each logical operand can be multiple MI operands.
    MinOperands = Inst.OperandList.back().MIOperandNo +
                  Inst.OperandList.back().MINumOperands;
  else
    MinOperands = 0;

  OS << "  { ";
  OS << Num << ",\t" << MinOperands << ",\t"
     << Inst.NumDefs << ",\t\"";

  if (Inst.Name.empty())
    OS << Inst.TheDef->getName();
  else
    OS << Inst.Name;

  unsigned ItinClass = !IsItineraries ? 0 :
            ItinClassNumber(Inst.TheDef->getValueAsDef("Itinerary")->getName());

  OS << "\",\t" << ItinClass << ", 0";

  // Try to determine (from the pattern), if the instruction is a store.
  bool isStore = false;
  if (dynamic_cast<ListInit*>(Inst.TheDef->getValueInit("Pattern"))) {
    ListInit *LI = Inst.TheDef->getValueAsListInit("Pattern");
    if (LI && LI->getSize() > 0) {
      DagInit *Dag = (DagInit *)LI->getElement(0);
      DefInit *OpDef = dynamic_cast<DefInit*>(Dag->getOperator());
      if (OpDef) {
        Record *Operator = OpDef->getDef();
        if (Operator->isSubClassOf("SDNode")) {
          const std::string Opcode = Operator->getValueAsString("Opcode");
          if (Opcode == "ISD::STORE" || Opcode == "ISD::TRUNCSTORE")
            isStore = true;
        }
      }
    }
  }

  // Emit all of the target indepedent flags...
  if (Inst.isReturn)     OS << "|M_RET_FLAG";
  if (Inst.isBranch)     OS << "|M_BRANCH_FLAG";
  if (Inst.isIndirectBranch) OS << "|M_INDIRECT_FLAG";
  if (Inst.isBarrier)    OS << "|M_BARRIER_FLAG";
  if (Inst.hasDelaySlot) OS << "|M_DELAY_SLOT_FLAG";
  if (Inst.isCall)       OS << "|M_CALL_FLAG";
  if (Inst.isLoad)       OS << "|M_LOAD_FLAG";
  if (Inst.isStore || isStore) OS << "|M_STORE_FLAG";
  if (Inst.isImplicitDef)OS << "|M_IMPLICIT_DEF_FLAG";
  if (Inst.isPredicable) OS << "|M_PREDICABLE";
  if (Inst.isConvertibleToThreeAddress) OS << "|M_CONVERTIBLE_TO_3_ADDR";
  if (Inst.isCommutable) OS << "|M_COMMUTABLE";
  if (Inst.isTerminator) OS << "|M_TERMINATOR_FLAG";
  if (Inst.isReMaterializable) OS << "|M_REMATERIALIZIBLE";
  if (Inst.isNotDuplicable) OS << "|M_NOT_DUPLICABLE";
  if (Inst.hasOptionalDef) OS << "|M_HAS_OPTIONAL_DEF";
  if (Inst.usesCustomDAGSchedInserter)
    OS << "|M_USES_CUSTOM_DAG_SCHED_INSERTION";
  if (Inst.hasVariableNumberOfOperands) OS << "|M_VARIABLE_OPS";
  if (Inst.mayHaveSideEffects) OS << "|M_MAY_HAVE_SIDE_EFFECTS";
  if (Inst.neverHasSideEffects) OS << "|M_NEVER_HAS_SIDE_EFFECTS";
  OS << ", 0";

  // Emit all of the target-specific flags...
  ListInit *LI    = InstrInfo->getValueAsListInit("TSFlagsFields");
  ListInit *Shift = InstrInfo->getValueAsListInit("TSFlagsShifts");
  if (LI->getSize() != Shift->getSize())
    throw "Lengths of " + InstrInfo->getName() +
          ":(TargetInfoFields, TargetInfoPositions) must be equal!";

  for (unsigned i = 0, e = LI->getSize(); i != e; ++i)
    emitShiftedValue(Inst.TheDef, dynamic_cast<StringInit*>(LI->getElement(i)),
                     dynamic_cast<IntInit*>(Shift->getElement(i)), OS);

  OS << ", ";

  // Emit the implicit uses and defs lists...
  std::vector<Record*> UseList = Inst.TheDef->getValueAsListOfDefs("Uses");
  if (UseList.empty())
    OS << "NULL, ";
  else
    OS << "ImplicitList" << EmittedLists[UseList] << ", ";

  std::vector<Record*> DefList = Inst.TheDef->getValueAsListOfDefs("Defs");
  if (DefList.empty())
    OS << "NULL, ";
  else
    OS << "ImplicitList" << EmittedLists[DefList] << ", ";

  // Emit the operand info.
  std::vector<std::string> OperandInfo = GetOperandInfo(Inst);
  if (OperandInfo.empty())
    OS << "0";
  else
    OS << "OperandInfo" << OpInfo[OperandInfo];

  OS << " },  // Inst #" << Num << " = " << Inst.TheDef->getName() << "\n";
}

struct LessRecord {
  bool operator()(const Record *Rec1, const Record *Rec2) const {
    return Rec1->getName() < Rec2->getName();
  }
};
void InstrInfoEmitter::GatherItinClasses() {
  std::vector<Record*> DefList =
                          Records.getAllDerivedDefinitions("InstrItinClass");
  IsItineraries = !DefList.empty();

  if (!IsItineraries) return;

  std::sort(DefList.begin(), DefList.end(), LessRecord());

  for (unsigned i = 0, N = DefList.size(); i < N; i++) {
    Record *Def = DefList[i];
    ItinClassMap[Def->getName()] = i;
  }
}

unsigned InstrInfoEmitter::ItinClassNumber(std::string ItinName) {
  return ItinClassMap[ItinName];
}

void InstrInfoEmitter::emitShiftedValue(Record *R, StringInit *Val,
                                        IntInit *ShiftInt, std::ostream &OS) {
  if (Val == 0 || ShiftInt == 0)
    throw std::string("Illegal value or shift amount in TargetInfo*!");
  RecordVal *RV = R->getValue(Val->getValue());
  int Shift = ShiftInt->getValue();

  if (RV == 0 || RV->getValue() == 0) {
    // This isn't an error if this is a builtin instruction.
    if (R->getName() != "PHI" &&
        R->getName() != "INLINEASM" &&
        R->getName() != "LABEL" &&
        R->getName() != "EXTRACT_SUBREG" &&
        R->getName() != "INSERT_SUBREG")
      throw R->getName() + " doesn't have a field named '" +
            Val->getValue() + "'!";
    return;
  }

  Init *Value = RV->getValue();
  if (BitInit *BI = dynamic_cast<BitInit*>(Value)) {
    if (BI->getValue()) OS << "|(1<<" << Shift << ")";
    return;
  } else if (BitsInit *BI = dynamic_cast<BitsInit*>(Value)) {
    // Convert the Bits to an integer to print...
    Init *I = BI->convertInitializerTo(new IntRecTy());
    if (I)
      if (IntInit *II = dynamic_cast<IntInit*>(I)) {
        if (II->getValue()) {
          if (Shift)
            OS << "|(" << II->getValue() << "<<" << Shift << ")";
          else
            OS << "|" << II->getValue();
        }
        return;
      }

  } else if (IntInit *II = dynamic_cast<IntInit*>(Value)) {
    if (II->getValue()) {
      if (Shift)
        OS << "|(" << II->getValue() << "<<" << Shift << ")";
      else
        OS << II->getValue();
    }
    return;
  }

  std::cerr << "Unhandled initializer: " << *Val << "\n";
  throw "In record '" + R->getName() + "' for TSFlag emission.";
}

<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2013.  All rights reserved
 */
#include    "../StroikaPreComp.h"

#include    "../Characters/Format.h"
#include    "../Time/Date.h"
#include    "../Time/DateTime.h"

#include    "ObjectVariantMapper.h"

using   namespace   Stroika::Foundation;
using   namespace   Stroika::Foundation::DataExchangeFormat;

using   Time::Date;
using   Time::DateTime;

/*
 ********************************************************************************
 ******* DataExchangeFormat::ObjectVariantMapper::TypeMappingDetails ************
 ********************************************************************************
 */
ObjectVariantMapper::TypeMappingDetails::TypeMappingDetails (
    const type_index& forTypeInfo,
    const std::function<VariantValue(ObjectVariantMapper* mapper, const Byte* objOfType)>& toVariantMapper,
    const std::function<void(ObjectVariantMapper* mapper, const VariantValue& d, Byte* into)>& fromVariantMapper
)
    : fForType (forTypeInfo)
    , fToVariantMapper (toVariantMapper)
    , fFromVariantMapper (fromVariantMapper)
{
}

/*
 ********************************************************************************
 ****************** DataExchangeFormat::ObjectVariantMapper *********************
 ********************************************************************************
 */
ObjectVariantMapper::ObjectVariantMapper ()
{
    RegisterCommonSerializers ();
}

void    ObjectVariantMapper::RegisterSerializer (const TypeMappingDetails& serializerInfo)
{
    fSerializers_.Add (serializerInfo);
}

void    ObjectVariantMapper::ClearRegistry ()
{
    fSerializers_.clear ();
}

void    ObjectVariantMapper::ResetToDefaultRegistry ()
{
    ClearRegistry ();
    RegisterCommonSerializers ();
}

namespace {
    template    <typename T, typename UseVariantType>
    ObjectVariantMapper::TypeMappingDetails mkSerializerInfo_ ()
    {
        auto toVariantMapper = [] (ObjectVariantMapper * mapper, const Byte * objOfType) -> VariantValue {
            return VariantValue (static_cast<UseVariantType> (*reinterpret_cast<const T*> (objOfType)));
        };
        auto fromVariantMapper = [] (ObjectVariantMapper * mapper, const VariantValue & d, Byte * into) -> void {
            *reinterpret_cast<T*> (into) = static_cast<T> (d.As<UseVariantType> ());
        };
        return ObjectVariantMapper::TypeMappingDetails (typeid (T), toVariantMapper, fromVariantMapper);
    }
}

void    ObjectVariantMapper::RegisterCommonSerializers ()
{
    RegisterSerializer (mkSerializerInfo_<bool, bool> ());
    RegisterSerializer (mkSerializerInfo_<int, int> ());
    RegisterSerializer (mkSerializerInfo_<float, VariantValue::FloatType> ());
    RegisterSerializer (mkSerializerInfo_<double, VariantValue::FloatType> ());
    RegisterSerializer (mkSerializerInfo_<Date, Date> ());
    RegisterSerializer (mkSerializerInfo_<DateTime, DateTime> ());
    /// TODO - ARRAY??? Maybe using Sequence???
    RegisterSerializer (mkSerializerInfo_<String, String> ());
}

VariantValue    ObjectVariantMapper::Serialize (const type_index& forTypeInfo, const Byte* objOfType)
{
    Require (Lookup_ (forTypeInfo).fToVariantMapper);
    return Lookup_ (forTypeInfo).fToVariantMapper (this, objOfType);
}

void    ObjectVariantMapper::Deserialize (const type_index& forTypeInfo, const VariantValue& d, Byte* into)
{
    Require (Lookup_ (forTypeInfo).fFromVariantMapper);
    Lookup_ (forTypeInfo).fFromVariantMapper (this, d, into);
}

ObjectVariantMapper::TypeMappingDetails  ObjectVariantMapper::mkSerializerForStruct (const type_index& forTypeInfo, size_t n, const Sequence<StructureFieldInfo>& fields)
{
#if     qDebug
    for (auto i : fields) {
        Require (i.fOffset < n);
    }
#endif

    // foo magic (could do cleaner?) to assure lifetime for whats captured in lambda
    struct foo {
        Sequence<StructureFieldInfo> fields;
    };
    shared_ptr<foo> fooptr (new foo ());
    fooptr->fields = fields;
    auto toVariantMapper = [fooptr] (ObjectVariantMapper * mapper, const Byte * objOfType) -> VariantValue {
        Mapping<String, VariantValue> m;
        for (auto i : fooptr->fields) {
            const Byte* fieldObj = objOfType + i.fOffset;
            m.Add (i.fSerializedFieldName, mapper->Serialize (i.fTypeInfo, objOfType + i.fOffset));
        }
        return VariantValue (m);
    };
    auto fromVariantMapper = [fooptr] (ObjectVariantMapper * mapper, const VariantValue & d, Byte * into) -> void {
        Mapping<String, VariantValue> m  =   d.As<Mapping<String, VariantValue>> ();
        for (auto i : fooptr->fields) {
            Memory::Optional<VariantValue> o = m.Lookup (i.fSerializedFieldName);
            if (not o.empty ()) {
                mapper->Deserialize (i.fTypeInfo, *o, into + i.fOffset);
            }
        }
    };
    return TypeMappingDetails (forTypeInfo, toVariantMapper, fromVariantMapper);
}

ObjectVariantMapper::TypeMappingDetails  ObjectVariantMapper::Lookup_ (const type_index& forTypeInfo) const
{
    TypeMappingDetails  foo (forTypeInfo, nullptr, nullptr);
    auto i  = fSerializers_.Lookup (foo);
    Require (i.IsPresent ());   // if not present, this is a usage error - only use types which are registered
    return *i;
}
<commit_msg>Assertions in ObjectVariantMapper::mkSerializerForStr ()<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2013.  All rights reserved
 */
#include    "../StroikaPreComp.h"

#include    "../Characters/Format.h"
#include    "../Containers/Tally.h"
#include    "../Time/Date.h"
#include    "../Time/DateTime.h"

#include    "ObjectVariantMapper.h"

using   namespace   Stroika::Foundation;
using   namespace   Stroika::Foundation::DataExchangeFormat;

using   Time::Date;
using   Time::DateTime;

/*
 ********************************************************************************
 ******* DataExchangeFormat::ObjectVariantMapper::TypeMappingDetails ************
 ********************************************************************************
 */
ObjectVariantMapper::TypeMappingDetails::TypeMappingDetails (
    const type_index& forTypeInfo,
    const std::function<VariantValue(ObjectVariantMapper* mapper, const Byte* objOfType)>& toVariantMapper,
    const std::function<void(ObjectVariantMapper* mapper, const VariantValue& d, Byte* into)>& fromVariantMapper
)
    : fForType (forTypeInfo)
    , fToVariantMapper (toVariantMapper)
    , fFromVariantMapper (fromVariantMapper)
{
}

/*
 ********************************************************************************
 ****************** DataExchangeFormat::ObjectVariantMapper *********************
 ********************************************************************************
 */
ObjectVariantMapper::ObjectVariantMapper ()
{
    RegisterCommonSerializers ();
}

void    ObjectVariantMapper::RegisterSerializer (const TypeMappingDetails& serializerInfo)
{
    fSerializers_.Add (serializerInfo);
}

void    ObjectVariantMapper::ClearRegistry ()
{
    fSerializers_.clear ();
}

void    ObjectVariantMapper::ResetToDefaultRegistry ()
{
    ClearRegistry ();
    RegisterCommonSerializers ();
}

namespace {
    template    <typename T, typename UseVariantType>
    ObjectVariantMapper::TypeMappingDetails mkSerializerInfo_ ()
    {
        auto toVariantMapper = [] (ObjectVariantMapper * mapper, const Byte * objOfType) -> VariantValue {
            return VariantValue (static_cast<UseVariantType> (*reinterpret_cast<const T*> (objOfType)));
        };
        auto fromVariantMapper = [] (ObjectVariantMapper * mapper, const VariantValue & d, Byte * into) -> void {
            *reinterpret_cast<T*> (into) = static_cast<T> (d.As<UseVariantType> ());
        };
        return ObjectVariantMapper::TypeMappingDetails (typeid (T), toVariantMapper, fromVariantMapper);
    }
}

void    ObjectVariantMapper::RegisterCommonSerializers ()
{
    RegisterSerializer (mkSerializerInfo_<bool, bool> ());
    RegisterSerializer (mkSerializerInfo_<int, int> ());
    RegisterSerializer (mkSerializerInfo_<float, VariantValue::FloatType> ());
    RegisterSerializer (mkSerializerInfo_<double, VariantValue::FloatType> ());
    RegisterSerializer (mkSerializerInfo_<Date, Date> ());
    RegisterSerializer (mkSerializerInfo_<DateTime, DateTime> ());
    /// TODO - ARRAY??? Maybe using Sequence???
    RegisterSerializer (mkSerializerInfo_<String, String> ());
}

VariantValue    ObjectVariantMapper::Serialize (const type_index& forTypeInfo, const Byte* objOfType)
{
    Require (Lookup_ (forTypeInfo).fToVariantMapper);
    return Lookup_ (forTypeInfo).fToVariantMapper (this, objOfType);
}

void    ObjectVariantMapper::Deserialize (const type_index& forTypeInfo, const VariantValue& d, Byte* into)
{
    Require (Lookup_ (forTypeInfo).fFromVariantMapper);
    Lookup_ (forTypeInfo).fFromVariantMapper (this, d, into);
}

ObjectVariantMapper::TypeMappingDetails  ObjectVariantMapper::mkSerializerForStruct (const type_index& forTypeInfo, size_t n, const Sequence<StructureFieldInfo>& fields)
{
#if     qDebug
    for (auto i : fields) {
        Require (i.fOffset < n);
    }
    {
        // assure each field unique
        Containers::Tally<size_t> t;
        for (auto i : fields) {
            t.Add (i.fOffset);
        }
        for (auto i : t) {
            Require (i.fCount == 1);
        }
    }
    {
        // Assure for each field type is registered
        for (auto i : fields) {
            Require (Lookup_ (i.fTypeInfo).fFromVariantMapper);
            Require (Lookup_ (i.fTypeInfo).fToVariantMapper);
        }
    }
#endif

    // foo magic (could do cleaner?) to assure lifetime for whats captured in lambda
    struct foo {
        Sequence<StructureFieldInfo> fields;
    };
    shared_ptr<foo> fooptr (new foo ());
    fooptr->fields = fields;
    auto toVariantMapper = [fooptr] (ObjectVariantMapper * mapper, const Byte * objOfType) -> VariantValue {
        Mapping<String, VariantValue> m;
        for (auto i : fooptr->fields) {
            const Byte* fieldObj = objOfType + i.fOffset;
            m.Add (i.fSerializedFieldName, mapper->Serialize (i.fTypeInfo, objOfType + i.fOffset));
        }
        return VariantValue (m);
    };
    auto fromVariantMapper = [fooptr] (ObjectVariantMapper * mapper, const VariantValue & d, Byte * into) -> void {
        Mapping<String, VariantValue> m  =   d.As<Mapping<String, VariantValue>> ();
        for (auto i : fooptr->fields) {
            Memory::Optional<VariantValue> o = m.Lookup (i.fSerializedFieldName);
            if (not o.empty ()) {
                mapper->Deserialize (i.fTypeInfo, *o, into + i.fOffset);
            }
        }
    };
    return TypeMappingDetails (forTypeInfo, toVariantMapper, fromVariantMapper);
}

ObjectVariantMapper::TypeMappingDetails  ObjectVariantMapper::Lookup_ (const type_index& forTypeInfo) const
{
    TypeMappingDetails  foo (forTypeInfo, nullptr, nullptr);
    auto i  = fSerializers_.Lookup (foo);
    Require (i.IsPresent ());   // if not present, this is a usage error - only use types which are registered
    return *i;
}
<|endoftext|>


<commit_before>/**
 *  For conditions of distribution and use, see copyright notice in license.txt
 *
 *  @file   UiService.cpp
 *  @brief  Light-weight UI service. Implements UiServiceInterface and provides
 *          means of embedding Qt widgets to the same scene/canvas as the 3D in-world
 *          view. Uses only one UI scene for everything.
 */

#include "StableHeaders.h"
#include "DebugOperatorNew.h"

#include "UiService.h"
#include "UiProxyWidget.h"

#include "MemoryLeakCheck.h"

#include <QUiLoader>

UiService::UiService(QGraphicsView *view) : view_(view), scene_(view->scene())
{
    assert(view_);
    assert(scene_);

    connect(scene_, SIGNAL(sceneRectChanged(const QRectF &)), SLOT(SceneRectChanged(const QRectF &)));
}

UiService::~UiService()
{
}

UiProxyWidget *UiService::AddWidgetToScene(QWidget *widget, Qt::WindowFlags flags)
{
    /*  QGraphicsProxyWidget maintains symmetry for the following states:
     *  state, enabled, visible, geometry, layoutDirection, style, palette,
     *  font, cursor, sizeHint, getContentsMargins and windowTitle
     */

    UiProxyWidget *proxy = new UiProxyWidget(widget, flags);

    // Synchorize windowState flags
    proxy->widget()->setWindowState(widget->windowState());

    AddWidgetToScene(proxy);

    // If the widget has WA_DeleteOnClose on, connect its proxy's visibleChanged()
    // signal to a slot which handles the deletion. This must be done because closing
    // proxy window in our system doesn't yield closeEvent, but hideEvent instead.
    if (widget->testAttribute(Qt::WA_DeleteOnClose))
        connect(proxy, SIGNAL(visibleChanged()), SLOT(DeleteCallingWidgetOnClose()));

    return proxy;
}

bool UiService::AddWidgetToScene(UiProxyWidget *widget)
{
    if (widgets_.contains(widget))
        return false;

    widgets_.append(widget);

    if (widget->isVisible())
        widget->hide();

    // If no position has been set for Qt::Dialog widget, use default one so that the window's title
    // bar - or any other critical part, doesn't go outside the view.
    if ((widget->windowFlags() & Qt::Dialog) && widget->pos() == QPointF())
        widget->setPos(10.0, 200.0);

    // Resize full screen widgets to fit the scene rect.
    if (widget->widget()->windowState() & Qt::WindowFullScreen)
    {
        fullScreenWidgets_ << widget;
        widget->setGeometry(scene_->sceneRect().toRect());
    }

    scene_->addItem(widget);
    return true;
}

void UiService::AddWidgetToMenu(QWidget *widget)
{
}

void UiService::AddWidgetToMenu(QWidget *widget, const QString &entry, const QString &menu, const QString &icon)
{
}

void UiService::AddWidgetToMenu(UiProxyWidget *widget, const QString &entry, const QString &menu, const QString &icon)
{
}

void UiService::RemoveWidgetFromScene(QWidget *widget)
{
    scene_->removeItem(widget->graphicsProxyWidget());
    widgets_.removeOne(widget->graphicsProxyWidget());
    fullScreenWidgets_.removeOne(widget->graphicsProxyWidget());
}

void UiService::RemoveWidgetFromScene(QGraphicsProxyWidget *widget)
{
    scene_->removeItem(widget);
    widgets_.removeOne(widget);
    fullScreenWidgets_.removeOne(widget);
}

QWidget *UiService::LoadFromFile(const QString &file_path, bool add_to_scene, QWidget *parent)
{
    QWidget *widget = 0;
    QUiLoader loader;
    QFile file(file_path);
    file.open(QFile::ReadOnly);
    widget = loader.load(&file, parent);
    if(add_to_scene && widget)
        AddWidgetToScene(widget);
    return widget;
}

void UiService::RemoveWidgetFromMenu(QWidget *widget)
{
}

void UiService::RemoveWidgetFromMenu(QGraphicsProxyWidget *widget)
{
}

void UiService::ShowWidget(QWidget *widget) const
{
    widget->graphicsProxyWidget()->show();
}

void UiService::HideWidget(QWidget *widget) const
{
    widget->graphicsProxyWidget()->hide();
}

void UiService::BringWidgetToFront(QWidget *widget) const
{
    ShowWidget(widget);
    scene_->setActiveWindow(widget->graphicsProxyWidget());
    scene_->setFocusItem(widget->graphicsProxyWidget(), Qt::ActiveWindowFocusReason);
}

void UiService::BringWidgetToFront(QGraphicsProxyWidget *widget) const
{
    scene_->setActiveWindow(widget);
    scene_->setFocusItem(widget, Qt::ActiveWindowFocusReason);
}

void UiService::SceneRectChanged(const QRectF &rect)
{
    foreach(QGraphicsProxyWidget *widget, fullScreenWidgets_)
        widget->setGeometry(rect);
}

void UiService::DeleteCallingWidgetOnClose()
{
    QGraphicsProxyWidget *proxy = dynamic_cast<QGraphicsProxyWidget *>(sender());
    if (proxy && !proxy->isVisible())
        proxy->deleteLater();
}
<commit_msg>Added null pointer access guards to UiService.cpp.<commit_after>/**
 *  For conditions of distribution and use, see copyright notice in license.txt
 *
 *  @file   UiService.cpp
 *  @brief  Light-weight UI service. Implements UiServiceInterface and provides
 *          means of embedding Qt widgets to the same scene/canvas as the 3D in-world
 *          view. Uses only one UI scene for everything.
 */

#include "StableHeaders.h"
#include "DebugOperatorNew.h"

#include "UiService.h"
#include "UiProxyWidget.h"

#include "MemoryLeakCheck.h"

#include <QUiLoader>

UiService::UiService(QGraphicsView *view) : view_(view), scene_(view->scene())
{
    assert(view_);
    assert(scene_);

    connect(scene_, SIGNAL(sceneRectChanged(const QRectF &)), SLOT(SceneRectChanged(const QRectF &)));
}

UiService::~UiService()
{
}

UiProxyWidget *UiService::AddWidgetToScene(QWidget *widget, Qt::WindowFlags flags)
{
    if (!widget)
        return 0;

    /*  QGraphicsProxyWidget maintains symmetry for the following states:
     *  state, enabled, visible, geometry, layoutDirection, style, palette,
     *  font, cursor, sizeHint, getContentsMargins and windowTitle
     */

    UiProxyWidget *proxy = new UiProxyWidget(widget, flags);
    assert(proxy->widget());

    // Synchorize windowState flags
    proxy->widget()->setWindowState(widget->windowState());

    AddWidgetToScene(proxy);

    // If the widget has WA_DeleteOnClose on, connect its proxy's visibleChanged()
    // signal to a slot which handles the deletion. This must be done because closing
    // proxy window in our system doesn't yield closeEvent, but hideEvent instead.
    if (widget->testAttribute(Qt::WA_DeleteOnClose))
        connect(proxy, SIGNAL(visibleChanged()), SLOT(DeleteCallingWidgetOnClose()));

    return proxy;
}

bool UiService::AddWidgetToScene(UiProxyWidget *widget)
{
    if (!widget)
        return false;

    if (widgets_.contains(widget))
        return false;

    widgets_.append(widget);

    if (widget->isVisible())
        widget->hide();

    // If no position has been set for Qt::Dialog widget, use default one so that the window's title
    // bar - or any other critical part, doesn't go outside the view.
    if ((widget->windowFlags() & Qt::Dialog) && widget->pos() == QPointF())
        widget->setPos(10.0, 200.0);

    // Resize full screen widgets to fit the scene rect.
    if (widget->widget()->windowState() & Qt::WindowFullScreen)
    {
        fullScreenWidgets_ << widget;
        widget->setGeometry(scene_->sceneRect().toRect());
    }

    scene_->addItem(widget);
    return true;
}

void UiService::AddWidgetToMenu(QWidget *widget)
{
}

void UiService::AddWidgetToMenu(QWidget *widget, const QString &entry, const QString &menu, const QString &icon)
{
}

void UiService::AddWidgetToMenu(UiProxyWidget *widget, const QString &entry, const QString &menu, const QString &icon)
{
}

void UiService::RemoveWidgetFromScene(QWidget *widget)
{
    if (!widget)
        return;

    if (scene_)
        scene_->removeItem(widget->graphicsProxyWidget());
    widgets_.removeOne(widget->graphicsProxyWidget());
    fullScreenWidgets_.removeOne(widget->graphicsProxyWidget());
}

void UiService::RemoveWidgetFromScene(QGraphicsProxyWidget *widget)
{
    if (!widget)
        return;

    if (scene_)
        scene_->removeItem(widget);
    widgets_.removeOne(widget);
    fullScreenWidgets_.removeOne(widget);
}

QWidget *UiService::LoadFromFile(const QString &file_path, bool add_to_scene, QWidget *parent)
{
    QWidget *widget = 0;
    QUiLoader loader;
    QFile file(file_path);
    file.open(QFile::ReadOnly);
    widget = loader.load(&file, parent);
    if(add_to_scene && widget)
        AddWidgetToScene(widget);
    return widget;
}

void UiService::RemoveWidgetFromMenu(QWidget *widget)
{
}

void UiService::RemoveWidgetFromMenu(QGraphicsProxyWidget *widget)
{
}

void UiService::ShowWidget(QWidget *widget) const
{
    if (!widget)
        return;

    if (widget->graphicsProxyWidget())
        widget->graphicsProxyWidget()->show();
    else
        widget->show();
}

void UiService::HideWidget(QWidget *widget) const
{
    if (!widget)
        return;

    if (widget->graphicsProxyWidget())
        widget->graphicsProxyWidget()->hide();
    else
        widget->hide();
}

void UiService::BringWidgetToFront(QWidget *widget) const
{
    if (!widget)
        return;

    ShowWidget(widget);
    scene_->setActiveWindow(widget->graphicsProxyWidget());
    scene_->setFocusItem(widget->graphicsProxyWidget(), Qt::ActiveWindowFocusReason);
}

void UiService::BringWidgetToFront(QGraphicsProxyWidget *widget) const
{
    if (!widget)
        return;

    scene_->setActiveWindow(widget);
    scene_->setFocusItem(widget, Qt::ActiveWindowFocusReason);
}

void UiService::SceneRectChanged(const QRectF &rect)
{
    foreach(QGraphicsProxyWidget *widget, fullScreenWidgets_)
        widget->setGeometry(rect);
}

void UiService::DeleteCallingWidgetOnClose()
{
    QGraphicsProxyWidget *proxy = dynamic_cast<QGraphicsProxyWidget *>(sender());
    if (proxy && !proxy->isVisible())
        proxy->deleteLater();
}
<|endoftext|>