text:
#include "stdafx.h"
#include "Font.h"
#include "Renderer.h"
#include "VertexBuffer.h"
#include "Texture.h"
#include "ShaderDefines.h"
#include "InputLayout.h"
#include "Material.h"
#include "TextureAtlas.h"
#include "RendererOptions.h"
#include "Shader.h"
#include "ResourceProvider.h"
#include "ResourceTypes.h"
#include "FBTimer/Profiler.h"
#include "FBFileSystem/FileSystem.h"
#include "FBStringLib/StringLib.h"
#include "FBStringLib/StringConverter.h"
#include "EssentialEngineData/shaders/Constants.h"
namespace fb{
struct SCharDescr
{
	SCharDescr() : srcX(0), srcY(0), srcW(0), srcH(0), xOff(0), yOff(0), xAdv(0), page(0) {}

	short srcX;
	short srcY;
	short srcW;
	short srcH;
	short xOff;
	short yOff;
	short xAdv;
	short page;
	unsigned int chnl;

	std::vector<int> kerningPairs;
};
//----------------------------------------------------------------------------
// FontLoader
//----------------------------------------------------------------------------
class FontLoader
{
public:
	FontLoader(FileSystem::Open& f, Font *font, const char *fontFile);
	virtual int Load() = 0; // Must be implemented by derived class

protected:
	void LoadPage(int id, const char *pageFile, const std::string& fontFile);
	void SetFontInfo(int fontSize, int outlineThickness);
	void SetCommonInfo(int fontHeight, int base, int scaleW, int scaleH, int pages, bool isPacked);
	void AddChar(int id, int x, int y, int w, int h, int xoffset, int yoffset, int xadvance, int page, int chnl);
	void AddKerningPair(int first, int second, int amount);

	FileSystem::Open& f;
	Font *font;
	std::string fontFile;

	int outlineThickness;
};

class FontLoaderTextFormat : public FontLoader
{
public:
	FontLoaderTextFormat(FileSystem::Open& f, Font *font, const char *fontFile);

	int Load();

	int SkipWhiteSpace(const std::string &str, int start);
	int FindEndOfToken(const std::string &str, int start);

	void InterpretInfo(const std::string &str, int start);
	void InterpretCommon(const std::string &str, int start);
	void InterpretChar(const std::string &str, int start);
	void InterpretSpacing(const std::string &str, int start);
	void InterpretKerning(const std::string &str, int start);
	// intentionally not reference
	void InterpretPage(const std::string str, int start, const std::string fontFile);
};

class FontLoaderBinaryFormat : public FontLoader
{
public:
	FontLoaderBinaryFormat(FileSystem::Open& f, Font *font, const char *fontFile);

	int Load();

	void ReadInfoBlock(int size);
	void ReadCommonBlock(int size);
	void ReadPagesBlock(int size);
	void ReadCharsBlock(int size);
	void ReadKerningPairsBlock(int size);
};

const unsigned int Font::MAX_BATCH = 4 * 2000;

class Font::Impl{
public:
	bool mInitialized;
	std::string mFilePath;
	FontWeakPtr mSelf;
	short mFontHeight; // total height of the font
	Real mScaledFontHeight;
	short mFontSize;
	short mBase;       // y of base line
	short mScaleW;
	short mScaleH;
	SCharDescr mDefChar;
	bool mHasOutline;
	Real mScale;
	EFontTextEncoding mEncoding;
	unsigned int mColor;
	std::stack<unsigned int> mColorBackup;
	std::map<int, SCharDescr*> mChars;
	std::vector<TexturePtr> mPages;
	VertexBufferPtr mVertexBuffer;
	unsigned int mVertexLocation;
	ShaderPtr mShader;
	InputLayoutPtr mInputLayout;
	MaterialPtr mTextureMaterial;
	OBJECT_CONSTANTS mObjectConstants;
	Vec2I mRenderTargetSize;
	TextureAtlasPtr mTextureAtlas;
	float mFixedWidth;
	float mFixedWidthStart;

	//---------------------------------------------------------------------------
	Impl()
		: mFontHeight(0)
		, mScaledFontHeight(0)
		, mBase(0)
		, mScaleW(0)
		, mScaleH(0)
		, mScale(1.0f)
		, mVertexLocation(0)
		, mHasOutline(false)
		, mEncoding(NONE)
		, mColor(0xFFFFFFFF)
		, mInitialized(false)
		, mFontSize(0)
		, mFixedWidth(0)
		, mFixedWidthStart(0)
	{}

	~Impl(){
		std::map<int, SCharDescr*>::iterator it = mChars.begin();
		while (it != mChars.end())
		{
			FB_SAFE_DELETE(it->second);
			it++;
		}
	}

	int Init(const char *fontFile) {
		if (!ValidCString(fontFile))
			return -1;
		if (mInitialized)
			return 0;
		mFilePath = fontFile;
		Profiler profiler("'Font Init'");
		// Load the font
		FileSystem::Open f(fontFile, "rb");
		auto err = f.Error();
		if (err)
		{
			Logger::Log(FB_ERROR_LOG_ARG, FormatString("Failed to open a font file(%s).", fontFile).c_str());
			return -1;
		}

		// Determine format by reading the first bytes of the file
		char str[4] = { 0 };
		fread(str, 3, 1, f);
		fseek(f, 0, SEEK_SET);
		int r = 0;
		{
			Profiler profiler("'Font loding'");
			FontLoader *loader = 0;
			if (strcmp(str, "BMF") == 0)
				loader = FB_NEW(FontLoaderBinaryFormat)(f, mSelf.lock().get(), fontFile);
			else
				loader = FB_NEW(FontLoaderTextFormat)(f, mSelf.lock().get(), fontFile);

			r = loader->Load();
			FB_SAFE_DELETE(loader);
		}
		auto& renderer = Renderer::GetInstance();
		mVertexBuffer = renderer.CreateVertexBuffer(0, sizeof(FontVertex), MAX_BATCH,
			BUFFER_USAGE_DYNAMIC, BUFFER_CPU_ACCESS_WRITE);
		assert(mVertexBuffer);

		// init shader
		mShader = renderer.CreateShader("EssentialEngineData/shaders/Font.hlsl",
			SHADER_TYPE_VS | SHADER_TYPE_PS, SHADER_DEFINES());
		mInputLayout = renderer.GetInputLayout(
			DEFAULT_INPUTS::POSITION_COLOR_TEXCOORD_BLENDINDICES, mShader);

		mInitialized = r == 0;
		auto provider = renderer.GetResourceProvider();
		mTextureMaterial = provider->GetMaterial(ResourceTypes::Materials::QuadTextured)->Clone();

		BLEND_DESC desc;
		desc.RenderTarget[0].BlendEnable = true;
		desc.RenderTarget[0].BlendOp = BLEND_OP_ADD;
		desc.RenderTarget[0].SrcBlend = BLEND_SRC_ALPHA;
		desc.RenderTarget[0].DestBlend = BLEND_INV_SRC_ALPHA;
		desc.RenderTarget[0].RenderTargetWriteMask = COLOR_WRITE_MASK_RED | COLOR_WRITE_MASK_GREEN | COLOR_WRITE_MASK_BLUE;
		mTextureMaterial->SetBlendState(desc);

		mRenderTargetSize = renderer.GetMainRenderTargetSize();
		mObjectConstants.gWorldViewProj = MakeOrthogonalMatrix(0, 0,
			(Real)mRenderTargetSize.x,
			(Real)mRenderTargetSize.y,
			0.f, 1.0f);
		mObjectConstants.gWorld.MakeIdentity();

		return r;
	}

	int Reload(){
		if (!mInitialized)
			return -1;

		mInitialized = false;
		Init(mFilePath.c_str());
		return 0;
	}

	//----------------------------------------------------------------------------
	void SetTextEncoding(EFontTextEncoding encoding)
	{
		mEncoding = encoding;
	}

	// y is center
	bool ApplyTag(const char* text, int start, int end, Real& x, Real y)
	{
		auto& renderer = Renderer::GetInstance();

		assert(end - start > 8);
		char buf[256];
		TextTags::Enum tagType = GetTagType(&text[start], end - start, buf);
		switch (tagType)
		{
		case TextTags::Img:
		{
			if (mTextureAtlas)
			{
				auto region = mTextureAtlas->GetRegion(buf);
				if (region)
				{
					auto& regionSize = region->GetSize();
					Real ratio = regionSize.x / (Real)regionSize.y;
					Vec2I imgSize = regionSize;
					//Real yoffset = (mScaledFontHeight - imgSize.y) * .5f;
					Real yoffset = imgSize.y * .5f;
					mTextureMaterial->SetDiffuseColor(Vec4(1, 1, 1, ((mColor & 0xff000000) >> 24) / 255.f));
					renderer.DrawQuadWithTextureUV(Vec2I(Round(x), Round(y - yoffset)), imgSize, region->mUVStart, region->mUVEnd,
						Color::White, mTextureAtlas->GetTexture(), mTextureMaterial);
					x += (Real)imgSize.x;
					PrepareRenderResources();
					return true;
				}
			}
			x += 24.f;
			return true;
			break;
		}
		case TextTags::ColorStart:
		{
			unsigned color = StringConverter::ParseHexa(buf);

			int prevAlpha = mColor & 0xff000000;
			mColorBackup.push(mColor);
			mColor = Color::FixColorByteOrder(color);
			mColor = mColor & 0x00ffffff + prevAlpha;
			break;
		}
		case TextTags::ColorEnd:
		{
			if (!mColorBackup.empty()){
				mColor = mColorBackup.top();
				mColorBackup.pop();
			}
			break;
		}

		case TextTags::FixedWidthStart:
		{
			mFixedWidthStart = x;
			mFixedWidth = StringConverter::ParseReal(buf);
			break;
		}

		case TextTags::FixedWidthEnd:
		{
			if (x - mFixedWidthStart < mFixedWidth) {
				x = mFixedWidthStart + mFixedWidth;
			}
			break;
		}
		}

		return false;
	}

	int SkipTags(const char* text, float curX, TextTags::Enum* tag = 0, int* xAddition = 0)
	{
		if (tag)
		{
			*tag = TextTags::Num;
		}

		if (text[0] == 0)
		{
			return 0;
		}

		if (text[0] == '[' && text[2] == '$')
		{
			// found end
			int pos = 4;
			for (; text[pos] != 0; pos += 2)
			{
				if (text[pos] == '$' && text[pos + 2] == ']')
				{
					int endLen = pos + 4;
					char buf[256];
					TextTags::Enum tagType = GetTagType(text, endLen, buf);

					if (tag)
					{
						*tag = tagType;
					}
					if (tagType == TextTags::Img){
						if (xAddition){
							*xAddition = 24;
							if (mTextureAtlas){
								auto region = mTextureAtlas->GetRegion(buf);
								if (region)
								{
									auto& regionSize = region->GetSize();
									*xAddition = regionSize.x;
								}
							}
						}
					}
					if (tagType == TextTags::FixedWidthStart) {
						mFixedWidthStart = curX;
						mFixedWidth = StringConverter::ParseReal(buf);
					}
					else if (tagType == TextTags::FixedWidthEnd) {
						if (curX - mFixedWidthStart < mFixedWidth) {
							if (xAddition) {
								*xAddition = Round(mFixedWidth - (curX - mFixedWidthStart));
							}
						}
					}
					return endLen;
				}
			}
		}
		return 0;
	}

	TextTags::Enum GetTagType(const char* tagStart, int length, char* buf) const
	{
		if (length < 8)
			return TextTags::Num;

		if (tagStart[0] != '[' || tagStart[length - 2] != ']')
			return TextTags::Num;

		if (tagStart[4] == 'i' && tagStart[6] == 'm' && tagStart[8] == 'g')
		{
			if (buf)
			{
				int oneI = 0;
				for (int i = 10; tagStart[i] != '$'; i += 2)
				{
					buf[oneI++] = tagStart[i];
				}
				buf[oneI] = 0;
			}

			return TextTags::Img;
		}

		if (tagStart[4] == 'c' && tagStart[6] == 'r')
		{
			if (buf)
			{
				int oneI = 0;
				for (int i = 8; tagStart[i] != '$'&& tagStart[i+2] != ']'; i += 2)
				{
					buf[oneI++] = tagStart[i];
				}
				buf[oneI] = 0;
			}
			return tagStart[8] == '$' ? TextTags::ColorEnd : TextTags::ColorStart;
		}

		if (tagStart[4] == 'f' && tagStart[6] == 'w') {
			if (buf) {
				int oneI = 0;
				for (int i = 8; tagStart[i] != '$'&& tagStart[i + 2] != ']'; i += 2)
				{
					buf[oneI++] = tagStart[i];
				}
				buf[oneI] = 0;
			}
			return tagStart[8] == '$' ? TextTags::FixedWidthEnd : TextTags::FixedWidthStart;
		}

		return TextTags::Num;
	}

	//----------------------------------------------------------------------------
	void InternalWrite(Real fx, Real fy, Real fz, const char *text, int count, int spacing=0)
	{
		static FontVertex vertices[MAX_BATCH];
		const Real initialX = fx;
		Real minY = FLT_MAX;
		Real maxY = -FLT_MAX;
		int page = -1;
		// this is moving up the text slight to the top.
		Real oy2 = mScale * (mFontHeight - mBase);
		fy -= oy2;
		Real newLineHeight = LineHeightForText((const wchar_t*)text);
		// fy is the basis of the glyphs.
		unsigned int batchingVertices = 0;
		for (int n = 0; n < count;)
		{
			bool reapplyRender = false;
			int skiplen = SkipTags(&text[n], fx);
			if (skiplen>0)
			{
				do
				{
					// passing center of y
					reapplyRender = ApplyTag(text, n, n + skiplen,
						fx, fy - (mBase * mScale) + mScaledFontHeight * .5f) || reapplyRender;
					n += skiplen;
					skiplen = SkipTags(&text[n], fx);
				} while (skiplen > 0);
			}

			if (n >= count){
				break;
			}

			if (reapplyRender)
			{
				PrepareRenderResources();
				auto& renderer = Renderer::GetInstance();
				renderer.UpdateObjectConstantsBuffer(&mObjectConstants);
			}

			int charId = GetTextChar(text, n, &n);

			if (charId == L'\n')
			{
				fy += newLineHeight;
				fx = (Real)initialX;
				if (batchingVertices > 0)
				{
					Flush(page, vertices, batchingVertices);
					batchingVertices = 0;
					mVertexLocation += batchingVertices;
				}

				continue;
			}

			SCharDescr *ch = GetChar(charId);
			if (ch == 0)
				ch = &mDefChar;

			Real u = (Real(ch->srcX)) / (Real)mScaleW;
			Real v = (Real(ch->srcY)) / (Real)mScaleH;
			Real u2 = u + Real(ch->srcW) / (Real)mScaleW;
			Real v2 = v + Real(ch->srcH) / (Real)mScaleH;

			Real a = mScale * Real(ch->xAdv);
			Real w = mScale * Real(ch->srcW);
			Real h = mScale * Real(ch->srcH);
			Real ox = mScale * Real(ch->xOff);
			Real oy = mScale * Real(ch->yOff);

			if (ch->page != page)
			{
				if (batchingVertices)
					Flush(page, vertices, batchingVertices);

				mVertexLocation += batchingVertices;
				batchingVertices = 0;
				page = ch->page;
			}

			if (mVertexLocation + batchingVertices + 4 >= MAX_BATCH)
			{
				Flush(page, vertices, batchingVertices);
				batchingVertices = 0;
				mVertexLocation = 0;
			}

			Real left, top, right, bottom;
			left = fx + ox;
			right = left + w;

			top = fy - (mBase - ch->yOff)*mScale;
			bottom = top + h;

			vertices[mVertexLocation + batchingVertices++] = FontVertex(
				Vec3(left, top, fz), mColor, Vec2(u, v), ch->chnl);
			vertices[mVertexLocation + batchingVertices++] = FontVertex(
				Vec3(right, top, fz), mColor, Vec2(u2, v), ch->chnl);
			vertices[mVertexLocation + batchingVertices++] = FontVertex(
				Vec3(left, bottom, fz), mColor, Vec2(u, v2), ch->chnl);

			vertices[mVertexLocation + batchingVertices++] = FontVertex(
				Vec3(right, top, fz), mColor, Vec2(u2, v), ch->chnl);
			vertices[mVertexLocation + batchingVertices++] = FontVertex(
				Vec3(right, bottom, fz), mColor, Vec2(u2, v2), ch->chnl);
			vertices[mVertexLocation + batchingVertices++] = FontVertex(
				Vec3(left, bottom, fz), mColor, Vec2(u, v2), ch->chnl);

			fx += a;
			if (charId == L' ')
				fx += spacing;

			if (n < count)
				fx += AdjustForKerningPairs(charId, GetTextChar(text, n));
		}
		Flush(page, vertices, batchingVertices);
		mVertexLocation += batchingVertices;
	}

	//----------------------------------------------------------------------------
	void Flush(int page, const FontVertex* pVertices, unsigned int vertexCount)
	{
		if (page == -1 || vertexCount == 0)
			return;

		auto& renderer = Renderer::GetInstance();
		mPages[page]->Bind(SHADER_TYPE_PS, 0);
		MapData data = mVertexBuffer->Map(0, MAP_TYPE_WRITE_DISCARD, MAP_FLAG_NONE);
		FontVertex* pDest = (FontVertex*)data.pData;
		memcpy(pDest + mVertexLocation, pVertices + mVertexLocation,
			vertexCount * sizeof(FontVertex));
		mVertexBuffer->Unmap(0);
		mVertexBuffer->Bind();
		renderer.SetPrimitiveTopology(PRIMITIVE_TOPOLOGY_TRIANGLELIST);
		renderer.Draw(vertexCount, mVertexLocation);
	}

	//----------------------------------------------------------------------------
	void Write(Real x, Real y, Real z, unsigned int color,
		const char *text, int count, FONT_ALIGN mode)
	{
		if (!mInitialized)
			return;
		auto& renderer = Renderer::GetInstance();
		if (renderer.GetRendererOptions()->r_noText)
			return;

		//
		if (count < 0)
			count = GetTextLength(text);

		if (mode == FONT_ALIGN_CENTER)
		{
			Real w = GetTextWidth(text, count);
			x -= w / 2;
		}
		else if (mode == FONT_ALIGN_RIGHT)
		{
			Real w = GetTextWidth(text, count);
			x -= w;
		}

		mColor = color;

		renderer.UpdateObjectConstantsBuffer(&mObjectConstants);

		InternalWrite(x, y, z, text, count);
	}

	//----------------------------------------------------------------------------
	void ScaleFontSizeTo(int desiredSize){
		if (mFontSize == 0){
			return;
		}
		mScale = desiredSize / (Real)mFontSize;
		mScaledFontHeight = mFontHeight * mScale;
	}

	void ScaleFontHeightTo(float desiredHeight){
		if (mFontSize == 0){
			return;
		}
		mScale = desiredHeight / (Real)mFontHeight;
		mScaledFontHeight = desiredHeight;
	}

	//----------------------------------------------------------------------------
	Real GetOriginalHeight() const{
		return mFontHeight;
	}

	Real GetHeight() const
	{
		return mScale * mFontHeight;
	}

	Real GetBaseHeight() const
	{
		return mScale * mBase;
	}

	std::wstring InsertLineFeed(const char *text, int count, unsigned wrapAt, Real* outWidth, unsigned* outLines)
	{
		if (count < 0)
			count = GetTextLength(text);

		unsigned lines = 1;
		std::vector<Real> maxes;
		Real dummyMax = 0;
		Real curX = 0;
		std::wstring multilineString;
		unsigned inputBeforeSpace = 0;
		Real lengthAfterSpace = 0;
		for (int n = 0; n < count;)
		{
			TextTags::Enum tag = TextTags::Num;
			int xAddition = 0;
			int numSkip = SkipTags(&text[n], curX, &tag, &xAddition);
			if (numSkip)
			{
				do
				{
					if (tag == TextTags::Img)
					{
						curX += xAddition;
						lengthAfterSpace += xAddition;
					}
					else if (tag == TextTags::FixedWidthEnd) {
						lengthAfterSpace = curX = mFixedWidthStart + mFixedWidth;
					}
					int startN = n;
					for (; n < startN + numSkip;)
					{
						int charId = GetTextChar(text, n, &n);
						++inputBeforeSpace;
						multilineString.push_back(charId);
					}
					numSkip = SkipTags(&text[n], curX, &tag, &xAddition);

				} while (numSkip);
				if (n >= count)
					break;
			}

			int charId = GetTextChar(text, n, &n);
			if (charId == L'\n')
			{
				maxes.push_back(curX);
				curX = 0;
				lengthAfterSpace = 0;
				++lines;
			}
			else
			{
				SCharDescr *ch = GetChar(charId);
				if (ch == 0) ch = &mDefChar;
				Real length = (mScale * (ch->xAdv));
				if (n < count)
					length += AdjustForKerningPairs(charId, GetTextChar(text, n));
				curX += length;
				lengthAfterSpace += length;
			}

			if (curX > wrapAt)
			{
				multilineString.insert(multilineString.end() - inputBeforeSpace, L'\n');
				maxes.push_back(curX - lengthAfterSpace);
				curX = lengthAfterSpace;
				multilineString.push_back(charId);
				++lines;
				inputBeforeSpace = 0;
				lengthAfterSpace = 0;
			}
			else
			{
				if (iswspace(charId))
				{
					inputBeforeSpace = 0;
					lengthAfterSpace = 0;
				}
				else
				{
					++inputBeforeSpace;
				}
				multilineString.push_back(charId);
			}
			dummyMax = std::max(dummyMax, curX);
		}
		maxes.push_back(curX);

		if (outWidth)
		{
			if (maxes.empty())
				*outWidth = dummyMax;
			else
			{
				Real biggest = 0;
				for (auto val : maxes)
				{
					biggest = std::max(biggest, val);
					*outWidth = biggest;
				}
			}
		}

		if (outLines)
			*outLines = lines;

		return multilineString;
	}
	//----------------------------------------------------------------------------
	Real GetTextWidth(const char *text, int count = -1, Real *outMinY = 0, Real *outMaxY = 0)
	{
		if (count < 0)
			count = GetTextLength(text);

		Real x = 0;
		Real minY = 10000;
		Real maxY = -10000;

		for (int n = 0; n < count;)
		{
			TextTags::Enum tag;
			int xAddition;
			int skiplen = SkipTags(&text[n], x, &tag, &xAddition);
			if (skiplen>0)
			{
				if (tag == TextTags::Img)
				{
					x += xAddition;
				}
				do
				{
					n += skiplen;
					skiplen = SkipTags(&text[n], x, &tag, &xAddition);
					if (tag == TextTags::Img)
					{
						x += xAddition;
					}
				} while (skiplen > 0);
			}
			if (n >= count)
				break;

			int charId = GetTextChar(text, n, &n);

			SCharDescr *ch = GetChar(charId);
			if (ch == 0) ch = &mDefChar;

			x += mScale * (ch->xAdv);
			Real h = mScale * Real(ch->srcH);
			Real y = mScale * (Real(mBase) - Real(ch->yOff));
			if (minY > y - h)
				minY = y - h;
			if (maxY < y)
				maxY = y;

			if (n < count)
				x += AdjustForKerningPairs(charId, GetTextChar(text, n));
		}

		if (outMinY) *outMinY = minY;
		if (outMaxY) *outMaxY = maxY;

		return x;
	}

	//----------------------------------------------------------------------------
	void PrepareRenderResources()
	{
		if (!mInitialized)
			return;
		auto& renderer = Renderer::GetInstance();
		renderer.GetResourceProvider()->BindBlendState(ResourceTypes::BlendStates::AlphaBlend);
		//renderer.GetResourceProvider()->BindRasterizerState(ResourceTypes::RasterizerStates::Default);
		mShader->Bind(true);
		mInputLayout->Bind();
	}

	void SetRenderStates(bool depthEnable, bool scissorEnable)
	{
		if (!mInitialized)
			return;

		if (scissorEnable)
		{
			RASTERIZER_DESC rd;
			rd.SetScissorEnable(true);
			mTextureMaterial->SetRasterizerState(rd);
		}
		else
		{
			RASTERIZER_DESC rd;
			rd.SetScissorEnable(false);
			mTextureMaterial->SetRasterizerState(rd);
		}
		if (depthEnable)
		{
			mTextureMaterial->SetDepthStencilState(DEPTH_STENCIL_DESC());

		}
		else
		{
			DEPTH_STENCIL_DESC desc;
			desc.SetDepthEnable(false);
			mTextureMaterial->SetDepthStencilState(desc);
		}
	}

	//----------------------------------------------------------------------------
	int GetTextLength(const char *text)
	{
		if (mEncoding == UTF16)
		{
			int textLen = 0;
			for (;;)
			{
				unsigned int len;
				int r = DecodeUTF16((const unsigned char *)&text[textLen], &len);
				if (r > 0)
				{
					textLen += len;
				}
				else if (r < 0)
				{
					textLen++;
				}
				else
					return textLen;
			}
		}

		// Both UTF8 and standard ASCII strings can use strlen
		return (int)strlen(text);
	}

	//----------------------------------------------------------------------------
	// Own
	//----------------------------------------------------------------------------
	Real GetBottomOffset()
	{
		return mScale * (mBase - mFontHeight);
	}

	Real GetTopOffset()
	{
		return mScale * (mBase - 0);
	}

	//----------------------------------------------------------------------------
	int AdjustForKerningPairs(int first, int second)
	{
		SCharDescr *ch = GetChar(first);
		if (ch == 0) return 0;
		for (UINT n = 0; n < ch->kerningPairs.size(); n += 2)
		{
			if (ch->kerningPairs[n] == second)
			{
				return Round(ch->kerningPairs[n + 1] * mScale);
			}
		}

		return 0;
	}

	//----------------------------------------------------------------------------
	SCharDescr *GetChar(int id)
	{
		std::map<int, SCharDescr*>::iterator it = mChars.find(id);
		if (it == mChars.end()) return 0;

		return it->second;
	}

	//----------------------------------------------------------------------------
	int GetTextChar(const char *text, int pos, int *nextPos=0)
	{
		int ch;
		unsigned int len;
		if (mEncoding == UTF8)
		{
			ch = DecodeUTF8((const unsigned char *)&text[pos], &len);
			if (ch == -1) len = 1;
		}
		else if (mEncoding == UTF16)
		{
			ch = DecodeUTF16((const unsigned char *)&text[pos], &len);
			if (ch == -1) len = 2;
		}
		else
		{
			len = 1;
			ch = (unsigned char)text[pos];
		}

		if (nextPos) *nextPos = pos + len;
		return ch;
	}

	void SetRenderTargetSize(const Vec2I& rtSize)
	{
		mRenderTargetSize = rtSize;
		mObjectConstants.gWorldViewProj = MakeOrthogonalMatrix(0, 0,
			(Real)mRenderTargetSize.x,
			(Real)mRenderTargetSize.y,
			0.f, 1.0f);
		mObjectConstants.gWorld.MakeIdentity();
	}

	void RestoreRenderTargetSize()
	{
		auto& renderer = Renderer::GetInstance();
		const auto& rtSize = renderer.GetMainRenderTargetSize();
		mRenderTargetSize = rtSize;
		mObjectConstants.gWorldViewProj = MakeOrthogonalMatrix(0, 0,
			(Real)mRenderTargetSize.x,
			(Real)mRenderTargetSize.y,
			0.f, 1.0f);
		mObjectConstants.gWorld.MakeIdentity();
	}

	std::wstring StripTags(const wchar_t* text)
	{
		std::wstring newText;
		int len = wcslen(text);
		bool tagStarted = false;
		for (int i = 0; i < len; i++)
		{
			if (text[i] == L'[' && text[i + 1] == '$')
			{
				for (int e = i + 2; e < len; ++e)
				{
					if (text[e] == '$' && text[e + 1] == ']')
					{
						i = e + 2;
						break;

					}
				}
			}
			if (i >= len)
			{
				break;
			}
			newText.push_back(text[i]);
		}
		return newText;
	}

	void SetTextureAtlas(TextureAtlasPtr atlas){
		mTextureAtlas = atlas;
	}

	Real GetImageHeight(const wchar_t* text){
		auto start = text + 5;
		auto end = wcsstr(text, L"$]");
		wchar_t wcsImg[255] = {0};
		wcsncpy_s(wcsImg, start, end - start);
		auto imgRegion = WideToAnsi(wcsImg);
		if (mTextureAtlas)
		{
			auto region = mTextureAtlas->GetRegion(imgRegion);
			if (region)
			{
				auto& regionSize = region->GetSize();
				Real ratio = regionSize.x / (Real)regionSize.y;
				return (Real)regionSize.y;
			}
		}
		return mScaledFontHeight;
	}

	Real LineHeightForText(const wchar_t* text){
		Real height = mScaledFontHeight;
		auto imgStart = wcsstr(text, L"[$img");
		if (imgStart == 0)
			return height;

		while (imgStart){
			height = std::max(height, GetImageHeight(imgStart));
			imgStart = wcsstr(imgStart + 1, L"[$img");
		}
		if (height > mScaledFontHeight) {
			height -= (height - mScaledFontHeight)*.5f;
		}
		return height;
	}
};

//----------------------------------------------------------------------------
FontPtr Font::Create(){
	FontPtr p(new Font, [](Font* obj){ delete obj; });
	p->mImpl->mSelf = p;
	return p;
}
Font::Font()
	: mImpl(new Impl)
{
}

Font::~Font(){

}

int Font::Init(const char *fontFile) {
	return mImpl->Init(fontFile);
}

void Font::Reload(){
	mImpl->Reload();
}

const char* Font::GetFilePath() const{
	return mImpl->mFilePath.c_str();
}

void Font::SetTextEncoding(EFontTextEncoding encoding) {
	mImpl->SetTextEncoding(encoding);
}

bool Font::ApplyTag(const char* text, int start, int end, Real& x, Real y) {
	return mImpl->ApplyTag(text, start, end, x, y);
}

int Font::SkipTags(const char* text, float curX, TextTags::Enum* tag, int* xAddition){
	return mImpl->SkipTags(text, curX, tag, xAddition);
}

TextTags::Enum Font::GetTagType(const char* tagStart, int length, char* buf) const {
	return mImpl->GetTagType(tagStart, length, buf);
}

void Font::Flush(int page, const FontVertex* pVertices, unsigned int vertexCount){
	return mImpl->Flush(page, pVertices, vertexCount);
}

void Font::Write(Real x, Real y, Real z, unsigned int color,
	const char *text, int count, FONT_ALIGN mode){
	return mImpl->Write(x, y, z, color, text, count, mode);
}

int Font::GetFontSize() const{
	return mImpl->mFontSize;
}

void Font::ScaleFontSizeTo(int desiredSize){
	mImpl->ScaleFontSizeTo(desiredSize);
}

void Font::ScaleFontHeightTo(float desiredHeight){
	mImpl->ScaleFontHeightTo(desiredHeight);
}

Real Font::GetOriginalHeight() const{
	return mImpl->GetOriginalHeight();
}

Real Font::GetHeight() const{
	return mImpl->GetHeight();
}

Real Font::GetBaseHeight() const{
	return mImpl->GetBaseHeight();
}

std::wstring Font::InsertLineFeed(const char *text, int count, unsigned wrapAt, Real* outWidth, unsigned* outLines){
	return mImpl->InsertLineFeed(text, count, wrapAt, outWidth, outLines);
}

Real Font::GetTextWidth(const char *text, int count, Real *outMinY/* = 0*/, Real *outMaxY/* = 0*/){
	return mImpl->GetTextWidth(text, count, outMinY, outMaxY);
}

void Font::PrepareRenderResources(){
	mImpl->PrepareRenderResources();
}

void Font::SetRenderStates(bool depthEnable, bool scissorEnable){
	mImpl->SetRenderStates(depthEnable, scissorEnable);
}

//----------------------------------------------------------------------------
int Font::GetTextLength(const char *text) {
	return mImpl->GetTextLength(text);
}

Real Font::GetBottomOffset() {
	return mImpl->GetBottomOffset();
}

Real Font::GetTopOffset() {
	return mImpl->GetTopOffset();
}

int Font::AdjustForKerningPairs(int first, int second) {
	return mImpl->AdjustForKerningPairs(first, second);
}

SCharDescr *Font::GetChar(int id){
	return mImpl->GetChar(id);
}

int Font::GetTextChar(const char *text, int pos, int *nextPos){
	return mImpl->GetTextChar(text, pos, nextPos);
}

void Font::SetRenderTargetSize(const Vec2I& rtSize) {
	return mImpl->SetRenderTargetSize(rtSize);
}

void Font::RestoreRenderTargetSize(){
	return mImpl->RestoreRenderTargetSize();
}

std::wstring Font::StripTags(const wchar_t* text){
	return mImpl->StripTags(text);
}

void Font::SetTextureAtlas(TextureAtlasPtr atlas){
	mImpl->SetTextureAtlas(atlas);
}

Real Font::LineHeightForText(const wchar_t* text){
	return mImpl->LineHeightForText(text);
}

//=============================================================================
// FontLoader
//
// This is the base class for all loader classes. This is the only class
// that has access to and knows how to set the Font members.
//=============================================================================

FontLoader::FontLoader(FileSystem::Open& f_, Font *font, const char *fontFile)
	: f(f_)
{
	this->font = font;
	this->fontFile = fontFile;

	outlineThickness = 0;
}

void FontLoader::LoadPage(int id, const char *pageFile, const std::string& fontFile)
{
	std::string str;

	// Load the texture from the same directory as the font descriptor file

	// Find the directory
	str = fontFile;
	for (size_t n = 0; (n = str.find('\\', n)) != std::string::npos;)
		str.replace(n, 1, "/");
	size_t i = str.rfind('/');
	if (i != std::string::npos)
		str = str.substr(0, i + 1);
	else
		str = "";

	// Load the font textures
	str += pageFile;
	auto& renderer = Renderer::GetInstance();
	font->mImpl->mPages[id] = renderer.CreateTexture(str.c_str(), TextureCreationOption{});
	if (font->mImpl->mPages[id] == 0)
		Logger::Log(FB_ERROR_LOG_ARG, FormatString("Failed to load font page '%s'", str.c_str()).c_str());
}

void FontLoader::SetFontInfo(int fontSize, int outlineThickness)
{
	this->outlineThickness = outlineThickness;
	if (fontSize < 0)
		fontSize = -fontSize;
	font->mImpl->mFontSize = fontSize;
}

void FontLoader::SetCommonInfo(int fontHeight, int base, int scaleW, int scaleH, int pages, bool isPacked)
{
	font->mImpl->mFontHeight = fontHeight;
	font->mImpl->mScaledFontHeight = (Real)font->mImpl->mFontHeight;
	font->mImpl->mScale = 1.f;
	font->mImpl->mBase = base;
	font->mImpl->mScaleW = scaleW;
	font->mImpl->mScaleH = scaleH;
	font->mImpl->mPages.resize(pages);
	for (int n = 0; n < pages; n++)
		font->mImpl->mPages[n] = 0;

	if (isPacked && outlineThickness)
		font->mImpl->mHasOutline = true;
}

void FontLoader::AddChar(int id, int x, int y, int w, int h, int xoffset, int yoffset, int xadvance, int page, int chnl)
{
	// Convert to a 4 element vector
	// TODO: Does this depend on hardware? It probably does
	if (chnl == 1) chnl = 0x00010000;  // Blue channel
	else if (chnl == 2) chnl = 0x00000100;  // Green channel
	else if (chnl == 4) chnl = 0x00000001;  // Red channel
	else if (chnl == 8) chnl = 0x01000000;  // Alpha channel
	else chnl = 0;

	if (id >= 0)
	{
		SCharDescr *ch = FB_NEW(SCharDescr);
		ch->srcX = x;
		ch->srcY = y;
		ch->srcW = w;
		ch->srcH = h;
		ch->xOff = xoffset;
		ch->yOff = yoffset;
		ch->xAdv = xadvance;
		ch->page = page;
		ch->chnl = chnl;

		font->mImpl->mChars.insert(std::map<int, SCharDescr*>::value_type(id, ch));
	}

	if (id == -1)
	{
		font->mImpl->mDefChar.srcX = x;
		font->mImpl->mDefChar.srcY = y;
		font->mImpl->mDefChar.srcW = w;
		font->mImpl->mDefChar.srcH = h;
		font->mImpl->mDefChar.xOff = xoffset;
		font->mImpl->mDefChar.yOff = yoffset;
		font->mImpl->mDefChar.xAdv = xadvance;
		font->mImpl->mDefChar.page = page;
		font->mImpl->mDefChar.chnl = chnl;
	}
}

void FontLoader::AddKerningPair(int first, int second, int amount)
{
	if (first >= 0 && first < 256 && font->mImpl->mChars[first])
	{
		font->mImpl->mChars[first]->kerningPairs.push_back(second);
		font->mImpl->mChars[first]->kerningPairs.push_back(amount);
	}
}

//=============================================================================
// FontLoaderTextFormat
//
// This class implements the logic for loading a BMFont file in text format
//=============================================================================

FontLoaderTextFormat::FontLoaderTextFormat(FileSystem::Open& f, Font *font, const char *fontFile)
	: FontLoader(f, font, fontFile)
{
}

int FontLoaderTextFormat::Load()
{
	std::string line;

	while (!feof(f))
	{
		// Read until line feed (or EOF)
		line = "";
		line.reserve(256);
		while (!feof(f))
		{
			char ch;
			if (fread(&ch, 1, 1, f))
			{
				if (ch != '\n')
					line += ch;
				else
					break;
			}
		}

		// Skip white spaces
		int pos = SkipWhiteSpace(line, 0);
		if (pos == line.size())
			break;
		// Read token
		int pos2 = FindEndOfToken(line, pos);
		std::string token = line.substr(pos, pos2 - pos);

		// Interpret line
		if (token == "info")
		{
			InterpretInfo(line, pos2);
		}
		else if (token == "common")
		{
			InterpretCommon(line, pos2);
		}
		else if (token == "char")
		{
			InterpretChar(line, pos2);
		}
		else if (token == "kerning")
		{
			InterpretKerning(line, pos2);
		}
		else if (token == "page")
		{
			InterpretPage(line, pos2, fontFile);
		}
	}

	// Success
	return 0;
}

int FontLoaderTextFormat::SkipWhiteSpace(const std::string &str, int start)
{
	UINT n = start;
	while (n < str.size())
	{
		char ch = str[n];
		if (ch != ' ' &&
			ch != '\t' &&
			ch != '\r' &&
			ch != '\n')
			break;

		++n;
	}

	return n;
}

int FontLoaderTextFormat::FindEndOfToken(const std::string &str, int start)
{
	UINT n = start;
	if (str[n] == '"')
	{
		n++;
		while (n < str.size())
		{
			char ch = str[n];
			if (ch == '"')
			{
				// Include the last quote char in the token
				++n;
				break;
			}
			++n;
		}
	}
	else
	{
		while (n < str.size())
		{
			char ch = str[n];
			if (ch == ' ' ||
				ch == '\t' ||
				ch == '\r' ||
				ch == '\n' ||
				ch == '=')
				break;

			++n;
		}
	}

	return n;
}

void FontLoaderTextFormat::InterpretKerning(const std::string &str, int start)
{
	// Read the attributes
	int first = 0;
	int second = 0;
	int amount = 0;

	int pos, pos2 = start;
	while (true)
	{
		pos = SkipWhiteSpace(str, pos2);
		if (pos == str.size())
			break;
		pos2 = FindEndOfToken(str, pos);

		std::string token = str.substr(pos, pos2 - pos);

		pos = SkipWhiteSpace(str, pos2);
		if (pos == str.size() || str[pos] != '=') break;

		pos = SkipWhiteSpace(str, pos + 1);
		pos2 = FindEndOfToken(str, pos);

		std::string value = str.substr(pos, pos2 - pos);

		if (token == "first")
			first = strtol(value.c_str(), 0, 10);
		else if (token == "second")
			second = strtol(value.c_str(), 0, 10);
		else if (token == "amount")
			amount = strtol(value.c_str(), 0, 10);

		if (pos == str.size()) break;
	}

	// Store the attributes
	AddKerningPair(first, second, amount);
}

void FontLoaderTextFormat::InterpretChar(const std::string &str, int start)
{
	// Read all attributes
	int id = 0;
	int x = 0;
	int y = 0;
	int width = 0;
	int height = 0;
	int xoffset = 0;
	int yoffset = 0;
	int xadvance = 0;
	int page = 0;
	int chnl = 0;

	int pos, pos2 = start;
	while (true)
	{
		pos = SkipWhiteSpace(str, pos2);
		if (pos == str.size())
			break;
		pos2 = FindEndOfToken(str, pos);

		std::string token = str.substr(pos, pos2 - pos);

		pos = SkipWhiteSpace(str, pos2);
		if (pos == str.size() || str[pos] != '=') break;

		pos = SkipWhiteSpace(str, pos + 1);
		pos2 = FindEndOfToken(str, pos);

		std::string value = str.substr(pos, pos2 - pos);

		if (token == "id")
			id = strtol(value.c_str(), 0, 10);
		else if (token == "x")
			x = strtol(value.c_str(), 0, 10);
		else if (token == "y")
			y = strtol(value.c_str(), 0, 10);
		else if (token == "width")
			width = strtol(value.c_str(), 0, 10);
		else if (token == "height")
			height = strtol(value.c_str(), 0, 10);
		else if (token == "xoffset")
			xoffset = strtol(value.c_str(), 0, 10);
		else if (token == "yoffset")
			yoffset = strtol(value.c_str(), 0, 10);
		else if (token == "xadvance")
			xadvance = strtol(value.c_str(), 0, 10);
		else if (token == "page")
			page = strtol(value.c_str(), 0, 10);
		else if (token == "chnl")
			chnl = strtol(value.c_str(), 0, 10);

		if (pos == str.size()) break;
	}

	// Store the attributes
	AddChar(id, x, y, width, height, xoffset, yoffset, xadvance, page, chnl);
}

void FontLoaderTextFormat::InterpretCommon(const std::string &str, int start)
{
	int fontHeight;
	int base;
	int scaleW;
	int scaleH;
	int pages;
	int packed = 0;

	// Read all attributes
	int pos, pos2 = start;
	while (true)
	{
		pos = SkipWhiteSpace(str, pos2);
		if (pos == str.size())
			break;
		pos2 = FindEndOfToken(str, pos);

		std::string token = str.substr(pos, pos2 - pos);

		pos = SkipWhiteSpace(str, pos2);
		if (pos == str.size() || str[pos] != '=') break;

		pos = SkipWhiteSpace(str, pos + 1);
		pos2 = FindEndOfToken(str, pos);

		std::string value = str.substr(pos, pos2 - pos);

		if (token == "lineHeight")
			fontHeight = (short)strtol(value.c_str(), 0, 10);
		else if (token == "base")
			base = (short)strtol(value.c_str(), 0, 10);
		else if (token == "scaleW")
			scaleW = (short)strtol(value.c_str(), 0, 10);
		else if (token == "scaleH")
			scaleH = (short)strtol(value.c_str(), 0, 10);
		else if (token == "pages")
			pages = strtol(value.c_str(), 0, 10);
		else if (token == "packed")
			packed = strtol(value.c_str(), 0, 10);

		if (pos == str.size()) break;
	}

	SetCommonInfo(fontHeight, base, scaleW, scaleH, pages, packed ? true : false);
}

void FontLoaderTextFormat::InterpretInfo(const std::string &str, int start)
{
	int outlineThickness = 0;
	int fontSize = 0;
	// Read all attributes
	int pos, pos2 = start;
	while (true)
	{
		pos = SkipWhiteSpace(str, pos2);
		if (pos == str.size())
			break;
		pos2 = FindEndOfToken(str, pos);

		std::string token = str.substr(pos, pos2 - pos);

		pos = SkipWhiteSpace(str, pos2);
		if (pos == str.size() || str[pos] != '=')
			break;

		pos = SkipWhiteSpace(str, pos + 1);
		pos2 = FindEndOfToken(str, pos);

		std::string value = str.substr(pos, pos2 - pos);

		if (token == "size")
			fontSize = (short)strtol(value.c_str(), 0, 10);
		else if (token == "outline")
			outlineThickness = (short)strtol(value.c_str(), 0, 10);

		if (pos == str.size())
			break;
	}

	SetFontInfo(fontSize, outlineThickness);
}

void FontLoaderTextFormat::InterpretPage(const std::string str, int start,
	const std::string fontFile)
{
	int id = 0;
	std::string file;

	// Read all attributes
	int pos, pos2 = start;
	while (true)
	{
		pos = SkipWhiteSpace(str, pos2);
		if (pos == str.size())
			break;
		pos2 = FindEndOfToken(str, pos);

		std::string token = str.substr(pos, pos2 - pos);

		pos = SkipWhiteSpace(str, pos2);
		if (pos == str.size() || str[pos] != '=') break;

		pos = SkipWhiteSpace(str, pos + 1);
		pos2 = FindEndOfToken(str, pos);

		std::string value = str.substr(pos, pos2 - pos);

		if (token == "id")
			id = strtol(value.c_str(), 0, 10);
		else if (token == "file")
			file = value.substr(1, value.length() - 2);

		if (pos == str.size()) break;
	}

	LoadPage(id, file.c_str(), fontFile);
}

//=============================================================================
// FontLoaderBinaryFormat
//
// This class implements the logic for loading a BMFont file in binary format
//=============================================================================

FontLoaderBinaryFormat::FontLoaderBinaryFormat(FileSystem::Open& f, Font *font, const char *fontFile)
	: FontLoader(f, font, fontFile)
{
}

int FontLoaderBinaryFormat::Load()
{
	// Read and validate the tag. It should be 66, 77, 70, 2,
	// or 'BMF' and 2 where the number is the file version.
	char magicString[4];
	fread(magicString, 4, 1, f);
	if (strncmp(magicString, "BMF\003", 4) != 0)
	{
		Logger::Log(FB_ERROR_LOG_ARG, FormatString("Unrecognized format for '%s'", fontFile.c_str()).c_str());
		return -1;
	}

	// Read each block
	char blockType;
	int blockSize;
	while (fread(&blockType, 1, 1, f))
	{
		// Read the blockSize
		fread(&blockSize, 4, 1, f);

		switch (blockType)
		{
		case 1: // info
			ReadInfoBlock(blockSize);
			break;
		case 2: // common
			ReadCommonBlock(blockSize);
			break;
		case 3: // pages
			ReadPagesBlock(blockSize);
			break;
		case 4: // chars
			ReadCharsBlock(blockSize);
			break;
		case 5: // kerning pairs
			ReadKerningPairsBlock(blockSize);
			break;
		default:
			Logger::Log(FB_ERROR_LOG_ARG, FormatString("Unexpected block type(%d)", blockType).c_str());
			return -1;
		}
	}

	// Success
	return 0;
}

void FontLoaderBinaryFormat::ReadInfoBlock(int size)
{
#pragma pack(push)
#pragma pack(1)
	struct infoBlock
	{
		unsigned short fontSize;
		unsigned char  reserved : 4;
		unsigned char  bold : 1;
		unsigned char  italic : 1;
		unsigned char  unicode : 1;
		unsigned char  smooth : 1;
		unsigned char  charSet;
		unsigned short stretchH;
		unsigned char  aa;
		unsigned char  paddingUp;
		unsigned char  paddingRight;
		unsigned char  paddingDown;
		unsigned char  paddingLeft;
		unsigned char  spacingHoriz;
		unsigned char  spacingVert;
		unsigned char  outline;         // Added with version 2
		char fontName[1];
	};
#pragma pack(pop)

	char *buffer = FB_ARRAY_NEW(char, size);
	fread(buffer, size, 1, f);

	// We're only interested in the outline thickness
	infoBlock *blk = (infoBlock*)buffer;
	SetFontInfo(blk->fontSize,  blk->outline);

	FB_ARRAY_DELETE(buffer);
}

void FontLoaderBinaryFormat::ReadCommonBlock(int size)
{
#pragma pack(push)
#pragma pack(1)
	struct commonBlock
	{
		unsigned short lineHeight;
		unsigned short base;
		unsigned short scaleW;
		unsigned short scaleH;
		unsigned short pages;
		unsigned char  packed : 1;
		unsigned char  reserved : 7;
		unsigned char  alphaChnl;
		unsigned char  redChnl;
		unsigned char  greenChnl;
		unsigned char  blueChnl;
	};
#pragma pack(pop)

	char *buffer = FB_ARRAY_NEW(char, size);
	fread(buffer, size, 1, f);

	commonBlock *blk = (commonBlock*)buffer;

	SetCommonInfo(blk->lineHeight, blk->base, blk->scaleW, blk->scaleH, blk->pages, blk->packed ? true : false);

	FB_ARRAY_DELETE(buffer);
}

void FontLoaderBinaryFormat::ReadPagesBlock(int size)
{
#pragma pack(push)
#pragma pack(1)
	struct pagesBlock
	{
		char pageNames[1];
	};
#pragma pack(pop)

	char *buffer = FB_ARRAY_NEW(char, size);
	fread(buffer, size, 1, f);

	pagesBlock *blk = (pagesBlock*)buffer;

	for (int id = 0, pos = 0; pos < size; id++)
	{
		LoadPage(id, &blk->pageNames[pos], fontFile);
		pos += 1 + (int)strlen(&blk->pageNames[pos]);
	}

	FB_ARRAY_DELETE(buffer);
}

void FontLoaderBinaryFormat::ReadCharsBlock(int size)
{
#pragma pack(push)
#pragma pack(1)
	struct charsBlock
	{
		struct charInfo
		{
			DWORD id;
			unsigned short x;
			unsigned short y;
			unsigned short width;
			unsigned short height;
			short xoffset;
			short yoffset;
			short xadvance;
			unsigned char page;
			unsigned char chnl;
		} chars[1];
	};
#pragma pack(pop)

	char *buffer = FB_ARRAY_NEW(char, size);
	fread(buffer, size, 1, f);

	charsBlock *blk = (charsBlock*)buffer;

	for (int n = 0; int(n*sizeof(charsBlock::charInfo)) < size; n++)
	{
		AddChar(blk->chars[n].id,
			blk->chars[n].x,
			blk->chars[n].y,
			blk->chars[n].width,
			blk->chars[n].height,
			blk->chars[n].xoffset,
			blk->chars[n].yoffset,
			blk->chars[n].xadvance,
			blk->chars[n].page,
			blk->chars[n].chnl);
	}

	FB_ARRAY_DELETE(buffer);
}

void FontLoaderBinaryFormat::ReadKerningPairsBlock(int size)
{
#pragma pack(push)
#pragma pack(1)
	struct kerningPairsBlock
	{
		struct kerningPair
		{
			DWORD first;
			DWORD second;
			short amount;
		} kerningPairs[1];
	};
#pragma pack(pop)

	char *buffer = FB_ARRAY_NEW(char, size);
	fread(buffer, size, 1, f);

	kerningPairsBlock *blk = (kerningPairsBlock*)buffer;

	for (int n = 0; int(n*sizeof(kerningPairsBlock::kerningPair)) < size; n++)
	{
		AddKerningPair(blk->kerningPairs[n].first,
			blk->kerningPairs[n].second,
			blk->kerningPairs[n].amount);
	}

	FB_ARRAY_DELETE(buffer);
}

}


text:
namespace rubbish{

    template <class T> struct tree_node{
        T data;
        tree_node<T> *child,*sibling;

        tree_node():data(T()),child(nullptr),sibling(nullptr){}
        explicit tree_node(const T &e):data(e),child(nullptr),sibling(nullptr){}
        explicit tree_node(T &&e):data(e),child(nullptr),sibling(nullptr){}
    };

    // Minimum requirements of type `node`:
    //   A data member variable named `data`;
    //   Two pointer member variables named `child`, `sibling`, respectively;
    //   `node` can be default-initialized and value-initialized.

    template <class T,class node = rubbish::tree_node<T> > class tree_base{
        public:
            class iterator_base{
                public:
                    typedef T                           value_type;
                    typedef T*                          pointer;
                    typedef T&                          reference;
                    typedef std::forward_iterator_tag   iterator_category;
                    typedef std::ptrdiff_t              difference_type;

                    typedef iterator_base                        self_type;
                    typedef std::shared_ptr< std::deque<node*> > data_type;

                    explicit iterator_base(node *root);
                    explicit iterator_base(const data_type &cursor):m_cursor(cursor) {}
                    virtual ~iterator_base() =default;

                    virtual reference operator*() const = 0;
                    pointer operator->() const { return &operator*(); }
                    data_type get() const {return m_cursor;}
                    virtual bool operator==(const self_type &other) const;
                    bool operator!=(const self_type &other) const {return !operator==(other);}
                    self_type& operator=(const self_type &other) {m_cursor=other.m_cursor; return *this;}
                protected:
                    data_type m_cursor;
            };

            class preorder_iterator: public iterator_base{
                private:
                    typedef iterator_base base_class;
                public:
                    typedef preorder_iterator self_type;
                    typedef typename base_class::pointer pointer;
                    typedef typename base_class::reference reference;

                    explicit preorder_iterator(node*);
                    preorder_iterator(const self_type &o):base_class(o.m_cursor) {}
                    reference operator*() const override {return m_cursor->back()->data;}
                    self_type& operator++();
                    self_type operator++(int) {auto i=*this;operator++();return *this;}
                    bool operator==(const self_type &other) const override {return base_class::operator==(other)&&m_cursor->back()==other.m_cursor->back();}
                private:
                    using base_class::m_cursor;
            };

            class postorder_iterator: public iterator_base{
                private:
                    typedef iterator_base base_class;
                public:
                    typedef postorder_iterator self_type;
                    typedef typename base_class::reference reference;

                    explicit postorder_iterator(node*);
                    postorder_iterator(const self_type &o):base_class(o.m_cursor) {}
                    reference operator*() const override {return m_cursor->back()->data;}
                    self_type& operator++();
                    self_type operator++(int) {auto i=*this;operator++();return *this;}
                    bool operator==(const self_type &other) const override {return base_class::operator==(other)&&m_cursor->back()==other.m_cursor->back();}
                private:
                    using base_class::m_cursor;
            };

            class level_iterator: public iterator_base{
                private:
                    typedef iterator_base base_class;
                public:
                    typedef level_iterator self_type;
                    typedef typename base_class::reference reference;

                    explicit level_iterator(node*);
                    level_iterator(const self_type &o):base_class(o.m_cursor) {}
                    reference operator*() const override {return m_cursor->front()->data;}
                    self_type& operator++();
                    self_type operator++(int) {auto i=*this;operator++();return *this;}
                    bool operator==(const self_type &other) const override {return base_class::operator==(other)&&m_cursor->front()==other.m_cursor->front();}
                private:
                    using base_class::m_cursor;
            };

        protected:
            // Deep-copy a tree from `src` to `dest`, recursively
            void copy_subtree(node* &dest, const node *src);

            // Return the depth of a binary tree whose root is `root`, recursively
            unsigned int depth(const node *root) const noexcept;

            // Destroy a tree whose root is `root`, recursively
            void delete_subtree(const node *root);
        public:
            // Construct a binary tree with given root(a raw pointer, by default it is nullptr).
            explicit tree_base(node* =nullptr);

            // Copy-construtor
            tree_base(const tree_base<T,node> &);

            // Move-construtor
            tree_base(tree_base<T,node>&&);

            // Destructor
            virtual ~tree_base();

            // Insert root to a new node as a parent
            void insert_parent(const T &data);

            // Insert a new node to root as a child
            void insert_child(const T &data);

            // Iterator functions
            preorder_iterator preorder_begin() {return preorder_iterator(m_root);}

            preorder_iterator preorder_end() {return preorder_iterator(nullptr);}

            // There isn't a well-defined in-order traversal of a non-binary tree

            postorder_iterator postorder_begin() {return postorder_iterator(m_root);}

            postorder_iterator postorder_end() {return postorder_iterator(nullptr);}

            level_iterator level_begin() {return level_iterator(m_root);}

            level_iterator level_end() {return level_iterator(nullptr);}

        protected:
            node *m_root;
    };

} // namespace rubbish

#include "tree_base.cc"

#endif // __RUBBISH_TREE_BASE__

redpajama_set_name: RedPajamaGithub


text:
require 'test_helper'

module Espace
  class PagesControllerTest < ActionController::TestCase
    setup do
      @page = espace_pages(:one)
      @routes = Engine.routes
    end

    test "should get index" do
      get :index
      assert_response :success
      assert_not_nil assigns(:pages)
    end

    test "should get new" do
      get :new
      assert_response :success
    end

    test "should create page" do
      assert_difference('Page.count') do
        post :create, page: { deleted_at: @page.deleted_at, text: @page.text, title: @page.title }
      end

      assert_redirected_to page_path(assigns(:page))
    end

    test "should show page" do
      get :show, id: @page
      assert_response :success
    end

    test "should get edit" do
      get :edit, id: @page
      assert_response :success
    end

    test "should update page" do
      patch :update, id: @page, page: { deleted_at: @page.deleted_at, text: @page.text, title: @page.title }
      assert_redirected_to page_path(assigns(:page))
    end

    test "should destroy page" do
      assert_difference('Page.count', -1) do
        delete :destroy, id: @page
      end

      assert_redirected_to pages_path
    end
  end
end


text:
<?php
/**
 * Model M_user
 * The Users of the application
 * This model is used for user administration.
 * @see library Simplelogin for CRUD actions and authentification.
 *
 * @author
 */
class M_user extends MY_Model {
	/**
	 * Class variables
	 *
	 */
	public $id = 0;
	public $email = '';
	public $username = NULL;
	public $auth_level = 0;
	public $banned = '0';
	public $passwd_recovery_code = '';
	public $passwd_recovery_date = NULL;
	private $password = '';
	public $passwd_modified_at = NULL;
	public $last_login = NULL;
	public $created_at = NULL;
	public $modified_at = NULL;

	public $vorname = '';
	public $nachname = '';
	public $strasse = '';
	public $plz = '';
	public $ort = '';
	public $telefon = '';
	public $iban = '';

	/**
	 * Constructor
	 *
	 */
	public function __construct() {
		parent::__construct();
	}

	/**
	 * Array aller Benutzer
	 *
	 * @return	array of M_user
	 */
	public static function all()
	{
		$arrOut = array();
		$CI =& get_instance();

		$CI->db->select(array(
		    config_item('user_table').'.user_id',
		    'username',
		    'email',
		    'vorname',
		    'nachname',
		    'strasse',
		    'plz',
		    'ort',
		    'telefon',
		    'iban',
		    'auth_level',
		    'banned',
		    'passwd_recovery_code',
		    'passwd_recovery_date',
		    'passwd_modified_at',
		    'last_login',
		    'created_at',
		    'modified_at'));
	    $CI->db->order_by('email', 'asc');
	    $CI->db->join('private', 'private.user_id = '.config_item('user_table').'.user_id', 'left');
	    $query = $CI->db->get(config_item('user_table'));
		if ($query->num_rows() == 0) {
			return $arrOut;
		}

		foreach ($query->result() as $row) {
			$thisUser = new M_user();
			$thisUser->id		= $row->user_id;
			$thisUser->email	= $row->email;
			$thisUser->username = $row->username;
			$thisUser->auth_level = $row->auth_level;
			$thisUser->banned = $row->banned;
			$thisUser->created_at = $row->created_at;
			$thisUser->last_login = $row->last_login;
			$thisUser->modified_at = $row->modified_at;
			$thisUser->passwd_modified_at = $row->passwd_modified_at;
			$thisUser->passwd_recovery_code = $row->passwd_recovery_code;
			$thisUser->passwd_recovery_date = $row->passwd_recovery_date;
			$thisUser->vorname = $row->vorname;
			$thisUser->nachname = $row->nachname;
			$thisUser->strasse = $row->strasse;
			$thisUser->plz = $row->plz;
			$thisUser->ort = $row->ort;
			$thisUser->telefon = $row->telefon;
			$thisUser->iban = $row->iban;

			$arrOut[$row->user_id] = $thisUser;
		}
		return $arrOut;
	}

	/**
	 * Change a user's password
	 *
	 * @param  string  the new password
	 * @param  string  the new password confirmed
	 * @param  string  the user ID
	 * @param  string  the password recovery code
	 */
	protected function _change_password( $password, $password2, $user_id, $recovery_code )
	{
	    // User ID check
	    if( isset( $user_id ) && $user_id !== FALSE )
	    {
	        $query = $this->db->select( 'user_id' )
	        ->from( $this->db_table('user_table') )
	        ->where( 'user_id', $user_id )
	        ->where( 'passwd_recovery_code', $recovery_code )
	        ->get();

	        // If above query indicates a match, change the password
	        if( $query->num_rows() == 1 )
	        {
	            $user_data = $query->row();

	            $this->db->where( 'user_id', $user_data->user_id )
	            ->update(
	                $this->db_table('user_table'),
	                [
	                    'passwd' => $this->authentication->hash_passwd( $password ),
	                    'passwd_recovery_code' => NULL,
	                    'passwd_recovery_date' => NULL
	                ]
	                );
	        }
	    }
	}

	/**
	 * Delete a user from all used tables
	 * @return bool    True if successfully deleted
	 */
	public function delete()
	{
	    $ret = true;
	    // Delete from joined table "private"
	    $this->db->where('user_id', $this->id);
	    $this->db->delete('private');

	    // Maybe in the future we have to deal with acl records - not yet.

	    // Delete from users table
	    $this->db->where('user_id', $this->id);
	    $ret = $this->db->delete('users');
	    if (!$ret) {
	        log_message('error', 'Could not delete user #' . $this->id . ' from users table.');
	    }

	    return $ret;
	}

	/**
	 * Get the data from database and populate the class attributes
	 *
	 * @param	int		$id
	 * @return	boolean	True if a user with this id could be found
	 */
	public function fetch($id)
	{
		$this->db->where('users.user_id', $id);
		$this->db->join('private', 'users.user_id = private.user_id', 'left');
		$query = $this->db->get('users', 1);
		if (1 != $query->num_rows()) {
			return false;
		}
		$row = $query->row();
		$this->id		= $row->user_id;
		$this->email	= $row->email;
		$this->username = $row->username;
		$this->auth_level = $row->auth_level;
		$this->banned = $row->banned;
		$this->created_at = $row->created_at;
		$this->last_login = $row->last_login;
		$this->modified_at = $row->modified_at;
		$this->passwd_modified_at = $row->passwd_modified_at;
		$this->passwd_recovery_code = $row->passwd_recovery_code;
		$this->passwd_recovery_date = $row->passwd_recovery_date;
		$this->vorname = $row->vorname;
		$this->nachname = $row->nachname;
		$this->strasse = $row->strasse;
		$this->plz = $row->plz;
		$this->ort = $row->ort;
		$this->telefon = $row->telefon;
		$this->iban = $row->iban;

		return true;
	}

	/**
	 * Fetches data from db.
	 * @uses	$this->fetch()
	 * @param 	String	$email
	 * @return boolean	True if data was found in db
	 */
	public function fetch4email($email)
	{
	    $q = $this->db->query('SELECT user_id FROM users WHERE email = ?', array($email));
	    if (0 == $q->num_rows()) {
	        return false;
	    } else {
	        return $this->fetch($q->row()->user_id);
	    }
	}

	/**
	 * Fetches data from db.
	 * @uses	$this->fetch()
	 * @param 	String	$email
	 * @return boolean	True if data was found in db
	 */
	public function fetch4username($username)
	{
	    $q = $this->db->query('SELECT user_id FROM users WHERE username = ?', array($username));
	    if (0 == $q->num_rows()) {
	        return false;
	    } else {
	        return $this->fetch($q->row()->user_id);
	    }
	}

	/**
	 * Get data for a recovery
	 *
	 * @param   string  the email address
	 * @return  mixed   either query data or FALSE
	 */
	public function get_recovery_data( $email )
	{
	    $query = $this->db->select( 'u.user_id, u.email, u.banned' )
	    ->from( $this->db_table('user_table') . ' u' )
	    ->where( 'LOWER( u.email ) =', strtolower( $email ) )
	    ->limit(1)
	    ->get();

	    if( $query->num_rows() == 1 )
	        return $query->row();

	        return FALSE;
	}

	/**
	 * Get the user name, user salt, and hashed recovery code,
	 * but only if the recovery code hasn't expired.
	 *
	 * @param  int  the user ID
	 */
	public function get_recovery_verification_data( $user_id )
	{
	    $recovery_code_expiration = date('Y-m-d H:i:s', time() - config_item('recovery_code_expiration') );

	    $query = $this->db->select( 'username, passwd_recovery_code' )
	    ->from( $this->db_table('user_table') )
	    ->where( 'user_id', $user_id )
	    ->where( 'passwd_recovery_date >', $recovery_code_expiration )
	    ->limit(1)
	    ->get();

	    if ( $query->num_rows() == 1 )
	        return $query->row();

	        return FALSE;
	}

	/**
	 * Get an unused ID for user creation
	 *
	 * @return  int between 12000 and 4294967295
	 */
	private function get_unused_id()
	{
	    // Create a random user id between 12000 and 4294967295
	    $random_unique_int = 2147483648 + random_int( -2147471648, 2147483647 );

	    // Make sure the random user_id isn't already in use
	    $query = $this->db->where( 'user_id', $random_unique_int )
	    ->get_where( $this->db_table('user_table') );

	    if( $query->num_rows() > 0 )
	    {
	        $query->free_result();

	        // If the random user_id is already in use, try again
	        return $this->get_unused_id();
	    }

	    return $random_unique_int;
	}

	/**
	 * Validation and processing for password change during account recovery
	 */
	public function recovery_password_change()
	{
	    $this->load->library('form_validation');

	    // Load form validation rules
	    $this->load->model('validation_callables');
	    $this->form_validation->set_rules([
	        [
	            'field' => 'passwd',
	            'label' => 'Neues Passwort',
	            'rules' => [
	                'trim',
	                'required',
	                'matches[passwd_confirm]',
	                [
	                    '_check_password_strength',
	                    [$this->validation_callables, 'check_password_strength']
	                ]
	            ]
	        ],
	        [
	            'field' => 'passwd_confirm',
	            'label' => 'Passwort Bestätigung',
	            'rules' => 'trim|required'
	        ],
	        [
	            'field' => 'recovery_code'
	        ],
	        [
	            'field' => 'user_id'
	        ]
	    ]);

	    if( $this->form_validation->run() !== FALSE )
	    {
	        $this->load->vars( ['validation_passed' => 1] );

	        $this->_change_password(
	            $this->input->post('passwd'),
	            $this->input->post('passwd_confirm'),
	            set_value('user_id'),
	            set_value('recovery_code')
	            );
	    }
	    else
	    {
	        $this->load->vars( ['validation_errors' => validation_errors()] );
	    }
	}

	/**
	 * Return all types a user can have. Used for dropdowns
	 * @return array	key: auth_level; value: lang text
	 */
	public static function roles()
	{
	    return config_item('levels_and_roles');
	}

	/**
	 * Save class attributes to database
	 * To create a user and for changing the password
	 * the SimpleLoginSecure library is used.
	 *
	 * @see SimpleLoginSecure
	 * @return	boolean							True on success
	 */
	public function save()
	{
	    $success = FALSE;
	    $this->db->set('auth_level', $this->auth_level);
	    $this->db->set('banned', $this->banned);
	    $this->db->set('created_at', $this->created_at);
	    $this->db->set('email', $this->email);
	    $this->db->set('last_login', $this->last_login);
	    $this->db->set('modified_at', $this->modified_at);
	    $this->db->set('passwd_modified_at', $this->passwd_modified_at);
	    $this->db->set('passwd_recovery_code', $this->passwd_recovery_code);
	    $this->db->set('passwd_recovery_date', $this->passwd_recovery_date);
	    if (!empty($this->password)) {
	        $this->db->set('passwd', $this->password);
	    }
	    if (!empty($this->username)) {
	        $this->db->set('username', $this->username);
	    }

		// New user
		if (0 == $this->id) {
			// Check if another user has this email address
			$this->db->where('email', $this->email);
			$query = $this->db->get('users', 1);
			if ($query->num_rows() == 1) {
				log_message('error', 'Benutzer mit dieser Mail Adresse existiert schon.');
				return false;
			}
			// Check if another user has this username
		    if (!empty($this->username)) {
		        $this->db->where('username', $this->username);
		        $query = $this->db->get('users', 1);
		        if ($query->num_rows() == 1) {
		            log_message('error', 'Benutzer mit diesem Benutzernamen existiert schon.');
		            return false;
		        }
		    }

		    $this->id = $this->get_unused_id();
		    $this->db->set('user_id', $this->id);

		    $success = $this->db->insert(db_table('user_table'));

		} // End if new user
		else {
		    $this->db->where('user_id', $this->id);
		    $success = $this->db->update(db_table('user_table'));
		}

		// Both new and existing
		if( TRUE !== $success ) {
		    log_message('error', 'Benutzer speichern fehlgeschlagen.');
		    return false;
		}

		// Personal informations to table "private"
		$this->db->where('user_id', $this->id);
		$query = $this->db->get('private');

		$this->db->set('vorname', $this->vorname);
		$this->db->set('nachname', $this->nachname);
		$this->db->set('strasse', $this->strasse);
		$this->db->set('plz', $this->plz);
		$this->db->set('ort', $this->ort);
		$this->db->set('telefon', $this->telefon);
		$this->db->set('iban', $this->iban);
		if (1 != $query->num_rows()) {
		    $this->db->set('user_id', $this->id);
		    $ret = $this->db->insert('private');
		} else {
		    $this->db->where('user_id', $this->id);
		    $ret = $this->db->update('private');
		}
		if (!$ret) {
		    log_message('error', 'Benutzer speichern in Tabelle "private" fehlgeschlagen.');
		}

        return TRUE;
	} // End of function save()

	/**
	 * Set hashed password
	 * @param String $pwd  The unhashed password
	 * @return void
	 */
	public function set_password($pwd) {
	    $this->password = $this->authentication->hash_passwd( $pwd );
	}

	/**
	 * Update a user record with data not from POST
	 *
	 * @param  int     the user ID to update
	 * @param  array   the data to update in the user table
	 * @return bool
	 */
	public function update_user_raw_data( $the_user, $user_data = [] )
	{
	    return $this->db->where('user_id', $the_user)->update( $this->db_table('user_table'), $user_data );
	}

} // End of class M_user


text:
layout: master
include: person
name: Jacob Brandrup
home: DTU
country: DK
photo:
email: jbran@dtu.dk
phone:
on_contract:
has_been_on_contract:
groups:
  tryggve2:
---


text:
//Copyright (C) 2012 by Lee Millward

//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:

//The above copyright notice and this permission notice shall be included in
//all copies or substantial portions of the Software.

//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//THE SOFTWARE.

using CookComputing.XmlRpc;

namespace Bugzilla.Proxies.Bug.Params
{
  /// <summary>
  /// Parameters required when adding an attachment to a bug.
  /// </summary>
  internal struct AddAttachmentParams
  {
    /// <summary>
    /// List of bug IDs or aliases to add the attachment to.
    /// </summary>
    [XmlRpcMember("ids")]
    public string[] IdsOrAliases;

    /// <summary>
    /// Base64 encoded data of the attachment.
    /// </summary>
    [XmlRpcMember("data")]
    public byte[] Data;

    /// <summary>
    /// The 'file name' that will be shown in the UI.
    /// </summary>
    [XmlRpcMember("file_name")]
    public string FileName;

    /// <summary>
    /// Short description for the attachment.
    /// </summary>
    [XmlRpcMember("summary")]
    public string Summary;

    /// <summary>
    /// MIME type of the attachment.
    /// </summary>
    [XmlRpcMember("content_type")]
    public string MIMEType;

    /// <summary>
    /// Comment text to add along with the attachment.
    /// </summary>
    [XmlRpcMember("comment")]
    public string Comment;

    /// <summary>
    /// Whether Bugzilla should treat the attachment as a patch.
    /// </summary>
    [XmlRpcMember("is_patch")]
    public bool IsPatch;

    /// <summary>
    /// Whether the attachment is private or not.
    /// </summary>
    [XmlRpcMember("is_private")]
    public bool IsPrivate;
  }
}


text:
<?xml version="1.0" encoding="utf-8"?>

<Deployment xmlns="http://schemas.microsoft.com/windowsphone/2012/deployment" AppPlatformVersion="8.0">
  <DefaultLanguage xmlns="" code="en-US"/>
  <App xmlns="" ProductID="{7cba147b-d6cc-4a42-8bff-e3df47269284}" Title="BehaviorEntryValidation.WinPhone" RuntimeType="Silverlight" Version="1.0.0.0" Genre="apps.normal"  Author="BehaviorEntryValidation.WinPhone author" Description="Sample description" Publisher="BehaviorEntryValidation.WinPhone" PublisherID="{1d42a881-e111-4f02-bd95-b0696b00f085}">
    <IconPath IsRelative="true" IsResource="false">Assets\ApplicationIcon.png</IconPath>
    <Capabilities>
      <Capability Name="ID_CAP_NETWORKING"/>
      <Capability Name="ID_CAP_MEDIALIB_AUDIO"/>
      <Capability Name="ID_CAP_MEDIALIB_PLAYBACK"/>
      <Capability Name="ID_CAP_SENSORS"/>
      <Capability Name="ID_CAP_WEBBROWSERCOMPONENT"/>
    </Capabilities>
    <Tasks>
      <DefaultTask  Name ="_default" NavigationPage="MainPage.xaml"/>
    </Tasks>
    <Tokens>
      <PrimaryToken TokenID="PhoneApp1Token" TaskName="_default">
        <TemplateFlip>
          <SmallImageURI IsRelative="true" IsResource="false">Assets\Tiles\FlipCycleTileSmall.png</SmallImageURI>
          <Count>0</Count>
          <BackgroundImageURI IsRelative="true" IsResource="false">Assets\Tiles\FlipCycleTileMedium.png</BackgroundImageURI>
          <Title>BehaviorEntryValidation.WinPhone</Title>
          <BackContent></BackContent>
          <BackBackgroundImageURI></BackBackgroundImageURI>
          <BackTitle></BackTitle>
          <DeviceLockImageURI></DeviceLockImageURI>
          <HasLarge></HasLarge>
        </TemplateFlip>
      </PrimaryToken>
    </Tokens>
    <ScreenResolutions>
      <ScreenResolution Name="ID_RESOLUTION_WVGA"/>
      <ScreenResolution Name="ID_RESOLUTION_WXGA"/>
      <ScreenResolution Name="ID_RESOLUTION_HD720P"/>
    </ScreenResolutions>
  </App>
</Deployment>


text:
/*!
 * \file elemwise_binary_broadcast_op_extended.cc
 * \brief Implementation of the API of functions in
 * src/operator/tensor/elemwise_binary_broadcast_op_extended.cc
 */
#include <mxnet/api_registry.h>
#include <mxnet/runtime/packed_func.h>
#include "../utils.h"
#include "../ufunc_helper.h"

namespace mxnet {

MXNET_REGISTER_API("_npi.maximum")
    .set_body([](runtime::MXNetArgs args, runtime::MXNetRetValue* ret) {
      using namespace runtime;
      const nnvm::Op* op        = Op::Get("_npi_maximum");
      const nnvm::Op* op_scalar = Op::Get("_npi_maximum_scalar");
      UFuncHelper(args, ret, op, op_scalar, nullptr);
    });

MXNET_REGISTER_API("_npi.minimum")
    .set_body([](runtime::MXNetArgs args, runtime::MXNetRetValue* ret) {
      using namespace runtime;
      const nnvm::Op* op        = Op::Get("_npi_minimum");
      const nnvm::Op* op_scalar = Op::Get("_npi_minimum_scalar");
      UFuncHelper(args, ret, op, op_scalar, nullptr);
    });

}  // namespace mxnet


text:
import sys
from . import context

#
# Copy stuff from default context
#

globals().update((name, getattr(context._default_context, name))
                 for name in context._default_context.__all__)
__all__ = context._default_context.__all__

#
# XXX These should not really be documented or public.
#

SUBDEBUG = 5
SUBWARNING = 25

#
# Alias for main module -- will be reset by bootstrapping child processes
#

if '__main__' in sys.modules:
    sys.modules['__mp_main__'] = sys.modules['__main__']


text:
// This header is a shim that manages differences between CUDA and ROCM APIs.
// Jaxlib GPU kernels can be compiled for either CUDA or ROCM by defining
// JAX_GPU_CUDA or JAX_GPU_HIP respectively.

#ifndef JAXLIB_GPU_VENDOR_H_
#define JAXLIB_GPU_VENDOR_H_

#if defined(JAX_GPU_CUDA)

#include "third_party/gpus/cuda/include/cuComplex.h"
#include "third_party/gpus/cuda/include/cublas_v2.h"
#include "third_party/gpus/cuda/include/cuda.h"
#include "third_party/gpus/cuda/include/cuda_runtime_api.h"
#include "third_party/gpus/cuda/include/cusolverDn.h"
#include "third_party/gpus/cuda/include/cusparse.h"

// Some sparse functionality is only available in CUSPARSE 11.3 or newer.
#define JAX_GPU_HAVE_SPARSE (CUSPARSE_VERSION >= 11300)

// CUDA-11.8 introduces FP8 E4M3/E5M2 types.
#define JAX_GPU_HAVE_FP8 (CUDA_VERSION >= 11080)

#if JAX_GPU_HAVE_FP8
#include "third_party/gpus/cuda/include/cuda_fp8.h"
#endif

// cuSPARSE generic APIs are not supported on Windows until 11.0
// cusparseIndexType_t is used in very limited scope so manually define will
// workaround compiling issue without harm.
#if defined(_WIN32) && (CUSPARSE_VERSION < 11000)
typedef enum {
  CUSPARSE_INDEX_16U = 1,
  CUSPARSE_INDEX_32I = 2,
  CUSPARSE_INDEX_64I = 3
} cusparseIndexType_t;
#endif

#define JAX_GPU_NAMESPACE cuda
#define JAX_GPU_PREFIX "cu"

typedef cuComplex gpuComplex;
typedef cuDoubleComplex gpuDoubleComplex;

typedef cuComplex gpublasComplex;
typedef cuDoubleComplex gpublasDoubleComplex;
typedef cublasFillMode_t gpusolverFillMode_t;
typedef cublasStatus_t gpublasStatus_t;
typedef cublasHandle_t gpublasHandle_t;
typedef cudaDataType gpuDataType;
typedef cudaStream_t gpuStream_t;
typedef cudaError_t gpuError_t;
typedef cusolverDnHandle_t gpusolverDnHandle_t;
typedef cusolverStatus_t gpusolverStatus_t;
typedef cusolverEigMode_t gpusolverEigMode_t;
typedef syevjInfo gpuSyevjInfo;
typedef syevjInfo_t gpuSyevjInfo_t;
typedef cusparseIndexType_t gpusparseIndexType_t;
typedef cusparseHandle_t gpusparseHandle_t;
typedef cusparseOperation_t gpusparseOperation_t;
typedef cusparseStatus_t gpusparseStatus_t;
typedef cusparseSpMatDescr_t gpusparseSpMatDescr_t;
typedef cusparseDnMatDescr_t gpusparseDnMatDescr_t;
typedef cusparseDnVecDescr_t gpusparseDnVecDescr_t;

#define GPU_C_16F CUDA_C_16F
#define GPU_R_16F CUDA_R_16F
#define GPU_C_32F CUDA_C_32F
#define GPU_R_32F CUDA_R_32F
#define GPU_C_64F CUDA_C_64F
#define GPU_R_64F CUDA_R_64F

#define gpublasCreate cublasCreate
#define gpublasSetStream cublasSetStream
#define gpublasSgeqrfBatched cublasSgeqrfBatched
#define gpublasDgeqrfBatched cublasDgeqrfBatched
#define gpublasCgeqrfBatched cublasCgeqrfBatched
#define gpublasZgeqrfBatched cublasZgeqrfBatched
#define gpublasSgetrfBatched cublasSgetrfBatched
#define gpublasDgetrfBatched cublasDgetrfBatched
#define gpublasCgetrfBatched cublasCgetrfBatched
#define gpublasZgetrfBatched cublasZgetrfBatched

#define GPUBLAS_STATUS_SUCCESS CUBLAS_STATUS_SUCCESS

#define gpusolverDnCreate cusolverDnCreate
#define gpusolverDnSetStream cusolverDnSetStream
#define gpusolverDnCreateSyevjInfo cusolverDnCreateSyevjInfo
#define gpusolverDnDestroySyevjInfo cusolverDnDestroySyevjInfo
#define gpusolverDnSgeqrf cusolverDnSgeqrf
#define gpusolverDnDgeqrf cusolverDnDgeqrf
#define gpusolverDnCgeqrf cusolverDnCgeqrf
#define gpusolverDnZgeqrf cusolverDnZgeqrf
#define gpusolverDnSgeqrf_bufferSize cusolverDnSgeqrf_bufferSize
#define gpusolverDnDgeqrf_bufferSize cusolverDnDgeqrf_bufferSize
#define gpusolverDnCgeqrf_bufferSize cusolverDnCgeqrf_bufferSize
#define gpusolverDnZgeqrf_bufferSize cusolverDnZgeqrf_bufferSize
#define gpusolverDnSgetrf(h, m, n, a, lda, work, lwork, ipiv, info) \
  cusolverDnSgetrf(h, m, n, a, lda, work, ipiv, info)
#define gpusolverDnDgetrf(h, m, n, a, lda, work, lwork, ipiv, info) \
  cusolverDnDgetrf(h, m, n, a, lda, work, ipiv, info)
#define gpusolverDnCgetrf(h, m, n, a, lda, work, lwork, ipiv, info) \
  cusolverDnCgetrf(h, m, n, a, lda, work, ipiv, info)
#define gpusolverDnZgetrf(h, m, n, a, lda, work, lwork, ipiv, info) \
  cusolverDnZgetrf(h, m, n, a, lda, work, ipiv, info)
#define gpusolverDnSgetrf_bufferSize cusolverDnSgetrf_bufferSize
#define gpusolverDnDgetrf_bufferSize cusolverDnDgetrf_bufferSize
#define gpusolverDnCgetrf_bufferSize cusolverDnCgetrf_bufferSize
#define gpusolverDnZgetrf_bufferSize cusolverDnZgetrf_bufferSize
#define gpusolverDnSorgqr cusolverDnSorgqr
#define gpusolverDnDorgqr cusolverDnDorgqr
#define gpusolverDnCungqr cusolverDnCungqr
#define gpusolverDnZungqr cusolverDnZungqr
#define gpusolverDnSorgqr_bufferSize cusolverDnSorgqr_bufferSize
#define gpusolverDnDorgqr_bufferSize cusolverDnDorgqr_bufferSize
#define gpusolverDnCungqr_bufferSize cusolverDnCungqr_bufferSize
#define gpusolverDnZungqr_bufferSize cusolverDnZungqr_bufferSize
#define gpusolverDnSsyevd cusolverDnSsyevd
#define gpusolverDnDsyevd cusolverDnDsyevd
#define gpusolverDnCheevd cusolverDnCheevd
#define gpusolverDnZheevd cusolverDnZheevd
#define gpusolverDnSsyevd_bufferSize cusolverDnSsyevd_bufferSize
#define gpusolverDnDsyevd_bufferSize cusolverDnDsyevd_bufferSize
#define gpusolverDnCheevd_bufferSize cusolverDnCheevd_bufferSize
#define gpusolverDnZheevd_bufferSize cusolverDnZheevd_bufferSize
#define gpusolverDnSsyevj cusolverDnSsyevj
#define gpusolverDnDsyevj cusolverDnDsyevj
#define gpusolverDnCheevj cusolverDnCheevj
#define gpusolverDnZheevj cusolverDnZheevj
#define gpusolverDnSsyevj_bufferSize cusolverDnSsyevj_bufferSize
#define gpusolverDnDsyevj_bufferSize cusolverDnDsyevj_bufferSize
#define gpusolverDnCheevj_bufferSize cusolverDnCheevj_bufferSize
#define gpusolverDnZheevj_bufferSize cusolverDnZheevj_bufferSize
#define gpusolverDnSsyevjBatched cusolverDnSsyevjBatched
#define gpusolverDnDsyevjBatched cusolverDnDsyevjBatched
#define gpusolverDnCheevjBatched cusolverDnCheevjBatched
#define gpusolverDnZheevjBatched cusolverDnZheevjBatched
#define gpusolverDnSsyevjBatched_bufferSize cusolverDnSsyevjBatched_bufferSize
#define gpusolverDnDsyevjBatched_bufferSize cusolverDnDsyevjBatched_bufferSize
#define gpusolverDnCheevjBatched_bufferSize cusolverDnCheevjBatched_bufferSize
#define gpusolverDnZheevjBatched_bufferSize cusolverDnZheevjBatched_bufferSize
#define gpusolverDnSgesvd cusolverDnSgesvd
#define gpusolverDnDgesvd cusolverDnDgesvd
#define gpusolverDnCgesvd cusolverDnCgesvd
#define gpusolverDnZgesvd cusolverDnZgesvd
#define gpusolverDnSgesvd_bufferSize(h, jobu, jobvt, m, n, lwork) \
  cusolverDnSgesvd_bufferSize(h, m, n, lwork)
#define gpusolverDnDgesvd_bufferSize(h, jobu, jobvt, m, n, lwork) \
  cusolverDnDgesvd_bufferSize(h, m, n, lwork)
#define gpusolverDnCgesvd_bufferSize(h, jobu, jobvt, m, n, lwork) \
  cusolverDnCgesvd_bufferSize(h, m, n, lwork)
#define gpusolverDnZgesvd_bufferSize(h, jobu, jobvt, m, n, lwork) \
  cusolverDnZgesvd_bufferSize(h, m, n, lwork)
#define gpusolverDnSsytrd_bufferSize cusolverDnSsytrd_bufferSize
#define gpusolverDnDsytrd_bufferSize cusolverDnDsytrd_bufferSize
#define gpusolverDnChetrd_bufferSize cusolverDnChetrd_bufferSize
#define gpusolverDnZhetrd_bufferSize cusolverDnZhetrd_bufferSize
#define gpusolverDnSsytrd cusolverDnSsytrd
#define gpusolverDnDsytrd cusolverDnDsytrd
#define gpusolverDnChetrd cusolverDnChetrd
#define gpusolverDnZhetrd cusolverDnZhetrd

#define GPUSOLVER_FILL_MODE_LOWER CUBLAS_FILL_MODE_LOWER
#define GPUSOLVER_FILL_MODE_UPPER CUBLAS_FILL_MODE_UPPER
#define GPUSOLVER_EIG_MODE_VECTOR CUSOLVER_EIG_MODE_VECTOR
#define GPUSOLVER_STATUS_SUCCESS CUSOLVER_STATUS_SUCCESS

#define gpusparseCooSetStridedBatch cusparseCooSetStridedBatch
#define gpusparseCreate cusparseCreate
#define gpusparseCreateCoo cusparseCreateCoo
#define gpusparseCreateCsr cusparseCreateCsr
#define gpusparseCreateDnMat cusparseCreateDnMat
#define gpusparseCreateDnVec cusparseCreateDnVec
#define gpusparseDenseToSparse_analysis cusparseDenseToSparse_analysis
#define gpusparseDenseToSparse_bufferSize cusparseDenseToSparse_bufferSize
#define gpusparseDenseToSparse_convert cusparseDenseToSparse_convert
#define gpusparseDestroySpMat cusparseDestroySpMat
#define gpusparseDestroyDnMat cusparseDestroyDnMat
#define gpusparseDestroyDnVec cusparseDestroyDnVec
#define gpusparseDnMatSetStridedBatch cusparseDnMatSetStridedBatch
#define gpusparseSetStream cusparseSetStream
#define gpusparseSparseToDense cusparseSparseToDense
#define gpusparseSparseToDense_bufferSize cusparseSparseToDense_bufferSize
#define gpusparseSpMM cusparseSpMM
#define gpusparseSpMM_bufferSize cusparseSpMM_bufferSize
#define gpusparseSpMV cusparseSpMV
#define gpusparseSpMV_bufferSize cusparseSpMV_bufferSize
#define gpusparseSgtsv2 cusparseSgtsv2
#define gpusparseDgtsv2 cusparseDgtsv2
#define gpusparseSgtsv2_bufferSizeExt cusparseSgtsv2_bufferSizeExt
#define gpusparseDgtsv2_bufferSizeExt cusparseDgtsv2_bufferSizeExt

#define GPUSPARSE_INDEX_16U CUSPARSE_INDEX_16U
#define GPUSPARSE_INDEX_32I CUSPARSE_INDEX_32I
#define GPUSPARSE_INDEX_64I CUSPARSE_INDEX_64I
#define GPUSPARSE_DENSETOSPARSE_ALG_DEFAULT CUSPARSE_DENSETOSPARSE_ALG_DEFAULT
#define GPUSPARSE_INDEX_BASE_ZERO CUSPARSE_INDEX_BASE_ZERO
// Use CUSPARSE_SPMV_COO_ALG2 and CUSPARSE_SPMV_CSR_ALG2 for SPMV and
// use CUSPARSE_SPMM_COO_ALG2 and CUSPARSE_SPMM_CSR_ALG3 for SPMM, which
// provide deterministic (bit-wise) results for each run. These indexing modes
// are fully supported (both row- and column-major inputs) in CUSPARSE 11.7.1
// and newer (which was released as part of CUDA 11.8)
#if CUSPARSE_VERSION > 11700
#define GPUSPARSE_SPMV_COO_ALG CUSPARSE_SPMV_COO_ALG2
#define GPUSPARSE_SPMV_CSR_ALG CUSPARSE_SPMV_CSR_ALG2
#define GPUSPARSE_SPMM_COO_ALG CUSPARSE_SPMM_COO_ALG2
#define GPUSPARSE_SPMM_CSR_ALG CUSPARSE_SPMM_CSR_ALG3
#else
#define GPUSPARSE_SPMV_COO_ALG CUSPARSE_MV_ALG_DEFAULT
#define GPUSPARSE_SPMV_CSR_ALG CUSPARSE_MV_ALG_DEFAULT
#define GPUSPARSE_SPMM_COO_ALG CUSPARSE_SPMM_ALG_DEFAULT
#define GPUSPARSE_SPMM_CSR_ALG CUSPARSE_SPMM_ALG_DEFAULT
#endif
#define GPUSPARSE_OPERATION_NON_TRANSPOSE CUSPARSE_OPERATION_NON_TRANSPOSE
#define GPUSPARSE_OPERATION_TRANSPOSE CUSPARSE_OPERATION_TRANSPOSE
#define GPUSPARSE_ORDER_ROW CUSPARSE_ORDER_ROW
#define GPUSPARSE_SPARSETODENSE_ALG_DEFAULT CUSPARSE_SPARSETODENSE_ALG_DEFAULT
#define GPUSPARSE_STATUS_SUCCESS CUSPARSE_STATUS_SUCCESS

#define gpuGetLastError cudaGetLastError
#define gpuGetErrorString cudaGetErrorString
#define gpuMemcpyAsync cudaMemcpyAsync
#define gpuMemcpyDeviceToDevice cudaMemcpyDeviceToDevice
#define gpuMemcpyHostToDevice cudaMemcpyHostToDevice
#define gpuStreamSynchronize cudaStreamSynchronize
#define gpuSuccess cudaSuccess

#elif defined(JAX_GPU_HIP)

#include "rocm/include/hip/hip_runtime_api.h"
#include "rocm/include/hipblas.h"
#include "rocm/include/hipsolver.h"
#include "rocm/include/hipsparse.h"

#define JAX_GPU_NAMESPACE hip
#define JAX_GPU_PREFIX "hip"

#define JAX_GPU_HAVE_SPARSE 1
#define JAX_GPU_HAVE_FP8 0

typedef hipFloatComplex gpuComplex;
typedef hipDoubleComplex gpuDoubleComplex;

typedef hipblasComplex gpublasComplex;
typedef hipblasDoubleComplex gpublasDoubleComplex;
typedef hipsolverHandle_t gpusolverDnHandle_t;
typedef hipblasFillMode_t gpublasFillMode_t;
typedef hipsolverFillMode_t gpusolverFillMode_t;
typedef hipblasHandle_t gpublasHandle_t;
typedef hipblasStatus_t gpublasStatus_t;
typedef hipDataType gpuDataType;
typedef hipStream_t gpuStream_t;
typedef hipError_t gpuError_t;
typedef void gpuSyevjInfo;
typedef hipsolverSyevjInfo_t gpuSyevjInfo_t;
typedef hipsolverEigMode_t gpusolverEigMode_t;
typedef hipsolverStatus_t gpusolverStatus_t;
typedef hipsparseIndexType_t gpusparseIndexType_t;
typedef hipsparseHandle_t gpusparseHandle_t;
typedef hipsparseOperation_t gpusparseOperation_t;
typedef hipsparseStatus_t gpusparseStatus_t;
typedef hipsparseSpMatDescr_t gpusparseSpMatDescr_t;
typedef hipsparseDnMatDescr_t gpusparseDnMatDescr_t;
typedef hipsparseDnVecDescr_t gpusparseDnVecDescr_t;

#define GPU_C_16F HIP_C_16F
#define GPU_R_16F HIP_R_16F
#define GPU_C_32F HIP_C_32F
#define GPU_R_32F HIP_R_32F
#define GPU_C_64F HIP_C_64F
#define GPU_R_64F HIP_R_64F

#define gpublasCreate hipblasCreate
#define gpublasSetStream hipblasSetStream
#define gpublasSgeqrfBatched hipblasSgeqrfBatched
#define gpublasDgeqrfBatched hipblasDgeqrfBatched
#define gpublasCgeqrfBatched hipblasCgeqrfBatched
#define gpublasZgeqrfBatched hipblasZgeqrfBatched
#define gpublasSgetrfBatched hipblasSgetrfBatched
#define gpublasDgetrfBatched hipblasDgetrfBatched
#define gpublasCgetrfBatched hipblasCgetrfBatched
#define gpublasZgetrfBatched hipblasZgetrfBatched

#define GPUBLAS_STATUS_SUCCESS HIPBLAS_STATUS_SUCCESS

#define gpusolverDnCreate hipsolverCreate
#define gpusolverDnSetStream hipsolverSetStream
#define gpusolverDnCreateSyevjInfo hipsolverCreateSyevjInfo
#define gpusolverDnDestroySyevjInfo hipsolverDestroySyevjInfo
#define gpusolverDnSgeqrf hipsolverSgeqrf
#define gpusolverDnDgeqrf hipsolverDgeqrf
#define gpusolverDnCgeqrf hipsolverCgeqrf
#define gpusolverDnZgeqrf hipsolverZgeqrf
#define gpusolverDnSgeqrf_bufferSize hipsolverSgeqrf_bufferSize
#define gpusolverDnDgeqrf_bufferSize hipsolverDgeqrf_bufferSize
#define gpusolverDnCgeqrf_bufferSize hipsolverCgeqrf_bufferSize
#define gpusolverDnZgeqrf_bufferSize hipsolverZgeqrf_bufferSize
#define gpusolverDnSgetrf(h, m, n, a, lda, work, lwork, ipiv, info) \
  hipsolverSgetrf(h, m, n, a, lda, work, lwork, ipiv, info)
#define gpusolverDnDgetrf(h, m, n, a, lda, work, lwork, ipiv, info) \
  hipsolverDgetrf(h, m, n, a, lda, work, lwork, ipiv, info)
#define gpusolverDnCgetrf(h, m, n, a, lda, work, lwork, ipiv, info) \
  hipsolverCgetrf(h, m, n, a, lda, work, lwork, ipiv, info)
#define gpusolverDnZgetrf(h, m, n, a, lda, work, lwork, ipiv, info) \
  hipsolverZgetrf(h, m, n, a, lda, work, lwork, ipiv, info)
#define gpusolverDnSgetrf_bufferSize hipsolverSgetrf_bufferSize
#define gpusolverDnDgetrf_bufferSize hipsolverDgetrf_bufferSize
#define gpusolverDnCgetrf_bufferSize hipsolverCgetrf_bufferSize
#define gpusolverDnZgetrf_bufferSize hipsolverZgetrf_bufferSize
#define gpusolverDnSorgqr hipsolverSorgqr
#define gpusolverDnDorgqr hipsolverDorgqr
#define gpusolverDnCungqr hipsolverCungqr
#define gpusolverDnZungqr hipsolverZungqr
#define gpusolverDnSorgqr_bufferSize hipsolverSorgqr_bufferSize
#define gpusolverDnDorgqr_bufferSize hipsolverDorgqr_bufferSize
#define gpusolverDnCungqr_bufferSize hipsolverCungqr_bufferSize
#define gpusolverDnZungqr_bufferSize hipsolverZungqr_bufferSize
#define gpusolverDnSsyevd hipsolverSsyevd
#define gpusolverDnDsyevd hipsolverDsyevd
#define gpusolverDnCheevd hipsolverCheevd
#define gpusolverDnZheevd hipsolverZheevd
#define gpusolverDnSsyevd_bufferSize hipsolverSsyevd_bufferSize
#define gpusolverDnDsyevd_bufferSize hipsolverDsyevd_bufferSize
#define gpusolverDnCheevd_bufferSize hipsolverCheevd_bufferSize
#define gpusolverDnZheevd_bufferSize hipsolverZheevd_bufferSize
#define gpusolverDnSsyevj hipsolverSsyevj
#define gpusolverDnDsyevj hipsolverDsyevj
#define gpusolverDnCheevj hipsolverCheevj
#define gpusolverDnZheevj hipsolverZheevj
#define gpusolverDnSsyevj_bufferSize hipsolverSsyevj_bufferSize
#define gpusolverDnDsyevj_bufferSize hipsolverDsyevj_bufferSize
#define gpusolverDnCheevj_bufferSize hipsolverCheevj_bufferSize
#define gpusolverDnZheevj_bufferSize hipsolverZheevj_bufferSize
#define gpusolverDnSsyevjBatched hipsolverSsyevjBatched
#define gpusolverDnDsyevjBatched hipsolverDsyevjBatched
#define gpusolverDnCheevjBatched hipsolverCheevjBatched
#define gpusolverDnZheevjBatched hipsolverZheevjBatched
#define gpusolverDnSsyevjBatched_bufferSize hipsolverSsyevjBatched_bufferSize
#define gpusolverDnDsyevjBatched_bufferSize hipsolverDsyevjBatched_bufferSize
#define gpusolverDnCheevjBatched_bufferSize hipsolverCheevjBatched_bufferSize
#define gpusolverDnZheevjBatched_bufferSize hipsolverZheevjBatched_bufferSize
#define gpusolverDnSgesvd hipsolverSgesvd
#define gpusolverDnDgesvd hipsolverDgesvd
#define gpusolverDnCgesvd hipsolverCgesvd
#define gpusolverDnZgesvd hipsolverZgesvd
#define gpusolverDnSgesvd_bufferSize(h, jobu, jobvt, m, n, lwork) \
  hipsolverSgesvd_bufferSize(h, jobu, jobvt, m, n, lwork)
#define gpusolverDnDgesvd_bufferSize(h, jobu, jobvt, m, n, lwork) \
  hipsolverDgesvd_bufferSize(h, jobu, jobvt, m, n, lwork)
#define gpusolverDnCgesvd_bufferSize(h, jobu, jobvt, m, n, lwork) \
  hipsolverCgesvd_bufferSize(h, jobu, jobvt, m, n, lwork)
#define gpusolverDnZgesvd_bufferSize(h, jobu, jobvt, m, n, lwork) \
  hipsolverZgesvd_bufferSize(h, jobu, jobvt, m, n, lwork)
#define gpusolverDnSsytrd_bufferSize hipsolverDnSsytrd_bufferSize
#define gpusolverDnDsytrd_bufferSize hipsolverDnDsytrd_bufferSize
#define gpusolverDnChetrd_bufferSize hipsolverDnChetrd_bufferSize
#define gpusolverDnZhetrd_bufferSize hipsolverDnZhetrd_bufferSize
#define gpusolverDnSsytrd hipsolverDnSsytrd
#define gpusolverDnDsytrd hipsolverDnDsytrd
#define gpusolverDnChetrd hipsolverDnChetrd
#define gpusolverDnZhetrd hipsolverDnZhetrd

#define GPUSOLVER_FILL_MODE_LOWER HIPSOLVER_FILL_MODE_LOWER
#define GPUSOLVER_FILL_MODE_UPPER HIPSOLVER_FILL_MODE_UPPER
#define GPUSOLVER_EIG_MODE_VECTOR HIPSOLVER_EIG_MODE_VECTOR
#define GPUSOLVER_STATUS_SUCCESS HIPSOLVER_STATUS_SUCCESS

#define gpusparseCooSetStridedBatch hipsparseCooSetStridedBatch
#define gpusparseCreate hipsparseCreate
#define gpusparseSetStream hipsparseSetStream
#define gpusparseCreateCoo hipsparseCreateCoo
#define gpusparseCreateCsr hipsparseCreateCsr
#define gpusparseCreateDnMat hipsparseCreateDnMat
#define gpusparseCreateDnVec hipsparseCreateDnVec
#define gpusparseDenseToSparse_analysis hipsparseDenseToSparse_analysis
#define gpusparseDenseToSparse_bufferSize hipsparseDenseToSparse_bufferSize
#define gpusparseDenseToSparse_convert hipsparseDenseToSparse_convert
#define gpusparseDestroySpMat hipsparseDestroySpMat
#define gpusparseDestroyDnMat hipsparseDestroyDnMat
#define gpusparseDestroyDnVec hipsparseDestroyDnVec
#define gpusparseDnMatSetStridedBatch hipsparseDnMatSetStridedBatch
#define gpusparseSparseToDense hipsparseSparseToDense
#define gpusparseSparseToDense_bufferSize hipsparseSparseToDense_bufferSize
#define gpusparseSpMM hipsparseSpMM
#define gpusparseSpMM_bufferSize hipsparseSpMM_bufferSize
#define gpusparseSpMV hipsparseSpMV
#define gpusparseSpMV_bufferSize hipsparseSpMV_bufferSize
#define gpusparseSgtsv2 hipsparseSgtsv2
#define gpusparseDgtsv2 hipsparseDgtsv2
#define gpusparseSgtsv2_bufferSizeExt hipsparseSgtsv2_bufferSizeExt
#define gpusparseDgtsv2_bufferSizeExt hipsparseDgtsv2_bufferSizeExt

#define GPUSPARSE_INDEX_16U HIPSPARSE_INDEX_16U
#define GPUSPARSE_INDEX_32I HIPSPARSE_INDEX_32I
#define GPUSPARSE_INDEX_64I HIPSPARSE_INDEX_64I
#define GPUSPARSE_DENSETOSPARSE_ALG_DEFAULT HIPSPARSE_DENSETOSPARSE_ALG_DEFAULT
#define GPUSPARSE_SPMV_COO_ALG HIPSPARSE_MV_ALG_DEFAULT
#define GPUSPARSE_SPMV_CSR_ALG HIPSPARSE_MV_ALG_DEFAULT
#define GPUSPARSE_SPMM_COO_ALG HIPSPARSE_SPMM_ALG_DEFAULT
#define GPUSPARSE_SPMM_CSR_ALG HIPSPARSE_SPMM_ALG_DEFAULT
#define GPUSPARSE_INDEX_BASE_ZERO HIPSPARSE_INDEX_BASE_ZERO
#define GPUSPARSE_OPERATION_NON_TRANSPOSE HIPSPARSE_OPERATION_NON_TRANSPOSE
#define GPUSPARSE_OPERATION_TRANSPOSE HIPSPARSE_OPERATION_TRANSPOSE
#define GPUSPARSE_ORDER_ROW HIPSPARSE_ORDER_ROW
#define GPUSPARSE_SPARSETODENSE_ALG_DEFAULT HIPSPARSE_SPARSETODENSE_ALG_DEFAULT
#define GPUSPARSE_STATUS_SUCCESS HIPSPARSE_STATUS_SUCCESS

#define gpuGetLastError hipGetLastError
#define gpuGetErrorString hipGetErrorString
#define gpuMemcpyAsync hipMemcpyAsync
#define gpuMemcpyDeviceToDevice hipMemcpyDeviceToDevice
#define gpuMemcpyHostToDevice hipMemcpyHostToDevice
#define gpuStreamSynchronize hipStreamSynchronize
#define gpuSuccess hipSuccess

#else  // defined(GPU vendor)
#error "Either JAX_GPU_CUDA or JAX_GPU_HIP must be defined"
#endif  // defined(GPU vendor)

#endif  // JAXLIB_GPU_VENDOR_H_


text:
import redis
import tornadoredis
from opt import REDIS_SERVER_HOST, REDIS_SERVER_PORT

redis_db = redis.StrictRedis(host=REDIS_SERVER_HOST, port=REDIS_SERVER_PORT)
redis_pubsub = tornadoredis.Client(host=REDIS_SERVER_HOST, port=REDIS_SERVER_PORT)


text:
//
//  SimpleDAO.m
//  NSInvocationSample
//
//  Created by saku on 2013/12/18.
//  Copyright (c) 2013 Yoichiro Sakurai. All rights reserved.
//

#import "InvokedDAO.h"

@implementation InvokedDAO

static NSString *chapterFactoryMethod = @"createChapter";
static NSString *sectionFactoryMethod = @"createSection";
static NSString *paragraphFactoryMethod = @"createParagraph";

+ (NSArray *)getAllChapter
{
    NSString *sql = @"SELECT * FROM chapter";
	return [[self class] fetchDataAsNSArray:sql factoryMethod:chapterFactoryMethod];
}

+ (NSArray *)getAllSection
{
    NSString *sql = @"SELECT * FROM section";
	return [[self class] fetchDataAsNSArray:sql factoryMethod:sectionFactoryMethod];
}

+ (NSArray *)getAllParagraph
{
    NSString *sql = @"SELECT * FROM paragraph";
	return [[self class] fetchDataAsNSArray:sql factoryMethod:paragraphFactoryMethod];
}

+ (NSArray *)getSectionsByChapterId:(int)chapterId
{
    NSString *sql = [NSString stringWithFormat:@"SELECT * FROM section WHERE chapter_id = %d", chapterId];
	return [[self class] fetchDataAsNSArray:sql factoryMethod:sectionFactoryMethod];
}

+ (NSArray *)getParagraphsBySectionId:(int)sectionId
{
    NSString *sql = [NSString stringWithFormat:@"SELECT * FROM paragraph WHERE section_id = %d", sectionId];
	return [[self class] fetchDataAsNSArray:sql factoryMethod:paragraphFactoryMethod];
}

/**
 * To ommit garbage code, make one method fetch dictionary data from sqlite.
 *
 * @param NSString *sql : call sql.
 * @param NSString *factoryMethod : factory method name, appropreate object.
 * @return NSArray * : dictionary data array.
 */
+ (NSArray *)fetchDataAsNSArray:(NSString *)sql factoryMethod:(NSString *)factoryMethod
{
	NSMutableArray *result = [NSMutableArray array];
	NSString *dbFile = [[self class] getDBFileName];
	sqlite3 *database = nil;
	sqlite3_stmt *statement = nil;

	if (sqlite3_open([dbFile UTF8String], &database) != SQLITE_OK) {
		sqlite3_close(database);
		return result;
	}

    if (sqlite3_prepare_v2(database, [sql UTF8String], -1, &statement, NULL) == SQLITE_OK) {
        while (sqlite3_step(statement) == SQLITE_ROW) {
#warning change below condition "false", after you confirm crash app.
            if (true) {
                NSDictionary *dataDictionary;

                // invocate method by NSInvocation.
                SEL selector = NSSelectorFromString([NSString stringWithFormat:@"%@:", factoryMethod]);
                NSMethodSignature* signature = [[self class] methodSignatureForSelector:selector];
                NSInvocation* invocation = [ NSInvocation invocationWithMethodSignature:signature];
                [invocation setSelector:selector];
                [invocation setTarget:[self class]];
                [invocation setArgument:&statement atIndex:2];
                [invocation invoke];
                [invocation getReturnValue:&dataDictionary];

                [result addObject:[NSDictionary dictionaryWithDictionary:dataDictionary]];
            } else {
                CFTypeRef data;

                // invocate method by NSInvocation.
                SEL selector = NSSelectorFromString([NSString stringWithFormat:@"%@:", factoryMethod]);
                NSMethodSignature* signature = [[self class] methodSignatureForSelector:selector];
                NSInvocation* invocation = [ NSInvocation invocationWithMethodSignature:signature];
                [invocation setSelector:selector];
                [invocation setTarget:[self class]];
                [invocation setArgument:&statement atIndex:2];
                [invocation invoke];
                [invocation getReturnValue:&data];

                // When out of this method scope, then released data. So, use CFRetain and go well.
                // http://stackoverflow.com/questions/7078109/why-does-nsinvocation-getreturnvalue-loose-object/11569236#11569236
                if (data) CFRetain(data);
                NSDictionary *dataDictionary = (__bridge_transfer NSDictionary *)data;

                [result addObject:[NSDictionary dictionaryWithDictionary:dataDictionary]];
            }
        }
        sqlite3_finalize(statement);
    }else{
        NSLog(@"%s", sqlite3_errmsg(database));
    }

	sqlite3_close(database);
    return result;
}

@end


text:
<?xml version="1.0" encoding="ISO-8859-1"?>

<query entity="EUnit" type="statement">
  <statement>
    <select>
      <qcolumn id="eunit.id" entityattr="id" />
      <qcolumn id="eunit.navn" entityattr="name" />
      <qcolumn id="eunit.beskr" entityattr="descr" />
      <qcolumn id="eunit.eanlId" entityattr="buildingId" />
      <qcolumn id="eanl.navn" entityattr="buildingName" />
      <qcolumn id="eanl.kundeId" entityattr="customerId" />
      <qcolumn id="kund.navn" entityattr="customerName" />
      <qcolumn id="eunit.inMalerId" entityattr="inMeterId" />
      <qcolumn id="inMaler.navn" entityattr="inMeterName" />
      <qcolumn id="eunit.utMalerId" entityattr="outMeterId" />
      <qcolumn id="utMaler.navn" entityattr="utMeterName" />
      <qcolumn id="eunit.diffMalerId" entityattr="diffMeterId" />
      <qcolumn id="diffMaler.navn" entityattr="diffMeterName" />
      <qcolumn id="eunit.sumMalerId" entityattr="sumMeterId" />
      <qcolumn id="sumMaler.navn" entityattr="sumMeterName" />
      <qcolumn id="eunit.sumUtMalerId" entityattr="sumOutMeterId" />
      <qcolumn id="sumOutMaler.navn" entityattr="sumOutMeterName" />
      <qcolumn id="eunit.vproId" entityattr="profileId" />
      <qcolumn id="vpro.navn" entityattr="profileName" />
    </select>
    <from>EOSEnergiEnhet eunit LEFT JOIN EOSMaler inMaler ON (eunit.inMalerId = inMaler.id)
    LEFT JOIN EOSMaler utMaler ON (eunit.utMalerId = utMaler.id)
    LEFT JOIN EOSMaler diffMaler ON (eunit.diffMalerId = diffMaler.id)
    LEFT JOIN EOSMaler sumMaler ON (eunit.sumMalerId = sumMaler.id)
    LEFT JOIN EOSMaler sumOutMaler ON (eunit.sumUtMalerId = sumOutMaler.id)
    LEFT JOIN EOSVGProfil vpro ON (eunit.vproId = vpro.id),
    EOSAnlegg eanl, EOSKunde kund</from>
    <where>eunit.eanlId = eanl.id AND eanl.kundeId = kund.id</where>
  </statement>
</query>


text: export { default } from './FormHelperText';


text:
let implementationPackage = "transient_json_store";
let implementationType = "t_transient_json";

load("test/templates/implementation_type/is_XXX.js.tpl");


text:
<?php

namespace ExtendsFramework\Sourcing\Streamer;

interface EventStreamer
{
    /**
     * @param int $limit
     * @return void
     */
    public function process($limit);
}