<commit_before>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
** This file is part of the Qt Linguist of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the either Technology Preview License Agreement or the
** Beta Release License Agreement.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights. These rights are described in the Nokia Qt LGPL
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/

#include "lupdate.h"

#include <translator.h>

#include <QtCore/QDebug>
#include <QtCore/QFile>
#include <QtCore/QString>

QT_BEGIN_NAMESPACE

#include "parser/javascriptengine_p.h"
#include "parser/javascriptparser_p.h"
#include "parser/javascriptlexer_p.h"
#include "parser/javascriptnodepool_p.h"
#include "parser/javascriptastvisitor_p.h"
#include "parser/javascriptast_p.h"

#include <QCoreApplication>
#include <QFile>
#include <QFileInfo>
#include <QtDebug>
#include <QStringList>

#include <iostream>
#include <cstdlib>

using namespace JavaScript;

class FindTrCalls: protected AST::Visitor
{
public:
    void operator()(Translator *translator, const QString &fileName, AST::Node *node)
    {
        m_translator = translator;
        m_fileName = fileName;
        m_component = QFileInfo(fileName).baseName();   //matches qsTr usage in QScriptEngine
        accept(node);
    }

protected:
    using AST::Visitor::visit;
    using AST::Visitor::endVisit;

    void accept(AST::Node *node)
    { AST::Node::acceptChild(node, this); }

    virtual void endVisit(AST::CallExpression *node)
    {
        if (AST::IdentifierExpression *idExpr = AST::cast<AST::IdentifierExpression *>(node->base)) {
            if (idExpr->name->asString() == QLatin1String("qsTr")) {
                if (node->arguments && AST::cast<AST::StringLiteral *>(node->arguments->expression)) {
                    AST::StringLiteral *literal = AST::cast<AST::StringLiteral *>(node->arguments->expression);
                    const QString source = literal->value->asString();

                    QString comment;
                    bool plural = false;
                    AST::ArgumentList *commentNode = node->arguments->next;
                    if (commentNode) {
                        literal = AST::cast<AST::StringLiteral *>(commentNode->expression);
                        comment = literal->value->asString();

                        AST::ArgumentList *nNode = commentNode->next;
                        if (nNode) {
                            AST::NumericLiteral *literal3 = AST::cast<AST::NumericLiteral *>(nNode->expression);
                            if (literal3) {
                                plural = true;
                            }
                        }
                    }

                    TranslatorMessage msg(m_component, source,
                        comment, QString(), m_fileName,
                        node->firstSourceLocation().startLine, QStringList(),
                        TranslatorMessage::Unfinished, plural);
                    m_translator->extend(msg);
                }
            }
            //### support qsTranslate, QT_TR_NOOP, and QT_TRANSLATE_NOOP
        }
    }

private:
    Translator *m_translator;
    QString m_fileName;
    QString m_component;
};

QString createErrorString(const QString &filename, const QString &code, Parser &parser)
{
    // print out error
    QStringList lines = code.split(QLatin1Char('\n'));
    lines.append(QLatin1String("\n")); // sentinel.
    QString errorString;

    foreach (const DiagnosticMessage &m, parser.diagnosticMessages()) {

        if (m.isWarning())
            continue;

        QString error = filename + QLatin1Char(':') + QString::number(m.loc.startLine)
                        + QLatin1Char(':') + QString::number(m.loc.startColumn) + QLatin1String(": error: ")
                        + m.message + QLatin1Char('\n');

        int line = 0;
        if (m.loc.startLine > 0)
            line = m.loc.startLine - 1;

        const QString textLine = lines.at(line);

        error += textLine + QLatin1Char('\n');

        int column = m.loc.startColumn - 1;
        if (column < 0)
            column = 0;

        column = qMin(column, textLine.length());

        for (int i = 0; i < column; ++i) {
            const QChar ch = textLine.at(i);
            if (ch.isSpace())
                error += ch.unicode();
            else
                error += QLatin1Char(' ');
        }
        error += QLatin1String("^\n");
        errorString += error;
    }
    return errorString;
}

bool loadQml(Translator &translator, const QString &filename, ConversionData &cd)
{
    cd.m_sourceFileName = filename;
    QFile file(filename);
    if (!file.open(QIODevice::ReadOnly)) {
        cd.appendError(QString::fromLatin1("Cannot open %1: %2")
            .arg(filename, file.errorString()));
        return false;
    }

    const QString code = QTextStream(&file).readAll();

    Engine driver;
    Parser parser(&driver);

    NodePool nodePool(filename, &driver);
    driver.setNodePool(&nodePool);

    Lexer lexer(&driver);
    lexer.setCode(code, /*line = */ 1);
    driver.setLexer(&lexer);

    if (parser.parse()) {
        FindTrCalls trCalls;
        trCalls(&translator, filename, parser.ast());
    } else {
        QString error = createErrorString(filename, code, parser);
        cd.appendError(error);
        return false;
    }
    return true;
}

QT_END_NAMESPACE
<commit_msg>Add support for qsTranslate, QT_TR_NOOP, and QT_TRANSLATE_NOOP.<commit_after>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
** This file is part of the Qt Linguist of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the either Technology Preview License Agreement or the
** Beta Release License Agreement.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights. These rights are described in the Nokia Qt LGPL
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/

#include "lupdate.h"

#include <translator.h>

#include <QtCore/QDebug>
#include <QtCore/QFile>
#include <QtCore/QString>

QT_BEGIN_NAMESPACE

#include "parser/javascriptengine_p.h"
#include "parser/javascriptparser_p.h"
#include "parser/javascriptlexer_p.h"
#include "parser/javascriptnodepool_p.h"
#include "parser/javascriptastvisitor_p.h"
#include "parser/javascriptast_p.h"

#include <QCoreApplication>
#include <QFile>
#include <QFileInfo>
#include <QtDebug>
#include <QStringList>

#include <iostream>
#include <cstdlib>

using namespace JavaScript;

class FindTrCalls: protected AST::Visitor
{
public:
    void operator()(Translator *translator, const QString &fileName, AST::Node *node)
    {
        m_translator = translator;
        m_fileName = fileName;
        m_component = QFileInfo(fileName).baseName();   //matches qsTr usage in QScriptEngine
        accept(node);
    }

protected:
    using AST::Visitor::visit;
    using AST::Visitor::endVisit;

    void accept(AST::Node *node)
    { AST::Node::acceptChild(node, this); }

    virtual void endVisit(AST::CallExpression *node)
    {
        if (AST::IdentifierExpression *idExpr = AST::cast<AST::IdentifierExpression *>(node->base)) {
            if (idExpr->name->asString() == QLatin1String("qsTr") ||
                idExpr->name->asString() == QLatin1String("QT_TR_NOOP")) {
                if (node->arguments && AST::cast<AST::StringLiteral *>(node->arguments->expression)) {
                    AST::StringLiteral *literal = AST::cast<AST::StringLiteral *>(node->arguments->expression);
                    const QString source = literal->value->asString();

                    QString comment;
                    bool plural = false;
                    AST::ArgumentList *commentNode = node->arguments->next;
                    if (commentNode) {
                        literal = AST::cast<AST::StringLiteral *>(commentNode->expression);
                        comment = literal->value->asString();

                        AST::ArgumentList *nNode = commentNode->next;
                        if (nNode) {
                            AST::NumericLiteral *numLiteral = AST::cast<AST::NumericLiteral *>(nNode->expression);
                            if (numLiteral) {
                                plural = true;
                            }
                        }
                    }

                    TranslatorMessage msg(m_component, source,
                        comment, QString(), m_fileName,
                        node->firstSourceLocation().startLine, QStringList(),
                        TranslatorMessage::Unfinished, plural);
                    m_translator->extend(msg);
                }
            } else if (idExpr->name->asString() == QLatin1String("qsTranslate") ||
                       idExpr->name->asString() == QLatin1String("QT_TRANSLATE_NOOP")) {
                if (node->arguments && AST::cast<AST::StringLiteral *>(node->arguments->expression)) {
                    AST::StringLiteral *literal = AST::cast<AST::StringLiteral *>(node->arguments->expression);
                    const QString context = literal->value->asString();

                    QString source;
                    QString comment;
                    bool plural = false;
                    AST::ArgumentList *sourceNode = node->arguments->next;
                    if (sourceNode) {
                        literal = AST::cast<AST::StringLiteral *>(sourceNode->expression);
                        source = literal->value->asString();
                        AST::ArgumentList *commentNode = sourceNode->next;
                        if (commentNode) {
                            literal = AST::cast<AST::StringLiteral *>(commentNode->expression);
                            comment = literal->value->asString();

                            AST::ArgumentList *nNode = commentNode->next;
                            if (nNode) {
                                AST::NumericLiteral *numLiteral = AST::cast<AST::NumericLiteral *>(nNode->expression);
                                if (numLiteral) {
                                    plural = true;
                                }
                            }
                        }
                    }

                    TranslatorMessage msg(context, source,
                        comment, QString(), m_fileName,
                        node->firstSourceLocation().startLine, QStringList(),
                        TranslatorMessage::Unfinished, plural);
                    m_translator->extend(msg);
                }

            }
        }
    }

private:
    Translator *m_translator;
    QString m_fileName;
    QString m_component;
};

QString createErrorString(const QString &filename, const QString &code, Parser &parser)
{
    // print out error
    QStringList lines = code.split(QLatin1Char('\n'));
    lines.append(QLatin1String("\n")); // sentinel.
    QString errorString;

    foreach (const DiagnosticMessage &m, parser.diagnosticMessages()) {

        if (m.isWarning())
            continue;

        QString error = filename + QLatin1Char(':') + QString::number(m.loc.startLine)
                        + QLatin1Char(':') + QString::number(m.loc.startColumn) + QLatin1String(": error: ")
                        + m.message + QLatin1Char('\n');

        int line = 0;
        if (m.loc.startLine > 0)
            line = m.loc.startLine - 1;

        const QString textLine = lines.at(line);

        error += textLine + QLatin1Char('\n');

        int column = m.loc.startColumn - 1;
        if (column < 0)
            column = 0;

        column = qMin(column, textLine.length());

        for (int i = 0; i < column; ++i) {
            const QChar ch = textLine.at(i);
            if (ch.isSpace())
                error += ch.unicode();
            else
                error += QLatin1Char(' ');
        }
        error += QLatin1String("^\n");
        errorString += error;
    }
    return errorString;
}

bool loadQml(Translator &translator, const QString &filename, ConversionData &cd)
{
    cd.m_sourceFileName = filename;
    QFile file(filename);
    if (!file.open(QIODevice::ReadOnly)) {
        cd.appendError(QString::fromLatin1("Cannot open %1: %2")
            .arg(filename, file.errorString()));
        return false;
    }

    const QString code = QTextStream(&file).readAll();

    Engine driver;
    Parser parser(&driver);

    NodePool nodePool(filename, &driver);
    driver.setNodePool(&nodePool);

    Lexer lexer(&driver);
    lexer.setCode(code, /*line = */ 1);
    driver.setLexer(&lexer);

    if (parser.parse()) {
        FindTrCalls trCalls;
        trCalls(&translator, filename, parser.ast());
    } else {
        QString error = createErrorString(filename, code, parser);
        cd.appendError(error);
        return false;
    }
    return true;
}

QT_END_NAMESPACE
<|endoftext|>


<commit_before>// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp

#include <Nazara/Utility/PixelFormat.hpp>
#include <Nazara/Core/Error.hpp>
#include <algorithm>
#include <array>
#include <cstring>
#include <Nazara/Utility/Debug.hpp>

namespace Nz
{
	inline PixelFormatInfo::PixelFormatInfo() :
	content(PixelFormatContent_Undefined),
	bitsPerPixel(0)
	{
	}

	inline PixelFormatInfo::PixelFormatInfo(PixelFormatContent formatContent, UInt8 bpp, PixelFormatSubType subType) :
	content(formatContent),
	redType(subType),
	greenType(subType),
	blueType(subType),
	alphaType(subType),
	bitsPerPixel(bpp)
	{
	}

	inline PixelFormatInfo::PixelFormatInfo(const String& formatName, PixelFormatContent formatContent, UInt8 bpp, PixelFormatSubType subType) :
	content(formatContent),
	redType(subType),
	greenType(subType),
	blueType(subType),
	alphaType(subType),
	name(formatName),
	bitsPerPixel(bpp)
	{
	}

	inline PixelFormatInfo::PixelFormatInfo(const String& formatName, PixelFormatContent formatContent, Bitset<> rMask, Bitset<> gMask, Bitset<> bMask, Bitset<> aMask, PixelFormatSubType subType) :
	redMask(rMask),
	greenMask(gMask),
	blueMask(bMask),
	alphaMask(aMask),
	content(formatContent),
	redType(subType),
	greenType(subType),
	blueType(subType),
	alphaType(subType),
	name(formatName)
	{
		RecomputeBitsPerPixel();
	}

	inline PixelFormatInfo::PixelFormatInfo(const String& formatName, PixelFormatContent formatContent, PixelFormatSubType rType, Bitset<> rMask, PixelFormatSubType gType, Bitset<> gMask, PixelFormatSubType bType, Bitset<> bMask, PixelFormatSubType aType, Bitset<> aMask, UInt8 bpp) :
	redMask(rMask),
	greenMask(gMask),
	blueMask(bMask),
	alphaMask(aMask),
	content(formatContent),
	redType(rType),
	greenType(gType),
	blueType(bType),
	alphaType(aType),
	name(formatName)
	{
		if (bpp == 0)
			RecomputeBitsPerPixel();
	}

	inline void PixelFormatInfo::Clear()
	{
		bitsPerPixel = 0;
		alphaMask.Clear();
		blueMask.Clear();
		greenMask.Clear();
		redMask.Clear();
		name.Clear();
	}

	inline bool PixelFormatInfo::IsCompressed() const
	{
		return redType   == PixelFormatSubType_Compressed ||
		       greenType == PixelFormatSubType_Compressed ||
		       blueType  == PixelFormatSubType_Compressed ||
		       alphaType == PixelFormatSubType_Compressed;
	}

	inline bool PixelFormatInfo::IsValid() const
	{
		return bitsPerPixel != 0;
	}

	inline void PixelFormatInfo::RecomputeBitsPerPixel()
	{
		Bitset<> counter;
		counter |= redMask;
		counter |= greenMask;
		counter |= blueMask;
		counter |= alphaMask;

		bitsPerPixel = static_cast<UInt8>(counter.Count());
	}

	inline bool PixelFormatInfo::Validate() const
	{
		if (!IsValid())
			return false;

		if (content <= PixelFormatContent_Undefined || content > PixelFormatContent_Max)
			return false;

		std::array<const Nz::Bitset<>*, 4> masks = { {&redMask, &greenMask, &blueMask, &alphaMask} };
		std::array<PixelFormatSubType, 4> types = { {redType, greenType, blueType, alphaType} };

		for (unsigned int i = 0; i < 4; ++i)
		{
			UInt8 usedBits = static_cast<UInt8>(masks[i]->Count());
			if (usedBits == 0)
				continue;

			if (usedBits > bitsPerPixel)
				return false;

			switch (types[i])
			{
				case PixelFormatSubType_Half:
					if (usedBits != 16)
						return false;

					break;

				case PixelFormatSubType_Float:
					if (usedBits != 32)
						return false;

					break;

				default:
					break;
			}
		}

		return true;
	}

	inline std::size_t PixelFormat::ComputeSize(PixelFormatType format, unsigned int width, unsigned int height, unsigned int depth)
	{
		if (IsCompressed(format))
		{
			switch (format)
			{
				case PixelFormatType_DXT1:
				case PixelFormatType_DXT3:
				case PixelFormatType_DXT5:
					return (((width + 3) / 4) * ((height + 3) / 4) * ((format == PixelFormatType_DXT1) ? 8 : 16)) * depth;

				default:
					NazaraError("Unsupported format");
					return 0;
			}
		}
		else
			return width * height * depth * GetBytesPerPixel(format);
	}

	inline bool PixelFormat::Convert(PixelFormatType srcFormat, PixelFormatType dstFormat, const void* src, void* dst)
	{
		if (srcFormat == dstFormat)
		{
			std::memcpy(dst, src, GetBytesPerPixel(srcFormat));
			return true;
		}

		#if NAZARA_UTILITY_SAFE
		if (IsCompressed(srcFormat))
		{
			NazaraError("Cannot convert single pixel from compressed format");
			return false;
		}

		if (IsCompressed(dstFormat))
		{
			NazaraError("Cannot convert single pixel to compressed format");
			return false;
		}
		#endif

		ConvertFunction func = s_convertFunctions[srcFormat][dstFormat];
		if (!func)
		{
			NazaraError("Pixel format conversion from " + GetName(srcFormat) + " to " + GetName(dstFormat) + " is not supported");
			return false;
		}

		if (!func(reinterpret_cast<const UInt8*>(src), reinterpret_cast<const UInt8*>(src) + GetBytesPerPixel(srcFormat), reinterpret_cast<UInt8*>(dst)))
		{
			NazaraError("Pixel format conversion from " + GetName(srcFormat) + " to " + GetName(dstFormat) + " failed");
			return false;
		}

		return true;
	}

	inline bool PixelFormat::Convert(PixelFormatType srcFormat, PixelFormatType dstFormat, const void* start, const void* end, void* dst)
	{
		if (srcFormat == dstFormat)
		{
			std::memcpy(dst, start, reinterpret_cast<const UInt8*>(end)-reinterpret_cast<const UInt8*>(start));
			return true;
		}

		ConvertFunction func = s_convertFunctions[srcFormat][dstFormat];
		if (!func)
		{
			NazaraError("Pixel format conversion from " + GetName(srcFormat) + " to " + GetName(dstFormat) + " is not supported");
			return false;
		}

		if (!func(reinterpret_cast<const UInt8*>(start), reinterpret_cast<const UInt8*>(end), reinterpret_cast<UInt8*>(dst)))
		{
			NazaraError("Pixel format conversion from " + GetName(srcFormat) + " to " + GetName(dstFormat) + " failed");
			return false;
		}

		return true;
	}

	inline bool PixelFormat::Flip(PixelFlipping flipping, PixelFormatType format, unsigned int width, unsigned int height, unsigned int depth, const void* src, void* dst)
	{
		#if NAZARA_UTILITY_SAFE
		if (!IsValid(format))
		{
			NazaraError("Invalid pixel format");
			return false;
		}
		#endif

		auto it = s_flipFunctions[flipping].find(format);
		if (it != s_flipFunctions[flipping].end())
			it->second(width, height, depth, reinterpret_cast<const UInt8*>(src), reinterpret_cast<UInt8*>(dst));
		else
		{
			// Flipping générique

			#if NAZARA_UTILITY_SAFE
			if (IsCompressed(format))
			{
				NazaraError("No function to flip compressed format");
				return false;
			}
			#endif

			UInt8 bpp = GetBytesPerPixel(format);
			unsigned int lineStride = width*bpp;
			switch (flipping)
			{
				case PixelFlipping_Horizontally:
				{
					if (src == dst)
					{
						for (unsigned int z = 0; z < depth; ++z)
						{
							UInt8* ptr = reinterpret_cast<UInt8*>(dst) + width*height*z;
							for (unsigned int y = 0; y < height/2; ++y)
								std::swap_ranges(&ptr[y*lineStride], &ptr[(y+1)*lineStride-1], &ptr[(height-y-1)*lineStride]);
						}
					}
					else
					{
						for (unsigned int z = 0; z < depth; ++z)
						{
							const UInt8* srcPtr = reinterpret_cast<const UInt8*>(src);
							UInt8* dstPtr = reinterpret_cast<UInt8*>(dst) + (width-1)*height*depth*bpp;
							for (unsigned int y = 0; y < height; ++y)
							{
								std::memcpy(dstPtr, srcPtr, lineStride);

								srcPtr += lineStride;
								dstPtr -= lineStride;
							}
						}
					}
					break;
				}

				case PixelFlipping_Vertically:
				{
					if (src == dst)
					{
						for (unsigned int z = 0; z < depth; ++z)
						{
							UInt8* ptr = reinterpret_cast<UInt8*>(dst) + width*height*z;
							for (unsigned int y = 0; y < height; ++y)
							{
								for (unsigned int x = 0; x < width/2; ++x)
									std::swap_ranges(&ptr[x*bpp], &ptr[(x+1)*bpp], &ptr[(width-x)*bpp]);

								ptr += lineStride;
							}
						}
					}
					else
					{
						for (unsigned int z = 0; z < depth; ++z)
						{
							UInt8* ptr = reinterpret_cast<UInt8*>(dst) + width*height*z;
							for (unsigned int y = 0; y < height; ++y)
							{
								for (unsigned int x = 0; x < width; ++x)
									std::memcpy(&ptr[x*bpp], &ptr[(width-x)*bpp], bpp);

								ptr += lineStride;
							}
						}
					}
					break;
				}
			}
		}

		return true;
	}

	inline UInt8 PixelFormat::GetBitsPerPixel(PixelFormatType format)
	{
		return s_pixelFormatInfos[format].bitsPerPixel;
	}

	inline UInt8 PixelFormat::GetBytesPerPixel(PixelFormatType format)
	{
		return GetBitsPerPixel(format)/8;
	}

	inline PixelFormatContent PixelFormat::GetContent(PixelFormatType format)
	{
		return s_pixelFormatInfos[format].content;
	}

	inline const PixelFormatInfo& PixelFormat::GetInfo(PixelFormatType format)
	{
		return s_pixelFormatInfos[format];
	}

	inline const String& PixelFormat::GetName(PixelFormatType format)
	{
		return s_pixelFormatInfos[format].name;
	}

	inline bool PixelFormat::HasAlpha(PixelFormatType format)
	{
		return s_pixelFormatInfos[format].alphaMask.TestAny();
	}

	inline bool PixelFormat::IsCompressed(PixelFormatType format)
	{
		return s_pixelFormatInfos[format].IsCompressed();
	}

	inline bool PixelFormat::IsConversionSupported(PixelFormatType srcFormat, PixelFormatType dstFormat)
	{
		if (srcFormat == dstFormat)
			return true;

		return s_convertFunctions[srcFormat][dstFormat] != nullptr;
	}

	inline bool PixelFormat::IsValid(PixelFormatType format)
	{
		return format != PixelFormatType_Undefined;
	}

	inline void PixelFormat::SetConvertFunction(PixelFormatType srcFormat, PixelFormatType dstFormat, ConvertFunction func)
	{
		s_convertFunctions[srcFormat][dstFormat] = func;
	}

	inline void PixelFormat::SetFlipFunction(PixelFlipping flipping, PixelFormatType format, FlipFunction func)
	{
		s_flipFunctions[flipping][format] = func;
	}
}

#include <Nazara/Utility/DebugOff.hpp>
<commit_msg>Utility/PixelFormat: Reject formats with over 64 bpp per component<commit_after>// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp

#include <Nazara/Utility/PixelFormat.hpp>
#include <Nazara/Core/Error.hpp>
#include <algorithm>
#include <array>
#include <cstring>
#include <Nazara/Utility/Debug.hpp>

namespace Nz
{
	inline PixelFormatInfo::PixelFormatInfo() :
	content(PixelFormatContent_Undefined),
	bitsPerPixel(0)
	{
	}

	inline PixelFormatInfo::PixelFormatInfo(PixelFormatContent formatContent, UInt8 bpp, PixelFormatSubType subType) :
	content(formatContent),
	redType(subType),
	greenType(subType),
	blueType(subType),
	alphaType(subType),
	bitsPerPixel(bpp)
	{
	}

	inline PixelFormatInfo::PixelFormatInfo(const String& formatName, PixelFormatContent formatContent, UInt8 bpp, PixelFormatSubType subType) :
	content(formatContent),
	redType(subType),
	greenType(subType),
	blueType(subType),
	alphaType(subType),
	name(formatName),
	bitsPerPixel(bpp)
	{
	}

	inline PixelFormatInfo::PixelFormatInfo(const String& formatName, PixelFormatContent formatContent, Bitset<> rMask, Bitset<> gMask, Bitset<> bMask, Bitset<> aMask, PixelFormatSubType subType) :
	redMask(rMask),
	greenMask(gMask),
	blueMask(bMask),
	alphaMask(aMask),
	content(formatContent),
	redType(subType),
	greenType(subType),
	blueType(subType),
	alphaType(subType),
	name(formatName)
	{
		RecomputeBitsPerPixel();
	}

	inline PixelFormatInfo::PixelFormatInfo(const String& formatName, PixelFormatContent formatContent, PixelFormatSubType rType, Bitset<> rMask, PixelFormatSubType gType, Bitset<> gMask, PixelFormatSubType bType, Bitset<> bMask, PixelFormatSubType aType, Bitset<> aMask, UInt8 bpp) :
	redMask(rMask),
	greenMask(gMask),
	blueMask(bMask),
	alphaMask(aMask),
	content(formatContent),
	redType(rType),
	greenType(gType),
	blueType(bType),
	alphaType(aType),
	name(formatName)
	{
		if (bpp == 0)
			RecomputeBitsPerPixel();
	}

	inline void PixelFormatInfo::Clear()
	{
		bitsPerPixel = 0;
		alphaMask.Clear();
		blueMask.Clear();
		greenMask.Clear();
		redMask.Clear();
		name.Clear();
	}

	inline bool PixelFormatInfo::IsCompressed() const
	{
		return redType   == PixelFormatSubType_Compressed ||
		       greenType == PixelFormatSubType_Compressed ||
		       blueType  == PixelFormatSubType_Compressed ||
		       alphaType == PixelFormatSubType_Compressed;
	}

	inline bool PixelFormatInfo::IsValid() const
	{
		return bitsPerPixel != 0;
	}

	inline void PixelFormatInfo::RecomputeBitsPerPixel()
	{
		Bitset<> counter;
		counter |= redMask;
		counter |= greenMask;
		counter |= blueMask;
		counter |= alphaMask;

		bitsPerPixel = static_cast<UInt8>(counter.Count());
	}

	inline bool PixelFormatInfo::Validate() const
	{
		if (!IsValid())
			return false;

		if (content <= PixelFormatContent_Undefined || content > PixelFormatContent_Max)
			return false;

		std::array<const Nz::Bitset<>*, 4> masks = { {&redMask, &greenMask, &blueMask, &alphaMask} };
		std::array<PixelFormatSubType, 4> types = { {redType, greenType, blueType, alphaType} };

		for (unsigned int i = 0; i < 4; ++i)
		{
			UInt8 usedBits = static_cast<UInt8>(masks[i]->Count());
			if (usedBits == 0)
				continue;

			if (usedBits > bitsPerPixel)
				return false;

			if (usedBits > 64) //< Currently, formats with over 64 bits per component are not supported
				return false;

			switch (types[i])
			{
				case PixelFormatSubType_Half:
					if (usedBits != 16)
						return false;

					break;

				case PixelFormatSubType_Float:
					if (usedBits != 32)
						return false;

					break;

				default:
					break;
			}
		}

		return true;
	}

	inline std::size_t PixelFormat::ComputeSize(PixelFormatType format, unsigned int width, unsigned int height, unsigned int depth)
	{
		if (IsCompressed(format))
		{
			switch (format)
			{
				case PixelFormatType_DXT1:
				case PixelFormatType_DXT3:
				case PixelFormatType_DXT5:
					return (((width + 3) / 4) * ((height + 3) / 4) * ((format == PixelFormatType_DXT1) ? 8 : 16)) * depth;

				default:
					NazaraError("Unsupported format");
					return 0;
			}
		}
		else
			return width * height * depth * GetBytesPerPixel(format);
	}

	inline bool PixelFormat::Convert(PixelFormatType srcFormat, PixelFormatType dstFormat, const void* src, void* dst)
	{
		if (srcFormat == dstFormat)
		{
			std::memcpy(dst, src, GetBytesPerPixel(srcFormat));
			return true;
		}

		#if NAZARA_UTILITY_SAFE
		if (IsCompressed(srcFormat))
		{
			NazaraError("Cannot convert single pixel from compressed format");
			return false;
		}

		if (IsCompressed(dstFormat))
		{
			NazaraError("Cannot convert single pixel to compressed format");
			return false;
		}
		#endif

		ConvertFunction func = s_convertFunctions[srcFormat][dstFormat];
		if (!func)
		{
			NazaraError("Pixel format conversion from " + GetName(srcFormat) + " to " + GetName(dstFormat) + " is not supported");
			return false;
		}

		if (!func(reinterpret_cast<const UInt8*>(src), reinterpret_cast<const UInt8*>(src) + GetBytesPerPixel(srcFormat), reinterpret_cast<UInt8*>(dst)))
		{
			NazaraError("Pixel format conversion from " + GetName(srcFormat) + " to " + GetName(dstFormat) + " failed");
			return false;
		}

		return true;
	}

	inline bool PixelFormat::Convert(PixelFormatType srcFormat, PixelFormatType dstFormat, const void* start, const void* end, void* dst)
	{
		if (srcFormat == dstFormat)
		{
			std::memcpy(dst, start, reinterpret_cast<const UInt8*>(end)-reinterpret_cast<const UInt8*>(start));
			return true;
		}

		ConvertFunction func = s_convertFunctions[srcFormat][dstFormat];
		if (!func)
		{
			NazaraError("Pixel format conversion from " + GetName(srcFormat) + " to " + GetName(dstFormat) + " is not supported");
			return false;
		}

		if (!func(reinterpret_cast<const UInt8*>(start), reinterpret_cast<const UInt8*>(end), reinterpret_cast<UInt8*>(dst)))
		{
			NazaraError("Pixel format conversion from " + GetName(srcFormat) + " to " + GetName(dstFormat) + " failed");
			return false;
		}

		return true;
	}

	inline bool PixelFormat::Flip(PixelFlipping flipping, PixelFormatType format, unsigned int width, unsigned int height, unsigned int depth, const void* src, void* dst)
	{
		#if NAZARA_UTILITY_SAFE
		if (!IsValid(format))
		{
			NazaraError("Invalid pixel format");
			return false;
		}
		#endif

		auto it = s_flipFunctions[flipping].find(format);
		if (it != s_flipFunctions[flipping].end())
			it->second(width, height, depth, reinterpret_cast<const UInt8*>(src), reinterpret_cast<UInt8*>(dst));
		else
		{
			// Flipping générique

			#if NAZARA_UTILITY_SAFE
			if (IsCompressed(format))
			{
				NazaraError("No function to flip compressed format");
				return false;
			}
			#endif

			UInt8 bpp = GetBytesPerPixel(format);
			unsigned int lineStride = width*bpp;
			switch (flipping)
			{
				case PixelFlipping_Horizontally:
				{
					if (src == dst)
					{
						for (unsigned int z = 0; z < depth; ++z)
						{
							UInt8* ptr = reinterpret_cast<UInt8*>(dst) + width*height*z;
							for (unsigned int y = 0; y < height/2; ++y)
								std::swap_ranges(&ptr[y*lineStride], &ptr[(y+1)*lineStride-1], &ptr[(height-y-1)*lineStride]);
						}
					}
					else
					{
						for (unsigned int z = 0; z < depth; ++z)
						{
							const UInt8* srcPtr = reinterpret_cast<const UInt8*>(src);
							UInt8* dstPtr = reinterpret_cast<UInt8*>(dst) + (width-1)*height*depth*bpp;
							for (unsigned int y = 0; y < height; ++y)
							{
								std::memcpy(dstPtr, srcPtr, lineStride);

								srcPtr += lineStride;
								dstPtr -= lineStride;
							}
						}
					}
					break;
				}

				case PixelFlipping_Vertically:
				{
					if (src == dst)
					{
						for (unsigned int z = 0; z < depth; ++z)
						{
							UInt8* ptr = reinterpret_cast<UInt8*>(dst) + width*height*z;
							for (unsigned int y = 0; y < height; ++y)
							{
								for (unsigned int x = 0; x < width/2; ++x)
									std::swap_ranges(&ptr[x*bpp], &ptr[(x+1)*bpp], &ptr[(width-x)*bpp]);

								ptr += lineStride;
							}
						}
					}
					else
					{
						for (unsigned int z = 0; z < depth; ++z)
						{
							UInt8* ptr = reinterpret_cast<UInt8*>(dst) + width*height*z;
							for (unsigned int y = 0; y < height; ++y)
							{
								for (unsigned int x = 0; x < width; ++x)
									std::memcpy(&ptr[x*bpp], &ptr[(width-x)*bpp], bpp);

								ptr += lineStride;
							}
						}
					}
					break;
				}
			}
		}

		return true;
	}

	inline UInt8 PixelFormat::GetBitsPerPixel(PixelFormatType format)
	{
		return s_pixelFormatInfos[format].bitsPerPixel;
	}

	inline UInt8 PixelFormat::GetBytesPerPixel(PixelFormatType format)
	{
		return GetBitsPerPixel(format)/8;
	}

	inline PixelFormatContent PixelFormat::GetContent(PixelFormatType format)
	{
		return s_pixelFormatInfos[format].content;
	}

	inline const PixelFormatInfo& PixelFormat::GetInfo(PixelFormatType format)
	{
		return s_pixelFormatInfos[format];
	}

	inline const String& PixelFormat::GetName(PixelFormatType format)
	{
		return s_pixelFormatInfos[format].name;
	}

	inline bool PixelFormat::HasAlpha(PixelFormatType format)
	{
		return s_pixelFormatInfos[format].alphaMask.TestAny();
	}

	inline bool PixelFormat::IsCompressed(PixelFormatType format)
	{
		return s_pixelFormatInfos[format].IsCompressed();
	}

	inline bool PixelFormat::IsConversionSupported(PixelFormatType srcFormat, PixelFormatType dstFormat)
	{
		if (srcFormat == dstFormat)
			return true;

		return s_convertFunctions[srcFormat][dstFormat] != nullptr;
	}

	inline bool PixelFormat::IsValid(PixelFormatType format)
	{
		return format != PixelFormatType_Undefined;
	}

	inline void PixelFormat::SetConvertFunction(PixelFormatType srcFormat, PixelFormatType dstFormat, ConvertFunction func)
	{
		s_convertFunctions[srcFormat][dstFormat] = func;
	}

	inline void PixelFormat::SetFlipFunction(PixelFlipping flipping, PixelFormatType format, FlipFunction func)
	{
		s_flipFunctions[flipping][format] = func;
	}
}

#include <Nazara/Utility/DebugOff.hpp>
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2012 Sacha Refshauge
 *
 */
// Qt 4.7+ / 5.0+ implementation of the framework.
// Currently supports: Symbian, Blackberry, Meego, Linux, Windows

#include <QApplication>
#include <QUrl>
#include <QDir>
#include <QDesktopWidget>
#include <QDesktopServices>
#include <QLocale>
#include <QThread>

#ifdef __SYMBIAN32__
#include <e32std.h>
#include <QSystemScreenSaver>
#include <QFeedbackHapticsEffect>
#include "SymbianMediaKeys.h"
#endif
#include "QtMain.h"

InputState* input_state;

std::string System_GetProperty(SystemProperty prop) {
	switch (prop) {
	case SYSPROP_NAME:
#ifdef __SYMBIAN32__
		return "Qt:Symbian";
#elif defined(BLACKBERRY)
		return "Qt:Blackberry10";
#elif defined(MEEGO_EDITION_HARMATTAN)
		return "Qt:Meego";
#elif defined(Q_OS_LINUX)
		return "Qt:Linux";
#elif defined(_WIN32)
		return "Qt:Windows";
#else
		return "Qt";
#endif
	case SYSPROP_LANGREGION:
		return QLocale::system().name().toStdString();
	default:
		return "";
	}
}

void Vibrate(int length_ms) {
	if (length_ms == -1 || length_ms == -3)
		length_ms = 50;
	else if (length_ms == -2)
		length_ms = 25;
	// Symbian only for now
#if defined(__SYMBIAN32__)
	QFeedbackHapticsEffect effect;
	effect.setIntensity(0.8);
	effect.setDuration(length_ms);
	effect.start();
#endif
}

void LaunchBrowser(const char *url)
{
	QDesktopServices::openUrl(QUrl(url));
}

float CalculateDPIScale()
{
	// Sane default rather than check DPI
#ifdef __SYMBIAN32__
	return 1.4f;
#elif defined(ARM)
	return 1.2f;
#else
	return 1.0f;
#endif
}

Q_DECL_EXPORT int main(int argc, char *argv[])
{
#ifdef Q_OS_LINUX
	QApplication::setAttribute(Qt::AA_X11InitThreads, true);
#endif
	QApplication a(argc, argv);
	QSize res = QApplication::desktop()->screenGeometry().size();
	if (res.width() < res.height())
		res.transpose();
	pixel_xres = res.width();
	pixel_yres = res.height();
	g_dpi_scale = CalculateDPIScale();
	dp_xres = (int)(pixel_xres * g_dpi_scale); dp_yres = (int)(pixel_yres * g_dpi_scale);
	net::Init();
#ifdef __SYMBIAN32__
	const char *savegame_dir = "E:/PPSSPP/";
	const char *assets_dir = "E:/PPSSPP/";
#elif defined(BLACKBERRY)
	const char *savegame_dir = "/accounts/1000/shared/misc/";
	const char *assets_dir = "app/native/assets/";
#elif defined(MEEGO_EDITION_HARMATTAN)
	const char *savegame_dir = "/home/user/MyDocs/PPSSPP/";
	QDir myDocs("/home/user/MyDocs/");
	if (!myDocs.exists("PPSSPP"))
		myDocs.mkdir("PPSSPP");
	const char *assets_dir = "/opt/PPSSPP/";
#else
	const char *savegame_dir = "./";
	const char *assets_dir = "./";
#endif
	NativeInit(argc, (const char **)argv, savegame_dir, assets_dir, "BADCOFFEE");

#if !defined(Q_OS_LINUX) || defined(ARM)
	MainUI w;
	w.resize(pixel_xres, pixel_yres);
#ifdef ARM
	w.showFullScreen();
#else
	w.show();
#endif
#endif
#ifdef __SYMBIAN32__
	// Set RunFast hardware mode for VFPv2.
	User::SetFloatingPointMode(EFpModeRunFast);
	// Disable screensaver
	QSystemScreenSaver *ssObject = new QSystemScreenSaver(&w);
	ssObject->setScreenSaverInhibit();
	SymbianMediaKeys* mediakeys = new SymbianMediaKeys();
#endif

	QThread* thread = new QThread;
	MainAudio *audio = new MainAudio();
	audio->moveToThread(thread);
	QObject::connect(thread, SIGNAL(started()), audio, SLOT(run()));
	QObject::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
	thread->start();

	int ret = a.exec();
	delete audio;
	thread->quit();
	NativeShutdown();
	net::Shutdown();
	return ret;
}

<commit_msg>disable non-menu Main Window for all non ARM Qt platforms including Linux, Windows and OSX.<commit_after>/*
 * Copyright (c) 2012 Sacha Refshauge
 *
 */
// Qt 4.7+ / 5.0+ implementation of the framework.
// Currently supports: Symbian, Blackberry, Meego, Linux, Windows

#include <QApplication>
#include <QUrl>
#include <QDir>
#include <QDesktopWidget>
#include <QDesktopServices>
#include <QLocale>
#include <QThread>

#ifdef __SYMBIAN32__
#include <e32std.h>
#include <QSystemScreenSaver>
#include <QFeedbackHapticsEffect>
#include "SymbianMediaKeys.h"
#endif
#include "QtMain.h"

InputState* input_state;

std::string System_GetProperty(SystemProperty prop) {
	switch (prop) {
	case SYSPROP_NAME:
#ifdef __SYMBIAN32__
		return "Qt:Symbian";
#elif defined(BLACKBERRY)
		return "Qt:Blackberry10";
#elif defined(MEEGO_EDITION_HARMATTAN)
		return "Qt:Meego";
#elif defined(Q_OS_LINUX)
		return "Qt:Linux";
#elif defined(_WIN32)
		return "Qt:Windows";
#else
		return "Qt";
#endif
	case SYSPROP_LANGREGION:
		return QLocale::system().name().toStdString();
	default:
		return "";
	}
}

void Vibrate(int length_ms) {
	if (length_ms == -1 || length_ms == -3)
		length_ms = 50;
	else if (length_ms == -2)
		length_ms = 25;
	// Symbian only for now
#if defined(__SYMBIAN32__)
	QFeedbackHapticsEffect effect;
	effect.setIntensity(0.8);
	effect.setDuration(length_ms);
	effect.start();
#endif
}

void LaunchBrowser(const char *url)
{
	QDesktopServices::openUrl(QUrl(url));
}

float CalculateDPIScale()
{
	// Sane default rather than check DPI
#ifdef __SYMBIAN32__
	return 1.4f;
#elif defined(ARM)
	return 1.2f;
#else
	return 1.0f;
#endif
}

Q_DECL_EXPORT int main(int argc, char *argv[])
{
#ifdef Q_OS_LINUX
	QApplication::setAttribute(Qt::AA_X11InitThreads, true);
#endif
	QApplication a(argc, argv);
	QSize res = QApplication::desktop()->screenGeometry().size();
	if (res.width() < res.height())
		res.transpose();
	pixel_xres = res.width();
	pixel_yres = res.height();
	g_dpi_scale = CalculateDPIScale();
	dp_xres = (int)(pixel_xres * g_dpi_scale); dp_yres = (int)(pixel_yres * g_dpi_scale);
	net::Init();
#ifdef __SYMBIAN32__
	const char *savegame_dir = "E:/PPSSPP/";
	const char *assets_dir = "E:/PPSSPP/";
#elif defined(BLACKBERRY)
	const char *savegame_dir = "/accounts/1000/shared/misc/";
	const char *assets_dir = "app/native/assets/";
#elif defined(MEEGO_EDITION_HARMATTAN)
	const char *savegame_dir = "/home/user/MyDocs/PPSSPP/";
	QDir myDocs("/home/user/MyDocs/");
	if (!myDocs.exists("PPSSPP"))
		myDocs.mkdir("PPSSPP");
	const char *assets_dir = "/opt/PPSSPP/";
#else
	const char *savegame_dir = "./";
	const char *assets_dir = "./";
#endif
	NativeInit(argc, (const char **)argv, savegame_dir, assets_dir, "BADCOFFEE");

#if defined(ARM)
	MainUI w;
	w.resize(pixel_xres, pixel_yres);
#ifdef ARM
	w.showFullScreen();
#else
	w.show();
#endif
#endif
#ifdef __SYMBIAN32__
	// Set RunFast hardware mode for VFPv2.
	User::SetFloatingPointMode(EFpModeRunFast);
	// Disable screensaver
	QSystemScreenSaver *ssObject = new QSystemScreenSaver(&w);
	ssObject->setScreenSaverInhibit();
	SymbianMediaKeys* mediakeys = new SymbianMediaKeys();
#endif

	QThread* thread = new QThread;
	MainAudio *audio = new MainAudio();
	audio->moveToThread(thread);
	QObject::connect(thread, SIGNAL(started()), audio, SLOT(run()));
	QObject::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
	thread->start();

	int ret = a.exec();
	delete audio;
	thread->quit();
	NativeShutdown();
	net::Shutdown();
	return ret;
}

<|endoftext|>


<commit_before>/*
            This file is part of:
                NoahFrame
            https://github.com/ketoo/NoahGameFrame

   Copyright 2009 - 2018 NoahFrame(NoahGameFrame)

   File creator: lvsheng.huang

   NoahFrame is open-source software and you can redistribute it and/or modify
   it under the terms of the License; besides, anyone who use this file/software must include this copyright announcement.

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

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

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

#include "NFCLevelModule.h"

bool NFCLevelModule::Init()
{
	mbExpForHero = true;
    return true;
}

bool NFCLevelModule::Shut()
{
    return true;
}

bool NFCLevelModule::Execute()
{

    return true;
}

bool NFCLevelModule::AfterInit()
{
    m_pKernelModule = pPluginManager->FindModule<NFIKernelModule>();
    m_pLogModule = pPluginManager->FindModule<NFILogModule>();
    m_pPropertyConfigModule = pPluginManager->FindModule<NFIPropertyConfigModule>();
	m_pElementModule = pPluginManager->FindModule<NFIElementModule>();
	//m_pHeroModule = pPluginManager->FindModule<NFIHeroModule>();

    return true;
}

int NFCLevelModule::AddExp(const NFGUID& self, const int64_t nExp)
{
	if (mbExpForHero)
	{
		//m_pHeroModule->AddHeroExp(self, nExp);
		return 0;
	}

    int eJobType = m_pKernelModule->GetPropertyInt32(self, NFrame::Player::Job());
    int64_t nCurExp = m_pKernelModule->GetPropertyInt(self, NFrame::Player::EXP());
    int nLevel = m_pKernelModule->GetPropertyInt32(self, NFrame::Player::Level());
    int64_t nMaxExp = (int)m_pPropertyConfigModule->CalculateBaseValue(eJobType, nLevel, NFrame::Player::MAXEXP());

    nCurExp += nExp;

    int64_t nRemainExp = nCurExp - nMaxExp;
    while (nRemainExp >= 0)
    {

        nLevel++;

        m_pKernelModule->SetPropertyInt(self, NFrame::Player::Level(), nLevel);

        nCurExp = nRemainExp;

        nMaxExp = (int)m_pPropertyConfigModule->CalculateBaseValue(eJobType, nLevel, NFrame::Player::MAXEXP());
        if (nMaxExp <= 0)
        {
            break;
        }

        nRemainExp -= nMaxExp;
    }

    m_pKernelModule->SetPropertyInt(self, NFrame::Player::EXP(), nCurExp);

    return 0;
}<commit_msg>add hero module for game server<commit_after>/*
            This file is part of:
                NoahFrame
            https://github.com/ketoo/NoahGameFrame

   Copyright 2009 - 2018 NoahFrame(NoahGameFrame)

   File creator: lvsheng.huang

   NoahFrame is open-source software and you can redistribute it and/or modify
   it under the terms of the License; besides, anyone who use this file/software must include this copyright announcement.

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

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

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

#include "NFCLevelModule.h"

bool NFCLevelModule::Init()
{
	mbExpForHero = true;
    return true;
}

bool NFCLevelModule::Shut()
{
    return true;
}

bool NFCLevelModule::Execute()
{

    return true;
}

bool NFCLevelModule::AfterInit()
{
    m_pKernelModule = pPluginManager->FindModule<NFIKernelModule>();
    m_pLogModule = pPluginManager->FindModule<NFILogModule>();
    m_pPropertyConfigModule = pPluginManager->FindModule<NFIPropertyConfigModule>();
	m_pElementModule = pPluginManager->FindModule<NFIElementModule>();
	m_pHeroModule = pPluginManager->FindModule<NFIHeroModule>();

    return true;
}

int NFCLevelModule::AddExp(const NFGUID& self, const int64_t nExp)
{
	if (mbExpForHero)
	{
		m_pHeroModule->AddHeroExp(self, nExp);
		return 0;
	}

    int eJobType = m_pKernelModule->GetPropertyInt32(self, NFrame::Player::Job());
    int64_t nCurExp = m_pKernelModule->GetPropertyInt(self, NFrame::Player::EXP());
    int nLevel = m_pKernelModule->GetPropertyInt32(self, NFrame::Player::Level());
    int64_t nMaxExp = (int)m_pPropertyConfigModule->CalculateBaseValue(eJobType, nLevel, NFrame::Player::MAXEXP());

    nCurExp += nExp;

    int64_t nRemainExp = nCurExp - nMaxExp;
    while (nRemainExp >= 0)
    {

        nLevel++;

        m_pKernelModule->SetPropertyInt(self, NFrame::Player::Level(), nLevel);

        nCurExp = nRemainExp;

        nMaxExp = (int)m_pPropertyConfigModule->CalculateBaseValue(eJobType, nLevel, NFrame::Player::MAXEXP());
        if (nMaxExp <= 0)
        {
            break;
        }

        nRemainExp -= nMaxExp;
    }

    m_pKernelModule->SetPropertyInt(self, NFrame::Player::EXP(), nCurExp);

    return 0;
}<|endoftext|>


<commit_before>// Time:  O(n)
// Space: O(1)

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        auto dummy = ListNode(0);

        while (head) {
            auto tmp = head->next;
            head->next = dummy.next;
            dummy.next = head;
            head = tmp;
        }

        return dummy.next;
    }
};
<commit_msg>Update reverse-linked-list.cpp<commit_after>// Time:  O(n)
// Space: O(1)

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        auto dummy = ListNode{0};

        while (head) {
            auto tmp = head->next;
            head->next = dummy.next;
            dummy.next = head;
            head = tmp;
        }

        return dummy.next;
    }
};
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2006-2011 by Benedict Paten (benedictpaten@gmail.com)
 *
 * Released under the MIT license, see LICENSE.txt
 */

/*
 * sonLibKVDatabase_KyotoTycoon.cpp
 *
 *  Created on: 5-1-11
 *      Author: epaull
 *
 * Note: all the KT methods seem to have a C and a CPP version (in terms of the arguments) ,
 * and for this implementation we're using the plain C versions as much as we can.
 */

//Database functions
#ifdef HAVE_KYOTO_TYCOON
#include <ktremotedb.h>
#include "sonLibGlobalsInternal.h"
#include "sonLibKVDatabasePrivate.h"

using namespace std;
using namespace kyototycoon;

/*
* construct in the Tokyo Tyrant case means connect to the remote DB
*/
static RemoteDB *constructDB(stKVDatabaseConf *conf, bool create) {

    // we actually do need a local DB dir for Kyoto Tycoon to store the sequences file
    const char *dbDir = stKVDatabaseConf_getDir(conf);
    mkdir(dbDir, S_IRWXU); // just let open of database generate error (FIXME: would be better to make this report errors)
    char *databaseName = stString_print("%s/%s", dbDir, "data");

    const char *dbRemote_Host = stKVDatabaseConf_getHost(conf);
    unsigned dbRemote_Port = stKVDatabaseConf_getPort(conf);
    int timeout = stKVDatabaseConf_getTimeout(conf);

    // create the database object
    RemoteDB db;
    RemoteDB *rdb = &db;

    // tcrdb open sets the host and port for the rdb object
    if (!rdb->open(dbRemote_Host, dbRemote_Port, timeout)) {
        stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "Opening connection to host: %s with error: %s", dbRemote_Host, rdb->error().name());
    }
    free(databaseName);
    return rdb;
}

/* closes the remote DB connection and deletes the rdb object, but does not destroy the
remote database */
static void destructDB(stKVDatabase *database) {
    RemoteDB *rdb = (RemoteDB*)database->dbImpl;
    if (rdb != NULL) {

        // close the connection: first try a graceful close, then a forced close
        if (!rdb->close(true)) {
            if (!rdb->close(false)) {
                stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "Closing database error: %s",rdb->error().name());
            }
        }
        // delete the local in-memory object
        delete rdb;
        database->dbImpl = NULL;
    }
}

/* WARNING: removes all records from the remote database */
static void deleteDB(stKVDatabase *database) {
    RemoteDB *rdb = (RemoteDB *)database->dbImpl;
    if (rdb != NULL) {
        rdb->clear();
    }
    destructDB(database);
    // this removes all records from the remove database object
}

/* check if a record already exists */
static bool recordExists(RemoteDB *rdb, int64_t key) {
    size_t sp;
    if (rdb->get((char *)&key, (size_t)sizeof(key), &sp, NULL) == NULL) {
        return false;
    } else {
        return true;
    }
}

static bool containsRecord(stKVDatabase *database, int64_t key) {
    return recordExists((RemoteDB *)database->dbImpl, key);
}

static void insertRecord(stKVDatabase *database, int64_t key, const void *value, int64_t sizeOfRecord) {
    RemoteDB *rdb = (RemoteDB *)database->dbImpl;
    // add method: If the key already exists the record will not be modified and it'll return false
    if (!rdb->add((char *)&key, (size_t)sizeof(int64_t), (const char *)value, sizeOfRecord)) {
        stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "Inserting key/value to database error: %s", rdb->error().name());
    }
}

static void updateRecord(stKVDatabase *database, int64_t key, const void *value, int64_t sizeOfRecord) {
    RemoteDB *rdb = (RemoteDB *)database->dbImpl;
    // replace method: If the key doesn't already exist it won't be created, and we'll get an error
    if (!rdb->replace((char *)&key, (size_t)sizeof(int64_t), (const char *)value, sizeOfRecord)) {
        stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "Updating key/value to database error: %s", rdb->error().name());
    }
}

static int64_t numberOfRecords(stKVDatabase *database) {
    RemoteDB *rdb = (RemoteDB *)database->dbImpl;
    return rdb->count();
}

static void *getRecord2(stKVDatabase *database, int64_t key, int64_t *recordSize) {
    RemoteDB *rdb = (RemoteDB *)database->dbImpl;
    //Return value must be freed.
    size_t i;
    void *record = (void *)rdb->get((char *)&key, (size_t)sizeof(int64_t), &i, NULL);
    *recordSize = (int64_t)i;
    return record;
}

/* get a single non-string record */
static void *getRecord(stKVDatabase *database, int64_t key) {
    int64_t i;
    return getRecord2(database, key, &i);
}

/* get part of a string record */
static void *getPartialRecord(stKVDatabase *database, int64_t key, int64_t zeroBasedByteOffset, int64_t sizeInBytes, int64_t recordSize) {
    int64_t recordSize2;
    char *record = (char *)getRecord2(database, key, &recordSize2);
    if(recordSize2 != recordSize) {
        stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "The given record size is incorrect: %lld, should be %lld", (long long)recordSize, recordSize2);
    }
    if(record == NULL) {
        stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "The record does not exist: %lld for partial retrieval", (long long)key);
    }
    if(zeroBasedByteOffset < 0 || sizeInBytes < 0 || zeroBasedByteOffset + sizeInBytes > recordSize) {
        stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "Partial record retrieval to out of bounds memory, record size: %lld, requested start: %lld, requested size: %lld", (long long)recordSize, (long long)zeroBasedByteOffset, (long long)sizeInBytes);
    }
    void *partialRecord = memcpy(st_malloc(sizeInBytes), record + zeroBasedByteOffset, sizeInBytes);
    free(record);
    return partialRecord;
}

static void removeRecord(stKVDatabase *database, int64_t key) {
    RemoteDB *rdb = (RemoteDB *)database->dbImpl;
    if (!rdb->remove((char *)&key, (size_t)sizeof(int64_t))) {
        stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "Removing key/value to database error: %s", rdb->error().name());
    }
}

static void startTransaction(stKVDatabase *database) {
    // transactions supported through bulk_... methods
    return;
}

static void commitTransaction(stKVDatabase *database) {
    // transactions supported through bulk_... methods
    return;
}

static void abortTransaction(stKVDatabase *database) {
    // transactions supported through bulk_... methods
    return;
}

void stKVDatabase_initialise_kyotoTycoon(stKVDatabase *database, stKVDatabaseConf *conf, bool create) {
    database->dbImpl = constructDB(stKVDatabase_getConf(database), create);
    database->destruct = destructDB;
    database->deleteDatabase = deleteDB;
    database->containsRecord = containsRecord;
    database->insertRecord = insertRecord;
    database->updateRecord = updateRecord;
    database->numberOfRecords = numberOfRecords;
    database->getRecord = getRecord;
    database->getRecord2 = getRecord2;
    database->getPartialRecord = getPartialRecord;
    database->removeRecord = removeRecord;
    database->startTransaction = startTransaction;
    database->commitTransaction = commitTransaction;
    database->abortTransaction = abortTransaction;
}

#endif
<commit_msg>-- oops, need to create remoteDB object on the heap<commit_after>/*
 * Copyright (C) 2006-2011 by Benedict Paten (benedictpaten@gmail.com)
 *
 * Released under the MIT license, see LICENSE.txt
 */

/*
 * sonLibKVDatabase_KyotoTycoon.cpp
 *
 *  Created on: 5-1-11
 *      Author: epaull
 *
 * Note: all the KT methods seem to have a C and a CPP version (in terms of the arguments) ,
 * and for this implementation we're using the plain C versions as much as we can.
 */

//Database functions
#ifdef HAVE_KYOTO_TYCOON
#include <ktremotedb.h>
#include "sonLibGlobalsInternal.h"
#include "sonLibKVDatabasePrivate.h"

using namespace std;
using namespace kyototycoon;

/*
* construct in the Tokyo Tyrant case means connect to the remote DB
*/
static RemoteDB *constructDB(stKVDatabaseConf *conf, bool create) {

    // we actually do need a local DB dir for Kyoto Tycoon to store the sequences file
    const char *dbDir = stKVDatabaseConf_getDir(conf);
    mkdir(dbDir, S_IRWXU); // just let open of database generate error (FIXME: would be better to make this report errors)
    char *databaseName = stString_print("%s/%s", dbDir, "data");

    const char *dbRemote_Host = stKVDatabaseConf_getHost(conf);
    unsigned dbRemote_Port = stKVDatabaseConf_getPort(conf);
    int timeout = stKVDatabaseConf_getTimeout(conf);

    // create the database object
    RemoteDB *rdb = new RemoteDB();

    // tcrdb open sets the host and port for the rdb object
    if (!rdb->open(dbRemote_Host, dbRemote_Port, timeout)) {
        stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "Opening connection to host: %s with error: %s", dbRemote_Host, rdb->error().name());
    }
    free(databaseName);
    return rdb;
}

/* closes the remote DB connection and deletes the rdb object, but does not destroy the
remote database */
static void destructDB(stKVDatabase *database) {
    RemoteDB *rdb = (RemoteDB*)database->dbImpl;
    if (rdb != NULL) {

        // close the connection: first try a graceful close, then a forced close
        if (!rdb->close(true)) {
            if (!rdb->close(false)) {
                stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "Closing database error: %s",rdb->error().name());
            }
        }
        // delete the local in-memory object
        delete rdb;
        database->dbImpl = NULL;
    }
}

/* WARNING: removes all records from the remote database */
static void deleteDB(stKVDatabase *database) {
    RemoteDB *rdb = (RemoteDB *)database->dbImpl;
    if (rdb != NULL) {
        rdb->clear();
    }
    destructDB(database);
    // this removes all records from the remove database object
}

/* check if a record already exists */
static bool recordExists(RemoteDB *rdb, int64_t key) {
    size_t sp;
    if (rdb->get((char *)&key, (size_t)sizeof(key), &sp, NULL) == NULL) {
        return false;
    } else {
        return true;
    }
}

static bool containsRecord(stKVDatabase *database, int64_t key) {
    return recordExists((RemoteDB *)database->dbImpl, key);
}

static void insertRecord(stKVDatabase *database, int64_t key, const void *value, int64_t sizeOfRecord) {
    RemoteDB *rdb = (RemoteDB *)database->dbImpl;
    // add method: If the key already exists the record will not be modified and it'll return false
    if (!rdb->add((char *)&key, (size_t)sizeof(int64_t), (const char *)value, sizeOfRecord)) {
        stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "Inserting key/value to database error: %s", rdb->error().name());
    }
}

static void updateRecord(stKVDatabase *database, int64_t key, const void *value, int64_t sizeOfRecord) {
    RemoteDB *rdb = (RemoteDB *)database->dbImpl;
    // replace method: If the key doesn't already exist it won't be created, and we'll get an error
    if (!rdb->replace((char *)&key, (size_t)sizeof(int64_t), (const char *)value, sizeOfRecord)) {
        stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "Updating key/value to database error: %s", rdb->error().name());
    }
}

static int64_t numberOfRecords(stKVDatabase *database) {
    RemoteDB *rdb = (RemoteDB *)database->dbImpl;
    return rdb->count();
}

static void *getRecord2(stKVDatabase *database, int64_t key, int64_t *recordSize) {
    RemoteDB *rdb = (RemoteDB *)database->dbImpl;
    //Return value must be freed.
    size_t i;
    void *record = (void *)rdb->get((char *)&key, (size_t)sizeof(int64_t), &i, NULL);
    *recordSize = (int64_t)i;
    return record;
}

/* get a single non-string record */
static void *getRecord(stKVDatabase *database, int64_t key) {
    int64_t i;
    return getRecord2(database, key, &i);
}

/* get part of a string record */
static void *getPartialRecord(stKVDatabase *database, int64_t key, int64_t zeroBasedByteOffset, int64_t sizeInBytes, int64_t recordSize) {
    int64_t recordSize2;
    char *record = (char *)getRecord2(database, key, &recordSize2);
    if(recordSize2 != recordSize) {
        stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "The given record size is incorrect: %lld, should be %lld", (long long)recordSize, recordSize2);
    }
    if(record == NULL) {
        stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "The record does not exist: %lld for partial retrieval", (long long)key);
    }
    if(zeroBasedByteOffset < 0 || sizeInBytes < 0 || zeroBasedByteOffset + sizeInBytes > recordSize) {
        stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "Partial record retrieval to out of bounds memory, record size: %lld, requested start: %lld, requested size: %lld", (long long)recordSize, (long long)zeroBasedByteOffset, (long long)sizeInBytes);
    }
    void *partialRecord = memcpy(st_malloc(sizeInBytes), record + zeroBasedByteOffset, sizeInBytes);
    free(record);
    return partialRecord;
}

static void removeRecord(stKVDatabase *database, int64_t key) {
    RemoteDB *rdb = (RemoteDB *)database->dbImpl;
    if (!rdb->remove((char *)&key, (size_t)sizeof(int64_t))) {
        stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "Removing key/value to database error: %s", rdb->error().name());
    }
}

static void startTransaction(stKVDatabase *database) {
    // transactions supported through bulk_... methods
    return;
}

static void commitTransaction(stKVDatabase *database) {
    // transactions supported through bulk_... methods
    return;
}

static void abortTransaction(stKVDatabase *database) {
    // transactions supported through bulk_... methods
    return;
}

void stKVDatabase_initialise_kyotoTycoon(stKVDatabase *database, stKVDatabaseConf *conf, bool create) {
    database->dbImpl = constructDB(stKVDatabase_getConf(database), create);
    database->destruct = destructDB;
    database->deleteDatabase = deleteDB;
    database->containsRecord = containsRecord;
    database->insertRecord = insertRecord;
    database->updateRecord = updateRecord;
    database->numberOfRecords = numberOfRecords;
    database->getRecord = getRecord;
    database->getRecord2 = getRecord2;
    database->getPartialRecord = getPartialRecord;
    database->removeRecord = removeRecord;
    database->startTransaction = startTransaction;
    database->commitTransaction = commitTransaction;
    database->abortTransaction = abortTransaction;
}

#endif
<|endoftext|>


<commit_before>/*
 * File:  PPSequenceTypes.cpp
 * Copyright (C) 2006 The Institute for System Programming of the Russian Academy of Sciences (ISP RAS)
 */

#include "sedna.h"
#include "PPSequenceTypes.h"
#include "PPUtils.h"
#include "casting_operations.h"

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/// PPCast
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

PPCast::PPCast(variable_context *_cxt_,
               PPOpIn _child_,
               xmlscm_type _target_type_,
               bool _can_be_empty_seq_) : PPIterator(_cxt_),
                                          child(_child_),
                                          target_type(_target_type_),
                                          can_be_empty_seq(_can_be_empty_seq_)
{
}

PPCast::~PPCast()
{
    delete child.op;
    child.op = NULL;
}

void PPCast::open  ()
{
    child.op->open();
    first_time = true;
}

void PPCast::reopen()
{
    child.op->reopen();
    first_time = true;
}

void PPCast::close ()
{
    child.op->close();
}

void PPCast::next  (tuple &t)
{
    if (first_time)
    {
		first_time = false;
        child.op->next(t);

        if (t.is_eos())
            if (can_be_empty_seq)
            {
                first_time = true;
                t.set_eos();
                return;
            }
            else throw USER_EXCEPTION2(XP0006, "cast expression ('?' is not specified in target type but empty sequence is given)");

        tuple_cell tc = atomize(child.get(t));

        child.op->next(t);
        if (!t.is_eos()) throw USER_EXCEPTION2(XP0006, "cast expression (the result of atomization is a sequence of more than one atomic value)");

        t.copy(cast(tc, target_type));
    }
    else
    {
        first_time = true;
        t.set_eos();
    }
}

PPIterator* PPCast::copy(variable_context *_cxt_)
{
    PPCast *res = new PPCast(_cxt_, child, target_type, can_be_empty_seq);
    res->child.op = child.op->copy(_cxt_);

    return res;
}

bool PPCast::result(PPIterator* cur, variable_context *cxt, void*& r)
{
    PPOpIn child;
    ((PPCast*)cur)->children(child);

    void *child_r;
    bool child_s = (child.op->res_fun())(child.op, cxt, child_r);

    if (!child_s) // if expression is not strict
    { // create PPCast and transmit state
        child.op = (PPIterator*)child_r;
        PPCast *res_op = new PPCast(cxt, child,
                                    ((PPCast*)cur)->target_type,
                                    ((PPCast*)cur)->can_be_empty_seq);

        r = res_op;
        return false;
    }

    sequence *child_seq = (sequence*)child_r;
    if (child_seq->size() == 0)
        if (((PPCast*)cur)->can_be_empty_seq)
        {
            r = child_seq;
            return true;
        }
        else throw USER_EXCEPTION2(XP0006, "cast expression ('?' is not specified in target type but empty sequence is given)");

    if (child_seq->size() != 1) throw USER_EXCEPTION2(XP0006, "cast expression (the result of atomization is a sequence of more than one atomic value)");

    tuple t(1);
    child_seq->get(t, child_seq->begin());
    t.cells[0] = cast(atomize(t.cells[0]), ((PPCast*)cur)->target_type);
    child_seq->clear();
    child_seq->add(t);

    r = child_seq;
    return true;
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/// PPCastable
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

PPCastable::PPCastable(variable_context *_cxt_,
               PPOpIn _child_,
               xmlscm_type _target_type_,
               bool _can_be_empty_seq_) : PPIterator(_cxt_),
                                          child(_child_),
                                          target_type(_target_type_),
                                          can_be_empty_seq(_can_be_empty_seq_)
{
}

PPCastable::~PPCastable()
{
    delete child.op;
    child.op = NULL;
}

void PPCastable::open  ()
{
    child.op->open();
    first_time = true;
}

void PPCastable::reopen()
{
    child.op->reopen();
    first_time = true;
}

void PPCastable::close ()
{
    child.op->close();
}

void PPCastable::next  (tuple &t)
{
    bool res;
    if (first_time)
    {
		first_time = false;
        child.op->next(t);

        if (t.is_eos())
        {
            if (can_be_empty_seq)
            {
                first_time = true;
                res = true;
            }
            else res = false; //cast expression ('?' is not specified in target type but empty sequence is given)
        }
        else
        {
        	tuple_cell tc = atomize(child.get(t));
        	child.op->next(t);
	        if (!t.is_eos())  res = false; //cast expression (the result of atomization is a sequence of more than one atomic value)
	        else res = is_castable(tc, target_type);
	    }

        t.copy(tuple_cell::atomic(res));
    }
    else
    {
        first_time = true;
        t.set_eos();
    }
}

PPIterator* PPCastable::copy(variable_context *_cxt_)
{
    PPCastable *res = new PPCastable(_cxt_, child, target_type, can_be_empty_seq);
    res->child.op = child.op->copy(_cxt_);

    return res;
}

bool PPCastable::result(PPIterator* cur, variable_context *cxt, void*& r)
{
	throw USER_EXCEPTION2(SE1002, "PPCastable::result");
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/// PPInstanceOf
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

PPInstanceOf::PPInstanceOf(variable_context *_cxt_,
                           PPOpIn _child_,
                           const sequence_type& _st_) : PPIterator(_cxt_),
                                                        child(_child_),
                                                        st(_st_)
{
}

PPInstanceOf::~PPInstanceOf()
{
    delete child.op;
    child.op = NULL;
}

void PPInstanceOf::open  ()
{
    child.op->open();
    first_time = true;
    eos_reached = true;
}

void PPInstanceOf::reopen()
{
    child.op->reopen();
    first_time = true;
    eos_reached = true;
}

void PPInstanceOf::close ()
{
    child.op->close();
}

bool type_matches(const PPOpIn &child, tuple &t, bool &eos_reached, const sequence_type& st);

void PPInstanceOf::next  (tuple &t)
{
    if (first_time)
    {
		first_time = false;

        if (!eos_reached) child.op->reopen();

        bool res = type_matches(child, t, eos_reached, st);

        t.copy(tuple_cell::atomic(res));
    }
    else
    {
        first_time = true;
        t.set_eos();
    }
}

PPIterator* PPInstanceOf::copy(variable_context *_cxt_)
{
    PPInstanceOf *res = new PPInstanceOf(_cxt_, child, st);
    res->child.op = child.op->copy(_cxt_);

    return res;
}

bool PPInstanceOf::result(PPIterator* cur, variable_context *cxt, void*& r)
{
    throw USER_EXCEPTION2(SE1002, "PPInstanceOf::result");
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/// PPTreat
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

PPTreat::PPTreat(variable_context *_cxt_,
                 PPOpIn _child_,
                 const sequence_type& _st_) : PPIterator(_cxt_),
                                              child(_child_),
                                              st(_st_)
{
}

PPTreat::~PPTreat()
{
    delete child.op;
    child.op = NULL;
}

void PPTreat::open  ()
{
    child.op->open();
    first_time = true;
    eos_reached = true;

    s = new sequence(child.ts);
    pos = 0;
}

void PPTreat::reopen()
{
    child.op->reopen();
    first_time = true;
    eos_reached = true;
    pos = 0;
    s->clear();
}

void PPTreat::close ()
{
    child.op->close();
}

void PPTreat::next(tuple &t)
{
    if (first_time)
    {
		first_time = false;
        if (!eos_reached) child.op->reopen();
        bool res = type_matches(child, s, t, eos_reached, st);
        //!!! FIXME: error code must be XPDY0050 there
        if(res == false) throw USER_EXCEPTION(XP0050);
    }

    if(pos < s->size())
    {
       	s->get(t, pos++);
       	return;
    }
    else if(!eos_reached)
    {
    	child.op->next(t);
    	if(t.is_eos()) eos_reached = true;
    	else return;
    }

    t.set_eos();
    first_time = true;
    s->clear();
    pos=0;
}

PPIterator* PPTreat::copy(variable_context *_cxt_)
{
    PPTreat *res = new PPTreat(_cxt_, child, st);
    res->child.op = child.op->copy(_cxt_);

    return res;
}

bool PPTreat::result(PPIterator* cur, variable_context *cxt, void*& r)
{
    throw USER_EXCEPTION2(SE1002, "PPTreat::result");
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/// PPTypeswitch
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

PPTypeswitch::PPTypeswitch(variable_context *_cxt_,
                 		   arr_of_var_dsc _var_dscs_,
                 		   PPOpIn _source_child_,
				 		   const arr_of_sequence_type& _types_,
 		                   arr_of_PPOpIn _cases_,
            		       PPOpIn _default_child_): PPVarIterator(_cxt_),
				                                    var_dscs(_var_dscs_),
                                                    source_child(_source_child_),
                                                    types(_types_),
                                                    cases(_cases_),
                                                    default_child(_default_child_)
{
	if(cases.size() != types.size())
		throw USER_EXCEPTION2(SE1003, "PPTypeswitch: number of cases must be equal to number of types");
}

PPTypeswitch::~PPTypeswitch()
{
    delete source_child.op;
    source_child.op = NULL;

    for( int i = 0; i < cases.size(); i++)
    {
    	delete (cases[i].op);
    	cases[i].op = NULL;
    }

    delete default_child.op;
    default_child.op = NULL;
}

void PPTypeswitch::open ()
{
    s = new sequence_tmp(source_child.ts);

    source_child.op->open();
    first_time = true;
    eos_reached = false;
    need_reopen = false;
    effective_case = NULL;

    for (int i = 0; i < var_dscs.size(); i++)
    {
        producer &p = cxt->producers[var_dscs[i]];
        p.type = pt_lazy_simple;
        p.op = this;
        p.cvc = new complex_var_consumption;
        p.tuple_pos = i;
    }

    for(int i = 0; i < cases.size(); i++)
		(cases[i].op) -> open();

    default_child.op->open();
}

void PPTypeswitch::reopen()
{
    if(!eos_reached) source_child.op->reopen();
    if(effective_case != NULL)
    {
    	(effective_case->op) -> reopen();
	    effective_case = NULL;
	}

    eos_reached = false;
    first_time = true;
    need_reopen = false;

    s->clear();
	reinit_consumer_table();
}

void PPTypeswitch::close ()
{
	source_child.op->close();

	for( int i = 0; i < cases.size(); i++)
        (cases[i].op) -> close();

    default_child.op->close();
    delete s;
}

void PPTypeswitch::next(tuple &t)
{
    if (first_time)
    {
        if(need_reopen)
	    {
	        if(!eos_reached) source_child.op->reopen();
    	    s->clear();
    	    reinit_consumer_table();
    	    need_reopen = false;
    	}

		first_time = false;
        eos_reached = false;

        effective_case = &default_child;
        for(int i = 0; i < cases.size(); i++)
        {
        	if(type_matches(source_child, s, t, eos_reached, types[i]))
        	{
        		effective_case = &cases[i];
        		break;
        	}
        }
    }

    (effective_case->op) -> next(t);

	if(t.is_eos())
	{
		first_time = true;
		need_reopen = true;
	}
}

PPIterator* PPTypeswitch::copy(variable_context *_cxt_)
{
    PPTypeswitch *res = new PPTypeswitch(_cxt_,
                                         var_dscs,
                                         source_child,
                                         types,
                                         cases,
                                         default_child);

    for (int i = 0; i < cases.size(); i++)
        res->cases[i].op = cases[i].op->copy(_cxt_);

    res->source_child.op = source_child.op->copy(_cxt_);
    res->default_child.op = default_child.op->copy(_cxt_);

    return res;
}

var_c_id PPTypeswitch::register_consumer(var_dsc dsc)
{
	complex_var_consumption &cvc = *(cxt->producers[dsc].cvc);
    cvc.push_back(0);
    return cvc.size() - 1;
}

void PPTypeswitch::next(tuple &t, var_dsc dsc, var_c_id id)
{
    producer &p = cxt->producers[dsc];
    complex_var_consumption &cvc = *(p.cvc);

    if (cvc[id] < s->size())
    {
        s->get(source, cvc[id]);
        t.copy(source.cells[p.tuple_pos]);
        cvc[id]++;
    }
    else
    {
        if (eos_reached)
        {
            t.set_eos();
            cvc[id] = 0;
        }
        else
        {
            source_child.op->next(source);
            if (source.is_eos())
            {
                eos_reached = true;
                t.set_eos();
                cvc[id] = 0;
            }
            else
            {
                s->add(source);
                t.copy(source.cells[p.tuple_pos]);
                cvc[id]++;
            }
        }
    }
}

void PPTypeswitch::reopen(var_dsc dsc, var_c_id id)
{
    cxt->producers[dsc].svc->at(id) = 0;
}

inline void PPTypeswitch::reinit_consumer_table()
{
	for (int i = 0; i < var_dscs.size(); i++)
    {
        producer &p = cxt->producers[var_dscs[i]];
        for (int j = 0; j < p.cvc->size(); j++) p.cvc->at(j) = 0;
    }
}

bool PPTypeswitch::result(PPIterator* cur, variable_context *cxt, void*& r)
{
    throw USER_EXCEPTION2(SE1002, "PPTypeswitch::result");
}
<commit_msg>castable empty bug fix<commit_after>/*
 * File:  PPSequenceTypes.cpp
 * Copyright (C) 2006 The Institute for System Programming of the Russian Academy of Sciences (ISP RAS)
 */

#include "sedna.h"
#include "PPSequenceTypes.h"
#include "PPUtils.h"
#include "casting_operations.h"

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/// PPCast
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

PPCast::PPCast(variable_context *_cxt_,
               PPOpIn _child_,
               xmlscm_type _target_type_,
               bool _can_be_empty_seq_) : PPIterator(_cxt_),
                                          child(_child_),
                                          target_type(_target_type_),
                                          can_be_empty_seq(_can_be_empty_seq_)
{
}

PPCast::~PPCast()
{
    delete child.op;
    child.op = NULL;
}

void PPCast::open  ()
{
    child.op->open();
    first_time = true;
}

void PPCast::reopen()
{
    child.op->reopen();
    first_time = true;
}

void PPCast::close ()
{
    child.op->close();
}

void PPCast::next  (tuple &t)
{
    if (first_time)
    {
		first_time = false;
        child.op->next(t);

        if (t.is_eos())
            if (can_be_empty_seq)
            {
                first_time = true;
                t.set_eos();
                return;
            }
            else throw USER_EXCEPTION2(XP0006, "cast expression ('?' is not specified in target type but empty sequence is given)");

        tuple_cell tc = atomize(child.get(t));

        child.op->next(t);
        if (!t.is_eos()) throw USER_EXCEPTION2(XP0006, "cast expression (the result of atomization is a sequence of more than one atomic value)");

        t.copy(cast(tc, target_type));
    }
    else
    {
        first_time = true;
        t.set_eos();
    }
}

PPIterator* PPCast::copy(variable_context *_cxt_)
{
    PPCast *res = new PPCast(_cxt_, child, target_type, can_be_empty_seq);
    res->child.op = child.op->copy(_cxt_);

    return res;
}

bool PPCast::result(PPIterator* cur, variable_context *cxt, void*& r)
{
    PPOpIn child;
    ((PPCast*)cur)->children(child);

    void *child_r;
    bool child_s = (child.op->res_fun())(child.op, cxt, child_r);

    if (!child_s) // if expression is not strict
    { // create PPCast and transmit state
        child.op = (PPIterator*)child_r;
        PPCast *res_op = new PPCast(cxt, child,
                                    ((PPCast*)cur)->target_type,
                                    ((PPCast*)cur)->can_be_empty_seq);

        r = res_op;
        return false;
    }

    sequence *child_seq = (sequence*)child_r;
    if (child_seq->size() == 0)
        if (((PPCast*)cur)->can_be_empty_seq)
        {
            r = child_seq;
            return true;
        }
        else throw USER_EXCEPTION2(XP0006, "cast expression ('?' is not specified in target type but empty sequence is given)");

    if (child_seq->size() != 1) throw USER_EXCEPTION2(XP0006, "cast expression (the result of atomization is a sequence of more than one atomic value)");

    tuple t(1);
    child_seq->get(t, child_seq->begin());
    t.cells[0] = cast(atomize(t.cells[0]), ((PPCast*)cur)->target_type);
    child_seq->clear();
    child_seq->add(t);

    r = child_seq;
    return true;
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/// PPCastable
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

PPCastable::PPCastable(variable_context *_cxt_,
               PPOpIn _child_,
               xmlscm_type _target_type_,
               bool _can_be_empty_seq_) : PPIterator(_cxt_),
                                          child(_child_),
                                          target_type(_target_type_),
                                          can_be_empty_seq(_can_be_empty_seq_)
{
}

PPCastable::~PPCastable()
{
    delete child.op;
    child.op = NULL;
}

void PPCastable::open  ()
{
    child.op->open();
    first_time = true;
}

void PPCastable::reopen()
{
    child.op->reopen();
    first_time = true;
}

void PPCastable::close ()
{
    child.op->close();
}

void PPCastable::next  (tuple &t)
{
    bool res;
    if (first_time)
    {
		first_time = false;
        child.op->next(t);

        if (t.is_eos())
        {
            if (can_be_empty_seq) res = true;
            else res = false; //cast expression ('?' is not specified in target type but empty sequence is given)
        }
        else
        {
        	tuple_cell tc = atomize(child.get(t));
        	child.op->next(t);
	        if (!t.is_eos())  res = false; //cast expression (the result of atomization is a sequence of more than one atomic value)
	        else res = is_castable(tc, target_type);
	    }

        t.copy(tuple_cell::atomic(res));
    }
    else
    {
        first_time = true;
        t.set_eos();
    }
}

PPIterator* PPCastable::copy(variable_context *_cxt_)
{
    PPCastable *res = new PPCastable(_cxt_, child, target_type, can_be_empty_seq);
    res->child.op = child.op->copy(_cxt_);

    return res;
}

bool PPCastable::result(PPIterator* cur, variable_context *cxt, void*& r)
{
	throw USER_EXCEPTION2(SE1002, "PPCastable::result");
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/// PPInstanceOf
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

PPInstanceOf::PPInstanceOf(variable_context *_cxt_,
                           PPOpIn _child_,
                           const sequence_type& _st_) : PPIterator(_cxt_),
                                                        child(_child_),
                                                        st(_st_)
{
}

PPInstanceOf::~PPInstanceOf()
{
    delete child.op;
    child.op = NULL;
}

void PPInstanceOf::open  ()
{
    child.op->open();
    first_time = true;
    eos_reached = true;
}

void PPInstanceOf::reopen()
{
    child.op->reopen();
    first_time = true;
    eos_reached = true;
}

void PPInstanceOf::close ()
{
    child.op->close();
}

bool type_matches(const PPOpIn &child, tuple &t, bool &eos_reached, const sequence_type& st);

void PPInstanceOf::next  (tuple &t)
{
    if (first_time)
    {
		first_time = false;

        if (!eos_reached) child.op->reopen();

        bool res = type_matches(child, t, eos_reached, st);

        t.copy(tuple_cell::atomic(res));
    }
    else
    {
        first_time = true;
        t.set_eos();
    }
}

PPIterator* PPInstanceOf::copy(variable_context *_cxt_)
{
    PPInstanceOf *res = new PPInstanceOf(_cxt_, child, st);
    res->child.op = child.op->copy(_cxt_);

    return res;
}

bool PPInstanceOf::result(PPIterator* cur, variable_context *cxt, void*& r)
{
    throw USER_EXCEPTION2(SE1002, "PPInstanceOf::result");
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/// PPTreat
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

PPTreat::PPTreat(variable_context *_cxt_,
                 PPOpIn _child_,
                 const sequence_type& _st_) : PPIterator(_cxt_),
                                              child(_child_),
                                              st(_st_)
{
}

PPTreat::~PPTreat()
{
    delete child.op;
    child.op = NULL;
}

void PPTreat::open  ()
{
    child.op->open();
    first_time = true;
    eos_reached = true;

    s = new sequence(child.ts);
    pos = 0;
}

void PPTreat::reopen()
{
    child.op->reopen();
    first_time = true;
    eos_reached = true;
    pos = 0;
    s->clear();
}

void PPTreat::close ()
{
    child.op->close();
}

void PPTreat::next(tuple &t)
{
    if (first_time)
    {
		first_time = false;
        if (!eos_reached) child.op->reopen();
        bool res = type_matches(child, s, t, eos_reached, st);
        //!!! FIXME: error code must be XPDY0050 there
        if(res == false) throw USER_EXCEPTION(XP0050);
    }

    if(pos < s->size())
    {
       	s->get(t, pos++);
       	return;
    }
    else if(!eos_reached)
    {
    	child.op->next(t);
    	if(t.is_eos()) eos_reached = true;
    	else return;
    }

    t.set_eos();
    first_time = true;
    s->clear();
    pos=0;
}

PPIterator* PPTreat::copy(variable_context *_cxt_)
{
    PPTreat *res = new PPTreat(_cxt_, child, st);
    res->child.op = child.op->copy(_cxt_);

    return res;
}

bool PPTreat::result(PPIterator* cur, variable_context *cxt, void*& r)
{
    throw USER_EXCEPTION2(SE1002, "PPTreat::result");
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/// PPTypeswitch
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

PPTypeswitch::PPTypeswitch(variable_context *_cxt_,
                 		   arr_of_var_dsc _var_dscs_,
                 		   PPOpIn _source_child_,
				 		   const arr_of_sequence_type& _types_,
 		                   arr_of_PPOpIn _cases_,
            		       PPOpIn _default_child_): PPVarIterator(_cxt_),
				                                    var_dscs(_var_dscs_),
                                                    source_child(_source_child_),
                                                    types(_types_),
                                                    cases(_cases_),
                                                    default_child(_default_child_)
{
	if(cases.size() != types.size())
		throw USER_EXCEPTION2(SE1003, "PPTypeswitch: number of cases must be equal to number of types");
}

PPTypeswitch::~PPTypeswitch()
{
    delete source_child.op;
    source_child.op = NULL;

    for( int i = 0; i < cases.size(); i++)
    {
    	delete (cases[i].op);
    	cases[i].op = NULL;
    }

    delete default_child.op;
    default_child.op = NULL;
}

void PPTypeswitch::open ()
{
    s = new sequence_tmp(source_child.ts);

    source_child.op->open();
    first_time = true;
    eos_reached = false;
    need_reopen = false;
    effective_case = NULL;

    for (int i = 0; i < var_dscs.size(); i++)
    {
        producer &p = cxt->producers[var_dscs[i]];
        p.type = pt_lazy_simple;
        p.op = this;
        p.cvc = new complex_var_consumption;
        p.tuple_pos = i;
    }

    for(int i = 0; i < cases.size(); i++)
		(cases[i].op) -> open();

    default_child.op->open();
}

void PPTypeswitch::reopen()
{
    if(!eos_reached) source_child.op->reopen();
    if(effective_case != NULL)
    {
    	(effective_case->op) -> reopen();
	    effective_case = NULL;
	}

    eos_reached = false;
    first_time = true;
    need_reopen = false;

    s->clear();
	reinit_consumer_table();
}

void PPTypeswitch::close ()
{
	source_child.op->close();

	for( int i = 0; i < cases.size(); i++)
        (cases[i].op) -> close();

    default_child.op->close();
    delete s;
}

void PPTypeswitch::next(tuple &t)
{
    if (first_time)
    {
        if(need_reopen)
	    {
	        if(!eos_reached) source_child.op->reopen();
    	    s->clear();
    	    reinit_consumer_table();
    	    need_reopen = false;
    	}

		first_time = false;
        eos_reached = false;

        effective_case = &default_child;
        for(int i = 0; i < cases.size(); i++)
        {
        	if(type_matches(source_child, s, t, eos_reached, types[i]))
        	{
        		effective_case = &cases[i];
        		break;
        	}
        }
    }

    (effective_case->op) -> next(t);

	if(t.is_eos())
	{
		first_time = true;
		need_reopen = true;
	}
}

PPIterator* PPTypeswitch::copy(variable_context *_cxt_)
{
    PPTypeswitch *res = new PPTypeswitch(_cxt_,
                                         var_dscs,
                                         source_child,
                                         types,
                                         cases,
                                         default_child);

    for (int i = 0; i < cases.size(); i++)
        res->cases[i].op = cases[i].op->copy(_cxt_);

    res->source_child.op = source_child.op->copy(_cxt_);
    res->default_child.op = default_child.op->copy(_cxt_);

    return res;
}

var_c_id PPTypeswitch::register_consumer(var_dsc dsc)
{
	complex_var_consumption &cvc = *(cxt->producers[dsc].cvc);
    cvc.push_back(0);
    return cvc.size() - 1;
}

void PPTypeswitch::next(tuple &t, var_dsc dsc, var_c_id id)
{
    producer &p = cxt->producers[dsc];
    complex_var_consumption &cvc = *(p.cvc);

    if (cvc[id] < s->size())
    {
        s->get(source, cvc[id]);
        t.copy(source.cells[p.tuple_pos]);
        cvc[id]++;
    }
    else
    {
        if (eos_reached)
        {
            t.set_eos();
            cvc[id] = 0;
        }
        else
        {
            source_child.op->next(source);
            if (source.is_eos())
            {
                eos_reached = true;
                t.set_eos();
                cvc[id] = 0;
            }
            else
            {
                s->add(source);
                t.copy(source.cells[p.tuple_pos]);
                cvc[id]++;
            }
        }
    }
}

void PPTypeswitch::reopen(var_dsc dsc, var_c_id id)
{
    cxt->producers[dsc].svc->at(id) = 0;
}

inline void PPTypeswitch::reinit_consumer_table()
{
	for (int i = 0; i < var_dscs.size(); i++)
    {
        producer &p = cxt->producers[var_dscs[i]];
        for (int j = 0; j < p.cvc->size(); j++) p.cvc->at(j) = 0;
    }
}

bool PPTypeswitch::result(PPIterator* cur, variable_context *cxt, void*& r)
{
    throw USER_EXCEPTION2(SE1002, "PPTypeswitch::result");
}
<|endoftext|>