<commit_before>/* libwpd
 * Copyright (C) 2002 William Lachance (wrlach@gmail.com)
 * Copyright (C) 2002 Marc Maurer (uwog@uwog.net)
 * Copyright (C) 2004 Fridrich Strba (fridrich.strba@bluewin.ch)
 *
 * 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 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 *
 * For further information visit http://libwpd.sourceforge.net
 */

/* "This product is not manufactured, approved, or supported by
 * Corel Corporation or Corel Corporation Limited."
 */

#include "WP6ParagraphGroup.h"
#include "libwpd_internal.h"
#include "WPXFileStructure.h"

WP6ParagraphGroup::WP6ParagraphGroup(WPXInputStream *input) :
	WP6VariableLengthGroup(),
	m_subGroupData(NULL)
{
	_read(input);
}

WP6ParagraphGroup::~WP6ParagraphGroup()
{
	if (m_subGroupData)
		delete(m_subGroupData);
}

void WP6ParagraphGroup::_readContents(WPXInputStream *input)
{
	switch (getSubGroup())
	{
	case WP6_PARAGRAPH_GROUP_LINE_SPACING:
		m_subGroupData = new WP6ParagraphGroup_LineSpacingSubGroup(input);
		break;
	case WP6_PARAGRAPH_GROUP_TAB_SET:
		m_subGroupData = new WP6ParagraphGroup_TabSetSubGroup(input);
		break;
	case WP6_PARAGRAPH_GROUP_JUSTIFICATION:
		m_subGroupData = new WP6ParagraphGroup_JustificationModeSubGroup(input);
		break;
	case WP6_PARAGRAPH_GROUP_SPACING_AFTER_PARAGRAPH:
		m_subGroupData = new WP6ParagraphGroup_SpacingAfterParagraphSubGroup(input, getSizeNonDeletable());
		break;
	case WP6_PARAGRAPH_GROUP_INDENT_FIRST_LINE_OF_PARAGRAPH:
		m_subGroupData = new WP6ParagraphGroup_IndentFirstLineSubGroup(input);
		break;
	case WP6_PARAGRAPH_GROUP_LEFT_MARGIN_ADJUSTMENT:
		m_subGroupData = new WP6ParagraphGroup_LeftMarginAdjustmentSubGroup(input);
		break;
	case WP6_PARAGRAPH_GROUP_RIGHT_MARGIN_ADJUSTMENT:
		m_subGroupData = new WP6ParagraphGroup_RightMarginAdjustmentSubGroup(input);
		break;
	case WP6_PARAGRAPH_GROUP_OUTLINE_DEFINE:
		m_subGroupData = new WP6ParagraphGroup_OutlineDefineSubGroup(input);
		break;
	}
}

void WP6ParagraphGroup::parse(WP6Listener *listener)
{
	WPD_DEBUG_MSG(("WordPerfect: handling a Paragraph group\n"));

	if (m_subGroupData)
		m_subGroupData->parse(listener, getNumPrefixIDs(), getPrefixIDs());
}

WP6ParagraphGroup_LineSpacingSubGroup::WP6ParagraphGroup_LineSpacingSubGroup(WPXInputStream *input)
{
	uint32_t lineSpacing = readU32(input);
	int16_t lineSpacingIntegerPart = (int16_t)((lineSpacing & 0xFFFF0000) >> 16);
	float lineSpacingFractionalPart = (float)(lineSpacing & 0xFFFF)/(float)0xFFFF;
	WPD_DEBUG_MSG(("WordPerfect: line spacing integer part: %i fractional part: %f (original value: %i)\n",
		       lineSpacingIntegerPart, lineSpacingFractionalPart, lineSpacing));
	m_lineSpacing = lineSpacingIntegerPart + lineSpacingFractionalPart;
}

void WP6ParagraphGroup_LineSpacingSubGroup::parse(WP6Listener *listener, const uint8_t /* numPrefixIDs */,
							uint16_t const * /* prefixIDs */) const
{
	WPD_DEBUG_MSG(("WordPerfect: parsing a line spacing change of: %f\n", m_lineSpacing));
	listener->lineSpacingChange(m_lineSpacing);
}

WP6ParagraphGroup_TabSetSubGroup::WP6ParagraphGroup_TabSetSubGroup(WPXInputStream *input) :
	m_isRelative(false),
	m_tabAdjustValue(0.0f)
{
	uint8_t tmp_definition = readU8(input);
	uint16_t tmp_tabAdjustValue = readU16(input);
	if (tmp_definition == 0)
	{
		m_isRelative = false;
		m_tabAdjustValue = 0.0f;
	}
	else
	{
		m_isRelative = true;
		m_tabAdjustValue = (float)((double)tmp_tabAdjustValue/(double)WPX_NUM_WPUS_PER_INCH);
	}
	uint8_t tmp_repetitionCount = 0;
	WPXTabStop tmp_tabStop;
	uint8_t tmp_numTabStops = readU8(input);
	bool tmp_usePreWP9LeaderMethod;
	uint8_t tmp_tabType;
	int i;
	for (i = 0; i < tmp_numTabStops; i++)
	{
		tmp_tabType = readU8(input);
		if ((tmp_tabType & 0x80) != 0)
		{
			tmp_repetitionCount = (tmp_tabType & 0x7F);
		}
		else
		{
			switch (tmp_tabType & 0x0F) //alignment bits
			{
			case 0x00:
				tmp_tabStop.m_alignment = LEFT;
				break;
			case 0x01:
				tmp_tabStop.m_alignment = CENTER;
				break;
			case 0x02:
				tmp_tabStop.m_alignment = RIGHT;
				break;
			case 0x03:
				tmp_tabStop.m_alignment = DECIMAL;
				break;
			case 0x04:
				tmp_tabStop.m_alignment = BAR;
				break;
			default: // should not happen, maybe corruption
				tmp_tabStop.m_alignment = LEFT;
				break;
			}
			tmp_tabStop.m_leaderNumSpaces = 0;
			if ((tmp_tabType & 0x10) == 0) // no leader character
			{
				tmp_tabStop.m_leaderCharacter = '\0';
				tmp_usePreWP9LeaderMethod = false;
			}
			else
			{
				switch ((tmp_tabType & 0x60) >> 5) // leader character type
				{
				case 0: // pre-WP9 leader method
					tmp_tabStop.m_leaderCharacter = '.';
					tmp_tabStop.m_leaderNumSpaces = 0;
					tmp_usePreWP9LeaderMethod = true;
					break;
				case 1: // dot leader
					tmp_tabStop.m_leaderCharacter = '.';
					tmp_tabStop.m_leaderNumSpaces = 0;
					tmp_usePreWP9LeaderMethod = false;
					break;
				case 2: // hyphen leader
					tmp_tabStop.m_leaderCharacter = '-';
					tmp_tabStop.m_leaderNumSpaces = 0;
					tmp_usePreWP9LeaderMethod = false;
					break;
				case 3: // underscore leader
					tmp_tabStop.m_leaderCharacter = '_';
					tmp_tabStop.m_leaderNumSpaces = 0;
					tmp_usePreWP9LeaderMethod = false;
					break;
				}
			}
		}
		uint16_t tmp_tabPosition = readU16(input);
		if (tmp_repetitionCount == 0)
		{
			if (tmp_tabPosition != 0xFFFF)
			{
				tmp_tabStop.m_position = (float)((double)tmp_tabPosition/(double)WPX_NUM_WPUS_PER_INCH) -
					m_tabAdjustValue;
				m_tabStops.push_back(tmp_tabStop);
				m_usePreWP9LeaderMethods.push_back(tmp_usePreWP9LeaderMethod);
			}
		}
		else
		{
			for (int k=0; k<tmp_repetitionCount; k++)
			{
				tmp_tabStop.m_position += (float)((double)tmp_tabPosition/(double)WPX_NUM_WPUS_PER_INCH);
				m_tabStops.push_back(tmp_tabStop);
				m_usePreWP9LeaderMethods.push_back(tmp_usePreWP9LeaderMethod);
			}
			tmp_repetitionCount = 0;
		}
	}
}

WP6ParagraphGroup_TabSetSubGroup::~WP6ParagraphGroup_TabSetSubGroup()
{
}

void WP6ParagraphGroup_TabSetSubGroup::parse(WP6Listener *listener, const uint8_t /* numPrefixIDs */,
						uint16_t const * /* prefixIDs */) const
{
#ifdef DEBUG
	WPD_DEBUG_MSG(("Parsing Tab Set (isRelative: %s, positions: ", (m_isRelative?"true":"false")));
	for(std::vector<WPXTabStop>::const_iterator i = m_tabStops.begin(); i != m_tabStops.end(); i++)
	{
		WPD_DEBUG_MSG((" %.4f", (*i).m_position));
	}
	WPD_DEBUG_MSG((")\n"));
#endif
	listener->defineTabStops(m_isRelative, m_tabStops, m_usePreWP9LeaderMethods);
}

WP6ParagraphGroup_IndentFirstLineSubGroup::WP6ParagraphGroup_IndentFirstLineSubGroup(WPXInputStream *input)
{
	m_firstLineOffset = (int16_t)readU16(input);
	WPD_DEBUG_MSG(("WordPerfect: indent first line: %i\n", m_firstLineOffset));
}

void WP6ParagraphGroup_IndentFirstLineSubGroup::parse(WP6Listener *listener, const uint8_t /* numPrefixIDs */,
							uint16_t const * /* prefixIDs */) const
{
	WPD_DEBUG_MSG(("WordPerfect: parsing first line indent change of: %i\n", m_firstLineOffset));
	listener->indentFirstLineChange(m_firstLineOffset);
}

WP6ParagraphGroup_LeftMarginAdjustmentSubGroup::WP6ParagraphGroup_LeftMarginAdjustmentSubGroup(WPXInputStream *input)
{
	m_leftMargin = (int16_t)readU16(input);
	WPD_DEBUG_MSG(("WordPerfect: left margin adjustment: %i\n", m_leftMargin));
}

void WP6ParagraphGroup_LeftMarginAdjustmentSubGroup::parse(WP6Listener *listener, const uint8_t /* numPrefixIDs */,
							uint16_t const * /* prefixIDs */) const
{
	WPD_DEBUG_MSG(("WordPerfect: parsing left margin adjustment change of: %i\n", m_leftMargin));
	listener->paragraphMarginChange(WPX_LEFT, m_leftMargin);
}

WP6ParagraphGroup_RightMarginAdjustmentSubGroup::WP6ParagraphGroup_RightMarginAdjustmentSubGroup(WPXInputStream *input)
{
	m_rightMargin = (int16_t)readU16(input);
	WPD_DEBUG_MSG(("WordPerfect: right margin adjustment: %i\n", m_rightMargin));
}

void WP6ParagraphGroup_RightMarginAdjustmentSubGroup::parse(WP6Listener *listener, const uint8_t /* numPrefixIDs */,
								uint16_t const */* prefixIDs */) const
{
	WPD_DEBUG_MSG(("WordPerfect: parsing right margin adjustment change of: %i\n", m_rightMargin));
	listener->paragraphMarginChange(WPX_RIGHT, m_rightMargin);
}

WP6ParagraphGroup_JustificationModeSubGroup::WP6ParagraphGroup_JustificationModeSubGroup(WPXInputStream *input)
{
	m_justification = readU8(input);
}

void WP6ParagraphGroup_JustificationModeSubGroup::parse(WP6Listener *listener, const uint8_t /* numPrefixIDs */,
								uint16_t const * /* prefixIDs */) const
{
	listener->justificationChange(m_justification);
}

WP6ParagraphGroup_SpacingAfterParagraphSubGroup::WP6ParagraphGroup_SpacingAfterParagraphSubGroup(WPXInputStream *input, const uint16_t sizeNonDeletable)
{
	m_sizeNonDeletable = sizeNonDeletable;
	m_spacingAfterParagraphAbsolute = 0.0f;
	m_spacingAfterParagraphRelative = 1.0f;
	uint32_t spacingAfterRelative = readU32(input);
	int16_t spacingAfterIntegerPart = (int16_t)((spacingAfterRelative & 0xFFFF0000) >> 16);
	float spacingAfterFractionalPart = (float)(spacingAfterRelative & 0xFFFF)/(float)0xFFFF;
	WPD_DEBUG_MSG(("WordPerfect: spacing after paragraph relative integer part: %i fractional part: %f (original value: %i)\n",
				spacingAfterIntegerPart, spacingAfterFractionalPart, spacingAfterRelative));
	m_spacingAfterParagraphRelative = spacingAfterIntegerPart + spacingAfterFractionalPart;
	if (m_sizeNonDeletable == (uint16_t)0x06) // Let us use the optional information that is in WPUs
	{
		uint16_t spacingAfterAbsolute = readU16(input);
		m_spacingAfterParagraphAbsolute = (float)((double)spacingAfterAbsolute / (double)WPX_NUM_WPUS_PER_INCH);
		WPD_DEBUG_MSG(("WordPerfect: spacing after paragraph absolute: %i\n", spacingAfterAbsolute));
	}
}

void WP6ParagraphGroup_SpacingAfterParagraphSubGroup::parse(WP6Listener *listener, const uint8_t /* numPrefixIDs */,
								uint16_t const * /* prefixIDs */) const
{
	WPD_DEBUG_MSG(("WordPerfect: parsing a change of spacing after paragraph: relative %f, absolute %f\n",
			m_spacingAfterParagraphRelative, m_spacingAfterParagraphAbsolute));
	listener->spacingAfterParagraphChange(m_spacingAfterParagraphRelative, m_spacingAfterParagraphAbsolute);
}

WP6ParagraphGroup_OutlineDefineSubGroup::WP6ParagraphGroup_OutlineDefineSubGroup(WPXInputStream *input)
{
	// NB: this is identical to WP6OutlineStylePacket::_readContents!!
	m_outlineHash = readU16(input);
	for (unsigned int i=0; i<WP6_NUM_LIST_LEVELS; i++)
		m_numberingMethods[i] = readU8(input);
	m_tabBehaviourFlag = readU8(input);

	WPD_DEBUG_MSG(("WordPerfect: Read Outline Style Packet (, outlineHash: %i, tab behaviour flag: %i)\n", (int) m_outlineHash, (int) m_tabBehaviourFlag));
	WPD_DEBUG_MSG(("WordPerfect: Read Outline Style Packet (m_numberingMethods: %i %i %i %i %i %i %i %i)\n",
		       m_numberingMethods[0], m_numberingMethods[1], m_numberingMethods[2], m_numberingMethods[3],
		       m_numberingMethods[4], m_numberingMethods[5], m_numberingMethods[6], m_numberingMethods[7]));
}

void WP6ParagraphGroup_OutlineDefineSubGroup::parse(WP6Listener *listener, const uint8_t /* numPrefixIDs */,
						uint16_t const * /* prefixIDs */) const
{
	listener->updateOutlineDefinition(paragraphGroup, m_outlineHash, m_numberingMethods, m_tabBehaviourFlag);
}
<commit_msg>question of personal preference<commit_after>/* libwpd
 * Copyright (C) 2002 William Lachance (wrlach@gmail.com)
 * Copyright (C) 2002 Marc Maurer (uwog@uwog.net)
 * Copyright (C) 2004 Fridrich Strba (fridrich.strba@bluewin.ch)
 *
 * 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 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 *
 * For further information visit http://libwpd.sourceforge.net
 */

/* "This product is not manufactured, approved, or supported by
 * Corel Corporation or Corel Corporation Limited."
 */

#include "WP6ParagraphGroup.h"
#include "libwpd_internal.h"
#include "WPXFileStructure.h"

WP6ParagraphGroup::WP6ParagraphGroup(WPXInputStream *input) :
	WP6VariableLengthGroup(),
	m_subGroupData(NULL)
{
	_read(input);
}

WP6ParagraphGroup::~WP6ParagraphGroup()
{
	if (m_subGroupData)
		delete(m_subGroupData);
}

void WP6ParagraphGroup::_readContents(WPXInputStream *input)
{
	switch (getSubGroup())
	{
	case WP6_PARAGRAPH_GROUP_LINE_SPACING:
		m_subGroupData = new WP6ParagraphGroup_LineSpacingSubGroup(input);
		break;
	case WP6_PARAGRAPH_GROUP_TAB_SET:
		m_subGroupData = new WP6ParagraphGroup_TabSetSubGroup(input);
		break;
	case WP6_PARAGRAPH_GROUP_JUSTIFICATION:
		m_subGroupData = new WP6ParagraphGroup_JustificationModeSubGroup(input);
		break;
	case WP6_PARAGRAPH_GROUP_SPACING_AFTER_PARAGRAPH:
		m_subGroupData = new WP6ParagraphGroup_SpacingAfterParagraphSubGroup(input, getSizeNonDeletable());
		break;
	case WP6_PARAGRAPH_GROUP_INDENT_FIRST_LINE_OF_PARAGRAPH:
		m_subGroupData = new WP6ParagraphGroup_IndentFirstLineSubGroup(input);
		break;
	case WP6_PARAGRAPH_GROUP_LEFT_MARGIN_ADJUSTMENT:
		m_subGroupData = new WP6ParagraphGroup_LeftMarginAdjustmentSubGroup(input);
		break;
	case WP6_PARAGRAPH_GROUP_RIGHT_MARGIN_ADJUSTMENT:
		m_subGroupData = new WP6ParagraphGroup_RightMarginAdjustmentSubGroup(input);
		break;
	case WP6_PARAGRAPH_GROUP_OUTLINE_DEFINE:
		m_subGroupData = new WP6ParagraphGroup_OutlineDefineSubGroup(input);
		break;
	}
}

void WP6ParagraphGroup::parse(WP6Listener *listener)
{
	WPD_DEBUG_MSG(("WordPerfect: handling a Paragraph group\n"));

	if (m_subGroupData)
		m_subGroupData->parse(listener, getNumPrefixIDs(), getPrefixIDs());
}

WP6ParagraphGroup_LineSpacingSubGroup::WP6ParagraphGroup_LineSpacingSubGroup(WPXInputStream *input)
{
	uint32_t lineSpacing = readU32(input);
	int16_t lineSpacingIntegerPart = (int16_t)((lineSpacing & 0xFFFF0000) >> 16);
	float lineSpacingFractionalPart = (float)(lineSpacing & 0xFFFF)/(float)0xFFFF;
	WPD_DEBUG_MSG(("WordPerfect: line spacing integer part: %i fractional part: %f (original value: %i)\n",
		       lineSpacingIntegerPart, lineSpacingFractionalPart, lineSpacing));
	m_lineSpacing = lineSpacingIntegerPart + lineSpacingFractionalPart;
}

void WP6ParagraphGroup_LineSpacingSubGroup::parse(WP6Listener *listener, const uint8_t /* numPrefixIDs */,
							const uint16_t * /* prefixIDs */) const
{
	WPD_DEBUG_MSG(("WordPerfect: parsing a line spacing change of: %f\n", m_lineSpacing));
	listener->lineSpacingChange(m_lineSpacing);
}

WP6ParagraphGroup_TabSetSubGroup::WP6ParagraphGroup_TabSetSubGroup(WPXInputStream *input) :
	m_isRelative(false),
	m_tabAdjustValue(0.0f)
{
	uint8_t tmp_definition = readU8(input);
	uint16_t tmp_tabAdjustValue = readU16(input);
	if (tmp_definition == 0)
	{
		m_isRelative = false;
		m_tabAdjustValue = 0.0f;
	}
	else
	{
		m_isRelative = true;
		m_tabAdjustValue = (float)((double)tmp_tabAdjustValue/(double)WPX_NUM_WPUS_PER_INCH);
	}
	uint8_t tmp_repetitionCount = 0;
	WPXTabStop tmp_tabStop;
	uint8_t tmp_numTabStops = readU8(input);
	bool tmp_usePreWP9LeaderMethod;
	uint8_t tmp_tabType;
	int i;
	for (i = 0; i < tmp_numTabStops; i++)
	{
		tmp_tabType = readU8(input);
		if ((tmp_tabType & 0x80) != 0)
		{
			tmp_repetitionCount = (tmp_tabType & 0x7F);
		}
		else
		{
			switch (tmp_tabType & 0x0F) //alignment bits
			{
			case 0x00:
				tmp_tabStop.m_alignment = LEFT;
				break;
			case 0x01:
				tmp_tabStop.m_alignment = CENTER;
				break;
			case 0x02:
				tmp_tabStop.m_alignment = RIGHT;
				break;
			case 0x03:
				tmp_tabStop.m_alignment = DECIMAL;
				break;
			case 0x04:
				tmp_tabStop.m_alignment = BAR;
				break;
			default: // should not happen, maybe corruption
				tmp_tabStop.m_alignment = LEFT;
				break;
			}
			tmp_tabStop.m_leaderNumSpaces = 0;
			if ((tmp_tabType & 0x10) == 0) // no leader character
			{
				tmp_tabStop.m_leaderCharacter = '\0';
				tmp_usePreWP9LeaderMethod = false;
			}
			else
			{
				switch ((tmp_tabType & 0x60) >> 5) // leader character type
				{
				case 0: // pre-WP9 leader method
					tmp_tabStop.m_leaderCharacter = '.';
					tmp_tabStop.m_leaderNumSpaces = 0;
					tmp_usePreWP9LeaderMethod = true;
					break;
				case 1: // dot leader
					tmp_tabStop.m_leaderCharacter = '.';
					tmp_tabStop.m_leaderNumSpaces = 0;
					tmp_usePreWP9LeaderMethod = false;
					break;
				case 2: // hyphen leader
					tmp_tabStop.m_leaderCharacter = '-';
					tmp_tabStop.m_leaderNumSpaces = 0;
					tmp_usePreWP9LeaderMethod = false;
					break;
				case 3: // underscore leader
					tmp_tabStop.m_leaderCharacter = '_';
					tmp_tabStop.m_leaderNumSpaces = 0;
					tmp_usePreWP9LeaderMethod = false;
					break;
				}
			}
		}
		uint16_t tmp_tabPosition = readU16(input);
		if (tmp_repetitionCount == 0)
		{
			if (tmp_tabPosition != 0xFFFF)
			{
				tmp_tabStop.m_position = (float)((double)tmp_tabPosition/(double)WPX_NUM_WPUS_PER_INCH) -
					m_tabAdjustValue;
				m_tabStops.push_back(tmp_tabStop);
				m_usePreWP9LeaderMethods.push_back(tmp_usePreWP9LeaderMethod);
			}
		}
		else
		{
			for (int k=0; k<tmp_repetitionCount; k++)
			{
				tmp_tabStop.m_position += (float)((double)tmp_tabPosition/(double)WPX_NUM_WPUS_PER_INCH);
				m_tabStops.push_back(tmp_tabStop);
				m_usePreWP9LeaderMethods.push_back(tmp_usePreWP9LeaderMethod);
			}
			tmp_repetitionCount = 0;
		}
	}
}

WP6ParagraphGroup_TabSetSubGroup::~WP6ParagraphGroup_TabSetSubGroup()
{
}

void WP6ParagraphGroup_TabSetSubGroup::parse(WP6Listener *listener, const uint8_t /* numPrefixIDs */,
						const uint16_t * /* prefixIDs */) const
{
#ifdef DEBUG
	WPD_DEBUG_MSG(("Parsing Tab Set (isRelative: %s, positions: ", (m_isRelative?"true":"false")));
	for(std::vector<WPXTabStop>::const_iterator i = m_tabStops.begin(); i != m_tabStops.end(); i++)
	{
		WPD_DEBUG_MSG((" %.4f", (*i).m_position));
	}
	WPD_DEBUG_MSG((")\n"));
#endif
	listener->defineTabStops(m_isRelative, m_tabStops, m_usePreWP9LeaderMethods);
}

WP6ParagraphGroup_IndentFirstLineSubGroup::WP6ParagraphGroup_IndentFirstLineSubGroup(WPXInputStream *input)
{
	m_firstLineOffset = (int16_t)readU16(input);
	WPD_DEBUG_MSG(("WordPerfect: indent first line: %i\n", m_firstLineOffset));
}

void WP6ParagraphGroup_IndentFirstLineSubGroup::parse(WP6Listener *listener, const uint8_t /* numPrefixIDs */,
							const uint16_t * /* prefixIDs */) const
{
	WPD_DEBUG_MSG(("WordPerfect: parsing first line indent change of: %i\n", m_firstLineOffset));
	listener->indentFirstLineChange(m_firstLineOffset);
}

WP6ParagraphGroup_LeftMarginAdjustmentSubGroup::WP6ParagraphGroup_LeftMarginAdjustmentSubGroup(WPXInputStream *input)
{
	m_leftMargin = (int16_t)readU16(input);
	WPD_DEBUG_MSG(("WordPerfect: left margin adjustment: %i\n", m_leftMargin));
}

void WP6ParagraphGroup_LeftMarginAdjustmentSubGroup::parse(WP6Listener *listener, const uint8_t /* numPrefixIDs */,
							const uint16_t * /* prefixIDs */) const
{
	WPD_DEBUG_MSG(("WordPerfect: parsing left margin adjustment change of: %i\n", m_leftMargin));
	listener->paragraphMarginChange(WPX_LEFT, m_leftMargin);
}

WP6ParagraphGroup_RightMarginAdjustmentSubGroup::WP6ParagraphGroup_RightMarginAdjustmentSubGroup(WPXInputStream *input)
{
	m_rightMargin = (int16_t)readU16(input);
	WPD_DEBUG_MSG(("WordPerfect: right margin adjustment: %i\n", m_rightMargin));
}

void WP6ParagraphGroup_RightMarginAdjustmentSubGroup::parse(WP6Listener *listener, const uint8_t /* numPrefixIDs */,
								const uint16_t * /* prefixIDs */) const
{
	WPD_DEBUG_MSG(("WordPerfect: parsing right margin adjustment change of: %i\n", m_rightMargin));
	listener->paragraphMarginChange(WPX_RIGHT, m_rightMargin);
}

WP6ParagraphGroup_JustificationModeSubGroup::WP6ParagraphGroup_JustificationModeSubGroup(WPXInputStream *input)
{
	m_justification = readU8(input);
}

void WP6ParagraphGroup_JustificationModeSubGroup::parse(WP6Listener *listener, const uint8_t /* numPrefixIDs */,
								const uint16_t * /* prefixIDs */) const
{
	listener->justificationChange(m_justification);
}

WP6ParagraphGroup_SpacingAfterParagraphSubGroup::WP6ParagraphGroup_SpacingAfterParagraphSubGroup(WPXInputStream *input, const uint16_t sizeNonDeletable)
{
	m_sizeNonDeletable = sizeNonDeletable;
	m_spacingAfterParagraphAbsolute = 0.0f;
	m_spacingAfterParagraphRelative = 1.0f;
	uint32_t spacingAfterRelative = readU32(input);
	int16_t spacingAfterIntegerPart = (int16_t)((spacingAfterRelative & 0xFFFF0000) >> 16);
	float spacingAfterFractionalPart = (float)(spacingAfterRelative & 0xFFFF)/(float)0xFFFF;
	WPD_DEBUG_MSG(("WordPerfect: spacing after paragraph relative integer part: %i fractional part: %f (original value: %i)\n",
				spacingAfterIntegerPart, spacingAfterFractionalPart, spacingAfterRelative));
	m_spacingAfterParagraphRelative = spacingAfterIntegerPart + spacingAfterFractionalPart;
	if (m_sizeNonDeletable == (uint16_t)0x06) // Let us use the optional information that is in WPUs
	{
		uint16_t spacingAfterAbsolute = readU16(input);
		m_spacingAfterParagraphAbsolute = (float)((double)spacingAfterAbsolute / (double)WPX_NUM_WPUS_PER_INCH);
		WPD_DEBUG_MSG(("WordPerfect: spacing after paragraph absolute: %i\n", spacingAfterAbsolute));
	}
}

void WP6ParagraphGroup_SpacingAfterParagraphSubGroup::parse(WP6Listener *listener, const uint8_t /* numPrefixIDs */,
								const uint16_t * /* prefixIDs */) const
{
	WPD_DEBUG_MSG(("WordPerfect: parsing a change of spacing after paragraph: relative %f, absolute %f\n",
			m_spacingAfterParagraphRelative, m_spacingAfterParagraphAbsolute));
	listener->spacingAfterParagraphChange(m_spacingAfterParagraphRelative, m_spacingAfterParagraphAbsolute);
}

WP6ParagraphGroup_OutlineDefineSubGroup::WP6ParagraphGroup_OutlineDefineSubGroup(WPXInputStream *input)
{
	// NB: this is identical to WP6OutlineStylePacket::_readContents!!
	m_outlineHash = readU16(input);
	for (unsigned int i=0; i<WP6_NUM_LIST_LEVELS; i++)
		m_numberingMethods[i] = readU8(input);
	m_tabBehaviourFlag = readU8(input);

	WPD_DEBUG_MSG(("WordPerfect: Read Outline Style Packet (, outlineHash: %i, tab behaviour flag: %i)\n", (int) m_outlineHash, (int) m_tabBehaviourFlag));
	WPD_DEBUG_MSG(("WordPerfect: Read Outline Style Packet (m_numberingMethods: %i %i %i %i %i %i %i %i)\n",
		       m_numberingMethods[0], m_numberingMethods[1], m_numberingMethods[2], m_numberingMethods[3],
		       m_numberingMethods[4], m_numberingMethods[5], m_numberingMethods[6], m_numberingMethods[7]));
}

void WP6ParagraphGroup_OutlineDefineSubGroup::parse(WP6Listener *listener, const uint8_t /* numPrefixIDs */,
						const uint16_t * /* prefixIDs */) const
{
	listener->updateOutlineDefinition(paragraphGroup, m_outlineHash, m_numberingMethods, m_tabBehaviourFlag);
}
<|endoftext|>


<commit_before>#include "CategoryClassifyMiningTask.h"
#include "CategoryClassifyTable.h"
#include <document-manager/DocumentManager.h>
#include <la-manager/KNlpWrapper.h>
#include <knlp/doc_naive_bayes.h>
#include <util/ustring/UString.h>
#include <glog/logging.h>
#include <boost/filesystem/path.hpp>

using namespace sf1r;
namespace bfs = boost::filesystem;

namespace
{
const std::string kOriginalCategoryPropName("OriginalCategory");
const std::string kSourcePropName("Source");
const std::string kClassifyCategoryValueBook("R>文娱>书籍杂志");

void getDocPropValue(
    const Document& doc,
    const std::string& propName,
    std::string& propValue)
{
    izenelib::util::UString ustr;
    doc.getProperty(propName, ustr);
    ustr.convertString(propValue, izenelib::util::UString::UTF_8);
}

}

CategoryClassifyMiningTask::CategoryClassifyMiningTask(
    DocumentManager& documentManager,
    CategoryClassifyTable& classifyTable,
    const std::string& targetCategoryPropName)
    : documentManager_(documentManager)
    , classifyTable_(classifyTable)
    , targetCategoryPropName_(targetCategoryPropName)
    , startDocId_(0)
{
}

bool CategoryClassifyMiningTask::buildDocument(docid_t docID, const Document& doc)
{
    std::string title;
    getDocPropValue(doc, classifyTable_.propName(), title);

    if (title.empty())
        return true;

    std::string classifyCategory;
    std::string targetCategory;
    bool isRule = true;

    if (ruleByTargetCategory_(doc, targetCategory, classifyCategory) ||
        ruleByOriginalCategory_(doc, classifyCategory) ||
        ruleBySource_(doc, targetCategory, classifyCategory) ||
        classifyByTitle_(title, classifyCategory, isRule))
    {
        classifyTable_.setCategory(docID, classifyCategory, isRule);
    }

    return true;
}

bool CategoryClassifyMiningTask::ruleByTargetCategory_(
    const Document& doc,
    std::string& targetCategory,
    std::string& classifyCategory)
{
    if (!targetCategoryPropName_.empty())
    {
        getDocPropValue(doc, targetCategoryPropName_, targetCategory);
        if (targetCategory.find("图书音像") != std::string::npos)
        {
            classifyCategory = kClassifyCategoryValueBook;
            return true;
        }
    }
    return false;
}

bool CategoryClassifyMiningTask::ruleByOriginalCategory_(
    const Document& doc,
    std::string& classifyCategory)
{
    std::string originalCategory;
    getDocPropValue(doc, kOriginalCategoryPropName, originalCategory);

    if (!originalCategory.empty())
    {
        KNlpWrapper* knlpWrapper = KNlpWrapper::get();
        classifyCategory = knlpWrapper->mapFromOriginalCategory(originalCategory);
    }

    return !classifyCategory.empty();
}

bool CategoryClassifyMiningTask::ruleBySource_(
    const Document& doc,
    const std::string& targetCategory,
    std::string& classifyCategory)
{
    if (!targetCategory.empty())
        return false;

    std::string source;
    getDocPropValue(doc, kSourcePropName, source);

    if (source == "文轩网官网")
    {
        classifyCategory = kClassifyCategoryValueBook;
        return true;
    }

    return false;
}

bool CategoryClassifyMiningTask::classifyByTitle_(
    const std::string& title,
    std::string& classifyCategory,
    bool& isRule)
{
    try
    {
        KNlpWrapper* knlpWrapper = KNlpWrapper::get();
        std::string cleanTitle = knlpWrapper->cleanGarbage(title);
        KNlpWrapper::string_t titleKStr(cleanTitle);

        KNlpWrapper::token_score_list_t tokenScores;
        knlpWrapper->fmmTokenize(titleKStr, tokenScores);

        KNlpWrapper::string_t classifyKStr = knlpWrapper->classifyToBestCategory(tokenScores);
        classifyCategory = classifyKStr.get_bytes("utf-8");
        isRule = false;
        return true;
    }
    catch(std::exception& ex)
    {
        LOG(ERROR) << "exception: " << ex.what()
                   << ", title: " << title;
        return false;
    }
}

bool CategoryClassifyMiningTask::preProcess()
{
    startDocId_ = classifyTable_.docIdNum();
    const docid_t endDocId = documentManager_.getMaxDocId();

    LOG(INFO) << "category classify mining task"
              << ", start docid: " << startDocId_
              << ", end docid: " << endDocId;

    if (startDocId_ > endDocId)
        return false;

    classifyTable_.resize(endDocId + 1);
    return true;
}

bool CategoryClassifyMiningTask::postProcess()
{
    if (!classifyTable_.flush())
    {
        LOG(ERROR) << "failed in CategoryClassifyTable::flush()";
        return false;
    }

    return true;
}
<commit_msg>In CategoryClassifyMiningTask get doc property value, change from UString to string.<commit_after>#include "CategoryClassifyMiningTask.h"
#include "CategoryClassifyTable.h"
#include <document-manager/DocumentManager.h>
#include <la-manager/KNlpWrapper.h>
#include <knlp/doc_naive_bayes.h>
#include <glog/logging.h>
#include <boost/filesystem/path.hpp>

using namespace sf1r;
namespace bfs = boost::filesystem;

namespace
{
const std::string kOriginalCategoryPropName("Category");
const std::string kSourcePropName("Source");
const std::string kClassifyCategoryValueBook("R>文娱>书籍杂志");

void getDocPropValue(
    const Document& doc,
    const std::string& propName,
    std::string& propValue)
{
    doc.getProperty(propName, propValue);
}

}

CategoryClassifyMiningTask::CategoryClassifyMiningTask(
    DocumentManager& documentManager,
    CategoryClassifyTable& classifyTable,
    const std::string& targetCategoryPropName)
    : documentManager_(documentManager)
    , classifyTable_(classifyTable)
    , targetCategoryPropName_(targetCategoryPropName)
    , startDocId_(0)
{
}

bool CategoryClassifyMiningTask::buildDocument(docid_t docID, const Document& doc)
{
    std::string title;
    getDocPropValue(doc, classifyTable_.propName(), title);

    if (title.empty())
        return true;

    std::string classifyCategory;
    std::string targetCategory;
    bool isRule = true;

    if (ruleByTargetCategory_(doc, targetCategory, classifyCategory) ||
        ruleByOriginalCategory_(doc, classifyCategory) ||
        ruleBySource_(doc, targetCategory, classifyCategory) ||
        classifyByTitle_(title, classifyCategory, isRule))
    {
        classifyTable_.setCategory(docID, classifyCategory, isRule);
    }

    return true;
}

bool CategoryClassifyMiningTask::ruleByTargetCategory_(
    const Document& doc,
    std::string& targetCategory,
    std::string& classifyCategory)
{
    if (!targetCategoryPropName_.empty())
    {
        getDocPropValue(doc, targetCategoryPropName_, targetCategory);
        if (targetCategory.find("图书音像") != std::string::npos)
        {
            classifyCategory = kClassifyCategoryValueBook;
            return true;
        }
    }
    return false;
}

bool CategoryClassifyMiningTask::ruleByOriginalCategory_(
    const Document& doc,
    std::string& classifyCategory)
{
    std::string originalCategory;
    getDocPropValue(doc, kOriginalCategoryPropName, originalCategory);

    if (!originalCategory.empty())
    {
        KNlpWrapper* knlpWrapper = KNlpWrapper::get();
        classifyCategory = knlpWrapper->mapFromOriginalCategory(originalCategory);
    }

    return !classifyCategory.empty();
}

bool CategoryClassifyMiningTask::ruleBySource_(
    const Document& doc,
    const std::string& targetCategory,
    std::string& classifyCategory)
{
    if (!targetCategory.empty())
        return false;

    std::string source;
    getDocPropValue(doc, kSourcePropName, source);

    if (source == "文轩网官网")
    {
        classifyCategory = kClassifyCategoryValueBook;
        return true;
    }

    return false;
}

bool CategoryClassifyMiningTask::classifyByTitle_(
    const std::string& title,
    std::string& classifyCategory,
    bool& isRule)
{
    try
    {
        KNlpWrapper* knlpWrapper = KNlpWrapper::get();
        std::string cleanTitle = knlpWrapper->cleanGarbage(title);
        KNlpWrapper::string_t titleKStr(cleanTitle);

        KNlpWrapper::token_score_list_t tokenScores;
        knlpWrapper->fmmTokenize(titleKStr, tokenScores);

        KNlpWrapper::string_t classifyKStr = knlpWrapper->classifyToBestCategory(tokenScores);
        classifyCategory = classifyKStr.get_bytes("utf-8");
        isRule = false;
        return true;
    }
    catch(std::exception& ex)
    {
        LOG(ERROR) << "exception: " << ex.what()
                   << ", title: " << title;
        return false;
    }
}

bool CategoryClassifyMiningTask::preProcess()
{
    startDocId_ = classifyTable_.docIdNum();
    const docid_t endDocId = documentManager_.getMaxDocId();

    LOG(INFO) << "category classify mining task"
              << ", start docid: " << startDocId_
              << ", end docid: " << endDocId;

    if (startDocId_ > endDocId)
        return false;

    classifyTable_.resize(endDocId + 1);
    return true;
}

bool CategoryClassifyMiningTask::postProcess()
{
    if (!classifyTable_.flush())
    {
        LOG(ERROR) << "failed in CategoryClassifyTable::flush()";
        return false;
    }

    return true;
}
<|endoftext|>


<commit_before>// __BEGIN_LICENSE__
// Copyright (C) 2006-2010 United States Government as represented by
// the Administrator of the National Aeronautics and Space Administration.
// All Rights Reserved.
// __END_LICENSE__

#include <vw/Plate/Rpc.h>
#include <vw/Plate/IndexService.h>
#include <vw/Core/Stopwatch.h>
#include <vw/Plate/HTTPUtils.h>
#include <vw/Core/Log.h>
#include <signal.h>
#include <boost/format.hpp>

#include <google/protobuf/descriptor.h>

#include <boost/program_options.hpp>
namespace po = boost::program_options;
using namespace vw::platefile;
using namespace vw;

// ------------------------------ SIGNAL HANDLER -------------------------------

volatile bool process_messages = true;
volatile bool force_sync = false;

void sig_unexpected_shutdown(int sig_num) {
  signal(sig_num, SIG_IGN);
  process_messages = false;
  signal(sig_num, sig_unexpected_shutdown);
}

void sig_sync(int sig_num) {
  signal(sig_num, SIG_IGN);
  force_sync = true;
  signal(sig_num, sig_sync);
}

struct Options {
  Url url;
  std::string root;
  float sync_interval;
  bool debug;
  bool help;
};

VW_DEFINE_EXCEPTION(Usage, Exception);

void process_args(Options& opt, int argc, char *argv[]) {
  po::options_description general_options("Runs a master index manager.\n\nGeneral Options:");
  general_options.add_options()
    ("url",             po::value(&opt.url),                               "Url to listen on")
    ("debug",           po::bool_switch(&opt.debug)->default_value(false), "Allow server to die.")
    ("help,h",          po::bool_switch(&opt.help)->default_value(false),  "Display this help message")
    ("sync-interval,s", po::value(&opt.sync_interval)->default_value(60.),
     "Specify the time interval (in minutes) for automatically synchronizing the index to disk.");

  po::options_description hidden_options("");
  hidden_options.add_options()
    ("root-directory", po::value(&opt.root));

  po::options_description options("Allowed Options");
  options.add(general_options).add(hidden_options);

  po::positional_options_description p;
  p.add("root-directory", -1);

  po::variables_map vm;
  po::store( po::command_line_parser( argc, argv ).options(options).positional(p).run(), vm );
  po::notify( vm );

  std::ostringstream usage;
  usage << "Usage: " << argv[0] << " --url <url> root_directory" << std::endl << std::endl;
  usage << general_options << std::endl;

  if(opt.help)
    vw_throw(Usage() << usage.str());

  if( vm.count("root-directory") != 1 ) {
    vw_throw(Usage() << usage.str()
                     << "\n\nError: must specify a root directory that contains plate files!");
  }

  if ( vm.count("url") != 1 ) {
    vw_throw(Usage() << usage.str()
                     << "\n\nMust specify a url to listen on");
  }
}

int main(int argc, char** argv) {
  Options opt;
  try {
    process_args(opt, argc, argv);
  } catch (const Usage& u) {
    std::cerr << u.what() << std::endl;
    ::exit(EXIT_FAILURE);
  }

  // Install Unix Signal Handlers.  These will help us to gracefully
  // recover and salvage the index under most unexpected error
  // conditions.
  signal(SIGINT,  sig_unexpected_shutdown);
  signal(SIGUSR1, sig_sync);

  // Start the server task in another thread
  RpcServer<IndexServiceImpl> server(opt.url, new IndexServiceImpl(opt.root));
  server.set_debug(opt.debug);

  vw_out(InfoMessage) << "Starting index server\n\n";
  uint64 sync_interval_us = uint64(opt.sync_interval * 60000000);
  uint64 t0 = Stopwatch::microtime(), t1;
  uint64 next_sync = t0 + sync_interval_us;

  size_t win = 0, lose = 0, draw = 0, total = 0;
  boost::format status("qps[%7.1f]   total[%9u]   server_err[%9u]   client_err[%9u]\r");

  while(process_messages) {
    bool should_sync = force_sync || (Stopwatch::microtime() >= next_sync);

    if (should_sync) {
      vw_out(InfoMessage) << "\nStarting sync to disk. (" << (force_sync ? "auto" : "manual") << ")\n";
      uint64 s0 = Stopwatch::microtime();
      server.impl()->sync();
      uint64 s1 = Stopwatch::microtime();
      next_sync = s1 + sync_interval_us;
      vw_out(InfoMessage) << "Sync complete (took " << float(s1-s0) / 1e6  << " seconds).\n";
      force_sync = false;
    }

    t1 = Stopwatch::microtime();

    size_t win_dt, lose_dt, draw_dt, total_dt;
    {
      ThreadMap::Locked stats = server.stats();
      win_dt = stats.get("msgs");
      lose_dt  = stats.get("server_error");
      draw_dt  = stats.get("client_error");
      stats.clear();
    }
    total_dt = win_dt + lose_dt + draw_dt;
    win   += win_dt;
    lose  += lose_dt;
    draw  += draw_dt;
    total += total_dt;

    float dt = float(t1 - t0) / 1e6f;
    t0 = t1;

    vw_out(InfoMessage)
      << status % (float(total_dt)/dt) % total % lose % draw
      << std::flush;

    Thread::sleep_ms(500);
  }

  vw_out(InfoMessage) << "\nShutting down the index service safely.\n";
  server.stop();
  server.impl()->sync();

  return 0;
}

<commit_msg>fix sync message logic (it was inverted)<commit_after>// __BEGIN_LICENSE__
// Copyright (C) 2006-2010 United States Government as represented by
// the Administrator of the National Aeronautics and Space Administration.
// All Rights Reserved.
// __END_LICENSE__

#include <vw/Plate/Rpc.h>
#include <vw/Plate/IndexService.h>
#include <vw/Core/Stopwatch.h>
#include <vw/Plate/HTTPUtils.h>
#include <vw/Core/Log.h>
#include <signal.h>
#include <boost/format.hpp>

#include <google/protobuf/descriptor.h>

#include <boost/program_options.hpp>
namespace po = boost::program_options;
using namespace vw::platefile;
using namespace vw;

// ------------------------------ SIGNAL HANDLER -------------------------------

volatile bool process_messages = true;
volatile bool force_sync = false;

void sig_unexpected_shutdown(int sig_num) {
  signal(sig_num, SIG_IGN);
  process_messages = false;
  signal(sig_num, sig_unexpected_shutdown);
}

void sig_sync(int sig_num) {
  signal(sig_num, SIG_IGN);
  force_sync = true;
  signal(sig_num, sig_sync);
}

struct Options {
  Url url;
  std::string root;
  float sync_interval;
  bool debug;
  bool help;
};

VW_DEFINE_EXCEPTION(Usage, Exception);

void process_args(Options& opt, int argc, char *argv[]) {
  po::options_description general_options("Runs a master index manager.\n\nGeneral Options:");
  general_options.add_options()
    ("url",             po::value(&opt.url),                               "Url to listen on")
    ("debug",           po::bool_switch(&opt.debug)->default_value(false), "Allow server to die.")
    ("help,h",          po::bool_switch(&opt.help)->default_value(false),  "Display this help message")
    ("sync-interval,s", po::value(&opt.sync_interval)->default_value(60.),
     "Specify the time interval (in minutes) for automatically synchronizing the index to disk.");

  po::options_description hidden_options("");
  hidden_options.add_options()
    ("root-directory", po::value(&opt.root));

  po::options_description options("Allowed Options");
  options.add(general_options).add(hidden_options);

  po::positional_options_description p;
  p.add("root-directory", -1);

  po::variables_map vm;
  po::store( po::command_line_parser( argc, argv ).options(options).positional(p).run(), vm );
  po::notify( vm );

  std::ostringstream usage;
  usage << "Usage: " << argv[0] << " --url <url> root_directory" << std::endl << std::endl;
  usage << general_options << std::endl;

  if(opt.help)
    vw_throw(Usage() << usage.str());

  if( vm.count("root-directory") != 1 ) {
    vw_throw(Usage() << usage.str()
                     << "\n\nError: must specify a root directory that contains plate files!");
  }

  if ( vm.count("url") != 1 ) {
    vw_throw(Usage() << usage.str()
                     << "\n\nMust specify a url to listen on");
  }
}

int main(int argc, char** argv) {
  Options opt;
  try {
    process_args(opt, argc, argv);
  } catch (const Usage& u) {
    std::cerr << u.what() << std::endl;
    ::exit(EXIT_FAILURE);
  }

  // Install Unix Signal Handlers.  These will help us to gracefully
  // recover and salvage the index under most unexpected error
  // conditions.
  signal(SIGINT,  sig_unexpected_shutdown);
  signal(SIGUSR1, sig_sync);

  // Start the server task in another thread
  RpcServer<IndexServiceImpl> server(opt.url, new IndexServiceImpl(opt.root));
  server.set_debug(opt.debug);

  vw_out(InfoMessage) << "Starting index server\n\n";
  uint64 sync_interval_us = uint64(opt.sync_interval * 60000000);
  uint64 t0 = Stopwatch::microtime(), t1;
  uint64 next_sync = t0 + sync_interval_us;

  size_t win = 0, lose = 0, draw = 0, total = 0;
  boost::format status("qps[%7.1f]   total[%9u]   server_err[%9u]   client_err[%9u]\r");

  while(process_messages) {
    bool should_sync = force_sync || (Stopwatch::microtime() >= next_sync);

    if (should_sync) {
      vw_out(InfoMessage) << "\nStarting sync to disk. (" << (force_sync ? "manual" : "auto") << ")\n";
      uint64 s0 = Stopwatch::microtime();
      server.impl()->sync();
      uint64 s1 = Stopwatch::microtime();
      next_sync = s1 + sync_interval_us;
      vw_out(InfoMessage) << "Sync complete (took " << float(s1-s0) / 1e6  << " seconds).\n";
      force_sync = false;
    }

    t1 = Stopwatch::microtime();

    size_t win_dt, lose_dt, draw_dt, total_dt;
    {
      ThreadMap::Locked stats = server.stats();
      win_dt = stats.get("msgs");
      lose_dt  = stats.get("server_error");
      draw_dt  = stats.get("client_error");
      stats.clear();
    }
    total_dt = win_dt + lose_dt + draw_dt;
    win   += win_dt;
    lose  += lose_dt;
    draw  += draw_dt;
    total += total_dt;

    float dt = float(t1 - t0) / 1e6f;
    t0 = t1;

    vw_out(InfoMessage)
      << status % (float(total_dt)/dt) % total % lose % draw
      << std::flush;

    Thread::sleep_ms(500);
  }

  vw_out(InfoMessage) << "\nShutting down the index service safely.\n";
  server.stop();
  server.impl()->sync();

  return 0;
}

<|endoftext|>


<commit_before>/**
 * Clever programming language
 * Copyright (c) 2011-2012 Clever Team
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

#include <utility>
#include "types/type.h"
#include "types/map.h"
#include "compiler/compiler.h"

namespace clever {

/**
 * Void Map::__assign__(Map)
 */
CLEVER_METHOD(Map::do_assign) {
	CLEVER_THIS()->copy(CLEVER_ARG(0));
}

/**
 * Int Map<K, V [,C]>::size()
 */
CLEVER_METHOD(Map::size) {
	MapValue* map = CLEVER_GET_VALUE(MapValue*, value);
	CLEVER_RETURN_INT(map->m_map.size());
}

/**
 * Bool Map<K, V [,C]>::isEmpty()
 */
CLEVER_METHOD(Map::isEmpty) {
	MapValue* map = CLEVER_GET_VALUE(MapValue*, value);
	CLEVER_RETURN_BOOL(map->m_map.empty());
}

/**
 * Void Map<K, V [,C]>::insert(K, V)
 */
CLEVER_METHOD(Map::insert) {
	MapValue* map = CLEVER_GET_VALUE(MapValue*, value);
	map->m_map.insert(std::make_pair(CLEVER_ARG(0), CLEVER_ARG(1)));

	CLEVER_ARG(0)->addRef();
	CLEVER_ARG(1)->addRef();
}

/**
 * Void Map<K, V [,C]>::clear()
 */
CLEVER_METHOD(Map::clear) {
	MapValue* map = CLEVER_GET_VALUE(MapValue*, value);
	MapValue::iterator it = map->m_map.begin(),
		end = map->m_map.end();

	while (it != end) {
		it->first->delRef();
		it->second->delRef();
		++it;
	}

	map->m_map.clear();
}

/**
 * String Map<K, V [,C]>::toString()
 */
CLEVER_METHOD(Map::toString) {
	MapValue* map = CLEVER_GET_VALUE(MapValue*, value);
	MapValue::iterator it = map->m_map.begin(),
		end = map->m_map.end();

	std::string ret = "[", sep = ", ";

	if (it != end) {
		ret += it->first->toString() + " => "
			+ it->second->toString();

		while (++it != end) {
			ret += sep + it->first->toString() + " => "
				+ it->second->toString();
		}
	}

	ret += "]";

	CLEVER_RETURN_STR(CSTRING(ret));
}

/**
 * Bool Map<K, V [, C]>::hasKey(K)
 */
CLEVER_METHOD(Map::hasKey) {
	MapValue* map = CLEVER_GET_VALUE(MapValue*, value);
	MapValue::iterator it = map->m_map.begin(),
		end = map->m_map.end();

	bool ret = false;

	if (it != end) {
		if (it->first->toString() == CLEVER_ARG(0)->toString()) {
			ret = true;
		}

		while (++it != end && !ret) {
			if (it->first->toString() == CLEVER_ARG(0)->toString()) {
				ret = true;
			}
		}
	}

	CLEVER_RETURN_BOOL(ret);
}

/**
 * Map type initializator
 */
void Map::init() {
	/**
	 * Check if we are in our "virtual" Map type
	 */
	if (CLEVER_TPL_ARG(0) == NULL) {
		return;
	}

	addMethod((new Method("insert", (MethodPtr)&Map::insert, CLEVER_VOID, false))
		->addArg("key", CLEVER_TPL_ARG(0))
		->addArg("value", CLEVER_TPL_ARG(1))
	);

	addMethod(new Method("toString", (MethodPtr)&Map::toString, CLEVER_STR));

	addMethod(new Method("size", (MethodPtr)&Map::size, CLEVER_INT));

	addMethod(new Method("isEmpty", (MethodPtr)&Map::isEmpty, CLEVER_BOOL));

	addMethod(new Method("clear", (MethodPtr)&Map::clear, CLEVER_VOID));

	addMethod((new Method("hasKey", (MethodPtr)&Map::hasKey, CLEVER_BOOL))
		->addArg("key", CLEVER_TPL_ARG(0))
	);
}

DataValue* Map::allocateValue() const {
	if (this->getNumArgs() == 2) {
		TypeVector tv(2, getTypeArg(0));
		return new MapValue(getTypeArg(0)
			->getMethod(CSTRING(CLEVER_OPERATOR_LESS), &tv));
	}

	TypeVector tv(2, getTypeArg(0));
	return new MapValue(getTypeArg(2)
		->getMethod(CSTRING("compare"), &tv), new Value(getTypeArg(2)));
}

} // clever
<commit_msg>Making Map<>::hasKey() to be O(log n)<commit_after>/**
 * Clever programming language
 * Copyright (c) 2011-2012 Clever Team
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

#include <utility>
#include "types/type.h"
#include "types/map.h"
#include "compiler/compiler.h"

namespace clever {

/**
 * Void Map::__assign__(Map)
 */
CLEVER_METHOD(Map::do_assign) {
	CLEVER_THIS()->copy(CLEVER_ARG(0));
}

/**
 * Int Map<K, V [,C]>::size()
 */
CLEVER_METHOD(Map::size) {
	MapValue* map = CLEVER_GET_VALUE(MapValue*, value);
	CLEVER_RETURN_INT(map->m_map.size());
}

/**
 * Bool Map<K, V [,C]>::isEmpty()
 */
CLEVER_METHOD(Map::isEmpty) {
	MapValue* map = CLEVER_GET_VALUE(MapValue*, value);
	CLEVER_RETURN_BOOL(map->m_map.empty());
}

/**
 * Void Map<K, V [,C]>::insert(K, V)
 */
CLEVER_METHOD(Map::insert) {
	MapValue* map = CLEVER_GET_VALUE(MapValue*, value);
	map->m_map.insert(std::make_pair(CLEVER_ARG(0), CLEVER_ARG(1)));

	CLEVER_ARG(0)->addRef();
	CLEVER_ARG(1)->addRef();
}

/**
 * Void Map<K, V [,C]>::clear()
 */
CLEVER_METHOD(Map::clear) {
	MapValue* map = CLEVER_GET_VALUE(MapValue*, value);
	MapValue::iterator it = map->m_map.begin(),
		end = map->m_map.end();

	while (it != end) {
		it->first->delRef();
		it->second->delRef();
		++it;
	}

	map->m_map.clear();
}

/**
 * String Map<K, V [,C]>::toString()
 */
CLEVER_METHOD(Map::toString) {
	MapValue* map = CLEVER_GET_VALUE(MapValue*, value);
	MapValue::iterator it = map->m_map.begin(),
		end = map->m_map.end();

	std::string ret = "[", sep = ", ";

	if (it != end) {
		ret += it->first->toString() + " => "
			+ it->second->toString();

		while (++it != end) {
			ret += sep + it->first->toString() + " => "
				+ it->second->toString();
		}
	}

	ret += "]";

	CLEVER_RETURN_STR(CSTRING(ret));
}

/**
 * Bool Map<K, V [, C]>::hasKey(K)
 */
CLEVER_METHOD(Map::hasKey) {
	MapValue::ValueType& map = CLEVER_GET_VALUE(MapValue*, value)->getMap();
	Value* search = CLEVER_ARG(0);

	MapValue::Iterator it = map.find(search);

	CLEVER_RETURN_BOOL(it != map.end());
}

/**
 * Map type initializator
 */
void Map::init() {
	/**
	 * Check if we are in our "virtual" Map type
	 */
	if (CLEVER_TPL_ARG(0) == NULL) {
		return;
	}

	addMethod((new Method("insert", (MethodPtr)&Map::insert, CLEVER_VOID, false))
		->addArg("key", CLEVER_TPL_ARG(0))
		->addArg("value", CLEVER_TPL_ARG(1))
	);

	addMethod(new Method("toString", (MethodPtr)&Map::toString, CLEVER_STR));

	addMethod(new Method("size", (MethodPtr)&Map::size, CLEVER_INT));

	addMethod(new Method("isEmpty", (MethodPtr)&Map::isEmpty, CLEVER_BOOL));

	addMethod(new Method("clear", (MethodPtr)&Map::clear, CLEVER_VOID));

	addMethod((new Method("hasKey", (MethodPtr)&Map::hasKey, CLEVER_BOOL))
		->addArg("key", CLEVER_TPL_ARG(0))
	);
}

DataValue* Map::allocateValue() const {
	if (this->getNumArgs() == 2) {
		TypeVector tv(2, getTypeArg(0));
		return new MapValue(getTypeArg(0)
			->getMethod(CSTRING(CLEVER_OPERATOR_LESS), &tv));
	}

	TypeVector tv(2, getTypeArg(0));
	return new MapValue(getTypeArg(2)
		->getMethod(CSTRING("compare"), &tv), new Value(getTypeArg(2)));
}

} // clever
<|endoftext|>


<commit_before>#include <GL/glew.h>
#include <GLFW/glfw3.h>

const auto WINDOW_WIDTH  = 800;
const auto WINDOW_HEIGHT = 600;
const auto WINDOW_TITLE  = "GL Cook Book - Window Creation";

int main(int argc, char const *argv[])
{
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);

    auto window = glfwCreateWindow(
        WINDOW_WIDTH,
        WINDOW_HEIGHT,
        WINDOW_TITLE,
        nullptr,
        nullptr);

    glfwMakeContextCurrent(window);

    // Give access to modern GL functions
    glewExperimental = GL_TRUE;
    glewInit();

    // Sync the rendering window with GLFW window
    glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);

    while (! glfwWindowShouldClose(window))
    {
        glfwPollEvents();

        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        glfwSwapBuffers(window);
    }

    glfwTerminate();
    return 0;
}<commit_msg>Pressing esc key exits GLFW window in window_creation.<commit_after>#include <GL/glew.h>
#include <GLFW/glfw3.h>

const auto WINDOW_WIDTH  = 800;
const auto WINDOW_HEIGHT = 600;
const auto WINDOW_TITLE  = "GL Cook Book - Window Creation";

void onKeyChange(GLFWwindow* window, int key, int scancode, int action, int mode);

int main(int argc, char const *argv[])
{
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);

    auto window = glfwCreateWindow(
        WINDOW_WIDTH,
        WINDOW_HEIGHT,
        WINDOW_TITLE,
        nullptr,
        nullptr);

    glfwMakeContextCurrent(window);
    glfwSetKeyCallback(window, onKeyChange);

    // Give access to modern GL functions
    glewExperimental = GL_TRUE;
    glewInit();

    // Sync the rendering window with GLFW window
    glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);

    while (! glfwWindowShouldClose(window))
    {
        glfwPollEvents();

        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        glfwSwapBuffers(window);
    }

    glfwTerminate();
    return 0;
}

void onKeyChange(GLFWwindow* window, int key, int scancode, int action, int mode)
{
    if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
        glfwSetWindowShouldClose(window, GL_TRUE);
    }
}<|endoftext|>


<commit_before>/*
 * WebSocket.cpp - Websocket Implementation - works on most browsers and Mobile Phones (but notably Not on IE8)
 *
 * Created: 3/30/2014 9:57:39 PM
 *
 *   Aritech Alarm Panel Arduino Internet Enabled Keypad -  CS350 - CD34 - CD72 - CD91 and more
 *
 *   For Arduino (UNO or Leonardo) with added Ethernet Shield
 *
 *   See Circuit Diagram for wiring instructions
 *
 *   Author: Ozmo
 *
 *   See: http://www.boards.ie/vbulletin/showthread.php?p=88215184
 *
*/

#include "sha1.h"
#include "Base64.h"
#include "RKP.h"	//for nKeyToSend
#include "LOG.h"
#include "websocket.h"

#ifdef AtmelStudio
  //Other modules
  #include <SPI.cpp>
  #include <Ethernet.cpp>
  #include <EthernetClient.cpp>
  #include <EthernetServer.cpp>
  #include <utility\socket.cpp>
  #include <utility\w5100.cpp>
#else
  #include <SPI.h>
  #include <Ethernet.h>
  #include <EthernetClient.h>
  #include <EthernetServer.h>
  #include <util.h>
#endif

//Workaround if needed for http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34734
#ifdef PROGMEM
#undef PROGMEM
#define PROGMEM __attribute__((section(".progmem.data")))
#endif

//--Sockets
//use this as password - pick random port - set code tamper on alarm also.
EthernetServer ethServer(IP_P);
//EthernetServer ethServerHTML(80);
EthernetClient ethClient;

//"*" will be replaced with button
char htmlSite[] PROGMEM=
"<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN'>"
"<title>Castle</title>"
"<meta name='viewport' content='width=320, initial-scale=1.2, user-scalable=no'>"
""
""
""
"

"
"
"
"
<button>1</button>	<button>2</button>	<button>3</button>	<button class=long>Y</button>
"
"
<button>4</button>	<button>5</button>	<button>6</button>
"
"
<button>7</button>	<button>8</button>	<button>9</button>	<button class=long>N</button>
"
"
<button>*</button>	<button>0</button>	<button>#</button>
"
"
"
"";

void WebSocket::EtherPoll()
{
	// Should be called for each loop.
	EthernetClient cli;
	if (cli = ethServer.available())
	{
		RKPClass::loop_PanelMon(); //most important we poll this or RKP will loose data
		//LogLn(F("browser req"));
		if (cli == true)
		{
			if (ethClient != cli)
			{//New connection
				//Secrisk
				ethClient = cli;
				WebSocket_doHandshake();
			}
			else
			{//Existing connection
				if (WebSocket_getFrame() == false)
				{//Request to end comms (rarely happens)
					RKPClass::loop_PanelMon(); //most important we poll this or RKP will loose data

					//Got bad frame, disconnect
					Log(F("Disconnect{"));
					while(ethClient.available()>0)
						ethClient.read();

					ethClient.flush();
					ethClient.stop();
				}
			}
		}
	}

/*	if (cli = ethServerHTML.available())
	{
		//Log(cli.available());
		if (cli == true)
			SendHTMLSite();
	}
*/
}

void WebSocket::SendHTMLSite(/*EthernetClient& cli*/)
{
	//Log(F("ConnectWWW{"));
	//	while(ethClient.available()>0)
	//	Log((char)cli.read());
	//LogLn(F("}"));
	ethClient.println(F("HTTP/1.0 200 OK"));	//
	ethClient.println(F("Content-Type: text/html"));
	ethClient.println(F("Connnection: close"));
	ethClient.println();
	char* p = &htmlSite[0];
	for(int n=0;n<2000;n++)
	{
		char c = pgm_read_byte(p++);
		if (c==0) break;
		//Can use tokens to compress the HTML a bit
		//if (c=='*')
		//	ethClient.print(F("button"));
		//else
		ethClient.print(c);
		if (n%100==0)
			RKPClass::loop_PanelMon(); //most important we poll this when doing other stuff or RKP will loose data
	}
	RKPClass::loop_PanelMon(); //most important we poll this or RKP will loose data

	// close the connection so browser gets data
	ethClient.flush();
	//delay(1);
	ethClient.stop();
	LogLn("Sent Page");
}

// Create a Websocket server
void WebSocket::WebSocket_EtherInit( IPAddress ip, IPAddress gateway )
{
	//IPAddress ip( 192, 168, 1 , 205);			//Give the device a unique IP
	//IPAddress gateway( 192, 168, 1, 1 );	//Gateway (the Router)

	IPAddress subnet( 255, 255, 255, 0 );	//typically dont need change
	// this sequence must be unique on your lan
	byte mac[] = { 0x90, 0xA2, 0xDA, 0x00, 0x59, 0x67 };	//typically dont need change

	//Start Ethernet
	Ethernet.begin(mac, ip, gateway, gateway, subnet);

	ethServer.begin();
	//ethServerHTML.begin();
	Log(F("server is at ")); LogLn(Ethernet.localIP());

	delay(150); // Settle time
}

//Send something to connected browser
bool WebSocket::WebSocket_send(char* data, byte length)
{
	if (!ethClient.connected())
	{
		LogLn(F("No Client."));
		return false;
	}
	//int length = strlen(data);
	ethClient.write(0x81);// string type

	if (length > 125) {
		ethClient.write(126);
		ethClient.write((uint8_t) (length >> 8));
		ethClient.write((uint8_t) (length && 0xFF));
	}
	else
		ethClient.write((uint8_t) length);

	for (int i=0; i<length; ++i)
		ethClient.write(data[i]);

	//LogLn(F("Sent OK."));
	return true;
}

void WebSocket::WebSocket_doHandshake()
{
	LogLn("HS");
	char htmlline[128];	//TODO: there are 3 buffers used - htmlline, key and sha - maybe could merge them
	char key[80];

	bool hasKey = false;
	bool bReqWebPage = false;

	byte counter = 0;

	while(ethClient.available()>0)
	{//Read each line
		byte bite = ethClient.read();
		//Log(bite);
		htmlline[counter++] = bite;
		if (counter > 127)
		{
			LogLn(F("HandShake Overflow{"));
			while(ethClient.available()>0)
				LogHex(ethClient.read());
			LogLn(F("}"));
			//htmlline[127] = 0;
			//LogHex(htmlline);
			counter=0;
			continue;
		}

		if (bite == '\n')
		{ // Parse the line
			htmlline[counter - 2] = 0; // Terminate string before CRLF

			bool bFound = (strstr_P(htmlline, PSTR("Sec-WebSocket-Key:")) != NULL);
			if (bFound)
			{
				hasKey = true;
				strtok(htmlline, " ");
				strcpy(key, strtok(NULL, " "));	//TODO: Not safe - need specify max 80 limit
			}

			if (strstr_P(htmlline, PSTR("GET / HTTP")) != NULL)
			{
				LogLn(F("Page Req"));
				bReqWebPage=true;
			}

			counter = 0; // Start saving new header string

			//Each Line - check if there is any comms to do
			RKPClass::loop_PanelMon(); //most important we poll this or RKP will loose data
		}
	}

	//Log("Got header: ");LogHex((byte*)htmlline,counter);

	if (hasKey)
	{
		LogLn(F("WS Req"));
		strcat_P(key, PSTR("258EAFA5-E914-47DA-95CA-C5AB0DC85B11")); // Magic Number GUID
		Sha1.init();
		Sha1.print(key);
		uint8_t* hash = Sha1.result();
		base64_encode(htmlline, (char*)hash, 20); //reuse htmlline buffer
		ethClient.print(F("HTTP/1.1 101 Switching Protocols\r\n"));
		ethClient.print(F("Upgrade: websocket\r\n"));
		ethClient.print(F("Connection: Upgrade\r\n"));
		ethClient.print(F("Sec-WebSocket-Accept: "));
		ethClient.print(htmlline);  //eg. VoNhf1LMVVTziHWxjiajVem5DB4=
		ethClient.print(F("\r\n\r\n"));

		LogLn(F("Connected"));

		//Send any display we might have
		RKPClass::bScreenHasUpdated = true; //RKPClass::SendDisplayToBrowser();
	}
	else if (bReqWebPage)
	{// Nope, Not a websocket request - send the main webpage
		//LogLn(F("WebPageReq"));
		SendHTMLSite();
	}
	else
	{
		ethClient.println(F("HTTP/1.0 404 File Not Found"));	//
		ethClient.println(F("Content-Type: text/html"));
		ethClient.println(F("Connnection: close"));
		ethClient.println();
		//delay(1);
		ethClient.stop();
	}
	return;
}

struct Frame {
	bool isMasked;
	bool isFinal;
	byte opcode;
	byte mask[4];
	byte length;
	char data[64+1];
} frame;

byte WebSocket::ReadNext()
{
	byte bite = ethClient.read();
	//LogHex(bite);
	return bite;
}

bool WebSocket::WebSocket_getFrame()
{
	// Get opcode
	byte bite = ReadNext(); if (bite==0xFF) return false;

	frame.opcode = bite & 0xf; // Opcode
	frame.isFinal = bite & 0x80; // Final frame?
	// Determine length (only accept <= 64 for now)
	bite = ReadNext(); if (bite==0xFF) return false;

	frame.length = bite & 0x7f; // Length of payload
	if (frame.length >= 64)
	{//Unlikely to happen
		Log(F("Frame Too Big")); LogLn(bite);
		return false;
	}
	// Client should always send mask, but check just to be sure
	frame.isMasked = bite & 0x80;
	if (frame.isMasked) {
		frame.mask[0] = ReadNext();
		frame.mask[1] = ReadNext();
		frame.mask[2] = ReadNext();
		frame.mask[3] = ReadNext();
	}

	// Get message bytes and unmask them if necessary
	int i = 0;
	for (; i < frame.length; i++)
	{
		bite = ReadNext();
		if (frame.isMasked)
			frame.data[i] = bite ^ frame.mask[i % 4];
		else
			frame.data[i] = bite;
	}
	frame.data[i]=0;

	// Frame complete!
	if (!frame.isFinal)
	{	// We don't handle fragments! Close and disconnect.
		LogLn(F("Unsurp"));
		return false; //RejectBroswerMsg();
	}

	if (frame.opcode== 0x01)
	{// Txt frame
		Log(F("Data: ")); //Got Data
		LogLn(frame.data);
		RKPClass::PushKey(atoi(frame.data));
		return true;
	}

	if (frame.opcode== 0x08)
	{
		// Close frame. Answer with close and terminate tcp connection
		LogLn(F("Close")); //Close frame
		ethClient.write((uint8_t) 0x08);
		return false;
	}

	// Unexpected. Ignore?
	LogLn(F("Ex.")); //Unhandled frame ignored
	return false;
}

<commit_msg>Update WebSocket.cpp<commit_after>/*
 * WebSocket.cpp - Websocket Implementation - works on most browsers and Mobile Phones (but notably Not on IE8)
 *
 * Created: 3/30/2014 9:57:39 PM
 *
 *   Aritech Alarm Panel Arduino Internet Enabled Keypad -  CS350 - CD34 - CD72 - CD91 and more
 *
 *   For Arduino (UNO or Leonardo) with added Ethernet Shield
 *
 *   See Circuit Diagram for wiring instructions
 *
 *   Author: Ozmo
 *
 *   See: http://www.boards.ie/vbulletin/showthread.php?p=88215184
 *
*/

#include "sha1.h"
#include "Base64.h"
#include "RKP.h"	//for nKeyToSend
#include "LOG.h"
#include "websocket.h"

#ifdef AtmelStudio
  //Other modules
  #include <SPI.cpp>
  #include <Ethernet.cpp>
  #include <EthernetClient.cpp>
  #include <EthernetServer.cpp>
  #include <utility\socket.cpp>
  #include <utility\w5100.cpp>
#else
  #include <SPI.h>
  #include <Ethernet.h>
  #include <EthernetClient.h>
  #include <EthernetServer.h>
  #include <util.h>
#endif

//Workaround if needed for http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34734
#ifdef PROGMEM
#undef PROGMEM
#define PROGMEM __attribute__((section(".progmem.data")))
#endif

//--Sockets
//use this as password - pick random port - set code tamper on alarm also.
EthernetServer ethServer(IP_P);
//EthernetServer ethServerHTML(80);
EthernetClient ethClient;

//"*" will be replaced with button
char htmlSite[] PROGMEM=
"<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN'>"
"<title>Castle</title>"
"<meta name='viewport' content='width=320, initial-scale=1.2, user-scalable=no'>"
""
""
""
"

"
"
"
"
<button>1</button>	<button>2</button>	<button>3</button>	<button class=long>Y</button>
"
"
<button>4</button>	<button>5</button>	<button>6</button>
"
"
<button>7</button>	<button>8</button>	<button>9</button>	<button class=long>N</button>
"
"
<button>*</button>	<button>0</button>	<button>#</button>
"
"
"
"";

void WebSocket::EtherPoll()
{
	// Should be called for each loop.
	EthernetClient cli;
	if (cli = ethServer.available())
	{
		RKPClass::loop_PanelMon(); //most important we poll this or RKP will loose data
		//LogLn(F("browser req"));
		if (cli == true)
		{
			if (ethClient != cli)
			{//New connection
				//Secrisk
				ethClient = cli;
				WebSocket_doHandshake();
			}
			else
			{//Existing connection
				if (WebSocket_getFrame() == false)
				{//Request to end comms (rarely happens)
					RKPClass::loop_PanelMon(); //most important we poll this or RKP will loose data

					//Got bad frame, disconnect
					Log(F("Disconnect{"));
					while(ethClient.available()>0)
						ethClient.read();

					ethClient.flush();
					ethClient.stop();
				}
			}
		}
	}

/*	if (cli = ethServerHTML.available())
	{
		//Log(cli.available());
		if (cli == true)
			SendHTMLSite();
	}
*/
}

void WebSocket::SendHTMLSite(/*EthernetClient& cli*/)
{
	//Log(F("ConnectWWW{"));
	//	while(ethClient.available()>0)
	//	Log((char)cli.read());
	//LogLn(F("}"));
	ethClient.println(F("HTTP/1.0 200 OK"));	//
	ethClient.println(F("Content-Type: text/html"));
	ethClient.println(F("Connnection: close"));
	ethClient.println();
	char* p = &htmlSite[0];
	for(int n=0;n<2000;n++)
	{
		char c = pgm_read_byte(p++);
		if (c==0) break;
		//Can use tokens to compress the HTML a bit
		//if (c=='*')
		//	ethClient.print(F("button"));
		//else
		ethClient.print(c);
		if (n%100==0)
			RKPClass::loop_PanelMon(); //most important we poll this when doing other stuff or RKP will loose data
	}
	RKPClass::loop_PanelMon(); //most important we poll this or RKP will loose data

	// close the connection so browser gets data
	ethClient.flush();
	//delay(1);
	ethClient.stop();
	LogLn("Sent Page");
}

// Create a Websocket server
void WebSocket::WebSocket_EtherInit( IPAddress ip, IPAddress gateway )
{
	//IPAddress ip( 192, 168, 1 , 205);			//Give the device a unique IP
	//IPAddress gateway( 192, 168, 1, 1 );	//Gateway (the Router)

	IPAddress subnet( 255, 255, 255, 0 );	//typically dont need change
	// this sequence must be unique on your lan
	byte mac[] = { 0x90, 0xA2, 0xDA, 0x00, 0x59, 0x67 };	//typically dont need change

	//Start Ethernet
	Ethernet.begin(mac, ip, gateway, gateway, subnet);

	ethServer.begin();
	//ethServerHTML.begin();
	Log(F("server is at ")); LogLn(Ethernet.localIP());

	delay(150); // Settle time
}

//Send something to connected browser
bool WebSocket::WebSocket_send(char* data, byte length)
{
	if (!ethClient.connected())
	{
		LogLn(F("No Client."));
		return false;
	}
	//int length = strlen(data);
	ethClient.write(0x81);// string type

	if (length > 125) {
		ethClient.write(126);
		ethClient.write((uint8_t) (length >> 8));
		ethClient.write((uint8_t) (length && 0xFF));
	}
	else
		ethClient.write((uint8_t) length);

	for (int i=0; i<length; ++i)
		ethClient.write(data[i]);

	//LogLn(F("Sent OK."));
	return true;
}

void WebSocket::WebSocket_doHandshake()
{
	LogLn("HS");
	char htmlline[128];	//TODO: there are 3 buffers used - htmlline, key and sha - maybe could merge them
	char key[80];

	bool hasKey = false;
	bool bReqWebPage = false;

	byte counter = 0;

	while(ethClient.available()>0)
	{//Read each line
		byte bite = ethClient.read();
		//Log(bite);
		htmlline[counter++] = bite;
		if (counter > 127)
		{
			LogLn(F("HandShake Overflow{"));
			while(ethClient.available()>0)
				LogHex(ethClient.read());
			LogLn(F("}"));
			//htmlline[127] = 0;
			//LogHex(htmlline);
			counter=0;
			continue;
		}

		if (bite == '\n')
		{ // Parse the line
			htmlline[counter - 2] = 0; // Terminate string before CRLF

			bool bFound = (strstr_P(htmlline, PSTR("Sec-WebSocket-Key:")) != NULL);
			if (bFound)
			{
				hasKey = true;
				strtok(htmlline, " ");
				strcpy(key, strtok(NULL, " "));	//TODO: Not safe - need specify max 80 limit
			}

			if (strstr_P(htmlline, PSTR("GET / HTTP")) != NULL)
			{
				LogLn(F("Page Req"));
				bReqWebPage=true;
			}

			counter = 0; // Start saving new header string

			//Each Line - check if there is any comms to do
			RKPClass::loop_PanelMon(); //most important we poll this or RKP will loose data
		}
	}

	//Log("Got header: ");LogHex((byte*)htmlline,counter);

	if (hasKey)
	{
		LogLn(F("WS Req"));
		strcat_P(key, PSTR("258EAFA5-E914-47DA-95CA-C5AB0DC85B11")); // Magic Number GUID
		Sha1.init();
		Sha1.print(key);
		uint8_t* hash = Sha1.result();
		base64_encode(htmlline, (char*)hash, 20); //reuse htmlline buffer
		ethClient.print(F("HTTP/1.1 101 Switching Protocols\r\n"));
		ethClient.print(F("Upgrade: websocket\r\n"));
		ethClient.print(F("Connection: Upgrade\r\n"));
		ethClient.print(F("Sec-WebSocket-Accept: "));
		ethClient.print(htmlline);  //eg. VoNhf1LMVVTziHWxjiajVem5DB4=
		ethClient.print(F("\r\n\r\n"));

		LogLn(F("Connected"));

		//Send any display we might have
		RKPClass::bScreenHasUpdated = true; //RKPClass::SendDisplayToBrowser();
	}
	else if (bReqWebPage)
	{// Nope, Not a websocket request - send the main webpage
		//LogLn(F("WebPageReq"));
		SendHTMLSite();
	}
	else
	{
		ethClient.println(F("HTTP/1.0 404 File Not Found"));	//
		ethClient.println(F("Content-Type: text/html"));
		ethClient.println(F("Connnection: close"));
		ethClient.println();
		//delay(1);
		ethClient.stop();
	}
	return;
}

struct Frame {
	bool isMasked;
	bool isFinal;
	byte opcode;
	byte mask[4];
	byte length;
	char data[64+1];
} frame;

byte WebSocket::ReadNext()
{
	byte bite = ethClient.read();
	//LogHex(bite);
	return bite;
}

bool WebSocket::WebSocket_getFrame()
{
	// Get opcode
	byte bite = ReadNext(); if (bite==0xFF) return false;

	frame.opcode = bite & 0xf; // Opcode
	frame.isFinal = bite & 0x80; // Final frame?
	// Determine length (only accept <= 64 for now)
	bite = ReadNext(); if (bite==0xFF) return false;

	frame.length = bite & 0x7f; // Length of payload
	if (frame.length >= 64)
	{//Unlikely to happen
		Log(F("Frame Too Big")); LogLn(bite);
		return false;
	}
	// Client should always send mask, but check just to be sure
	frame.isMasked = bite & 0x80;
	if (frame.isMasked) {
		frame.mask[0] = ReadNext();
		frame.mask[1] = ReadNext();
		frame.mask[2] = ReadNext();
		frame.mask[3] = ReadNext();
	}

	// Get message bytes and unmask them if necessary
	int i = 0;
	for (; i < frame.length; i++)
	{
		bite = ReadNext();
		if (frame.isMasked)
			frame.data[i] = bite ^ frame.mask[i % 4];
		else
			frame.data[i] = bite;
	}
	frame.data[i]=0;

	// Frame complete!
	if (!frame.isFinal)
	{	// We don't handle fragments! Close and disconnect.
		LogLn(F("Unsurp"));
		return false; //RejectBroswerMsg();
	}

	if (frame.opcode== 0x01)
	{// Txt frame
		Log(F("Data: ")); //Got Data
		LogLn(frame.data);
		RKPClass::PushKey(atoi(frame.data));
		return true;
	}

	if (frame.opcode== 0x08)
	{
		// Close frame. Answer with close and terminate tcp connection
		LogLn(F("Close")); //Close frame
		ethClient.write((uint8_t) 0x08);
		return false;
	}

	// Unexpected. Ignore?
	LogLn(F("Ex.")); //Unhandled frame ignored
	return false;
}

<|endoftext|>


<commit_before>/*
 * Copyright © 2010 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */
#include <string.h>
#include "main/imports.h"
#include "main/simple_list.h"
#include "ir.h"
#include "glsl_types.h"

ir_assignment::ir_assignment(ir_rvalue *lhs, ir_rvalue *rhs,
			     ir_rvalue *condition)
   : ir_rvalue()
{
   this->lhs = lhs;
   this->rhs = rhs;
   this->condition = condition;
}

ir_expression::ir_expression(int op, const struct glsl_type *type,
			     ir_rvalue *op0, ir_rvalue *op1)
   : ir_rvalue()
{
   this->type = type;
   this->operation = ir_expression_operation(op);
   this->operands[0] = op0;
   this->operands[1] = op1;
}

ir_label::ir_label(const char *label)
   : ir_instruction(), label(label)
{
   /* empty */
}

ir_constant::ir_constant(const struct glsl_type *type, const void *data)
   : ir_rvalue()
{
   unsigned size = 0;

   this->type = type;
   switch (type->base_type) {
   case GLSL_TYPE_UINT:  size = sizeof(this->value.u[0]); break;
   case GLSL_TYPE_INT:   size = sizeof(this->value.i[0]); break;
   case GLSL_TYPE_FLOAT: size = sizeof(this->value.f[0]); break;
   case GLSL_TYPE_BOOL:  size = sizeof(this->value.b[0]); break;
   default:
      /* FINISHME: What to do?  Exceptions are not the answer.
       */
      break;
   }

   memcpy(& this->value, data, size * type->components());
}

ir_constant::ir_constant(float f)
   : ir_rvalue()
{
   this->type = glsl_type::float_type;
   this->value.f[0] = f;
}

ir_constant::ir_constant(unsigned int u)
   : ir_rvalue()
{
   this->type = glsl_type::uint_type;
   this->value.u[0] = u;
}

ir_constant::ir_constant(int i)
   : ir_rvalue()
{
   this->type = glsl_type::int_type;
   this->value.i[0] = i;
}

ir_constant::ir_constant(bool b)
   : ir_rvalue()
{
   this->type = glsl_type::bool_type;
   this->value.b[0] = b;
}

ir_dereference::ir_dereference(ir_instruction *var)
   : ir_rvalue()
{
   this->mode = ir_reference_variable;
   this->var = var;
   this->type = (var != NULL) ? var->type : glsl_type::error_type;
}

ir_dereference::ir_dereference(ir_instruction *var,
			       ir_rvalue *array_index)
   : ir_rvalue(), mode(ir_reference_array),
     var(var)
{
   this->type = (var != NULL) ? var->type : glsl_type::error_type;
   this->selector.array_index = array_index;
}

ir_swizzle::ir_swizzle(ir_rvalue *val, unsigned x, unsigned y, unsigned z,
		       unsigned w, unsigned count)
   : val(val)
{
   assert((count >= 1) && (count <= 4));

   const unsigned dup_mask = 0
      | ((count > 1) ? ((1U << y) & ((1U << x)                        )) : 0)
      | ((count > 2) ? ((1U << z) & ((1U << x) | (1U << y)            )) : 0)
      | ((count > 3) ? ((1U << w) & ((1U << x) | (1U << y) | (1U << z))) : 0);

   assert(x <= 3);
   assert(y <= 3);
   assert(z <= 3);
   assert(w <= 3);

   mask.x = x;
   mask.y = y;
   mask.z = z;
   mask.w = w;
   mask.num_components = count;
   mask.has_duplicates = dup_mask != 0;

   /* Based on the number of elements in the swizzle and the base type
    * (i.e., float, int, unsigned, or bool) of the vector being swizzled,
    * generate the type of the resulting value.
    */
   type = glsl_type::get_instance(val->type->base_type, mask.num_components, 1);
}

#define X 1
#define R 5
#define S 9
#define I 13

ir_swizzle *
ir_swizzle::create(ir_rvalue *val, const char *str, unsigned vector_length)
{
   /* For each possible swizzle character, this table encodes the value in
    * \c idx_map that represents the 0th element of the vector.  For invalid
    * swizzle characters (e.g., 'k'), a special value is used that will allow
    * detection of errors.
    */
   static const unsigned char base_idx[26] = {
   /* a  b  c  d  e  f  g  h  i  j  k  l  m */
      R, R, I, I, I, I, R, I, I, I, I, I, I,
   /* n  o  p  q  r  s  t  u  v  w  x  y  z */
      I, I, S, S, R, S, S, I, I, X, X, X, X
   };

   /* Each valid swizzle character has an entry in the previous table.  This
    * table encodes the base index encoded in the previous table plus the actual
    * index of the swizzle character.  When processing swizzles, the first
    * character in the string is indexed in the previous table.  Each character
    * in the string is indexed in this table, and the value found there has the
    * value form the first table subtracted.  The result must be on the range
    * [0,3].
    *
    * For example, the string "wzyx" will get X from the first table.  Each of
    * the charcaters will get X+3, X+2, X+1, and X+0 from this table.  After
    * subtraction, the swizzle values are { 3, 2, 1, 0 }.
    *
    * The string "wzrg" will get X from the first table.  Each of the characters
    * will get X+3, X+2, R+0, and R+1 from this table.  After subtraction, the
    * swizzle values are { 3, 2, 4, 5 }.  Since 4 and 5 are outside the range
    * [0,3], the error is detected.
    */
   static const unsigned char idx_map[26] = {
   /* a    b    c    d    e    f    g    h    i    j    k    l    m */
      R+3, R+2, 0,   0,   0,   0,   R+1, 0,   0,   0,   0,   0,   0,
   /* n    o    p    q    r    s    t    u    v    w    x    y    z */
      0,   0,   S+2, S+3, R+0, S+0, S+1, 0,   0,   X+3, X+0, X+1, X+2
   };

   int swiz_idx[4] = { 0, 0, 0, 0 };
   unsigned i;

   /* Validate the first character in the swizzle string and look up the base
    * index value as described above.
    */
   if ((str[0] < 'a') || (str[0] > 'z'))
      return NULL;

   const unsigned base = base_idx[str[0] - 'a'];

   for (i = 0; (i < 4) && (str[i] != '\0'); i++) {
      /* Validate the next character, and, as described above, convert it to a
       * swizzle index.
       */
      if ((str[i] < 'a') || (str[i] > 'z'))
	 return NULL;

      swiz_idx[i] = idx_map[str[i] - 'a'] - base;
      if ((swiz_idx[i] < 0) || (swiz_idx[i] >= (int) vector_length))
	 return NULL;
   }

   if (str[i] != '\0')
	 return NULL;

   return new ir_swizzle(val, swiz_idx[0], swiz_idx[1], swiz_idx[2],
                         swiz_idx[3], i);
}

#undef X
#undef R
#undef S
#undef I

ir_variable::ir_variable(const struct glsl_type *type, const char *name)
   : ir_instruction(), read_only(false), centroid(false), invariant(false),
     mode(ir_var_auto), interpolation(ir_var_smooth)
{
   this->type = type;
   this->name = name;
}

ir_function_signature::ir_function_signature(const glsl_type *return_type)
   : ir_instruction(), return_type(return_type), definition(NULL)
{
   /* empty */
}

ir_function::ir_function(const char *name)
   : ir_instruction(), name(name)
{
   /* empty */
}

ir_call *
ir_call::get_error_instruction()
{
   ir_call *call = new ir_call;

   call->type = glsl_type::error_type;
   return call;
}
<commit_msg>Set variables with the sampler base type to read only.<commit_after>/*
 * Copyright © 2010 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */
#include <string.h>
#include "main/imports.h"
#include "main/simple_list.h"
#include "ir.h"
#include "glsl_types.h"

ir_assignment::ir_assignment(ir_rvalue *lhs, ir_rvalue *rhs,
			     ir_rvalue *condition)
   : ir_rvalue()
{
   this->lhs = lhs;
   this->rhs = rhs;
   this->condition = condition;
}

ir_expression::ir_expression(int op, const struct glsl_type *type,
			     ir_rvalue *op0, ir_rvalue *op1)
   : ir_rvalue()
{
   this->type = type;
   this->operation = ir_expression_operation(op);
   this->operands[0] = op0;
   this->operands[1] = op1;
}

ir_label::ir_label(const char *label)
   : ir_instruction(), label(label)
{
   /* empty */
}

ir_constant::ir_constant(const struct glsl_type *type, const void *data)
   : ir_rvalue()
{
   unsigned size = 0;

   this->type = type;
   switch (type->base_type) {
   case GLSL_TYPE_UINT:  size = sizeof(this->value.u[0]); break;
   case GLSL_TYPE_INT:   size = sizeof(this->value.i[0]); break;
   case GLSL_TYPE_FLOAT: size = sizeof(this->value.f[0]); break;
   case GLSL_TYPE_BOOL:  size = sizeof(this->value.b[0]); break;
   default:
      /* FINISHME: What to do?  Exceptions are not the answer.
       */
      break;
   }

   memcpy(& this->value, data, size * type->components());
}

ir_constant::ir_constant(float f)
   : ir_rvalue()
{
   this->type = glsl_type::float_type;
   this->value.f[0] = f;
}

ir_constant::ir_constant(unsigned int u)
   : ir_rvalue()
{
   this->type = glsl_type::uint_type;
   this->value.u[0] = u;
}

ir_constant::ir_constant(int i)
   : ir_rvalue()
{
   this->type = glsl_type::int_type;
   this->value.i[0] = i;
}

ir_constant::ir_constant(bool b)
   : ir_rvalue()
{
   this->type = glsl_type::bool_type;
   this->value.b[0] = b;
}

ir_dereference::ir_dereference(ir_instruction *var)
   : ir_rvalue()
{
   this->mode = ir_reference_variable;
   this->var = var;
   this->type = (var != NULL) ? var->type : glsl_type::error_type;
}

ir_dereference::ir_dereference(ir_instruction *var,
			       ir_rvalue *array_index)
   : ir_rvalue(), mode(ir_reference_array),
     var(var)
{
   this->type = (var != NULL) ? var->type : glsl_type::error_type;
   this->selector.array_index = array_index;
}

ir_swizzle::ir_swizzle(ir_rvalue *val, unsigned x, unsigned y, unsigned z,
		       unsigned w, unsigned count)
   : val(val)
{
   assert((count >= 1) && (count <= 4));

   const unsigned dup_mask = 0
      | ((count > 1) ? ((1U << y) & ((1U << x)                        )) : 0)
      | ((count > 2) ? ((1U << z) & ((1U << x) | (1U << y)            )) : 0)
      | ((count > 3) ? ((1U << w) & ((1U << x) | (1U << y) | (1U << z))) : 0);

   assert(x <= 3);
   assert(y <= 3);
   assert(z <= 3);
   assert(w <= 3);

   mask.x = x;
   mask.y = y;
   mask.z = z;
   mask.w = w;
   mask.num_components = count;
   mask.has_duplicates = dup_mask != 0;

   /* Based on the number of elements in the swizzle and the base type
    * (i.e., float, int, unsigned, or bool) of the vector being swizzled,
    * generate the type of the resulting value.
    */
   type = glsl_type::get_instance(val->type->base_type, mask.num_components, 1);
}

#define X 1
#define R 5
#define S 9
#define I 13

ir_swizzle *
ir_swizzle::create(ir_rvalue *val, const char *str, unsigned vector_length)
{
   /* For each possible swizzle character, this table encodes the value in
    * \c idx_map that represents the 0th element of the vector.  For invalid
    * swizzle characters (e.g., 'k'), a special value is used that will allow
    * detection of errors.
    */
   static const unsigned char base_idx[26] = {
   /* a  b  c  d  e  f  g  h  i  j  k  l  m */
      R, R, I, I, I, I, R, I, I, I, I, I, I,
   /* n  o  p  q  r  s  t  u  v  w  x  y  z */
      I, I, S, S, R, S, S, I, I, X, X, X, X
   };

   /* Each valid swizzle character has an entry in the previous table.  This
    * table encodes the base index encoded in the previous table plus the actual
    * index of the swizzle character.  When processing swizzles, the first
    * character in the string is indexed in the previous table.  Each character
    * in the string is indexed in this table, and the value found there has the
    * value form the first table subtracted.  The result must be on the range
    * [0,3].
    *
    * For example, the string "wzyx" will get X from the first table.  Each of
    * the charcaters will get X+3, X+2, X+1, and X+0 from this table.  After
    * subtraction, the swizzle values are { 3, 2, 1, 0 }.
    *
    * The string "wzrg" will get X from the first table.  Each of the characters
    * will get X+3, X+2, R+0, and R+1 from this table.  After subtraction, the
    * swizzle values are { 3, 2, 4, 5 }.  Since 4 and 5 are outside the range
    * [0,3], the error is detected.
    */
   static const unsigned char idx_map[26] = {
   /* a    b    c    d    e    f    g    h    i    j    k    l    m */
      R+3, R+2, 0,   0,   0,   0,   R+1, 0,   0,   0,   0,   0,   0,
   /* n    o    p    q    r    s    t    u    v    w    x    y    z */
      0,   0,   S+2, S+3, R+0, S+0, S+1, 0,   0,   X+3, X+0, X+1, X+2
   };

   int swiz_idx[4] = { 0, 0, 0, 0 };
   unsigned i;

   /* Validate the first character in the swizzle string and look up the base
    * index value as described above.
    */
   if ((str[0] < 'a') || (str[0] > 'z'))
      return NULL;

   const unsigned base = base_idx[str[0] - 'a'];

   for (i = 0; (i < 4) && (str[i] != '\0'); i++) {
      /* Validate the next character, and, as described above, convert it to a
       * swizzle index.
       */
      if ((str[i] < 'a') || (str[i] > 'z'))
	 return NULL;

      swiz_idx[i] = idx_map[str[i] - 'a'] - base;
      if ((swiz_idx[i] < 0) || (swiz_idx[i] >= (int) vector_length))
	 return NULL;
   }

   if (str[i] != '\0')
	 return NULL;

   return new ir_swizzle(val, swiz_idx[0], swiz_idx[1], swiz_idx[2],
                         swiz_idx[3], i);
}

#undef X
#undef R
#undef S
#undef I

ir_variable::ir_variable(const struct glsl_type *type, const char *name)
   : ir_instruction(), read_only(false), centroid(false), invariant(false),
     mode(ir_var_auto), interpolation(ir_var_smooth)
{
   this->type = type;
   this->name = name;

   if (type && type->base_type == GLSL_TYPE_SAMPLER)
      this->read_only = true;
}

ir_function_signature::ir_function_signature(const glsl_type *return_type)
   : ir_instruction(), return_type(return_type), definition(NULL)
{
   /* empty */
}

ir_function::ir_function(const char *name)
   : ir_instruction(), name(name)
{
   /* empty */
}

ir_call *
ir_call::get_error_instruction()
{
   ir_call *call = new ir_call;

   call->type = glsl_type::error_type;
   return call;
}
<|endoftext|>


<commit_before>/*
 * This file is part of the Yildiz-Engine project, licenced under the MIT License  (MIT)
 *
 * Copyright (c) 2019 Grégory Van den Borre
 *
 * More infos available: https://engine.yildiz-games.be
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
 * documentation files (the "Software"), to deal in the Software without restriction, including without
 * limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or substantial
 * portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
 * OR COPYRIGHT  HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE  SOFTWARE.
 */

/**
*@author Grégory Van den Borre
*/

#include "../includes/Root.hpp"
#include "../includes/EnumConversion.h"
#include "../includes/JniRoot.h"

JNIEXPORT void JNICALL Java_jni_JniRoot_constructor(
    JNIEnv *env,
    jobject) {
    LOG_FUNCTION
    try {
        yz::Root::create();
    } catch (std::exception& e) {
        throwException(env, e.what());
    }
}

JNIEXPORT void JNICALL Java_jni_JniRoot_initPhysFS(
    JNIEnv *env,
    jobject,
    POINTER vfsPointer) {
    LOG_FUNCTION
    yz::Root::get()->initPhysFS(reinterpret_cast<yz::physfs::Wrapper*>(vfsPointer));
}

JNIEXPORT void JNICALL Java_jni_JniRoot_loadPlugin(
    JNIEnv* env,
    jobject,
    jstring jplugin) {
    LOG_FUNCTION
    JniStringWrapper plugin = JniStringWrapper(env, jplugin);
    try {
        yz::Root::get()->loadPlugin(plugin.getValue());
    } catch (std::exception& e) {
        throwException(env, e.what());
    }
}

JNIEXPORT void JNICALL Java_jni_JniRoot_loadRenderer(
    JNIEnv *env,
    jobject,
    jstring jrenderer) {
    LOG_FUNCTION
    JniStringWrapper renderer = JniStringWrapper(env, jrenderer);
    try {
        yz::Root::get()->initialise(renderer.getValue());
    } catch (std::exception& e) {
        throwException(env, e.what());
    }
}

JNIEXPORT POINTER JNICALL Java_jni_JniRoot_createSceneManager(
    JNIEnv* env,
    jobject,
    jstring jname) {
    LOG_FUNCTION
    JniStringWrapper name = JniStringWrapper(env, jname);
    try {
        return reinterpret_cast<POINTER>(yz::Root::get()->createSceneManager(name.getValue()));
    } catch (std::exception& e) {
        throwException(env, e.what());
    }
    return INVALID_POINTER;
}

JNIEXPORT void JNICALL Java_jni_JniRoot_createRenderWindow(
    JNIEnv* env,
    jobject,
    jint width,
    jint height,
    jlong handle) {
    LOG_FUNCTION
    try {
        yz::Root::get()->createRenderWindow(width, height, handle);
    } catch (std::exception& e) {
        throwException(env, e.what());
    }
}

JNIEXPORT void JNICALL Java_jni_JniRoot_createRenderWindowGlContext(
    JNIEnv* env,
    jobject,
    jint width,
    jint height) {
    LOG_FUNCTION
    try {
        yz::Root::get()->createRenderWindow(width, height);
    } catch (std::exception& e) {
        throwException(env, e.what());
    }
}

JNIEXPORT void JNICALL Java_jni_JniRoot_addResourcePath(
    JNIEnv* env,
    jobject,
    jstring jname,
    jstring jpath,
    jint type) {
    LOG_FUNCTION
    JniStringWrapper name = JniStringWrapper(env, jname);
    JniStringWrapper path = JniStringWrapper(env, jpath);
    try {
        yz::Root::get()->addResourcePath(name.getValue(), path.getValue(), type);
    } catch (std::exception& e) {
        throwException(env, e.what());
    }
}

JNIEXPORT void JNICALL Java_jni_JniRoot_renderOneFrame(
    JNIEnv* env,
    jobject) {
    LOG_FUNCTION
    try {
        yz::Root::get()->renderOneFrame();
    } catch (std::exception& e) {
        throwException(env, e.what());
    }
}

JNIEXPORT void JNICALL Java_jni_JniRoot_close(
    JNIEnv* env,
    jobject) {
    LOG_FUNCTION
    try {
        yz::Root::get()->close();
    } catch (std::exception& e) {
        throwException(env, e.what());
    }
}
<commit_msg>Update JniRoot.cpp<commit_after>/*
 * This file is part of the Yildiz-Engine project, licenced under the MIT License  (MIT)
 *
 * Copyright (c) 2019 Grégory Van den Borre
 *
 * More infos available: https://engine.yildiz-games.be
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
 * documentation files (the "Software"), to deal in the Software without restriction, including without
 * limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or substantial
 * portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
 * OR COPYRIGHT  HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE  SOFTWARE.
 */

/**
*@author Grégory Van den Borre
*/

#include "../includes/Root.hpp"
#include "../includes/EnumConversion.h"
#include "../includes/JniRoot.h"

JNIEXPORT void JNICALL Java_jni_JniRoot_constructor(
    JNIEnv *env,
    jobject) {
    LOG_FUNCTION
    try {
        yz::Root::create();
    } catch (std::exception& e) {
        throwException(env, e.what());
    }
}

JNIEXPORT void JNICALL Java_jni_JniRoot_initPhysFS(
    JNIEnv *env,
    jobject,
    POINTER vfsPointer) {
    LOG_FUNCTION
    yz::ogre::vfs::registerPhysFSToOgre(reinterpret_cast<yz::physfs::Wrapper*>(vfsPointer));
}

JNIEXPORT void JNICALL Java_jni_JniRoot_loadPlugin(
    JNIEnv* env,
    jobject,
    jstring jplugin) {
    LOG_FUNCTION
    JniStringWrapper plugin = JniStringWrapper(env, jplugin);
    try {
        yz::Root::get()->loadPlugin(plugin.getValue());
    } catch (std::exception& e) {
        throwException(env, e.what());
    }
}

JNIEXPORT void JNICALL Java_jni_JniRoot_loadRenderer(
    JNIEnv *env,
    jobject,
    jstring jrenderer) {
    LOG_FUNCTION
    JniStringWrapper renderer = JniStringWrapper(env, jrenderer);
    try {
        yz::Root::get()->initialise(renderer.getValue());
    } catch (std::exception& e) {
        throwException(env, e.what());
    }
}

JNIEXPORT POINTER JNICALL Java_jni_JniRoot_createSceneManager(
    JNIEnv* env,
    jobject,
    jstring jname) {
    LOG_FUNCTION
    JniStringWrapper name = JniStringWrapper(env, jname);
    try {
        return reinterpret_cast<POINTER>(yz::Root::get()->createSceneManager(name.getValue()));
    } catch (std::exception& e) {
        throwException(env, e.what());
    }
    return INVALID_POINTER;
}

JNIEXPORT void JNICALL Java_jni_JniRoot_createRenderWindow(
    JNIEnv* env,
    jobject,
    jint width,
    jint height,
    jlong handle) {
    LOG_FUNCTION
    try {
        yz::Root::get()->createRenderWindow(width, height, handle);
    } catch (std::exception& e) {
        throwException(env, e.what());
    }
}

JNIEXPORT void JNICALL Java_jni_JniRoot_createRenderWindowGlContext(
    JNIEnv* env,
    jobject,
    jint width,
    jint height) {
    LOG_FUNCTION
    try {
        yz::Root::get()->createRenderWindow(width, height);
    } catch (std::exception& e) {
        throwException(env, e.what());
    }
}

JNIEXPORT void JNICALL Java_jni_JniRoot_addResourcePath(
    JNIEnv* env,
    jobject,
    jstring jname,
    jstring jpath,
    jint type) {
    LOG_FUNCTION
    JniStringWrapper name = JniStringWrapper(env, jname);
    JniStringWrapper path = JniStringWrapper(env, jpath);
    try {
        yz::Root::get()->addResourcePath(name.getValue(), path.getValue(), type);
    } catch (std::exception& e) {
        throwException(env, e.what());
    }
}

JNIEXPORT void JNICALL Java_jni_JniRoot_renderOneFrame(
    JNIEnv* env,
    jobject) {
    LOG_FUNCTION
    try {
        yz::Root::get()->renderOneFrame();
    } catch (std::exception& e) {
        throwException(env, e.what());
    }
}

JNIEXPORT void JNICALL Java_jni_JniRoot_close(
    JNIEnv* env,
    jobject) {
    LOG_FUNCTION
    try {
        yz::Root::get()->close();
    } catch (std::exception& e) {
        throwException(env, e.what());
    }
}
<|endoftext|>