<commit_before>/* libwpd
 * Copyright (C) 2002 William Lachance (william.lachance@sympatico.ca)
 * Copyright (C) 2002-2004 Marc Maurer (j.m.maurer@student.utwente.nl)
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 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 <stdio.h>
#include "RawListener.h"

RawListenerImpl::RawListenerImpl(bool printIndentLevel) :
	m_indent(0),
	m_actualIndentLevel(0),
	m_printIndentLevel(printIndentLevel)
{
}

RawListenerImpl::~RawListenerImpl()
{
	if (m_printIndentLevel)
		printf("%d\n", m_actualIndentLevel);
}

void RawListenerImpl::__iprintf(const char *format, ...)
{
	if (m_printIndentLevel) return;

	va_list args;
	va_start(args, format);
	for (int i=0; i<m_indent; i++)
		printf("  ");
	vprintf(format, args);
	va_end(args);
}

void RawListenerImpl::__iuprintf(const char *format, ...)
{
	if (m_printIndentLevel) return;

	va_list args;
	va_start(args, format);
	for (int i=0; i<m_indent; i++)
		printf("  ");
	vprintf(format, args);
	__indentUp();
	va_end(args);

	m_actualIndentLevel++;
}

void RawListenerImpl::__idprintf(const char *format, ...)
{
	if (m_printIndentLevel) return;

	va_list args;
	va_start(args, format);
	__indentDown();
	for (int i=0; i<m_indent; i++)
		printf("  ");
	vprintf(format, args);
	va_end(args);

	m_actualIndentLevel--;
}

void RawListenerImpl::setDocumentMetaData(const UCSString &author, const UCSString &subject,
					 const UCSString &publisher, const UCSString &category,
					 const UCSString &keywords, const UCSString &language,
					 const UCSString &abstract, const UCSString &descriptiveName,
					 const UCSString &descriptiveType)
{
	UTF8String authorUTF8(author);
	UTF8String subjectUTF8(subject);
	UTF8String publisherUTF8(publisher);
	UTF8String categoryUTF8(category);
	UTF8String keywordsUTF8(keywords);
	UTF8String languageUTF8(language);
	UTF8String abstractUTF8(abstract);
	UTF8String descriptiveNameUTF8(descriptiveName);
	UTF8String descriptiveTypeUTF8(descriptiveType);
	__iprintf("setDocumentMetaData(author: %s, subject: %s, publisher: %s, category: %s, keywords: %s, language: %s, abstract: %s, descriptiveName: %s, descriptiveType: %s)\n",
		authorUTF8.getUTF8(), subjectUTF8.getUTF8(),
		publisherUTF8.getUTF8(), categoryUTF8.getUTF8(),
		keywordsUTF8.getUTF8(), languageUTF8.getUTF8(),
		abstractUTF8.getUTF8(), descriptiveNameUTF8.getUTF8(),
		descriptiveTypeUTF8.getUTF8()
	);
}

void RawListenerImpl::startDocument()
{
	__iuprintf("startDocument()\n");
}

void RawListenerImpl::endDocument()
{
	__idprintf("endDocument()\n");
}

void RawListenerImpl::openPageSpan(const int span, const bool isLastPageSpan,
				  const float formLength, const float formWidth, const WPXFormOrientation orientation,
				  const float marginLeft, const float marginRight,
				  const float marginTop, const float marginBottom)
{
	__iuprintf("openPageSpan(span: %d, isLastPageSpan: %s, formLength: %.4f, formWidth: %.4f, Orientation: %s, marginLeft: %.4f, marginRight: %.4f, marginTop: %.4f, marginBottom: %.4f\n",
				span, (isLastPageSpan ? "true" : "false"), formLength, formWidth, ((orientation==LANDSCAPE) ? "landscape" : "portrait"), marginLeft, marginRight, marginTop, marginBottom);
}

void RawListenerImpl::closePageSpan()
{
	__idprintf("closePageSpan()\n");
}

void RawListenerImpl::openHeaderFooter(const WPXHeaderFooterType headerFooterType, const WPXHeaderFooterOccurence headerFooterOccurence)
{
	__iuprintf("openHeaderFooter(headerFooterType: %d, headerFooterOccurence: %d)\n",
		headerFooterType, headerFooterOccurence
	);
}

void RawListenerImpl::closeHeaderFooter(const WPXHeaderFooterType headerFooterType, const WPXHeaderFooterOccurence headerFooterOccurence)
{
	__idprintf("closeHeaderFooter(headerFooterType: %d, headerFooterOccurence: %d)\n",
		headerFooterType, headerFooterOccurence
	);
}

void RawListenerImpl::openParagraph(const guint8 paragraphJustification, const guint32 textAttributeBits,
				   const float marginLeftOffset, const float marginRightOffset, const float textIndent,
				   const gchar *fontName, const float fontSize, const RGBSColor *fontColor,
				   const RGBSColor *highlightColor, const float lineSpacing, const float spacingAfterParagraph,
				   const bool isColumnBreak, const bool isPageBreak)
{
	UTF8String fontNameUTF8(fontName);
	__iuprintf("openParagraph(paragraphJustification: %d, textAttributeBits: %d, marginLeftOffset: %.4f, marginRightOffset: %.4f, textIndent: %.4f, fontName: %s, fontSize: %.4f,  fontColor: #%02x%02x%02x s:%02x, highlightColor: #%02x%02x%02x s:%02x, lineSpacing: %.4f, spacingAfterParagraph: %.4f, isColumnBreak: %s, isPageBreak: %s)\n",
		paragraphJustification, textAttributeBits,
		marginLeftOffset, marginRightOffset, textIndent,
		fontNameUTF8.getUTF8(), fontSize, (fontColor?fontColor->m_r:0xff), (fontColor?fontColor->m_g:0xff),
		(fontColor?fontColor->m_b:0xff), (fontColor?fontColor->m_s:0xff), (highlightColor?highlightColor->m_r:0xff),
		(highlightColor?highlightColor->m_g:0xff), (highlightColor?highlightColor->m_b:0xff),
		(highlightColor?highlightColor->m_s:0xff), // saturation cannot be ever 0xff; if it is, the pointer is NULL.
		lineSpacing, spacingAfterParagraph, (isColumnBreak ? "true" : "false"), (isPageBreak ? "true" : "false")
	);
}

void RawListenerImpl::closeParagraph()
{
	__idprintf("closeParagraph()\n");
}

void RawListenerImpl::openSpan(const guint32 textAttributeBits, const gchar *fontName, const float fontSize,
					const RGBSColor *fontColor, const RGBSColor *highlightColor)
{
	__iuprintf("openSpan(textAttributeBits: %u, fontName: %s, fontSize: %.4f,  fontColor: #%02x%02x%02x s:%02x, highlightColor: #%02x%02x%02x s:%02x)\n",
			   textAttributeBits, fontName, fontSize, (fontColor?fontColor->m_r:0xff), (fontColor?fontColor->m_g:0xff),
			   (fontColor?fontColor->m_b:0xff), (fontColor?fontColor->m_s:0xff), (highlightColor?highlightColor->m_r:0xff),
			   (highlightColor?highlightColor->m_g:0xff), (highlightColor?highlightColor->m_b:0xff),
			   (highlightColor?highlightColor->m_s:0xff) // saturation cannot be ever 0xff; if it is, the pointer is NULL
	);
}

void RawListenerImpl::closeSpan()
{
	__idprintf("closeSpan()\n");
}

void RawListenerImpl::openSection(const unsigned int numColumns, const float spaceAfter)
{
	__iuprintf("openSection(numColumns: %u, spaceAfter: %.4f)\n", numColumns, spaceAfter);
}

void RawListenerImpl::closeSection()
{
	__idprintf("closeSection()\n");
}

void RawListenerImpl::insertTab()
{
	__iprintf("insertTab()\n");
}

void RawListenerImpl::insertText(const UCSString &text)
{
	UTF8String textUTF8(text);
	__iprintf("insertText(text: %s)\n", textUTF8.getUTF8());
}

void RawListenerImpl::insertLineBreak()
{
	__iprintf("insertLineBreak()\n");
}

void RawListenerImpl::defineOrderedListLevel(const int listID, const guint16 listLevel, const WPXNumberingType listType,
					    const UCSString &textBeforeNumber, const UCSString &textAfterNumber,
					    const int startingNumber)
{
	UTF8String textBeforeNumberUTF8(textBeforeNumber);
	UTF8String textAfterNumberUTF8(textAfterNumber);
	__iprintf("defineOrderedListLevel(listID: %d, listLevel: %d, listType: %d, textBeforeNumber: %s, textAfterNumber: %s, startingNumber: %d)\n",
		listID, listLevel, listType,
		textBeforeNumberUTF8.getUTF8(), textAfterNumberUTF8.getUTF8(),
		startingNumber
	);
}

void RawListenerImpl::defineUnorderedListLevel(const int listID, const guint16 listLevel, const UCSString &bullet)
{
	UTF8String bulletUTF8(bullet);
	__iprintf("defineUnorderedListLevel(listID: %d, listLevel: %d, bullet: %s)\n", listID, listLevel, bulletUTF8.getUTF8());
}

void RawListenerImpl::openOrderedListLevel(const int listID)
{
	__iuprintf("openOrderedListLevel(listID: %d)\n", listID);
}

void RawListenerImpl::openUnorderedListLevel(const int listID)
{
	__iuprintf("openUnorderedListLevel(listID: %d)\n", listID);
}

void RawListenerImpl::closeOrderedListLevel()
{
	__idprintf("closeOrderedListLevel()\n");
}

void RawListenerImpl::closeUnorderedListLevel()
{
	__idprintf("closeUnorderedListLevel()\n");
}

void RawListenerImpl::openListElement(const guint8 paragraphJustification, const guint32 textAttributeBits,
				   const float marginLeftOffset, const float marginRightOffset, const float textIndent,
				   const gchar *fontName, const float fontSize, const RGBSColor *fontColor,
				   const RGBSColor *highlightColor, const float lineSpacing, const float spacingAfterParagraph)
{
	UTF8String fontNameUTF8(fontName);
	__iuprintf("openListElement(paragraphJustification: %d, textAttributeBits: %d, marginLeftOffset: %.4f, marginRightOffset: %.4f, textIndent: %.4f, fontName: %s, fontSize: %.4f, fontColor: #%02x%02x%02x s:%02x, highlightColor: #%02x%02x%02x s:%02x, lineSpacing: %.4f, spacingAfterParagraph: %.4f)\n",
		paragraphJustification, textAttributeBits,
		marginLeftOffset, marginRightOffset, textIndent,
		fontNameUTF8.getUTF8(), fontSize, (fontColor?fontColor->m_r:0xff), (fontColor?fontColor->m_g:0xff),
		(fontColor?fontColor->m_b:0xff), (fontColor?fontColor->m_s:0xff), (highlightColor?highlightColor->m_r:0xff),
		(highlightColor?highlightColor->m_g:0xff), (highlightColor?highlightColor->m_b:0xff),
	        (highlightColor?highlightColor->m_s:0xff), // saturation cannot be ever 0xff; if it is, the pointer is NULL.
	        lineSpacing, spacingAfterParagraph
	);
}

void RawListenerImpl::closeListElement()
{
	__idprintf("closeListElement()\n");
}

void RawListenerImpl::openFootnote(int number)
{
	__iuprintf("openFootnote(number: %d)\n", number);
}

void RawListenerImpl::closeFootnote()
{
	__idprintf("closeFootnote()\n");
}

void RawListenerImpl::openEndnote(int number)
{
	__iuprintf("openEndnote(number: %d)\n", number);
}

void RawListenerImpl::closeEndnote()
{
	__idprintf("closeEndnote()\n");
}

void RawListenerImpl::openTable(const guint8 tablePositionBits,
			       const float marginLeftOffset, const float marginRightOffset,
			       const float leftOffset, const vector < WPXColumnDefinition > &columns)
{
	__iuprintf("openTable(tablePositionBits: %d, marginLeftOffset: %.4f, marginRightOffset: %.4f, leftOffset: %.4f, TODO: columns defs.)\n",
		tablePositionBits, marginLeftOffset, marginRightOffset, leftOffset);
}

void RawListenerImpl::openTableRow()
{
	__iuprintf("openTableRow()\n");
}

void RawListenerImpl::closeTableRow()
{
	__idprintf("closeTableRow()\n");
}

void RawListenerImpl::openTableCell(const guint32 col, const guint32 row, const guint32 colSpan, const guint32 rowSpan,
				   const guint8 borderBits,
				   const RGBSColor * cellFgColor, const RGBSColor * cellBgColor)
{
	__iuprintf("openTableCell(col: %d, row: %d, colSpan: %d, rowSpan: %d, borderBits: %d, cellFgColor: #%02x%02x%02x s:%02x, cellBgColor: #%02x%02x%02x s:%02x)\n",
		col, row, colSpan, rowSpan,
		borderBits,
		// The saturation cannot ever be more that 0x64. It it is, cellFgColor or cellBgColor is NULL
		(cellFgColor?cellFgColor->m_r:0xff), (cellFgColor?cellFgColor->m_g:0xff), (cellFgColor?cellFgColor->m_b:0xff), (cellFgColor?cellFgColor->m_s:0xff),
		(cellBgColor?cellBgColor->m_r:0xff), (cellBgColor?cellBgColor->m_g:0xff), (cellBgColor?cellBgColor->m_b:0xff), (cellBgColor?cellBgColor->m_s:0xff)
	);
}

void RawListenerImpl::closeTableCell()
{
	__idprintf("closeTableCell()\n");
}

void RawListenerImpl::insertCoveredTableCell(const guint32 col, const guint32 row)
{
	__iprintf("insertCoveredTableCell(col: %d, row: %d)\n", col, row);
}

void RawListenerImpl::closeTable()
{
	__idprintf("closeTable()\n");
}
<commit_msg>Fix callgraph test ;-/<commit_after>/* libwpd
 * Copyright (C) 2002 William Lachance (william.lachance@sympatico.ca)
 * Copyright (C) 2002-2004 Marc Maurer (j.m.maurer@student.utwente.nl)
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 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 <stdio.h>
#include "RawListener.h"

RawListenerImpl::RawListenerImpl(bool printIndentLevel) :
	m_indent(0),
	m_actualIndentLevel(0),
	m_printIndentLevel(printIndentLevel)
{
}

RawListenerImpl::~RawListenerImpl()
{
	if (m_printIndentLevel)
		printf("%d\n", m_actualIndentLevel);
}

void RawListenerImpl::__iprintf(const char *format, ...)
{
	if (m_printIndentLevel) return;

	va_list args;
	va_start(args, format);
	for (int i=0; i<m_indent; i++)
		printf("  ");
	vprintf(format, args);
	va_end(args);
}

void RawListenerImpl::__iuprintf(const char *format, ...)
{
	if (m_printIndentLevel)
	{
		m_actualIndentLevel++;
		return;
	}

	va_list args;
	va_start(args, format);
	for (int i=0; i<m_indent; i++)
		printf("  ");
	vprintf(format, args);
	__indentUp();
	va_end(args);
}

void RawListenerImpl::__idprintf(const char *format, ...)
{
	if (m_printIndentLevel)
	{
		m_actualIndentLevel--;
		return;
	}

	va_list args;
	va_start(args, format);
	__indentDown();
	for (int i=0; i<m_indent; i++)
		printf("  ");
	vprintf(format, args);
	va_end(args);
}

void RawListenerImpl::setDocumentMetaData(const UCSString &author, const UCSString &subject,
					 const UCSString &publisher, const UCSString &category,
					 const UCSString &keywords, const UCSString &language,
					 const UCSString &abstract, const UCSString &descriptiveName,
					 const UCSString &descriptiveType)
{
	UTF8String authorUTF8(author);
	UTF8String subjectUTF8(subject);
	UTF8String publisherUTF8(publisher);
	UTF8String categoryUTF8(category);
	UTF8String keywordsUTF8(keywords);
	UTF8String languageUTF8(language);
	UTF8String abstractUTF8(abstract);
	UTF8String descriptiveNameUTF8(descriptiveName);
	UTF8String descriptiveTypeUTF8(descriptiveType);
	__iprintf("setDocumentMetaData(author: %s, subject: %s, publisher: %s, category: %s, keywords: %s, language: %s, abstract: %s, descriptiveName: %s, descriptiveType: %s)\n",
		authorUTF8.getUTF8(), subjectUTF8.getUTF8(),
		publisherUTF8.getUTF8(), categoryUTF8.getUTF8(),
		keywordsUTF8.getUTF8(), languageUTF8.getUTF8(),
		abstractUTF8.getUTF8(), descriptiveNameUTF8.getUTF8(),
		descriptiveTypeUTF8.getUTF8()
	);
}

void RawListenerImpl::startDocument()
{
	__iuprintf("startDocument()\n");
}

void RawListenerImpl::endDocument()
{
	__idprintf("endDocument()\n");
}

void RawListenerImpl::openPageSpan(const int span, const bool isLastPageSpan,
				  const float formLength, const float formWidth, const WPXFormOrientation orientation,
				  const float marginLeft, const float marginRight,
				  const float marginTop, const float marginBottom)
{
	__iuprintf("openPageSpan(span: %d, isLastPageSpan: %s, formLength: %.4f, formWidth: %.4f, Orientation: %s, marginLeft: %.4f, marginRight: %.4f, marginTop: %.4f, marginBottom: %.4f\n",
				span, (isLastPageSpan ? "true" : "false"), formLength, formWidth, ((orientation==LANDSCAPE) ? "landscape" : "portrait"), marginLeft, marginRight, marginTop, marginBottom);
}

void RawListenerImpl::closePageSpan()
{
	__idprintf("closePageSpan()\n");
}

void RawListenerImpl::openHeaderFooter(const WPXHeaderFooterType headerFooterType, const WPXHeaderFooterOccurence headerFooterOccurence)
{
	__iuprintf("openHeaderFooter(headerFooterType: %d, headerFooterOccurence: %d)\n",
		headerFooterType, headerFooterOccurence
	);
}

void RawListenerImpl::closeHeaderFooter(const WPXHeaderFooterType headerFooterType, const WPXHeaderFooterOccurence headerFooterOccurence)
{
	__idprintf("closeHeaderFooter(headerFooterType: %d, headerFooterOccurence: %d)\n",
		headerFooterType, headerFooterOccurence
	);
}

void RawListenerImpl::openParagraph(const guint8 paragraphJustification, const guint32 textAttributeBits,
				   const float marginLeftOffset, const float marginRightOffset, const float textIndent,
				   const gchar *fontName, const float fontSize, const RGBSColor *fontColor,
				   const RGBSColor *highlightColor, const float lineSpacing, const float spacingAfterParagraph,
				   const bool isColumnBreak, const bool isPageBreak)
{
	UTF8String fontNameUTF8(fontName);
	__iuprintf("openParagraph(paragraphJustification: %d, textAttributeBits: %d, marginLeftOffset: %.4f, marginRightOffset: %.4f, textIndent: %.4f, fontName: %s, fontSize: %.4f,  fontColor: #%02x%02x%02x s:%02x, highlightColor: #%02x%02x%02x s:%02x, lineSpacing: %.4f, spacingAfterParagraph: %.4f, isColumnBreak: %s, isPageBreak: %s)\n",
		paragraphJustification, textAttributeBits,
		marginLeftOffset, marginRightOffset, textIndent,
		fontNameUTF8.getUTF8(), fontSize, (fontColor?fontColor->m_r:0xff), (fontColor?fontColor->m_g:0xff),
		(fontColor?fontColor->m_b:0xff), (fontColor?fontColor->m_s:0xff), (highlightColor?highlightColor->m_r:0xff),
		(highlightColor?highlightColor->m_g:0xff), (highlightColor?highlightColor->m_b:0xff),
		(highlightColor?highlightColor->m_s:0xff), // saturation cannot be ever 0xff; if it is, the pointer is NULL.
		lineSpacing, spacingAfterParagraph, (isColumnBreak ? "true" : "false"), (isPageBreak ? "true" : "false")
	);
}

void RawListenerImpl::closeParagraph()
{
	__idprintf("closeParagraph()\n");
}

void RawListenerImpl::openSpan(const guint32 textAttributeBits, const gchar *fontName, const float fontSize,
					const RGBSColor *fontColor, const RGBSColor *highlightColor)
{
	__iuprintf("openSpan(textAttributeBits: %u, fontName: %s, fontSize: %.4f,  fontColor: #%02x%02x%02x s:%02x, highlightColor: #%02x%02x%02x s:%02x)\n",
			   textAttributeBits, fontName, fontSize, (fontColor?fontColor->m_r:0xff), (fontColor?fontColor->m_g:0xff),
			   (fontColor?fontColor->m_b:0xff), (fontColor?fontColor->m_s:0xff), (highlightColor?highlightColor->m_r:0xff),
			   (highlightColor?highlightColor->m_g:0xff), (highlightColor?highlightColor->m_b:0xff),
			   (highlightColor?highlightColor->m_s:0xff) // saturation cannot be ever 0xff; if it is, the pointer is NULL
	);
}

void RawListenerImpl::closeSpan()
{
	__idprintf("closeSpan()\n");
}

void RawListenerImpl::openSection(const unsigned int numColumns, const float spaceAfter)
{
	__iuprintf("openSection(numColumns: %u, spaceAfter: %.4f)\n", numColumns, spaceAfter);
}

void RawListenerImpl::closeSection()
{
	__idprintf("closeSection()\n");
}

void RawListenerImpl::insertTab()
{
	__iprintf("insertTab()\n");
}

void RawListenerImpl::insertText(const UCSString &text)
{
	UTF8String textUTF8(text);
	__iprintf("insertText(text: %s)\n", textUTF8.getUTF8());
}

void RawListenerImpl::insertLineBreak()
{
	__iprintf("insertLineBreak()\n");
}

void RawListenerImpl::defineOrderedListLevel(const int listID, const guint16 listLevel, const WPXNumberingType listType,
					    const UCSString &textBeforeNumber, const UCSString &textAfterNumber,
					    const int startingNumber)
{
	UTF8String textBeforeNumberUTF8(textBeforeNumber);
	UTF8String textAfterNumberUTF8(textAfterNumber);
	__iprintf("defineOrderedListLevel(listID: %d, listLevel: %d, listType: %d, textBeforeNumber: %s, textAfterNumber: %s, startingNumber: %d)\n",
		listID, listLevel, listType,
		textBeforeNumberUTF8.getUTF8(), textAfterNumberUTF8.getUTF8(),
		startingNumber
	);
}

void RawListenerImpl::defineUnorderedListLevel(const int listID, const guint16 listLevel, const UCSString &bullet)
{
	UTF8String bulletUTF8(bullet);
	__iprintf("defineUnorderedListLevel(listID: %d, listLevel: %d, bullet: %s)\n", listID, listLevel, bulletUTF8.getUTF8());
}

void RawListenerImpl::openOrderedListLevel(const int listID)
{
	__iuprintf("openOrderedListLevel(listID: %d)\n", listID);
}

void RawListenerImpl::openUnorderedListLevel(const int listID)
{
	__iuprintf("openUnorderedListLevel(listID: %d)\n", listID);
}

void RawListenerImpl::closeOrderedListLevel()
{
	__idprintf("closeOrderedListLevel()\n");
}

void RawListenerImpl::closeUnorderedListLevel()
{
	__idprintf("closeUnorderedListLevel()\n");
}

void RawListenerImpl::openListElement(const guint8 paragraphJustification, const guint32 textAttributeBits,
				   const float marginLeftOffset, const float marginRightOffset, const float textIndent,
				   const gchar *fontName, const float fontSize, const RGBSColor *fontColor,
				   const RGBSColor *highlightColor, const float lineSpacing, const float spacingAfterParagraph)
{
	UTF8String fontNameUTF8(fontName);
	__iuprintf("openListElement(paragraphJustification: %d, textAttributeBits: %d, marginLeftOffset: %.4f, marginRightOffset: %.4f, textIndent: %.4f, fontName: %s, fontSize: %.4f, fontColor: #%02x%02x%02x s:%02x, highlightColor: #%02x%02x%02x s:%02x, lineSpacing: %.4f, spacingAfterParagraph: %.4f)\n",
		paragraphJustification, textAttributeBits,
		marginLeftOffset, marginRightOffset, textIndent,
		fontNameUTF8.getUTF8(), fontSize, (fontColor?fontColor->m_r:0xff), (fontColor?fontColor->m_g:0xff),
		(fontColor?fontColor->m_b:0xff), (fontColor?fontColor->m_s:0xff), (highlightColor?highlightColor->m_r:0xff),
		(highlightColor?highlightColor->m_g:0xff), (highlightColor?highlightColor->m_b:0xff),
	        (highlightColor?highlightColor->m_s:0xff), // saturation cannot be ever 0xff; if it is, the pointer is NULL.
	        lineSpacing, spacingAfterParagraph
	);
}

void RawListenerImpl::closeListElement()
{
	__idprintf("closeListElement()\n");
}

void RawListenerImpl::openFootnote(int number)
{
	__iuprintf("openFootnote(number: %d)\n", number);
}

void RawListenerImpl::closeFootnote()
{
	__idprintf("closeFootnote()\n");
}

void RawListenerImpl::openEndnote(int number)
{
	__iuprintf("openEndnote(number: %d)\n", number);
}

void RawListenerImpl::closeEndnote()
{
	__idprintf("closeEndnote()\n");
}

void RawListenerImpl::openTable(const guint8 tablePositionBits,
			       const float marginLeftOffset, const float marginRightOffset,
			       const float leftOffset, const vector < WPXColumnDefinition > &columns)
{
	__iuprintf("openTable(tablePositionBits: %d, marginLeftOffset: %.4f, marginRightOffset: %.4f, leftOffset: %.4f, TODO: columns defs.)\n",
		tablePositionBits, marginLeftOffset, marginRightOffset, leftOffset);
}

void RawListenerImpl::openTableRow()
{
	__iuprintf("openTableRow()\n");
}

void RawListenerImpl::closeTableRow()
{
	__idprintf("closeTableRow()\n");
}

void RawListenerImpl::openTableCell(const guint32 col, const guint32 row, const guint32 colSpan, const guint32 rowSpan,
				   const guint8 borderBits,
				   const RGBSColor * cellFgColor, const RGBSColor * cellBgColor)
{
	__iuprintf("openTableCell(col: %d, row: %d, colSpan: %d, rowSpan: %d, borderBits: %d, cellFgColor: #%02x%02x%02x s:%02x, cellBgColor: #%02x%02x%02x s:%02x)\n",
		col, row, colSpan, rowSpan,
		borderBits,
		// The saturation cannot ever be more that 0x64. It it is, cellFgColor or cellBgColor is NULL
		(cellFgColor?cellFgColor->m_r:0xff), (cellFgColor?cellFgColor->m_g:0xff), (cellFgColor?cellFgColor->m_b:0xff), (cellFgColor?cellFgColor->m_s:0xff),
		(cellBgColor?cellBgColor->m_r:0xff), (cellBgColor?cellBgColor->m_g:0xff), (cellBgColor?cellBgColor->m_b:0xff), (cellBgColor?cellBgColor->m_s:0xff)
	);
}

void RawListenerImpl::closeTableCell()
{
	__idprintf("closeTableCell()\n");
}

void RawListenerImpl::insertCoveredTableCell(const guint32 col, const guint32 row)
{
	__iprintf("insertCoveredTableCell(col: %d, row: %d)\n", col, row);
}

void RawListenerImpl::closeTable()
{
	__idprintf("closeTable()\n");
}
<|endoftext|>


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

#include "SkTypefaceCache.h"
#include "SkThread.h"

#define TYPEFACE_CACHE_LIMIT    128

void SkTypefaceCache::add(SkTypeface* face,
                          SkTypeface::Style requestedStyle,
                          bool strong) {
    if (fArray.count() >= TYPEFACE_CACHE_LIMIT) {
        this->purge(TYPEFACE_CACHE_LIMIT >> 2);
    }

    Rec* rec = fArray.append();
    rec->fFace = face;
    rec->fRequestedStyle = requestedStyle;
    rec->fStrong = strong;
    if (strong) {
        face->ref();
    } else {
        face->weak_ref();
    }
}

SkTypeface* SkTypefaceCache::findByID(SkFontID fontID) const {
    const Rec* curr = fArray.begin();
    const Rec* stop = fArray.end();
    while (curr < stop) {
        if (curr->fFace->uniqueID() == fontID) {
            return curr->fFace;
        }
        curr += 1;
    }
    return NULL;
}

SkTypeface* SkTypefaceCache::findByProcAndRef(FindProc proc, void* ctx) const {
    const Rec* curr = fArray.begin();
    const Rec* stop = fArray.end();
    while (curr < stop) {
        SkTypeface* currFace = curr->fFace;
        if (proc(currFace, curr->fRequestedStyle, ctx)) {
            if (curr->fStrong) {
                currFace->ref();
                return currFace;
            } else if (currFace->try_ref()) {
                return currFace;
            } else {
                //remove currFace from fArray?
            }
        }
        curr += 1;
    }
    return NULL;
}

void SkTypefaceCache::purge(int numToPurge) {
    int count = fArray.count();
    int i = 0;
    while (i < count) {
        SkTypeface* face = fArray[i].fFace;
        bool strong = fArray[i].fStrong;
        if ((strong && face->getRefCnt() == 1) ||
            (!strong && face->weak_expired()))
        {
            if (strong) {
                face->unref();
            } else {
                face->weak_unref();
            }
            fArray.remove(i);
            --count;
            if (--numToPurge == 0) {
                return;
            }
        } else {
            ++i;
        }
    }
}

void SkTypefaceCache::purgeAll() {
    this->purge(fArray.count());
}

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

SkTypefaceCache& SkTypefaceCache::Get() {
    static SkTypefaceCache gCache;
    return gCache;
}

SkFontID SkTypefaceCache::NewFontID() {
    static int32_t gFontID;
    return sk_atomic_inc(&gFontID) + 1;
}

SK_DECLARE_STATIC_MUTEX(gMutex);

void SkTypefaceCache::Add(SkTypeface* face,
                          SkTypeface::Style requestedStyle,
                          bool strong) {
    SkAutoMutexAcquire ama(gMutex);
    Get().add(face, requestedStyle, strong);
}

SkTypeface* SkTypefaceCache::FindByID(SkFontID fontID) {
    SkAutoMutexAcquire ama(gMutex);
    return Get().findByID(fontID);
}

SkTypeface* SkTypefaceCache::FindByProcAndRef(FindProc proc, void* ctx) {
    SkAutoMutexAcquire ama(gMutex);
    SkTypeface* typeface = Get().findByProcAndRef(proc, ctx);
    return typeface;
}

void SkTypefaceCache::PurgeAll() {
    SkAutoMutexAcquire ama(gMutex);
    Get().purgeAll();
}

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

#ifdef SK_DEBUG
static bool DumpProc(SkTypeface* face, SkTypeface::Style style, void* ctx) {
    SkDebugf("SkTypefaceCache: face %p fontID %d style %d refcnt %d\n",
             face, face->uniqueID(), style, face->getRefCnt());
    return false;
}
#endif

void SkTypefaceCache::Dump() {
#ifdef SK_DEBUG
    SkAutoMutexAcquire ama(gMutex);
    (void)Get().findByProcAndRef(DumpProc, NULL);
#endif
}
<commit_msg>move typeface cache limit from 128 to 1024 (128 is a joke, not sure what a real upper limit should be)<commit_after>
/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkTypefaceCache.h"
#include "SkThread.h"

#define TYPEFACE_CACHE_LIMIT    1024

void SkTypefaceCache::add(SkTypeface* face,
                          SkTypeface::Style requestedStyle,
                          bool strong) {
    if (fArray.count() >= TYPEFACE_CACHE_LIMIT) {
        this->purge(TYPEFACE_CACHE_LIMIT >> 2);
    }

    Rec* rec = fArray.append();
    rec->fFace = face;
    rec->fRequestedStyle = requestedStyle;
    rec->fStrong = strong;
    if (strong) {
        face->ref();
    } else {
        face->weak_ref();
    }
}

SkTypeface* SkTypefaceCache::findByID(SkFontID fontID) const {
    const Rec* curr = fArray.begin();
    const Rec* stop = fArray.end();
    while (curr < stop) {
        if (curr->fFace->uniqueID() == fontID) {
            return curr->fFace;
        }
        curr += 1;
    }
    return NULL;
}

SkTypeface* SkTypefaceCache::findByProcAndRef(FindProc proc, void* ctx) const {
    const Rec* curr = fArray.begin();
    const Rec* stop = fArray.end();
    while (curr < stop) {
        SkTypeface* currFace = curr->fFace;
        if (proc(currFace, curr->fRequestedStyle, ctx)) {
            if (curr->fStrong) {
                currFace->ref();
                return currFace;
            } else if (currFace->try_ref()) {
                return currFace;
            } else {
                //remove currFace from fArray?
            }
        }
        curr += 1;
    }
    return NULL;
}

void SkTypefaceCache::purge(int numToPurge) {
    int count = fArray.count();
    int i = 0;
    while (i < count) {
        SkTypeface* face = fArray[i].fFace;
        bool strong = fArray[i].fStrong;
        if ((strong && face->getRefCnt() == 1) ||
            (!strong && face->weak_expired()))
        {
            if (strong) {
                face->unref();
            } else {
                face->weak_unref();
            }
            fArray.remove(i);
            --count;
            if (--numToPurge == 0) {
                return;
            }
        } else {
            ++i;
        }
    }
}

void SkTypefaceCache::purgeAll() {
    this->purge(fArray.count());
}

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

SkTypefaceCache& SkTypefaceCache::Get() {
    static SkTypefaceCache gCache;
    return gCache;
}

SkFontID SkTypefaceCache::NewFontID() {
    static int32_t gFontID;
    return sk_atomic_inc(&gFontID) + 1;
}

SK_DECLARE_STATIC_MUTEX(gMutex);

void SkTypefaceCache::Add(SkTypeface* face,
                          SkTypeface::Style requestedStyle,
                          bool strong) {
    SkAutoMutexAcquire ama(gMutex);
    Get().add(face, requestedStyle, strong);
}

SkTypeface* SkTypefaceCache::FindByID(SkFontID fontID) {
    SkAutoMutexAcquire ama(gMutex);
    return Get().findByID(fontID);
}

SkTypeface* SkTypefaceCache::FindByProcAndRef(FindProc proc, void* ctx) {
    SkAutoMutexAcquire ama(gMutex);
    SkTypeface* typeface = Get().findByProcAndRef(proc, ctx);
    return typeface;
}

void SkTypefaceCache::PurgeAll() {
    SkAutoMutexAcquire ama(gMutex);
    Get().purgeAll();
}

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

#ifdef SK_DEBUG
static bool DumpProc(SkTypeface* face, SkTypeface::Style style, void* ctx) {
    SkDebugf("SkTypefaceCache: face %p fontID %d style %d refcnt %d\n",
             face, face->uniqueID(), style, face->getRefCnt());
    return false;
}
#endif

void SkTypefaceCache::Dump() {
#ifdef SK_DEBUG
    SkAutoMutexAcquire ama(gMutex);
    (void)Get().findByProcAndRef(DumpProc, NULL);
#endif
}
<|endoftext|>


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

#include "init.h"
#include "bitcoinrpc.h"
#include <boost/algorithm/string/predicate.hpp>

void DetectShutdownThread(boost::thread_group* threadGroup)
{
    bool shutdown = ShutdownRequested();
    // Tell the main threads to shutdown.
    while (!shutdown)
    {
        MilliSleep(200);
        shutdown = ShutdownRequested();
    }
    if (threadGroup)
        threadGroup->interrupt_all();
}

//////////////////////////////////////////////////////////////////////////////
//
// Start
//
bool AppInit(int argc, char* argv[])
{
    boost::thread_group threadGroup;
    boost::thread* detectShutdownThread = NULL;

    bool fRet = false;
    try
    {
        //
        // Parameters
        //
        // If Qt is used, parameters/bitcoin.conf are parsed in qt/bitcoin.cpp's main()
        ParseParameters(argc, argv);
        if (!boost::filesystem::is_directory(GetDataDir(false)))
        {
            fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", mapArgs["-datadir"].c_str());
            return false;
        }
        ReadConfigFile(mapArgs, mapMultiArgs);
        // Check for -testnet or -regtest parameter (TestNet() calls are only valid after this clause)
        if (!SelectParamsFromCommandLine()) {
            fprintf(stderr, "Error: Invalid combination of -regtest and -testnet.\n");
            return false;
        }

        if (mapArgs.count("-?") || mapArgs.count("--help"))
        {
            // First part of help message is specific to bitcoind / RPC client
            std::string strUsage = _("Bitcoin version") + " " + FormatFullVersion() + "\n\n" +
                _("Usage:") + "\n" +
                  "  bitcoind [options]                     " + "\n" +
                  "  bitcoind [options] <command> [params]  " + _("Send command to -server or bitcoind") + "\n" +
                  "  bitcoind [options] help                " + _("List commands") + "\n" +
                  "  bitcoind [options] help <command>      " + _("Get help for a command") + "\n";

            strUsage += "\n" + HelpMessage();

            fprintf(stdout, "%s", strUsage.c_str());
            return false;
        }

        // Command-line RPC
        for (int i = 1; i < argc; i++)
            if (!IsSwitchChar(argv[i][0]) && !boost::algorithm::istarts_with(argv[i], "bitcoin:"))
                fCommandLine = true;

        if (fCommandLine)
        {
            int ret = CommandLineRPC(argc, argv);
            exit(ret);
        }
#ifndef WIN32
        fDaemon = GetBoolArg("-daemon", false);
        if (fDaemon)
        {
            // Daemonize
            pid_t pid = fork();
            if (pid < 0)
            {
                fprintf(stderr, "Error: fork() returned %d errno %d\n", pid, errno);
                return false;
            }
            if (pid > 0) // Parent process, pid is child process id
            {
                CreatePidFile(GetPidFile(), pid);
                return true;
            }
            // Child process falls through to rest of initialization

            pid_t sid = setsid();
            if (sid < 0)
                fprintf(stderr, "Error: setsid() returned %d errno %d\n", sid, errno);
        }
#endif

        detectShutdownThread = new boost::thread(boost::bind(&DetectShutdownThread, &threadGroup));
        fRet = AppInit2(threadGroup);
    }
    catch (std::exception& e) {
        PrintExceptionContinue(&e, "AppInit()");
    } catch (...) {
        PrintExceptionContinue(NULL, "AppInit()");
    }
    if (!fRet) {
        if (detectShutdownThread)
            detectShutdownThread->interrupt();
        threadGroup.interrupt_all();
    }

    if (detectShutdownThread)
    {
        detectShutdownThread->join();
        delete detectShutdownThread;
        detectShutdownThread = NULL;
    }
    Shutdown();

    return fRet;
}

extern void noui_connect();
int main(int argc, char* argv[])
{
    bool fRet = false;
    fHaveGUI = false;

    // Connect bitcoind signal handlers
    noui_connect();

    fRet = AppInit(argc, argv);

    if (fRet && fDaemon)
        return 0;

    return (fRet ? 0 : 1);
}
<commit_msg>add missing Boost Thread join_all() call during shutdown<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "init.h"
#include "bitcoinrpc.h"
#include <boost/algorithm/string/predicate.hpp>

void DetectShutdownThread(boost::thread_group* threadGroup)
{
    bool fShutdown = ShutdownRequested();
    // Tell the main threads to shutdown.
    while (!fShutdown)
    {
        MilliSleep(200);
        fShutdown = ShutdownRequested();
    }
    if (threadGroup)
    {
        threadGroup->interrupt_all();
        threadGroup->join_all();
    }
}

//////////////////////////////////////////////////////////////////////////////
//
// Start
//
bool AppInit(int argc, char* argv[])
{
    boost::thread_group threadGroup;
    boost::thread* detectShutdownThread = NULL;

    bool fRet = false;
    try
    {
        //
        // Parameters
        //
        // If Qt is used, parameters/bitcoin.conf are parsed in qt/bitcoin.cpp's main()
        ParseParameters(argc, argv);
        if (!boost::filesystem::is_directory(GetDataDir(false)))
        {
            fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", mapArgs["-datadir"].c_str());
            return false;
        }
        ReadConfigFile(mapArgs, mapMultiArgs);
        // Check for -testnet or -regtest parameter (TestNet() calls are only valid after this clause)
        if (!SelectParamsFromCommandLine()) {
            fprintf(stderr, "Error: Invalid combination of -regtest and -testnet.\n");
            return false;
        }

        if (mapArgs.count("-?") || mapArgs.count("--help"))
        {
            // First part of help message is specific to bitcoind / RPC client
            std::string strUsage = _("Bitcoin version") + " " + FormatFullVersion() + "\n\n" +
                _("Usage:") + "\n" +
                  "  bitcoind [options]                     " + "\n" +
                  "  bitcoind [options] <command> [params]  " + _("Send command to -server or bitcoind") + "\n" +
                  "  bitcoind [options] help                " + _("List commands") + "\n" +
                  "  bitcoind [options] help <command>      " + _("Get help for a command") + "\n";

            strUsage += "\n" + HelpMessage();

            fprintf(stdout, "%s", strUsage.c_str());
            return false;
        }

        // Command-line RPC
        for (int i = 1; i < argc; i++)
            if (!IsSwitchChar(argv[i][0]) && !boost::algorithm::istarts_with(argv[i], "bitcoin:"))
                fCommandLine = true;

        if (fCommandLine)
        {
            int ret = CommandLineRPC(argc, argv);
            exit(ret);
        }
#ifndef WIN32
        fDaemon = GetBoolArg("-daemon", false);
        if (fDaemon)
        {
            // Daemonize
            pid_t pid = fork();
            if (pid < 0)
            {
                fprintf(stderr, "Error: fork() returned %d errno %d\n", pid, errno);
                return false;
            }
            if (pid > 0) // Parent process, pid is child process id
            {
                CreatePidFile(GetPidFile(), pid);
                return true;
            }
            // Child process falls through to rest of initialization

            pid_t sid = setsid();
            if (sid < 0)
                fprintf(stderr, "Error: setsid() returned %d errno %d\n", sid, errno);
        }
#endif

        detectShutdownThread = new boost::thread(boost::bind(&DetectShutdownThread, &threadGroup));
        fRet = AppInit2(threadGroup);
    }
    catch (std::exception& e) {
        PrintExceptionContinue(&e, "AppInit()");
    } catch (...) {
        PrintExceptionContinue(NULL, "AppInit()");
    }

    if (!fRet)
    {
        if (detectShutdownThread)
            detectShutdownThread->interrupt();

        threadGroup.interrupt_all();
        // threadGroup.join_all(); was left out intentionally here, because we didn't re-test all of
        // the startup-failure cases to make sure they don't result in a hang due to some
        // thread-blocking-waiting-for-another-thread-during-startup case
    }

    if (detectShutdownThread)
    {
        detectShutdownThread->join();
        delete detectShutdownThread;
        detectShutdownThread = NULL;
    }
    Shutdown();

    return fRet;
}

extern void noui_connect();
int main(int argc, char* argv[])
{
    bool fRet = false;
    fHaveGUI = false;

    // Connect bitcoind signal handlers
    noui_connect();

    fRet = AppInit(argc, argv);

    if (fRet && fDaemon)
        return 0;

    return (fRet ? 0 : 1);
}
<|endoftext|>


<commit_before>#include "string_utils.h"

#include <cwchar>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <string>
#include <memory>

#ifdef _MSC_VER
# define WIN32_LEAN_AND_MEAN
# define VC_EXTRALEAN
# include <windows.h>
// TODO use the functions below instead of the CRT versions (which break
//     on windows because msvcrt refuses any UTF-8 locale)
//     Using these should be enough to support unicode; fltk should accept
//     utf8 for its own internal use, and I use wide strings which are
//     OK on windows and seem to be okay on linux)
//
//     WideCharToMultiByte(CP_UTF8, 0, in.c_str(), in.size(), nullptr, &outLen, nullptr, nullptr);
//     WideCharToMultiByte(CP_UTF8, 0, in.c_str(), in.size(), out, &outLen, nullptr, nullptr);
//     MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, in, length, nullptr, &outLen, nullptr, nullptr);
//     MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, in, length, out, &outLen, nullptr, nullptr);
#endif

std::wstring MB2W(const char* in, size_t length)
{
    std::unique_ptr<char, std::default_delete<char[]>> store(new char[length + 1]);
    strncpy(store.get(), in, length);
    store.get()[length] = '\0';
    const char* s = store.get();
    mbstate_t ps;
    memset(&ps, 0, sizeof(ps));
#ifdef _MSC_VER
    int len = MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, in, length, nullptr, 0);
#else
    size_t len = mbsrtowcs(nullptr, &s, 0, &ps);
#endif
    if(len <= 0) return {};

    std::unique_ptr<wchar_t, std::default_delete<wchar_t[]>> ws(new wchar_t[len + 1]);
#ifdef _MSC_VER
    int written = MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, in, length, ws.get(), len + 1);
#else
    size_t written = mbsrtowcs(ws.get(), &s, len + 1, &ps);
#endif
    if(written != len) return {};

    return std::wstring(ws.get());
}

std::wstring MB2W(const char* in)
{
    return MB2W(in, strlen(in));
}

std::unique_ptr<char, std::default_delete<char[]>> W2MB(std::wstring const& in)
{
    const wchar_t* s = in.c_str();
    mbstate_t ps;
    memset(&ps, 0, sizeof(ps));
#ifdef _MSC_VER
    int len = WideCharToMultiByte(CP_UTF8, 0, s, in.size(), nullptr, 0, nullptr, nullptr);
#else
    int len = wcsrtombs(nullptr, &s, 0, &ps);
#endif
    if(len <= 0) return {};

    std::unique_ptr<char, std::default_delete<char[]>> mbs(new char[len + 1]);
#ifdef _MSC_VER
    int written = WideCharToMultiByte(CP_UTF8, 0, s, in.size(), mbs.get(), len + 1, nullptr, nullptr);
#else
    size_t written = wcsrtombs(mbs.get(), &s, len + 1, &ps);
#endif
    if(written != len) return {};

    return std::move(mbs);
}

#ifdef _MSC_VER
#include <fcntl.h>
#include <io.h>

FILE* open_read_unicode(const wchar_t* path)
{
    return _wfopen(path, L"rt, ccs=UTF-8");
}
FILE* reopen_read_unicode(FILE* f)
{
    int hr = _setmode( _fileno(f), _O_U8TEXT);
    return f;
}
FILE* open_write_binary(const wchar_t* path)
{
    return _wfopen(path, L"wb");
}
FILE* open_write_unicode(const wchar_t* path)
{
    return _wfopen(path, L"wt, ccs=UTF-8");
}
#else
FILE* open_read_unicode(const wchar_t* path)
{
    return fopen(W2MB(path).get(), "r");
}
FILE* reopen_read_unicode(FILE* f)
{
    return f;
}
FILE* open_write_binary(const wchar_t* path)
{
    return fopen(W2MB(path).get(), "wb");
}
FILE* open_write_unicode(const wchar_t* path)
{
    return fopen(W2MB(path).get(), "w");
}
#endif
<commit_msg>fix crash on clearing the text editor<commit_after>#include "string_utils.h"

#include <cwchar>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <string>
#include <memory>

#ifdef _MSC_VER
# define WIN32_LEAN_AND_MEAN
# define VC_EXTRALEAN
# include <windows.h>
// TODO use the functions below instead of the CRT versions (which break
//     on windows because msvcrt refuses any UTF-8 locale)
//     Using these should be enough to support unicode; fltk should accept
//     utf8 for its own internal use, and I use wide strings which are
//     OK on windows and seem to be okay on linux)
//
//     WideCharToMultiByte(CP_UTF8, 0, in.c_str(), in.size(), nullptr, &outLen, nullptr, nullptr);
//     WideCharToMultiByte(CP_UTF8, 0, in.c_str(), in.size(), out, &outLen, nullptr, nullptr);
//     MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, in, length, nullptr, &outLen, nullptr, nullptr);
//     MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, in, length, out, &outLen, nullptr, nullptr);
#endif

std::wstring MB2W(const char* in, size_t length)
{
    std::unique_ptr<char, std::default_delete<char[]>> store(new char[length + 1]);
    strncpy(store.get(), in, length);
    store.get()[length] = '\0';
    const char* s = store.get();
    mbstate_t ps;
    memset(&ps, 0, sizeof(ps));
#ifdef _MSC_VER
    int len = MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, in, length, nullptr, 0);
#else
    size_t len = mbsrtowcs(nullptr, &s, 0, &ps);
#endif
    if(len <= 0) return {};

    std::unique_ptr<wchar_t, std::default_delete<wchar_t[]>> ws(new wchar_t[len + 1]);
#ifdef _MSC_VER
    int written = MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, in, length, ws.get(), len + 1);
#else
    size_t written = mbsrtowcs(ws.get(), &s, len + 1, &ps);
#endif
    if(written != len) return {};

    return std::wstring(ws.get());
}

std::wstring MB2W(const char* in)
{
    return MB2W(in, strlen(in));
}

std::unique_ptr<char, std::default_delete<char[]>> W2MB(std::wstring const& in)
{
    std::unique_ptr<char, std::default_delete<char[]>> empty(new char[1]);
    empty.get()[0] = '\0';
    const wchar_t* s = in.c_str();
    mbstate_t ps;
    memset(&ps, 0, sizeof(ps));
#ifdef _MSC_VER
    int len = WideCharToMultiByte(CP_UTF8, 0, s, in.size(), nullptr, 0, nullptr, nullptr);
#else
    int len = wcsrtombs(nullptr, &s, 0, &ps);
#endif
    if(len <= 0) return std::move(empty);

    std::unique_ptr<char, std::default_delete<char[]>> mbs(new char[len + 1]);
#ifdef _MSC_VER
    int written = WideCharToMultiByte(CP_UTF8, 0, s, in.size(), mbs.get(), len + 1, nullptr, nullptr);
#else
    size_t written = wcsrtombs(mbs.get(), &s, len + 1, &ps);
#endif
    if(written != len) return std::move(empty);

    return std::move(mbs);
}

#ifdef _MSC_VER
#include <fcntl.h>
#include <io.h>

FILE* open_read_unicode(const wchar_t* path)
{
    return _wfopen(path, L"rt, ccs=UTF-8");
}
FILE* reopen_read_unicode(FILE* f)
{
    int hr = _setmode( _fileno(f), _O_U8TEXT);
    return f;
}
FILE* open_write_binary(const wchar_t* path)
{
    return _wfopen(path, L"wb");
}
FILE* open_write_unicode(const wchar_t* path)
{
    return _wfopen(path, L"wt, ccs=UTF-8");
}
#else
FILE* open_read_unicode(const wchar_t* path)
{
    return fopen(W2MB(path).get(), "r");
}
FILE* reopen_read_unicode(FILE* f)
{
    return f;
}
FILE* open_write_binary(const wchar_t* path)
{
    return fopen(W2MB(path).get(), "wb");
}
FILE* open_write_unicode(const wchar_t* path)
{
    return fopen(W2MB(path).get(), "w");
}
#endif
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2003-2004 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Gabe Black
 *          Ali Saidi
 */

#include "arch/sparc/isa_traits.hh"
#include "arch/sparc/process.hh"
#include "base/loader/object_file.hh"
#include "base/loader/elf_object.hh"
#include "base/misc.hh"
#include "cpu/thread_context.hh"
#include "mem/page_table.hh"
#include "mem/translating_port.hh"
#include "sim/system.hh"

using namespace std;
using namespace SparcISA;

SparcLiveProcess::SparcLiveProcess(const std::string &nm, ObjectFile *objFile,
        System *_system, int stdin_fd, int stdout_fd, int stderr_fd,
        std::vector<std::string> &argv, std::vector<std::string> &envp)
    : LiveProcess(nm, objFile, _system, stdin_fd, stdout_fd, stderr_fd,
        argv, envp)
{

    // XXX all the below need to be updated for SPARC - Ali
    brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize();
    brk_point = roundUp(brk_point, VMPageSize);

    // Set up stack. On SPARC Linux, stack goes from the top of memory
    // downward, less the hole for the kernel address space.
    stack_base = ((Addr)0x80000000000ULL);

    // Set up region for mmaps.  Tru64 seems to start just above 0 and
    // grow up from there.
    mmap_start = mmap_end = 0x800000;

    // Set pointer for next thread stack.  Reserve 8M for main stack.
    next_thread_stack_base = stack_base - (8 * 1024 * 1024);
}

void
SparcLiveProcess::startup()
{
    argsInit(MachineBytes, VMPageSize);

    //From the SPARC ABI

    //The process runs in user mode
    threadContexts[0]->setMiscRegWithEffect(MISCREG_PSTATE, 0x02);

    //Setup default FP state
    threadContexts[0]->setMiscReg(MISCREG_FSR, 0);

    threadContexts[0]->setMiscReg(MISCREG_TICK, 0);
    //
    /*
     * Register window management registers
     */

    //No windows contain info from other programs
    threadContexts[0]->setMiscRegWithEffect(MISCREG_OTHERWIN, 0);
    //There are no windows to pop
    threadContexts[0]->setMiscRegWithEffect(MISCREG_CANRESTORE, 0);
    //All windows are available to save into
    threadContexts[0]->setMiscRegWithEffect(MISCREG_CANSAVE, NWindows - 2);
    //All windows are "clean"
    threadContexts[0]->setMiscRegWithEffect(MISCREG_CLEANWIN, NWindows);
    //Start with register window 0
    threadContexts[0]->setMiscRegWithEffect(MISCREG_CWP, 0);
}

m5_auxv_t buildAuxVect(int64_t type, int64_t val)
{
    m5_auxv_t result;
    result.a_type = TheISA::htog(type);
    result.a_val = TheISA::htog(val);
    return result;
}

void
SparcLiveProcess::argsInit(int intSize, int pageSize)
{
    Process::startup();

    Addr alignmentMask = ~(intSize - 1);

    // load object file into target memory
    objFile->loadSections(initVirtMem);

    //These are the auxilliary vector types
    enum auxTypes
    {
        SPARC_AT_HWCAP = 16,
        SPARC_AT_PAGESZ = 6,
        SPARC_AT_CLKTCK = 17,
        SPARC_AT_PHDR = 3,
        SPARC_AT_PHENT = 4,
        SPARC_AT_PHNUM = 5,
        SPARC_AT_BASE = 7,
        SPARC_AT_FLAGS = 8,
        SPARC_AT_ENTRY = 9,
        SPARC_AT_UID = 11,
        SPARC_AT_EUID = 12,
        SPARC_AT_GID = 13,
        SPARC_AT_EGID = 14,
        SPARC_AT_SECURE = 23
    };

    enum hardwareCaps
    {
        M5_HWCAP_SPARC_FLUSH = 1,
        M5_HWCAP_SPARC_STBAR = 2,
        M5_HWCAP_SPARC_SWAP = 4,
        M5_HWCAP_SPARC_MULDIV = 8,
        M5_HWCAP_SPARC_V9 = 16,
        //This one should technically only be set
        //if there is a cheetah or cheetah_plus tlb,
        //but we'll use it all the time
        M5_HWCAP_SPARC_ULTRA3 = 32
    };

    const int64_t hwcap =
        M5_HWCAP_SPARC_FLUSH |
        M5_HWCAP_SPARC_STBAR |
        M5_HWCAP_SPARC_SWAP |
        M5_HWCAP_SPARC_MULDIV |
        M5_HWCAP_SPARC_V9 |
        M5_HWCAP_SPARC_ULTRA3;

    //Setup the auxilliary vectors. These will already have endian conversion.
    //Auxilliary vectors are loaded only for elf formatted executables.
    ElfObject * elfObject = dynamic_cast<ElfObject *>(objFile);
    if(elfObject)
    {
        //Bits which describe the system hardware capabilities
        auxv.push_back(buildAuxVect(SPARC_AT_HWCAP, hwcap));
        //The system page size
        auxv.push_back(buildAuxVect(SPARC_AT_PAGESZ, SparcISA::VMPageSize));
        //Defined to be 100 in the kernel source.
        //Frequency at which times() increments
        auxv.push_back(buildAuxVect(SPARC_AT_CLKTCK, 100));
        // For statically linked executables, this is the virtual address of the
        // program header tables if they appear in the executable image
        auxv.push_back(buildAuxVect(SPARC_AT_PHDR, elfObject->programHeaderTable()));
        // This is the size of a program header entry from the elf file.
        auxv.push_back(buildAuxVect(SPARC_AT_PHENT, elfObject->programHeaderSize()));
        // This is the number of program headers from the original elf file.
        auxv.push_back(buildAuxVect(SPARC_AT_PHNUM, elfObject->programHeaderCount()));
        //This is the address of the elf "interpreter", It should be set
        //to 0 for regular executables. It should be something else
        //(not sure what) for dynamic libraries.
        auxv.push_back(buildAuxVect(SPARC_AT_BASE, 0));
        //This is hardwired to 0 in the elf loading code in the kernel
        auxv.push_back(buildAuxVect(SPARC_AT_FLAGS, 0));
        //The entry point to the program
        auxv.push_back(buildAuxVect(SPARC_AT_ENTRY, objFile->entryPoint()));
        //Different user and group IDs
        auxv.push_back(buildAuxVect(SPARC_AT_UID, 100));
        auxv.push_back(buildAuxVect(SPARC_AT_EUID, 100));
        auxv.push_back(buildAuxVect(SPARC_AT_GID, 100));
        auxv.push_back(buildAuxVect(SPARC_AT_EGID, 100));
        //Whether to enable "secure mode" in the executable
        auxv.push_back(buildAuxVect(SPARC_AT_SECURE, 0));
    }

    //Figure out how big the initial stack needs to be

    //Each auxilliary vector is two 8 byte words
    int aux_data_size = 2 * intSize * auxv.size();
    int env_data_size = 0;
    for (int i = 0; i < envp.size(); ++i) {
        env_data_size += envp[i].size() + 1;
    }
    int arg_data_size = 0;
    for (int i = 0; i < argv.size(); ++i) {
        arg_data_size += argv[i].size() + 1;
    }

    int aux_array_size = intSize * 2 * (auxv.size() + 1);

    int argv_array_size = intSize * (argv.size() + 1);
    int envp_array_size = intSize * (envp.size() + 1);

    int argc_size = intSize;
    int window_save_size = intSize * 16;

    int info_block_size =
        (aux_data_size +
        env_data_size +
        arg_data_size +
        ~alignmentMask) & alignmentMask;

    int info_block_padding =
        info_block_size -
        aux_data_size -
        env_data_size -
        arg_data_size;

    int space_needed =
        info_block_size +
        aux_array_size +
        envp_array_size +
        argv_array_size +
        argc_size +
        window_save_size;

    stack_min = stack_base - space_needed;
    stack_min &= alignmentMask;
    stack_size = stack_base - stack_min;

    // map memory
    pTable->allocate(roundDown(stack_min, pageSize),
                     roundUp(stack_size, pageSize));

    // map out initial stack contents
    Addr aux_data_base = stack_base - aux_data_size - info_block_padding;
    Addr env_data_base = aux_data_base - env_data_size;
    Addr arg_data_base = env_data_base - arg_data_size;
    Addr auxv_array_base = arg_data_base - aux_array_size;
    Addr envp_array_base = auxv_array_base - envp_array_size;
    Addr argv_array_base = envp_array_base - argv_array_size;
    Addr argc_base = argv_array_base - argc_size;
#ifndef NDEBUG
    // only used in DPRINTF
    Addr window_save_base = argc_base - window_save_size;
#endif

    DPRINTF(Sparc, "The addresses of items on the initial stack:\n");
    DPRINTF(Sparc, "0x%x - aux data\n", aux_data_base);
    DPRINTF(Sparc, "0x%x - env data\n", env_data_base);
    DPRINTF(Sparc, "0x%x - arg data\n", arg_data_base);
    DPRINTF(Sparc, "0x%x - auxv array\n", auxv_array_base);
    DPRINTF(Sparc, "0x%x - envp array\n", envp_array_base);
    DPRINTF(Sparc, "0x%x - argv array\n", argv_array_base);
    DPRINTF(Sparc, "0x%x - argc \n", argc_base);
    DPRINTF(Sparc, "0x%x - window save\n", window_save_base);
    DPRINTF(Sparc, "0x%x - stack min\n", stack_min);

    // write contents to stack
    uint64_t argc = argv.size();
    uint64_t guestArgc = TheISA::htog(argc);

    //Copy the aux stuff
    for(int x = 0; x < auxv.size(); x++)
    {
        initVirtMem->writeBlob(auxv_array_base + x * 2 * intSize,
                (uint8_t*)&(auxv[x].a_type), intSize);
        initVirtMem->writeBlob(auxv_array_base + (x * 2 + 1) * intSize,
                (uint8_t*)&(auxv[x].a_val), intSize);
    }
    //Write out the terminating zeroed auxilliary vector
    const uint64_t zero = 0;
    initVirtMem->writeBlob(auxv_array_base + 2 * intSize * auxv.size(),
            (uint8_t*)&zero, 2 * intSize);

    copyStringArray(envp, envp_array_base, env_data_base, initVirtMem);
    copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem);

    initVirtMem->writeBlob(argc_base, (uint8_t*)&guestArgc, intSize);

    threadContexts[0]->setIntReg(ArgumentReg0, argc);
    threadContexts[0]->setIntReg(ArgumentReg1, argv_array_base);
    threadContexts[0]->setIntReg(StackPointerReg, stack_min - StackBias);

    Addr prog_entry = objFile->entryPoint();
    threadContexts[0]->setPC(prog_entry);
    threadContexts[0]->setNextPC(prog_entry + sizeof(MachInst));
    threadContexts[0]->setNextNPC(prog_entry + (2 * sizeof(MachInst)));

//    num_processes++;
}
<commit_msg>Got rid of the aux_data array since it shouldn't have existed. Added in the filename parameter which is provided for the user space linker. Fix the ordering and alignment of stack elements. Made mmap start with the address it has been seen starting with "in the wild"<commit_after>/*
 * Copyright (c) 2003-2004 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Gabe Black
 *          Ali Saidi
 */

#include "arch/sparc/isa_traits.hh"
#include "arch/sparc/process.hh"
#include "base/loader/object_file.hh"
#include "base/loader/elf_object.hh"
#include "base/misc.hh"
#include "cpu/thread_context.hh"
#include "mem/page_table.hh"
#include "mem/translating_port.hh"
#include "sim/system.hh"

using namespace std;
using namespace SparcISA;

SparcLiveProcess::SparcLiveProcess(const std::string &nm, ObjectFile *objFile,
        System *_system, int stdin_fd, int stdout_fd, int stderr_fd,
        std::vector<std::string> &argv, std::vector<std::string> &envp)
    : LiveProcess(nm, objFile, _system, stdin_fd, stdout_fd, stderr_fd,
        argv, envp)
{

    // XXX all the below need to be updated for SPARC - Ali
    brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize();
    brk_point = roundUp(brk_point, VMPageSize);

    // Set up stack. On SPARC Linux, stack goes from the top of memory
    // downward, less the hole for the kernel address space.
    stack_base = (Addr)0x80000000000ULL;

    // Set up region for mmaps.  Tru64 seems to start just above 0 and
    // grow up from there.
    mmap_start = mmap_end = 0xfffff80000000000ULL;

    // Set pointer for next thread stack.  Reserve 8M for main stack.
    next_thread_stack_base = stack_base - (8 * 1024 * 1024);
}

void
SparcLiveProcess::startup()
{
    argsInit(MachineBytes, VMPageSize);

    //From the SPARC ABI

    //The process runs in user mode
    threadContexts[0]->setMiscRegWithEffect(MISCREG_PSTATE, 0x02);

    //Setup default FP state
    threadContexts[0]->setMiscReg(MISCREG_FSR, 0);

    threadContexts[0]->setMiscReg(MISCREG_TICK, 0);
    //
    /*
     * Register window management registers
     */

    //No windows contain info from other programs
    threadContexts[0]->setMiscRegWithEffect(MISCREG_OTHERWIN, 0);
    //There are no windows to pop
    threadContexts[0]->setMiscRegWithEffect(MISCREG_CANRESTORE, 0);
    //All windows are available to save into
    threadContexts[0]->setMiscRegWithEffect(MISCREG_CANSAVE, NWindows - 2);
    //All windows are "clean"
    threadContexts[0]->setMiscRegWithEffect(MISCREG_CLEANWIN, NWindows);
    //Start with register window 0
    threadContexts[0]->setMiscRegWithEffect(MISCREG_CWP, 0);
}

m5_auxv_t buildAuxVect(int64_t type, int64_t val)
{
    m5_auxv_t result;
    result.a_type = TheISA::htog(type);
    result.a_val = TheISA::htog(val);
    return result;
}

void
SparcLiveProcess::argsInit(int intSize, int pageSize)
{
    Process::startup();

    string filename;
    if(argv.size() < 1)
        filename = "";
    else
        filename = argv[0];

    Addr alignmentMask = ~(intSize - 1);

    // load object file into target memory
    objFile->loadSections(initVirtMem);

    //These are the auxilliary vector types
    enum auxTypes
    {
        SPARC_AT_HWCAP = 16,
        SPARC_AT_PAGESZ = 6,
        SPARC_AT_CLKTCK = 17,
        SPARC_AT_PHDR = 3,
        SPARC_AT_PHENT = 4,
        SPARC_AT_PHNUM = 5,
        SPARC_AT_BASE = 7,
        SPARC_AT_FLAGS = 8,
        SPARC_AT_ENTRY = 9,
        SPARC_AT_UID = 11,
        SPARC_AT_EUID = 12,
        SPARC_AT_GID = 13,
        SPARC_AT_EGID = 14,
        SPARC_AT_SECURE = 23
    };

    enum hardwareCaps
    {
        M5_HWCAP_SPARC_FLUSH = 1,
        M5_HWCAP_SPARC_STBAR = 2,
        M5_HWCAP_SPARC_SWAP = 4,
        M5_HWCAP_SPARC_MULDIV = 8,
        M5_HWCAP_SPARC_V9 = 16,
        //This one should technically only be set
        //if there is a cheetah or cheetah_plus tlb,
        //but we'll use it all the time
        M5_HWCAP_SPARC_ULTRA3 = 32
    };

    const int64_t hwcap =
        M5_HWCAP_SPARC_FLUSH |
        M5_HWCAP_SPARC_STBAR |
        M5_HWCAP_SPARC_SWAP |
        M5_HWCAP_SPARC_MULDIV |
        M5_HWCAP_SPARC_V9 |
        M5_HWCAP_SPARC_ULTRA3;

    //Setup the auxilliary vectors. These will already have endian conversion.
    //Auxilliary vectors are loaded only for elf formatted executables.
    ElfObject * elfObject = dynamic_cast<ElfObject *>(objFile);
    if(elfObject)
    {
        //Bits which describe the system hardware capabilities
        auxv.push_back(buildAuxVect(SPARC_AT_HWCAP, hwcap));
        //The system page size
        auxv.push_back(buildAuxVect(SPARC_AT_PAGESZ, SparcISA::VMPageSize));
        //Defined to be 100 in the kernel source.
        //Frequency at which times() increments
        auxv.push_back(buildAuxVect(SPARC_AT_CLKTCK, 100));
        // For statically linked executables, this is the virtual address of the
        // program header tables if they appear in the executable image
        auxv.push_back(buildAuxVect(SPARC_AT_PHDR, elfObject->programHeaderTable()));
        // This is the size of a program header entry from the elf file.
        auxv.push_back(buildAuxVect(SPARC_AT_PHENT, elfObject->programHeaderSize()));
        // This is the number of program headers from the original elf file.
        auxv.push_back(buildAuxVect(SPARC_AT_PHNUM, elfObject->programHeaderCount()));
        //This is the address of the elf "interpreter", It should be set
        //to 0 for regular executables. It should be something else
        //(not sure what) for dynamic libraries.
        auxv.push_back(buildAuxVect(SPARC_AT_BASE, 0));
        //This is hardwired to 0 in the elf loading code in the kernel
        auxv.push_back(buildAuxVect(SPARC_AT_FLAGS, 0));
        //The entry point to the program
        auxv.push_back(buildAuxVect(SPARC_AT_ENTRY, objFile->entryPoint()));
        //Different user and group IDs
        auxv.push_back(buildAuxVect(SPARC_AT_UID, 100));
        auxv.push_back(buildAuxVect(SPARC_AT_EUID, 100));
        auxv.push_back(buildAuxVect(SPARC_AT_GID, 100));
        auxv.push_back(buildAuxVect(SPARC_AT_EGID, 100));
        //Whether to enable "secure mode" in the executable
        auxv.push_back(buildAuxVect(SPARC_AT_SECURE, 0));
    }

    //Figure out how big the initial stack needs to be

    // The unaccounted for 0 at the top of the stack
    int mysterious_size = intSize;

    //This is the name of the file which is present on the initial stack
    //It's purpose is to let the user space linker examine the original file.
    int file_name_size = filename.size() + 1;

    int env_data_size = 0;
    for (int i = 0; i < envp.size(); ++i) {
        env_data_size += envp[i].size() + 1;
    }
    int arg_data_size = 0;
    for (int i = 0; i < argv.size(); ++i) {
        arg_data_size += argv[i].size() + 1;
    }

    //The info_block needs to be padded so it's size is a multiple of the
    //alignment mask. Also, it appears that there needs to be at least some
    //padding, so if the size is already a multiple, we need to increase it
    //anyway.
    int info_block_size =
        (file_name_size +
        env_data_size +
        arg_data_size +
        intSize) & alignmentMask;

    int info_block_padding =
        info_block_size -
        file_name_size -
        env_data_size -
        arg_data_size;

    //Each auxilliary vector is two 8 byte words
    int aux_array_size = intSize * 2 * (auxv.size() + 1);

    int envp_array_size = intSize * (envp.size() + 1);
    int argv_array_size = intSize * (argv.size() + 1);

    int argc_size = intSize;
    int window_save_size = intSize * 16;

    int space_needed =
        mysterious_size +
        info_block_size +
        aux_array_size +
        envp_array_size +
        argv_array_size +
        argc_size +
        window_save_size;

    stack_min = stack_base - space_needed;
    stack_min &= alignmentMask;
    stack_size = stack_base - stack_min;

    // map memory
    pTable->allocate(roundDown(stack_min, pageSize),
                     roundUp(stack_size, pageSize));

    // map out initial stack contents
    Addr mysterious_base = stack_base - mysterious_size;
    Addr file_name_base = mysterious_base - file_name_size;
    Addr env_data_base = file_name_base - env_data_size;
    Addr arg_data_base = env_data_base - arg_data_size;
    Addr auxv_array_base = arg_data_base - aux_array_size - info_block_padding;
    Addr envp_array_base = auxv_array_base - envp_array_size;
    Addr argv_array_base = envp_array_base - argv_array_size;
    Addr argc_base = argv_array_base - argc_size;
#ifndef NDEBUG
    // only used in DPRINTF
    Addr window_save_base = argc_base - window_save_size;
#endif

    DPRINTF(Sparc, "The addresses of items on the initial stack:\n");
    DPRINTF(Sparc, "0x%x - file name\n", file_name_base);
    DPRINTF(Sparc, "0x%x - env data\n", env_data_base);
    DPRINTF(Sparc, "0x%x - arg data\n", arg_data_base);
    DPRINTF(Sparc, "0x%x - auxv array\n", auxv_array_base);
    DPRINTF(Sparc, "0x%x - envp array\n", envp_array_base);
    DPRINTF(Sparc, "0x%x - argv array\n", argv_array_base);
    DPRINTF(Sparc, "0x%x - argc \n", argc_base);
    DPRINTF(Sparc, "0x%x - window save\n", window_save_base);
    DPRINTF(Sparc, "0x%x - stack min\n", stack_min);

    // write contents to stack

    // figure out argc
    uint64_t argc = argv.size();
    uint64_t guestArgc = TheISA::htog(argc);

    //Write out the mysterious 0
    uint64_t mysterious_zero = 0;
    initVirtMem->writeBlob(mysterious_base,
            (uint8_t*)&mysterious_zero, mysterious_size);

    //Write the file name
    initVirtMem->writeString(file_name_base, filename.c_str());

    //Copy the aux stuff
    for(int x = 0; x < auxv.size(); x++)
    {
        initVirtMem->writeBlob(auxv_array_base + x * 2 * intSize,
                (uint8_t*)&(auxv[x].a_type), intSize);
        initVirtMem->writeBlob(auxv_array_base + (x * 2 + 1) * intSize,
                (uint8_t*)&(auxv[x].a_val), intSize);
    }
    //Write out the terminating zeroed auxilliary vector
    const uint64_t zero = 0;
    initVirtMem->writeBlob(auxv_array_base + 2 * intSize * auxv.size(),
            (uint8_t*)&zero, 2 * intSize);

    copyStringArray(envp, envp_array_base, env_data_base, initVirtMem);
    copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem);

    initVirtMem->writeBlob(argc_base, (uint8_t*)&guestArgc, intSize);

    threadContexts[0]->setIntReg(ArgumentReg0, argc);
    threadContexts[0]->setIntReg(ArgumentReg1, argv_array_base);
    threadContexts[0]->setIntReg(StackPointerReg, stack_min - StackBias);

    Addr prog_entry = objFile->entryPoint();
    threadContexts[0]->setPC(prog_entry);
    threadContexts[0]->setNextPC(prog_entry + sizeof(MachInst));
    threadContexts[0]->setNextNPC(prog_entry + (2 * sizeof(MachInst)));

//    num_processes++;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2015 - 2018 gtalent2@gmail.com
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#pragma once

#include <ox/std/trace.hpp>

#include "ptr.hpp"

namespace ox::ptrarith {

template<typename size_t, typename Item>
class __attribute__((packed)) NodeBuffer {

	public:
		struct __attribute__((packed)) Header {
			ox::LittleEndian<size_t> size = sizeof(Header); // capacity
			ox::LittleEndian<size_t> bytesUsed = sizeof(Header);
			ox::LittleEndian<size_t> firstItem = 0;
		};

		using ItemPtr = Ptr<Item, size_t, sizeof(Header)>;

		class Iterator {
			private:
				NodeBuffer *m_buffer = nullptr;
				ItemPtr m_current;
				size_t m_it = 0;

			public:
				Iterator(NodeBuffer *buffer, ItemPtr current) {
					m_buffer = buffer;
					m_current = current;
					oxTrace("ox::ptrarith::Iterator::start") << current.offset();
				}

				operator const Item*() const {
					return m_current;
				}

				ItemPtr ptr() {
					return m_current;
				}

				Item *get() {
					return m_current;
				}

				operator ItemPtr() {
					return m_current;
				}

				operator Item*() {
					return m_current;
				}

				const Item *operator->() const {
					return m_current;
				}

				Item *operator->() {
					return m_current;
				}

				[[nodiscard]] bool valid() const noexcept {
					return m_current.valid();
				}

				bool hasNext() {
					if (m_current.valid()) {
						oxTrace("ox::ptrarith::NodeBuffer::Iterator::hasNext::current") << m_current.offset();
						auto next = m_buffer->next(m_current);
						return next.valid() && m_buffer->firstItem() != next;
					}
					return false;
				}

				void next() {
					oxTrace("ox::ptrarith::NodeBuffer::Iterator::next") << m_it++;
					if (hasNext()) {
						m_current = m_buffer->next(m_current);
					} else {
						m_current = nullptr;
					}
				}
		};

		Header m_header;

	public:
		NodeBuffer() = default;

		NodeBuffer(const NodeBuffer &other);

		explicit NodeBuffer(size_t size);

		const Iterator iterator() const;

		Iterator iterator();

		ItemPtr firstItem();

		ItemPtr lastItem();

		/**
		 * @return the data section of the given item
		 */
		template<typename T>
		Ptr<T, size_t, sizeof(Item)> dataOf(ItemPtr);

		[[nodiscard]] ItemPtr prev(Item *item);

		[[nodiscard]] ItemPtr next(Item *item);

		[[nodiscard]] ItemPtr ptr(size_t offset);

		[[nodiscard]] ItemPtr ptr(void *item);

		[[nodiscard]] ItemPtr malloc(size_t size);

		[[nodiscard]] ox::Error free(ItemPtr item);

		[[nodiscard]] bool valid(size_t maxSize);

		/**
		 * Set size, capacity.
		 */
		[[nodiscard]] ox::Error setSize(size_t size);

		/**
		 * Get size, capacity.
		 * @return capacity
		 */
		size_t size();

		/**
		 * @return the bytes still available in this NodeBuffer
		 */
		size_t available();

		/**
		 * @return the actual number a bytes need to store the given number of
		 * bytes
		 */
		size_t spaceNeeded(size_t size);

		template<typename F>
		ox::Error compact(F cb = [](uint64_t, ItemPtr) {});

		void truncate();

	private:
		uint8_t *data();

};

template<typename size_t, typename Item>
NodeBuffer<size_t, Item>::NodeBuffer(size_t size) {
	m_header.size = size;
}

template<typename size_t, typename Item>
NodeBuffer<size_t, Item>::NodeBuffer(const NodeBuffer &other) {
	ox_memcpy(this, &other, other.size());
}

template<typename size_t, typename Item>
const typename NodeBuffer<size_t, Item>::Iterator NodeBuffer<size_t, Item>::iterator() const {
	return Iterator(this, firstItem());
}

template<typename size_t, typename Item>
typename NodeBuffer<size_t, Item>::Iterator NodeBuffer<size_t, Item>::iterator() {
	oxTrace("ox::ptrarith::NodeBuffer::iterator::size") << m_header.size;
	return Iterator(this, firstItem());
}

template<typename size_t, typename Item>
typename NodeBuffer<size_t, Item>::ItemPtr NodeBuffer<size_t, Item>::firstItem() {
	//oxTrace("ox::ptrarith::NodeBuffer::firstItem") << m_header.firstItem;
	return ptr(m_header.firstItem);
}

template<typename size_t, typename Item>
typename NodeBuffer<size_t, Item>::ItemPtr NodeBuffer<size_t, Item>::lastItem() {
	auto first = ptr(m_header.firstItem);
	if (first.valid()) {
		return prev(first);
	}
	return nullptr;
}

template<typename size_t, typename Item>
template<typename T>
Ptr<T, size_t, sizeof(Item)> NodeBuffer<size_t, Item>::dataOf(ItemPtr ip) {
	auto out = ip.template subPtr<T>(sizeof(Item));
	oxAssert(out.size() == ip.size() - sizeof(Item), "Sub Ptr has invalid size.");
	return out;
}

template<typename size_t, typename Item>
typename NodeBuffer<size_t, Item>::ItemPtr NodeBuffer<size_t, Item>::prev(Item *item) {
	return ptr(item->prev);
}

template<typename size_t, typename Item>
typename NodeBuffer<size_t, Item>::ItemPtr NodeBuffer<size_t, Item>::next(Item *item) {
	return ptr(item->next);
}

template<typename size_t, typename Item>
typename NodeBuffer<size_t, Item>::ItemPtr NodeBuffer<size_t, Item>::ptr(size_t itemOffset) {
	// make sure this can be read as an Item, and then use Item::size for the size
	std::size_t itemSpace = m_header.size - itemOffset;
	auto item = reinterpret_cast<Item*>(reinterpret_cast<uint8_t*>(this) + itemOffset);
	if (itemOffset >= sizeof(Header) &&
	    itemOffset + itemSpace <= size() &&
	    itemSpace >= sizeof(Item) &&
	    itemSpace >= item->fullSize()) {
		return ItemPtr(this, m_header.size, itemOffset, item->fullSize());
	} else {
		//oxTrace("ox::ptrarith::NodeBuffer::ptr::null") << "itemOffset:" << itemOffset;
		//oxTrace("ox::ptrarith::NodeBuffer::ptr::null") << "itemOffset >= sizeof(Header):" << (itemOffset >= sizeof(Header));
		//oxTrace("ox::ptrarith::NodeBuffer::ptr::null") << "itemSpace >= sizeof(Item):" << (itemSpace >= sizeof(Item));
		//oxTrace("ox::ptrarith::NodeBuffer::ptr::null") << "itemSpace >= item->fullSize():" << (itemSpace >= item->fullSize());
		return ItemPtr(this, m_header.size, 0, 0);
	}
}

template<typename size_t, typename Item>
typename NodeBuffer<size_t, Item>::ItemPtr NodeBuffer<size_t, Item>::malloc(size_t size) {
	oxTrace("ox::ptrarith::NodeBuffer::malloc") << "Size:" << size;
	size_t fullSize = size + sizeof(Item);
	if (m_header.size - m_header.bytesUsed >= fullSize) {
		auto last = lastItem();
		size_t addr = 0;
		if (last.valid()) {
			addr = last.offset() + last.size();
		} else {
			// there is no first item, so this must be the first item
			if (!m_header.firstItem) {
				oxTrace("ox::ptrarith::NodeBuffer::malloc") << "No first item, initializing.";
				m_header.firstItem = sizeof(m_header);
				addr = m_header.firstItem;
			}
		}
		auto out = ItemPtr(this, m_header.size, addr, fullSize);
		if (out.valid()) {
			new (out) Item;
			out->setSize(size);

			auto first = firstItem();
			auto oldLast = last;
			out->next = first.offset();
			if (first.valid()) {
				first->prev = out.offset();
			} else {
				oxTrace("ox::ptrarith::NodeBuffer::malloc::fail") << "NodeBuffer malloc failed due to invalid first element pointer.";
				return nullptr;
			}

			if (oldLast.valid()) {
				out->prev = oldLast.offset();
				oldLast->next = out.offset();
			} else { // check to see if this is the first allocation
				if (out.offset() != first.offset()) {
					// if this is not the first allocation, there should be an oldLast
					oxTrace("ox::ptrarith::NodeBuffer::malloc::fail") << "NodeBuffer malloc failed due to invalid last element pointer.";
					return nullptr;
				}
				out->prev = out.offset();
			}
			m_header.bytesUsed += out.size();
		} else {
			oxTrace("ox::ptrarith::NodeBuffer::malloc::fail") << "Unknown";
			return nullptr;
		}
		oxTrace("ox::ptrarith::NodeBuffer::malloc") << "Offset:" << out.offset();
		return out;
	}
	oxTrace("ox::ptrarith::NodeBuffer::malloc::fail") << "Insufficient space:" << fullSize << "needed," << available() << "available";
	return nullptr;
}

template<typename size_t, typename Item>
Error NodeBuffer<size_t, Item>::free(ItemPtr item) {
	oxTrace("ox::ptrarith::NodeBuffer::free") << "offset:" << item.offset();
	auto prev = this->prev(item);
	auto next = this->next(item);
	if (prev.valid() && next.valid()) {
		if (next != item) {
			prev->next = next;
			next->prev = prev;
			if (item.offset() == m_header.firstItem) {
				m_header.firstItem = next;
			}
		} else {
			// only one item, null out first
			oxTrace("ox::ptrarith::NodeBuffer::free") << "Nulling out firstItem.";
			m_header.firstItem = 0;
		}
	} else {
		if (!prev.valid()) {
			oxTrace("ox::ptrarith::NodeBuffer::free::fail") << "NodeBuffer free failed due to invalid prev element pointer:" << prev.offset();
			return OxError(1);
		}
		if (!next.valid()) {
			oxTrace("ox::ptrarith::NodeBuffer::free::fail") << "NodeBuffer free failed due to invalid next element pointer:" << next.offset();
			return OxError(1);
		}
	}
	m_header.bytesUsed -= item.size();
	return OxError(0);
}

template<typename size_t, typename Item>
Error NodeBuffer<size_t, Item>::setSize(size_t size) {
	oxTrace("ox::ptrarith::NodeBuffer::setSize") << size;
	auto last = lastItem();
	auto end = last.valid() ? last.end() : sizeof(m_header);
	oxTrace("ox::ptrarith::NodeBuffer::setSize") << "end:" << end;
	if (end > size) {
		return OxError(1);
	} else {
		m_header.size = size;
		return OxError(0);
	}
}

template<typename size_t, typename Item>
size_t NodeBuffer<size_t, Item>::size() {
	return m_header.size;
}

template<typename size_t, typename Item>
bool NodeBuffer<size_t, Item>::valid(size_t maxSize) {
	return m_header.size <= maxSize;
}

template<typename size_t, typename Item>
size_t NodeBuffer<size_t, Item>::available() {
	return m_header.size - m_header.bytesUsed;
}

template<typename size_t, typename Item>
size_t NodeBuffer<size_t, Item>::spaceNeeded(size_t size) {
	return sizeof(Item) + size;
}

template<typename size_t, typename Item>
template<typename F>
ox::Error NodeBuffer<size_t, Item>::compact(F cb) {
	auto src = firstItem();
	auto dest = ptr(sizeof(*this));
	while (src.valid() && dest.valid() && dest.offset() <= src.offset()) {
		// move node
		ox_memcpy(dest, src, src.size());
		oxReturnError(cb(src, dest));
		// update surrounding nodes
		auto prev = ptr(dest->prev);
		if (prev.valid()) {
			prev->next = dest;
		}
		auto next = ptr(dest->next);
		if (next.valid()) {
			next->prev = dest;
		}
		// update iterators
		src = ptr(dest->next);
		dest = ptr(dest.offset() + dest.size());
	}
	return OxError(0);
}

template<typename size_t, typename Item>
void NodeBuffer<size_t, Item>::truncate() {
	m_header.size = m_header.bytesUsed;
}

template<typename size_t, typename Item>
uint8_t *NodeBuffer<size_t, Item>::data() {
	return reinterpret_cast<uint8_t*>(ptr(sizeof(*this)).get());
}

template<typename size_t>
struct __attribute__((packed)) Item {
	public:
		ox::LittleEndian<size_t> prev = 0;
		ox::LittleEndian<size_t> next = 0;

	private:
		ox::LittleEndian<size_t> m_size = sizeof(Item);

	public:
		size_t size() const {
			return m_size;
		}

		void setSize(size_t size) {
			m_size = size;
		}
};

}
<commit_msg>[ox/ptrarith] Add nodiscard to Error return of NodeBuffer::compact<commit_after>/*
 * Copyright 2015 - 2018 gtalent2@gmail.com
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#pragma once

#include <ox/std/trace.hpp>

#include "ptr.hpp"

namespace ox::ptrarith {

template<typename size_t, typename Item>
class __attribute__((packed)) NodeBuffer {

	public:
		struct __attribute__((packed)) Header {
			ox::LittleEndian<size_t> size = sizeof(Header); // capacity
			ox::LittleEndian<size_t> bytesUsed = sizeof(Header);
			ox::LittleEndian<size_t> firstItem = 0;
		};

		using ItemPtr = Ptr<Item, size_t, sizeof(Header)>;

		class Iterator {
			private:
				NodeBuffer *m_buffer = nullptr;
				ItemPtr m_current;
				size_t m_it = 0;

			public:
				Iterator(NodeBuffer *buffer, ItemPtr current) {
					m_buffer = buffer;
					m_current = current;
					oxTrace("ox::ptrarith::Iterator::start") << current.offset();
				}

				operator const Item*() const {
					return m_current;
				}

				ItemPtr ptr() {
					return m_current;
				}

				Item *get() {
					return m_current;
				}

				operator ItemPtr() {
					return m_current;
				}

				operator Item*() {
					return m_current;
				}

				const Item *operator->() const {
					return m_current;
				}

				Item *operator->() {
					return m_current;
				}

				[[nodiscard]] bool valid() const noexcept {
					return m_current.valid();
				}

				bool hasNext() {
					if (m_current.valid()) {
						oxTrace("ox::ptrarith::NodeBuffer::Iterator::hasNext::current") << m_current.offset();
						auto next = m_buffer->next(m_current);
						return next.valid() && m_buffer->firstItem() != next;
					}
					return false;
				}

				void next() {
					oxTrace("ox::ptrarith::NodeBuffer::Iterator::next") << m_it++;
					if (hasNext()) {
						m_current = m_buffer->next(m_current);
					} else {
						m_current = nullptr;
					}
				}
		};

		Header m_header;

	public:
		NodeBuffer() = default;

		NodeBuffer(const NodeBuffer &other);

		explicit NodeBuffer(size_t size);

		const Iterator iterator() const;

		Iterator iterator();

		ItemPtr firstItem();

		ItemPtr lastItem();

		/**
		 * @return the data section of the given item
		 */
		template<typename T>
		Ptr<T, size_t, sizeof(Item)> dataOf(ItemPtr);

		[[nodiscard]] ItemPtr prev(Item *item);

		[[nodiscard]] ItemPtr next(Item *item);

		[[nodiscard]] ItemPtr ptr(size_t offset);

		[[nodiscard]] ItemPtr ptr(void *item);

		[[nodiscard]] ItemPtr malloc(size_t size);

		[[nodiscard]] ox::Error free(ItemPtr item);

		[[nodiscard]] bool valid(size_t maxSize);

		/**
		 * Set size, capacity.
		 */
		[[nodiscard]] ox::Error setSize(size_t size);

		/**
		 * Get size, capacity.
		 * @return capacity
		 */
		size_t size();

		/**
		 * @return the bytes still available in this NodeBuffer
		 */
		size_t available();

		/**
		 * @return the actual number a bytes need to store the given number of
		 * bytes
		 */
		size_t spaceNeeded(size_t size);

		template<typename F>
		[[nodiscard]] ox::Error compact(F cb = [](uint64_t, ItemPtr) {});

		void truncate();

	private:
		uint8_t *data();

};

template<typename size_t, typename Item>
NodeBuffer<size_t, Item>::NodeBuffer(size_t size) {
	m_header.size = size;
}

template<typename size_t, typename Item>
NodeBuffer<size_t, Item>::NodeBuffer(const NodeBuffer &other) {
	ox_memcpy(this, &other, other.size());
}

template<typename size_t, typename Item>
const typename NodeBuffer<size_t, Item>::Iterator NodeBuffer<size_t, Item>::iterator() const {
	return Iterator(this, firstItem());
}

template<typename size_t, typename Item>
typename NodeBuffer<size_t, Item>::Iterator NodeBuffer<size_t, Item>::iterator() {
	oxTrace("ox::ptrarith::NodeBuffer::iterator::size") << m_header.size;
	return Iterator(this, firstItem());
}

template<typename size_t, typename Item>
typename NodeBuffer<size_t, Item>::ItemPtr NodeBuffer<size_t, Item>::firstItem() {
	//oxTrace("ox::ptrarith::NodeBuffer::firstItem") << m_header.firstItem;
	return ptr(m_header.firstItem);
}

template<typename size_t, typename Item>
typename NodeBuffer<size_t, Item>::ItemPtr NodeBuffer<size_t, Item>::lastItem() {
	auto first = ptr(m_header.firstItem);
	if (first.valid()) {
		return prev(first);
	}
	return nullptr;
}

template<typename size_t, typename Item>
template<typename T>
Ptr<T, size_t, sizeof(Item)> NodeBuffer<size_t, Item>::dataOf(ItemPtr ip) {
	auto out = ip.template subPtr<T>(sizeof(Item));
	oxAssert(out.size() == ip.size() - sizeof(Item), "Sub Ptr has invalid size.");
	return out;
}

template<typename size_t, typename Item>
typename NodeBuffer<size_t, Item>::ItemPtr NodeBuffer<size_t, Item>::prev(Item *item) {
	return ptr(item->prev);
}

template<typename size_t, typename Item>
typename NodeBuffer<size_t, Item>::ItemPtr NodeBuffer<size_t, Item>::next(Item *item) {
	return ptr(item->next);
}

template<typename size_t, typename Item>
typename NodeBuffer<size_t, Item>::ItemPtr NodeBuffer<size_t, Item>::ptr(size_t itemOffset) {
	// make sure this can be read as an Item, and then use Item::size for the size
	std::size_t itemSpace = m_header.size - itemOffset;
	auto item = reinterpret_cast<Item*>(reinterpret_cast<uint8_t*>(this) + itemOffset);
	if (itemOffset >= sizeof(Header) &&
	    itemOffset + itemSpace <= size() &&
	    itemSpace >= sizeof(Item) &&
	    itemSpace >= item->fullSize()) {
		return ItemPtr(this, m_header.size, itemOffset, item->fullSize());
	} else {
		//oxTrace("ox::ptrarith::NodeBuffer::ptr::null") << "itemOffset:" << itemOffset;
		//oxTrace("ox::ptrarith::NodeBuffer::ptr::null") << "itemOffset >= sizeof(Header):" << (itemOffset >= sizeof(Header));
		//oxTrace("ox::ptrarith::NodeBuffer::ptr::null") << "itemSpace >= sizeof(Item):" << (itemSpace >= sizeof(Item));
		//oxTrace("ox::ptrarith::NodeBuffer::ptr::null") << "itemSpace >= item->fullSize():" << (itemSpace >= item->fullSize());
		return ItemPtr(this, m_header.size, 0, 0);
	}
}

template<typename size_t, typename Item>
typename NodeBuffer<size_t, Item>::ItemPtr NodeBuffer<size_t, Item>::malloc(size_t size) {
	oxTrace("ox::ptrarith::NodeBuffer::malloc") << "Size:" << size;
	size_t fullSize = size + sizeof(Item);
	if (m_header.size - m_header.bytesUsed >= fullSize) {
		auto last = lastItem();
		size_t addr = 0;
		if (last.valid()) {
			addr = last.offset() + last.size();
		} else {
			// there is no first item, so this must be the first item
			if (!m_header.firstItem) {
				oxTrace("ox::ptrarith::NodeBuffer::malloc") << "No first item, initializing.";
				m_header.firstItem = sizeof(m_header);
				addr = m_header.firstItem;
			}
		}
		auto out = ItemPtr(this, m_header.size, addr, fullSize);
		if (out.valid()) {
			new (out) Item;
			out->setSize(size);

			auto first = firstItem();
			auto oldLast = last;
			out->next = first.offset();
			if (first.valid()) {
				first->prev = out.offset();
			} else {
				oxTrace("ox::ptrarith::NodeBuffer::malloc::fail") << "NodeBuffer malloc failed due to invalid first element pointer.";
				return nullptr;
			}

			if (oldLast.valid()) {
				out->prev = oldLast.offset();
				oldLast->next = out.offset();
			} else { // check to see if this is the first allocation
				if (out.offset() != first.offset()) {
					// if this is not the first allocation, there should be an oldLast
					oxTrace("ox::ptrarith::NodeBuffer::malloc::fail") << "NodeBuffer malloc failed due to invalid last element pointer.";
					return nullptr;
				}
				out->prev = out.offset();
			}
			m_header.bytesUsed += out.size();
		} else {
			oxTrace("ox::ptrarith::NodeBuffer::malloc::fail") << "Unknown";
			return nullptr;
		}
		oxTrace("ox::ptrarith::NodeBuffer::malloc") << "Offset:" << out.offset();
		return out;
	}
	oxTrace("ox::ptrarith::NodeBuffer::malloc::fail") << "Insufficient space:" << fullSize << "needed," << available() << "available";
	return nullptr;
}

template<typename size_t, typename Item>
Error NodeBuffer<size_t, Item>::free(ItemPtr item) {
	oxTrace("ox::ptrarith::NodeBuffer::free") << "offset:" << item.offset();
	auto prev = this->prev(item);
	auto next = this->next(item);
	if (prev.valid() && next.valid()) {
		if (next != item) {
			prev->next = next;
			next->prev = prev;
			if (item.offset() == m_header.firstItem) {
				m_header.firstItem = next;
			}
		} else {
			// only one item, null out first
			oxTrace("ox::ptrarith::NodeBuffer::free") << "Nulling out firstItem.";
			m_header.firstItem = 0;
		}
	} else {
		if (!prev.valid()) {
			oxTrace("ox::ptrarith::NodeBuffer::free::fail") << "NodeBuffer free failed due to invalid prev element pointer:" << prev.offset();
			return OxError(1);
		}
		if (!next.valid()) {
			oxTrace("ox::ptrarith::NodeBuffer::free::fail") << "NodeBuffer free failed due to invalid next element pointer:" << next.offset();
			return OxError(1);
		}
	}
	m_header.bytesUsed -= item.size();
	return OxError(0);
}

template<typename size_t, typename Item>
Error NodeBuffer<size_t, Item>::setSize(size_t size) {
	oxTrace("ox::ptrarith::NodeBuffer::setSize") << size;
	auto last = lastItem();
	auto end = last.valid() ? last.end() : sizeof(m_header);
	oxTrace("ox::ptrarith::NodeBuffer::setSize") << "end:" << end;
	if (end > size) {
		return OxError(1);
	} else {
		m_header.size = size;
		return OxError(0);
	}
}

template<typename size_t, typename Item>
size_t NodeBuffer<size_t, Item>::size() {
	return m_header.size;
}

template<typename size_t, typename Item>
bool NodeBuffer<size_t, Item>::valid(size_t maxSize) {
	return m_header.size <= maxSize;
}

template<typename size_t, typename Item>
size_t NodeBuffer<size_t, Item>::available() {
	return m_header.size - m_header.bytesUsed;
}

template<typename size_t, typename Item>
size_t NodeBuffer<size_t, Item>::spaceNeeded(size_t size) {
	return sizeof(Item) + size;
}

template<typename size_t, typename Item>
template<typename F>
ox::Error NodeBuffer<size_t, Item>::compact(F cb) {
	auto src = firstItem();
	auto dest = ptr(sizeof(*this));
	while (src.valid() && dest.valid() && dest.offset() <= src.offset()) {
		// move node
		ox_memcpy(dest, src, src.size());
		oxReturnError(cb(src, dest));
		// update surrounding nodes
		auto prev = ptr(dest->prev);
		if (prev.valid()) {
			prev->next = dest;
		}
		auto next = ptr(dest->next);
		if (next.valid()) {
			next->prev = dest;
		}
		// update iterators
		src = ptr(dest->next);
		dest = ptr(dest.offset() + dest.size());
	}
	return OxError(0);
}

template<typename size_t, typename Item>
void NodeBuffer<size_t, Item>::truncate() {
	m_header.size = m_header.bytesUsed;
}

template<typename size_t, typename Item>
uint8_t *NodeBuffer<size_t, Item>::data() {
	return reinterpret_cast<uint8_t*>(ptr(sizeof(*this)).get());
}

template<typename size_t>
struct __attribute__((packed)) Item {
	public:
		ox::LittleEndian<size_t> prev = 0;
		ox::LittleEndian<size_t> next = 0;

	private:
		ox::LittleEndian<size_t> m_size = sizeof(Item);

	public:
		size_t size() const {
			return m_size;
		}

		void setSize(size_t size) {
			m_size = size;
		}
};

}
<|endoftext|>


<commit_before>#include <omp.h>
#include <stdio.h>
#include <opencv2/opencv.hpp>
#include <fstream>
#include <iostream>
#include <armadillo>
#include <iomanip>
#include <vector>

using namespace std;
using namespace arma;

#include "optflow-feat-def.hpp"
#include "optflow-feat-impl.hpp"

//Home
//const std::string path = "/media/johanna/HD1T/codes/datasets_codes/KTH/";

//WANDA
const std::string path = "/home/johanna/codes/datasets_codes/KTH/";

const std::string peopleList = "people_list.txt";
const std::string  actionNames = "actionNames.txt";

///kth
int ori_col = 160;
int ori_row = 120;

int
main(int argc, char** argv)
{

   if(argc < 3 )
  {
    cout << "usage: " << argv[0] << " scale_factor " << " shift_factor " << endl;
    return -1;
  }

  int scale_factor = atoi( argv[1] );
  int shift = atoi( argv[2] );
  int total_scene = 1;
  int dim = 12; // Without x and y.

  field<string> all_people;
  all_people.load(peopleList);

  opt_feat opt_feat_kth(path, actionNames, ori_col, ori_row, scale_factor, shift, total_scene, dim);
  opt_feat_kth.features_all_videos( all_people );

  return 0;

}
<commit_msg>Run Features dim12 all_shifts<commit_after>#include <omp.h>
#include <stdio.h>
#include <opencv2/opencv.hpp>
#include <fstream>
#include <iostream>
#include <armadillo>
#include <iomanip>
#include <vector>

using namespace std;
using namespace arma;

#include "optflow-feat-def.hpp"
#include "optflow-feat-impl.hpp"

//Home
//const std::string path = "/media/johanna/HD1T/codes/datasets_codes/KTH/";

//WANDA
const std::string path = "/home/johanna/codes/datasets_codes/KTH/";

const std::string peopleList = "people_list.txt";
const std::string  actionNames = "actionNames.txt";

///kth
int ori_col = 160;
int ori_row = 120;

int
main(int argc, char** argv)
{

  vec vec_shift;
  vec_shift << -25 << -20 << -15 << -10 << -5 << 5 << 10 << 15 << 20 << 25 << endr;
  int scale_factor =1;

  int total_scene = 1;
  int dim = 12; // Without x and y.

  field<string> all_people;
  all_people.load(peopleList);

  for (int i=0; i< vec_shift.n_elem; ++i)
  {

    int shift = vec_shift(i);
    cout << "Features for for shift " << shift << endl;
    opt_feat opt_feat_kth(path, actionNames, ori_col, ori_row, scale_factor, shift, total_scene, dim);
    opt_feat_kth.features_all_videos( all_people );
  }

  return 0;

}

// int
// main(int argc, char** argv)
// {
//
//    if(argc < 3 )
//   {
//     cout << "usage: " << argv[0] << " scale_factor " << " shift_factor " << endl;
//     return -1;
//   }
//
//
//   int scale_factor = atoi( argv[1] );
//   int shift = atoi( argv[2] );
//   int total_scene = 1;
//   int dim = 12; // Without x and y.
//
//   field<string> all_people;
//   all_people.load(peopleList);
//
//   opt_feat opt_feat_kth(path, actionNames, ori_col, ori_row, scale_factor, shift, total_scene, dim);
//   opt_feat_kth.features_all_videos( all_people );
//
//
//
//
//   return 0;
//
// }
<|endoftext|>