<commit_before>// Scintilla source code edit control
// @file LexAU3.cxx
// Lexer for AutoIt3  http://www.hiddensoft.com/autoit3
// by Jos van der Zande, jvdzande@yahoo.com
//
// Changes:
// March 28, 2004 - Added the standard Folding code
// April 21, 2004 - Added Preprosessor Table + Syntax Highlighting
//                  Fixed Number highlighting
//                  Changed default isoperator to IsAOperator to have a better match to AutoIt3
//                  Fixed "#comments_start" -> "#comments-start"
//                  Fixed "#comments_end" -> "#comments-end"
//                  Fixed Sendkeys in Strings when not terminated with }
//                  Added support for Sendkey strings that have second parameter e.g. {UP 5} or {a down}
// Copyright for Scintilla: 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
// Scintilla source code edit control

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>

#include "Platform.h"

#include "PropSet.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"

static bool IsAU3Comment(Accessor &styler, int pos, int len) {
	return len>0 && styler[pos]==';';
}

static inline bool IsTypeCharacter(const int ch)
{
    return ch == '$';
}
static inline bool IsAWordChar(const int ch)
{
    return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '-');
}

static inline bool IsAWordStart(const int ch)
{
    return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '@' || ch == '#' || ch == '$');
}

static inline bool IsAOperator(char ch) {
	if (isascii(ch) && isalnum(ch))
		return false;
	if (ch == '+' || ch == '-' || ch == '*' || ch == '/' ||
	    ch == '&' || ch == '^' || ch == '=' || ch == '<' || ch == '>' ||
	    ch == '(' || ch == ')' || ch == '[' || ch == ']' )
		return true;
	return false;
}

///////////////////////////////////////////////////////////////////////////////
// GetSendKey() filters the portion before and after a/multiple space(s)
// and return the first portion to be looked-up in the table
// also check if the second portion is valid... (up,down.on.off,toggle or a number)
///////////////////////////////////////////////////////////////////////////////

static int GetSendKey(const char *szLine, char *szKey)
{
	int		nFlag	= 0;
	int		nKeyPos	= 0;
	int		nSpecPos= 0;
	int		nSpecNum= 1;
	int		nPos	= 0;
	char	cTemp;
	char	szSpecial[100];

	// split the portion of the sendkey in the part before and after the spaces
	while ( ( (cTemp = szLine[nPos]) != '\0'))
	{
		if ((cTemp == ' ') && (nFlag == 0) ) // get the stuff till first space
		{
			nFlag = 1;
			// Add } to the end of the first bit for table lookup later.
			szKey[nKeyPos++] = '}';
		}
		else if (cTemp == ' ')
		{
			// skip other spaces
		}
		else if (nFlag == 0)
		{
			// save first portion into var till space or } is hit
			szKey[nKeyPos++] = cTemp;
		}
		else if ((nFlag == 1) && (cTemp != '}'))
		{
			// Save second portion into var...
			szSpecial[nSpecPos++] = cTemp;
			// check if Second portion is all numbers for repeat fuction
			if (isdigit(cTemp) == false) {nSpecNum = 0;}
		}
		nPos++;									// skip to next char

	} // End While

	// Check if the second portion is either a number or one of these keywords
	szKey[nKeyPos] = '\0';
	szSpecial[nSpecPos] = '\0';
	if (strcmp(szSpecial,"down")==0    || strcmp(szSpecial,"up")==0  ||
		strcmp(szSpecial,"on")==0      || strcmp(szSpecial,"off")==0 ||
		strcmp(szSpecial,"toggle")==0  || nSpecNum == 1 )
	{
		nFlag = 0;
	}
	else
	{
		nFlag = 1;
	}
	return nFlag;  // 1 is bad, 0 is good

} // GetSendKey()

static void ColouriseAU3Doc(unsigned int startPos,
							int length, int initStyle,
							WordList *keywordlists[],
							Accessor &styler) {

    WordList &keywords = *keywordlists[0];
    WordList &keywords2 = *keywordlists[1];
    WordList &keywords3 = *keywordlists[2];
    WordList &keywords4 = *keywordlists[3];
    WordList &keywords5 = *keywordlists[4];
    styler.StartAt(startPos);

    StyleContext sc(startPos, length, initStyle, styler);
	char si;     // string indicator "=1 '=2
	si=0;
	//$$$
    for (; sc.More(); sc.Forward()) {
		char s[100];
		sc.GetCurrentLowered(s, sizeof(s));
		switch (sc.state)
        {
            case SCE_AU3_COMMENTBLOCK:
            {
                if (sc.ch == '#') {sc.SetState(SCE_AU3_DEFAULT);}
				break;
			}
            case SCE_AU3_COMMENT:
            {
                if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);}
                break;
            }
            case SCE_AU3_OPERATOR:
            {
                sc.SetState(SCE_AU3_DEFAULT);
                break;
            }
            case SCE_AU3_KEYWORD:
            {
                if (!IsAWordChar(sc.ch))
                {
                    if (!IsTypeCharacter(sc.ch))
                    {
						if (strcmp(s, "#cs")==0 || strcmp(s, "#comments-start")==0)
						{
							sc.ChangeState(SCE_AU3_COMMENTBLOCK);
							sc.SetState(SCE_AU3_COMMENTBLOCK);
						}
						else if (strcmp(s, "#ce")==0 || strcmp(s, "#comments-end")==0)
						{
							sc.ChangeState(SCE_AU3_COMMENTBLOCK);
							sc.SetState(SCE_AU3_DEFAULT);
						}
						else if (keywords.InList(s)) {
							sc.ChangeState(SCE_AU3_KEYWORD);
							sc.SetState(SCE_AU3_DEFAULT);
						}
						else if (keywords2.InList(s)) {
							sc.ChangeState(SCE_AU3_FUNCTION);
							sc.SetState(SCE_AU3_DEFAULT);
						}
						else if (keywords3.InList(s)) {
							sc.ChangeState(SCE_AU3_MACRO);
							sc.SetState(SCE_AU3_DEFAULT);
						}
						else if (keywords5.InList(s)) {
							sc.ChangeState(SCE_AU3_PREPROCESSOR);
							sc.SetState(SCE_AU3_DEFAULT);
						}
						else if (!IsAWordChar(sc.ch)) {
							sc.ChangeState(SCE_AU3_DEFAULT);
							sc.SetState(SCE_AU3_DEFAULT);
						}
					}
				}
                if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);}
                break;
            }
            case SCE_AU3_NUMBER:
            {
                if (!IsAWordChar(sc.ch)) {sc.SetState(SCE_AU3_DEFAULT);}
                break;
            }
            case SCE_AU3_VARIABLE:
            {
                if (!IsAWordChar(sc.ch)) {sc.SetState(SCE_AU3_DEFAULT);}
                break;
            }
            case SCE_AU3_STRING:
            {
				// check for " to end a double qouted string or
				// check for ' to end a single qouted string
	            if ((si == 1 && sc.ch == '\"') || (si == 2 && sc.ch == '\''))
				{
					sc.ForwardSetState(SCE_AU3_DEFAULT);
				}
                if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);}
				// find Sendkeys in a STRING
				if (sc.ch == '{') {sc.SetState(SCE_AU3_SENT);}
				if (sc.ch == '+' && sc.chNext == '{') {sc.SetState(SCE_AU3_SENT);}
				if (sc.ch == '!' && sc.chNext == '{') {sc.SetState(SCE_AU3_SENT);}
				if (sc.ch == '^' && sc.chNext == '{') {sc.SetState(SCE_AU3_SENT);}
				if (sc.ch == '#' && sc.chNext == '{') {sc.SetState(SCE_AU3_SENT);}
				break;
            }

            case SCE_AU3_SENT:
            {
				// Send key string ended
				if (sc.chPrev == '}' && sc.ch != '}')
				{
					// set color to SENDKEY when valid sendkey .. else set back to regular string
					char sk[100];
					// split {111 222} and return {111} and check if 222 is valid.
					// if return code = 1 then invalid 222 so must be string
					if (GetSendKey(s,sk))
					{
						sc.ChangeState(SCE_AU3_STRING);
					}
					// if single char between {?} then its ok as sendkey for a single character
					else if (strlen(sk) == 3)
					{
						sc.ChangeState(SCE_AU3_SENT);
					}
					// if sendkey {111} is in table then ok as sendkey
					else if (keywords4.InList(sk))
					{
						sc.ChangeState(SCE_AU3_SENT);
					}
					else
					{
						sc.ChangeState(SCE_AU3_STRING);
					}
					sc.SetState(SCE_AU3_STRING);
				}
				// check if next portion is again a sendkey
				if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);}
				if (sc.ch == '{' && sc.chPrev != '{') {sc.SetState(SCE_AU3_SENT);}
				if (sc.ch == '+' && sc.chNext == '{') {sc.SetState(SCE_AU3_SENT);}
				if (sc.ch == '!' && sc.chNext == '{') {sc.SetState(SCE_AU3_SENT);}
				if (sc.ch == '^' && sc.chNext == '{') {sc.SetState(SCE_AU3_SENT);}
				if (sc.ch == '#' && sc.chNext == '{') {sc.SetState(SCE_AU3_SENT);}
				// check to see if the string ended...
				// Sentkey string isn't complete but the string ended....
				if ((si == 1 && sc.ch == '\"') || (si == 2 && sc.ch == '\''))
				{
					sc.ChangeState(SCE_AU3_STRING);
					sc.ForwardSetState(SCE_AU3_DEFAULT);
				}
				break;
            }
        }  //switch (sc.state)

        // Determine if a new state should be entered:

		if (sc.state == SCE_AU3_DEFAULT)
        {
            if (sc.ch == ';') {sc.SetState(SCE_AU3_COMMENT);}
            else if (sc.ch == '#') {sc.SetState(SCE_AU3_KEYWORD);}
            else if (sc.ch == '$') {sc.SetState(SCE_AU3_VARIABLE);}
            else if (sc.ch == '@') {sc.SetState(SCE_AU3_KEYWORD);}
            else if (sc.ch == '\"') {
				sc.SetState(SCE_AU3_STRING);
				si = 1;	}
            else if (sc.ch == '\'') {
				sc.SetState(SCE_AU3_STRING);
				si = 2;	}
            else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {sc.SetState(SCE_AU3_NUMBER);}
            else if (IsAOperator(static_cast<char>(sc.ch))) {sc.SetState(SCE_AU3_OPERATOR);}
            else if (IsAWordStart(sc.ch)) {sc.SetState(SCE_AU3_KEYWORD);}
			else if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);}
        }
    }      //for (; sc.More(); sc.Forward())
    sc.Complete();
}

//
//
static void FoldAU3Doc(unsigned int startPos, int length, int, WordList *[], Accessor &styler)
{
		int endPos = startPos + length;

	// Backtrack to previous line in case need to fix its fold status
	int lineCurrent = styler.GetLine(startPos);
	if (startPos > 0) {
		if (lineCurrent > 0) {
			lineCurrent--;
			startPos = styler.LineStart(lineCurrent);
		}
	}
	int spaceFlags = 0;
	int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, IsAU3Comment);
	char chNext = styler[startPos];
	for (int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);

		if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == endPos)) {
			int lev = indentCurrent;
			int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags, IsAU3Comment);
			if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
				// Only non whitespace lines can be headers
				if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) {
					lev |= SC_FOLDLEVELHEADERFLAG;
				} else if (indentNext & SC_FOLDLEVELWHITEFLAG) {
					// Line after is blank so check the next - maybe should continue further?
					int spaceFlags2 = 0;
					int indentNext2 = styler.IndentAmount(lineCurrent + 2, &spaceFlags2, IsAU3Comment);
					if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) {
						lev |= SC_FOLDLEVELHEADERFLAG;
					}
				}
			}
			indentCurrent = indentNext;
			styler.SetLevel(lineCurrent, lev);
			lineCurrent++;
		}
	}

}

//

static const char * const AU3WordLists[] = {
    "#autoit keywords",
    "#autoit functions",
    "#autoit macros",
    "#autoit Sent keys",
    "#autoit Pre-processors",
    0
};
LexerModule lmAU3(SCLEX_AU3, ColouriseAU3Doc, "au3", FoldAU3Doc , AU3WordLists);
<commit_msg>Fixed # pre-processor statement inside of comment block would invalidly change the color. Added logic for #include <xyz.au3> to treat the <> as string Added underscore to IsAOperator.<commit_after>// Scintilla source code edit control
// @file LexAU3.cxx
// Lexer for AutoIt3  http://www.hiddensoft.com/autoit3
// by Jos van der Zande, jvdzande@yahoo.com
//
// Changes:
// March 28, 2004 - Added the standard Folding code
// April 21, 2004 - Added Preprosessor Table + Syntax Highlighting
//                  Fixed Number highlighting
//                  Changed default isoperator to IsAOperator to have a better match to AutoIt3
//                  Fixed "#comments_start" -> "#comments-start"
//                  Fixed "#comments_end" -> "#comments-end"
//                  Fixed Sendkeys in Strings when not terminated with }
//                  Added support for Sendkey strings that have second parameter e.g. {UP 5} or {a down}
// April 26, 2004   Fixed # pre-processor statement inside of comment block would invalidly change the color.
//                  Added logic for #include <xyz.au3> to treat the <> as string
//                  Added underscore to IsAOperator.
// Copyright for Scintilla: 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
// Scintilla source code edit control

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>

#include "Platform.h"

#include "PropSet.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"

static bool IsAU3Comment(Accessor &styler, int pos, int len) {
	return len>0 && styler[pos]==';';
}

static inline bool IsTypeCharacter(const int ch)
{
    return ch == '$';
}
static inline bool IsAWordChar(const int ch)
{
    return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '-');
}

static inline bool IsAWordStart(const int ch)
{
    return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '@' || ch == '#' || ch == '$');
}

static inline bool IsAOperator(char ch) {
	if (isascii(ch) && isalnum(ch))
		return false;
	if (ch == '+' || ch == '-' || ch == '*' || ch == '/' ||
	    ch == '&' || ch == '^' || ch == '=' || ch == '<' || ch == '>' ||
	    ch == '(' || ch == ')' || ch == '[' || ch == ']' || ch == '_' )
		return true;
	return false;
}

///////////////////////////////////////////////////////////////////////////////
// GetSendKey() filters the portion before and after a/multiple space(s)
// and return the first portion to be looked-up in the table
// also check if the second portion is valid... (up,down.on.off,toggle or a number)
///////////////////////////////////////////////////////////////////////////////

static int GetSendKey(const char *szLine, char *szKey)
{
	int		nFlag	= 0;
	int		nKeyPos	= 0;
	int		nSpecPos= 0;
	int		nSpecNum= 1;
	int		nPos	= 0;
	char	cTemp;
	char	szSpecial[100];

	// split the portion of the sendkey in the part before and after the spaces
	while ( ( (cTemp = szLine[nPos]) != '\0'))
	{
		if ((cTemp == ' ') && (nFlag == 0) ) // get the stuff till first space
		{
			nFlag = 1;
			// Add } to the end of the first bit for table lookup later.
			szKey[nKeyPos++] = '}';
		}
		else if (cTemp == ' ')
		{
			// skip other spaces
		}
		else if (nFlag == 0)
		{
			// save first portion into var till space or } is hit
			szKey[nKeyPos++] = cTemp;
		}
		else if ((nFlag == 1) && (cTemp != '}'))
		{
			// Save second portion into var...
			szSpecial[nSpecPos++] = cTemp;
			// check if Second portion is all numbers for repeat fuction
			if (isdigit(cTemp) == false) {nSpecNum = 0;}
		}
		nPos++;									// skip to next char

	} // End While

	// Check if the second portion is either a number or one of these keywords
	szKey[nKeyPos] = '\0';
	szSpecial[nSpecPos] = '\0';
	if (strcmp(szSpecial,"down")==0    || strcmp(szSpecial,"up")==0  ||
		strcmp(szSpecial,"on")==0      || strcmp(szSpecial,"off")==0 ||
		strcmp(szSpecial,"toggle")==0  || nSpecNum == 1 )
	{
		nFlag = 0;
	}
	else
	{
		nFlag = 1;
	}
	return nFlag;  // 1 is bad, 0 is good

} // GetSendKey()

static void ColouriseAU3Doc(unsigned int startPos,
							int length, int initStyle,
							WordList *keywordlists[],
							Accessor &styler) {

    WordList &keywords = *keywordlists[0];
    WordList &keywords2 = *keywordlists[1];
    WordList &keywords3 = *keywordlists[2];
    WordList &keywords4 = *keywordlists[3];
    WordList &keywords5 = *keywordlists[4];
    styler.StartAt(startPos);

    StyleContext sc(startPos, length, initStyle, styler);
	char si;     // string indicator "=1 '=2
	si=0;
	//$$$
    for (; sc.More(); sc.Forward()) {
		char s[100];
		sc.GetCurrentLowered(s, sizeof(s));
		switch (sc.state)
        {
            case SCE_AU3_COMMENTBLOCK:
            {
				if (!IsAWordChar(sc.ch))
				{
					if ((strcmp(s, "#ce")==0 || strcmp(s, "#comments-end")==0))
					{sc.SetState(SCE_AU3_COMMENT);}  // set to comment line for the rest of the line
					else
					{sc.SetState(SCE_AU3_COMMENTBLOCK);}
				}
                break;
			}
            case SCE_AU3_COMMENT:
            {
                if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);}
                break;
            }
            case SCE_AU3_OPERATOR:
            {
                sc.SetState(SCE_AU3_DEFAULT);
                break;
            }
            case SCE_AU3_KEYWORD:
            {
                if (!IsAWordChar(sc.ch))
                {
                    if (!IsTypeCharacter(sc.ch))
                    {
						if (strcmp(s, "#cs")==0 || strcmp(s, "#comments-start")==0 )
						{
							sc.ChangeState(SCE_AU3_COMMENTBLOCK);
							sc.SetState(SCE_AU3_COMMENTBLOCK);
						}
						else if (keywords.InList(s)) {
							sc.ChangeState(SCE_AU3_KEYWORD);
							sc.SetState(SCE_AU3_DEFAULT);
						}
						else if (keywords2.InList(s)) {
							sc.ChangeState(SCE_AU3_FUNCTION);
							sc.SetState(SCE_AU3_DEFAULT);
						}
						else if (keywords3.InList(s)) {
							sc.ChangeState(SCE_AU3_MACRO);
							sc.SetState(SCE_AU3_DEFAULT);
						}
						else if (keywords5.InList(s)) {
							sc.ChangeState(SCE_AU3_PREPROCESSOR);
							sc.SetState(SCE_AU3_DEFAULT);
							if (strcmp(s, "#include")==0)
							{
								si = 3;   // use to determine string start for #inlude <>
							}
						}
						else if (!IsAWordChar(sc.ch)) {
							sc.ChangeState(SCE_AU3_DEFAULT);
							sc.SetState(SCE_AU3_DEFAULT);
						}
					}
				}
                if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);}
                break;
            }
            case SCE_AU3_NUMBER:
            {
                if (!IsAWordChar(sc.ch)) {sc.SetState(SCE_AU3_DEFAULT);}
                break;
            }
            case SCE_AU3_VARIABLE:
            {
                if (!IsAWordChar(sc.ch)) {sc.SetState(SCE_AU3_DEFAULT);}
                break;
            }
            case SCE_AU3_STRING:
            {
				// check for " to end a double qouted string or
				// check for ' to end a single qouted string
	            if ((si == 1 && sc.ch == '\"') || (si == 2 && sc.ch == '\'') || (si == 3 && sc.ch == '>'))
				{
					sc.ForwardSetState(SCE_AU3_DEFAULT);
				}
                if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);}
				// find Sendkeys in a STRING
				if (sc.ch == '{') {sc.SetState(SCE_AU3_SENT);}
				if (sc.ch == '+' && sc.chNext == '{') {sc.SetState(SCE_AU3_SENT);}
				if (sc.ch == '!' && sc.chNext == '{') {sc.SetState(SCE_AU3_SENT);}
				if (sc.ch == '^' && sc.chNext == '{') {sc.SetState(SCE_AU3_SENT);}
				if (sc.ch == '#' && sc.chNext == '{') {sc.SetState(SCE_AU3_SENT);}
				break;
            }

            case SCE_AU3_SENT:
            {
				// Send key string ended
				if (sc.chPrev == '}' && sc.ch != '}')
				{
					// set color to SENDKEY when valid sendkey .. else set back to regular string
					char sk[100];
					// split {111 222} and return {111} and check if 222 is valid.
					// if return code = 1 then invalid 222 so must be string
					if (GetSendKey(s,sk))
					{
						sc.ChangeState(SCE_AU3_STRING);
					}
					// if single char between {?} then its ok as sendkey for a single character
					else if (strlen(sk) == 3)
					{
						sc.ChangeState(SCE_AU3_SENT);
					}
					// if sendkey {111} is in table then ok as sendkey
					else if (keywords4.InList(sk))
					{
						sc.ChangeState(SCE_AU3_SENT);
					}
					else
					{
						sc.ChangeState(SCE_AU3_STRING);
					}
					sc.SetState(SCE_AU3_STRING);
				}
				// check if next portion is again a sendkey
				if (sc.atLineEnd)
				{
					sc.SetState(SCE_AU3_DEFAULT);
					si = 0;  // reset string indicator
				}
				if (sc.ch == '{' && sc.chPrev != '{') {sc.SetState(SCE_AU3_SENT);}
				if (sc.ch == '+' && sc.chNext == '{') {sc.SetState(SCE_AU3_SENT);}
				if (sc.ch == '!' && sc.chNext == '{') {sc.SetState(SCE_AU3_SENT);}
				if (sc.ch == '^' && sc.chNext == '{') {sc.SetState(SCE_AU3_SENT);}
				if (sc.ch == '#' && sc.chNext == '{') {sc.SetState(SCE_AU3_SENT);}
				// check to see if the string ended...
				// Sentkey string isn't complete but the string ended....
				if ((si == 1 && sc.ch == '\"') || (si == 2 && sc.ch == '\''))
				{
					sc.ChangeState(SCE_AU3_STRING);
					sc.ForwardSetState(SCE_AU3_DEFAULT);
				}
				break;
            }
        }  //switch (sc.state)

        // Determine if a new state should be entered:

		if (sc.state == SCE_AU3_DEFAULT)
        {
            if (sc.ch == ';') {sc.SetState(SCE_AU3_COMMENT);}
            else if (sc.ch == '#') {sc.SetState(SCE_AU3_KEYWORD);}
            else if (sc.ch == '$') {sc.SetState(SCE_AU3_VARIABLE);}
            else if (sc.ch == '@') {sc.SetState(SCE_AU3_KEYWORD);}
            else if (sc.ch == '<' && si==3) {sc.SetState(SCE_AU3_STRING);}  // string after #include
            else if (sc.ch == '\"') {
				sc.SetState(SCE_AU3_STRING);
				si = 1;	}
            else if (sc.ch == '\'') {
				sc.SetState(SCE_AU3_STRING);
				si = 2;	}
            else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {sc.SetState(SCE_AU3_NUMBER);}
            else if (IsAOperator(static_cast<char>(sc.ch))) {sc.SetState(SCE_AU3_OPERATOR);}
            else if (IsAWordStart(sc.ch)) {sc.SetState(SCE_AU3_KEYWORD);}
			else if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);}
        }
    }      //for (; sc.More(); sc.Forward())
    sc.Complete();
}

//
//
static void FoldAU3Doc(unsigned int startPos, int length, int, WordList *[], Accessor &styler)
{
		int endPos = startPos + length;

	// Backtrack to previous line in case need to fix its fold status
	int lineCurrent = styler.GetLine(startPos);
	if (startPos > 0) {
		if (lineCurrent > 0) {
			lineCurrent--;
			startPos = styler.LineStart(lineCurrent);
		}
	}
	int spaceFlags = 0;
	int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, IsAU3Comment);
	char chNext = styler[startPos];
	for (int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);

		if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == endPos)) {
			int lev = indentCurrent;
			int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags, IsAU3Comment);
			if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
				// Only non whitespace lines can be headers
				if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) {
					lev |= SC_FOLDLEVELHEADERFLAG;
				} else if (indentNext & SC_FOLDLEVELWHITEFLAG) {
					// Line after is blank so check the next - maybe should continue further?
					int spaceFlags2 = 0;
					int indentNext2 = styler.IndentAmount(lineCurrent + 2, &spaceFlags2, IsAU3Comment);
					if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) {
						lev |= SC_FOLDLEVELHEADERFLAG;
					}
				}
			}
			indentCurrent = indentNext;
			styler.SetLevel(lineCurrent, lev);
			lineCurrent++;
		}
	}

}

//

static const char * const AU3WordLists[] = {
    "#autoit keywords",
    "#autoit functions",
    "#autoit macros",
    "#autoit Sent keys",
    "#autoit Pre-processors",
    0
};
LexerModule lmAU3(SCLEX_AU3, ColouriseAU3Doc, "au3", FoldAU3Doc , AU3WordLists);
<|endoftext|>


<commit_before>// Scintilla source code edit control
/** @file LexPOV.cxx
 ** Lexer for POV-Ray, based on lexer for C++.
 **/
// Copyright 2003 by Steven te Brinke <steven.t.b@zonnet.nl>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>

#include "Platform.h"

#include "PropSet.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"

#define KEYWORD_BOXHEADER 1
#define KEYWORD_FOLDCONTRACTED 2

static inline bool IsAWordChar(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_');
}

static inline bool IsAWordStart(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '_');
}

static inline bool IsStateComment(const int state) {
	return ((state == SCE_POV_COMMENT) ||
	        (state == SCE_POV_COMMENTLINE) ||
	        (state == SCE_POV_COMMENTDOC));
}

static inline bool IsStateString(const int state) {
	return ((state == SCE_POV_STRING));
}

static void ColourisePOVDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
                            Accessor &styler) {

	WordList &keywords = *keywordlists[0];
	WordList &keywords2 = *keywordlists[1];

	// Do not leak onto next line
	/*if (initStyle == SCE_POV_STRINGEOL)
		initStyle = SCE_POV_DEFAULT;*/

	StyleContext sc(startPos, length, initStyle, styler);

	bool caseSensitive = styler.GetPropertyInt("case.sensitive", 1) != 0;

	for (; sc.More(); sc.Forward()) {

		/*if (sc.atLineStart && (sc.state == SCE_POV_STRING)) {
			// Prevent SCE_POV_STRINGEOL from leaking back to previous line
			sc.SetState(SCE_POV_STRING);
		}*/

		// Handle line continuation generically.
		if (sc.ch == '\\') {
			if (sc.chNext == '\n' || sc.chNext == '\r') {
				sc.Forward();
				if (sc.ch == '\r' && sc.chNext == '\n') {
					sc.Forward();
				}
				continue;
			}
		}

		// Determine if the current state should terminate.
		if (sc.state == SCE_POV_OPERATOR || sc.state == SCE_POV_BRACE) {
			sc.SetState(SCE_POV_DEFAULT);
		} else if (sc.state == SCE_POV_NUMBER) {
			if (!IsADigit(sc.ch) || sc.ch != '.') {
				sc.SetState(SCE_POV_DEFAULT);
			}
		} else if (sc.state == SCE_POV_IDENTIFIER) {
			if (!IsAWordChar(sc.ch) || (sc.ch == '.')) {
				char s[100];
				if (caseSensitive) {
					sc.GetCurrent(s, sizeof(s));
				} else {
					sc.GetCurrentLowered(s, sizeof(s));
				}
				if (keywords.InList(s)) {
					sc.ChangeState(SCE_POV_WORD);
				} else if (keywords2.InList(s)) {
					sc.ChangeState(SCE_POV_WORD2);
				}
				sc.SetState(SCE_POV_DEFAULT);
			}
		} else if (sc.state == SCE_POV_COMMENT) {
			if (sc.Match('*', '/')) {
				sc.Forward();
				sc.ForwardSetState(SCE_POV_DEFAULT);
			}
		} else if (sc.state == SCE_POV_COMMENTDOC) {
			if (sc.Match('*', '/')) {
				sc.Forward();
				sc.ForwardSetState(SCE_POV_DEFAULT);
			}
		} else if (sc.state == SCE_POV_COMMENTLINE) {
			if (sc.atLineEnd) {
				sc.SetState(SCE_POV_DEFAULT);
			}
		} else if (sc.state == SCE_POV_STRING) {
			if (sc.ch == '\\') {
				if (sc.chNext == '\"' || sc.chNext == '\\') {
					sc.Forward();
				}
			} else if (sc.ch == '\"') {
				sc.ForwardSetState(SCE_POV_DEFAULT);
			}
		}

		// Determine if a new state should be entered.
		if (sc.state == SCE_POV_DEFAULT) {
			if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
				sc.SetState(SCE_POV_NUMBER);
			} else if (IsAWordStart(sc.ch) || (sc.ch == '#')) {
				sc.SetState(SCE_POV_IDENTIFIER);
			} else if (sc.Match('/', '*')) {
				sc.SetState(SCE_POV_COMMENT);
				sc.Forward();	// Eat the * so it isn't used for the end of the comment
			} else if (sc.Match('/', '/')) {
				sc.SetState(SCE_POV_COMMENTLINE);
			} else if (sc.ch == '\"') {
				sc.SetState(SCE_POV_STRING);
				//} else if (isoperator(static_cast<char>(sc.ch))) {
			} else if (sc.ch == '+' || sc.ch == '-' || sc.ch == '*' || sc.ch == '/' || sc.ch == '=' || sc.ch == '<' || sc.ch == '>' || sc.ch == '&' || sc.ch == '|' || sc.ch == '!' || sc.ch == '?' || sc.ch == ':') {
				sc.SetState(SCE_POV_OPERATOR);
			} else if (sc.ch == '{' || sc.ch == '}') {
				sc.SetState(SCE_POV_BRACE);
			}
		}

	}
	sc.Complete();
}

static bool IsStreamCommentStyle(int style) {
	return style == SCE_POV_COMMENT ||
	       style == SCE_POV_COMMENTDOC;
}

static void FoldNoBoxPOVDoc(unsigned int startPos, int length, int initStyle,
                            Accessor &styler) {
	bool foldComment = styler.GetPropertyInt("fold.comment", 1) != 0;
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	unsigned int endPos = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	int styleNext = styler.StyleAt(startPos);
	int style = initStyle;
	for (unsigned int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int stylePrev = style;
		style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (foldComment && IsStreamCommentStyle(style)) {
			if (!IsStreamCommentStyle(stylePrev)) {
				levelCurrent++;
			} else if (!IsStreamCommentStyle(styleNext) && !atEOL) {
				// Comments don't end at end of line and the next character may be unstyled.
				levelCurrent--;
			}
		}
		if (style == SCE_POV_BRACE) {
			if (ch == '{') {
				levelCurrent++;
			} else if (ch == '}') {
				levelCurrent--;
			}
		}
		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0 && foldCompact)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if ((levelCurrent > levelPrev) && (visibleChars > 0))
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}
		if (!isspacechar(ch))
			visibleChars++;
	}
	// Fill in the real level of the next line, keeping the current flags as they will be filled in later
	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

static void FoldPOVDoc(unsigned int startPos, int length, int initStyle, WordList *[], Accessor &styler) {
	FoldNoBoxPOVDoc(startPos, length, initStyle, styler);
}

static const char * const POVWordLists[] = {
            "Primary keywords and identifiers",
            "Secondary keywords and identifiers",
            0,
        };

static void ColourisePOVDocSensitive(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
                                     Accessor &styler) {
	ColourisePOVDoc(startPos, length, initStyle, keywordlists, styler);
}

LexerModule lmPOV(SCLEX_POV, ColourisePOVDocSensitive, "pov", FoldPOVDoc, POVWordLists);
<commit_msg>POV-Ray support.<commit_after>// Scintilla source code edit control
/** @file LexPOV.cxx
 ** Lexer for POV-Ray, based on lexer for C++.
 **/
// Copyright 2003 by Steven te Brinke <steven.t.b@zonnet.nl>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>

#include "Platform.h"

#include "PropSet.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"

#define KEYWORD_BOXHEADER 1
#define KEYWORD_FOLDCONTRACTED 2

static inline bool IsAWordChar(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_');
}

static inline bool IsAWordStart(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '_');
}

static inline bool IsStateComment(const int state) {
	return ((state == SCE_POV_COMMENT) ||
	        (state == SCE_POV_COMMENTLINE) ||
	        (state == SCE_POV_COMMENTDOC));
}

static inline bool IsStateString(const int state) {
	return ((state == SCE_POV_STRING));
}

static void ColourisePOVDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
                            Accessor &styler) {

	WordList &keywords = *keywordlists[0];
	WordList &keywords2 = *keywordlists[1];

	// Do not leak onto next line
	/*if (initStyle == SCE_POV_STRINGEOL)
		initStyle = SCE_POV_DEFAULT;*/

	StyleContext sc(startPos, length, initStyle, styler);

	bool caseSensitive = styler.GetPropertyInt("pov.case.sensitive", 1) != 0;

	for (; sc.More(); sc.Forward()) {

		/*if (sc.atLineStart && (sc.state == SCE_POV_STRING)) {
			// Prevent SCE_POV_STRINGEOL from leaking back to previous line
			sc.SetState(SCE_POV_STRING);
		}*/

		// Handle line continuation generically.
		if (sc.ch == '\\') {
			if (sc.chNext == '\n' || sc.chNext == '\r') {
				sc.Forward();
				if (sc.ch == '\r' && sc.chNext == '\n') {
					sc.Forward();
				}
				continue;
			}
		}

		// Determine if the current state should terminate.
		if (sc.state == SCE_POV_OPERATOR || sc.state == SCE_POV_BRACE) {
			sc.SetState(SCE_POV_DEFAULT);
		} else if (sc.state == SCE_POV_NUMBER) {
			if (!IsADigit(sc.ch) || sc.ch != '.') {
				sc.SetState(SCE_POV_DEFAULT);
			}
		} else if (sc.state == SCE_POV_IDENTIFIER) {
			if (!IsAWordChar(sc.ch) || (sc.ch == '.')) {
				char s[100];
				if (caseSensitive) {
					sc.GetCurrent(s, sizeof(s));
				} else {
					sc.GetCurrentLowered(s, sizeof(s));
				}
				if (keywords.InList(s)) {
					sc.ChangeState(SCE_POV_WORD);
				} else if (keywords2.InList(s)) {
					sc.ChangeState(SCE_POV_WORD2);
				}
				sc.SetState(SCE_POV_DEFAULT);
			}
		} else if (sc.state == SCE_POV_COMMENT) {
			if (sc.Match('*', '/')) {
				sc.Forward();
				sc.ForwardSetState(SCE_POV_DEFAULT);
			}
		} else if (sc.state == SCE_POV_COMMENTDOC) {
			if (sc.Match('*', '/')) {
				sc.Forward();
				sc.ForwardSetState(SCE_POV_DEFAULT);
			}
		} else if (sc.state == SCE_POV_COMMENTLINE) {
			if (sc.atLineEnd) {
				sc.SetState(SCE_POV_DEFAULT);
			}
		} else if (sc.state == SCE_POV_STRING) {
			if (sc.ch == '\\') {
				if (sc.chNext == '\"' || sc.chNext == '\\') {
					sc.Forward();
				}
			} else if (sc.ch == '\"') {
				sc.ForwardSetState(SCE_POV_DEFAULT);
			}
		}

		// Determine if a new state should be entered.
		if (sc.state == SCE_POV_DEFAULT) {
			if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
				sc.SetState(SCE_POV_NUMBER);
			} else if (IsAWordStart(sc.ch) || (sc.ch == '#')) {
				sc.SetState(SCE_POV_IDENTIFIER);
			} else if (sc.Match('/', '*')) {
				sc.SetState(SCE_POV_COMMENT);
				sc.Forward();	// Eat the * so it isn't used for the end of the comment
			} else if (sc.Match('/', '/')) {
				sc.SetState(SCE_POV_COMMENTLINE);
			} else if (sc.ch == '\"') {
				sc.SetState(SCE_POV_STRING);
				//} else if (isoperator(static_cast<char>(sc.ch))) {
			} else if (sc.ch == '+' || sc.ch == '-' || sc.ch == '*' || sc.ch == '/' || sc.ch == '=' || sc.ch == '<' || sc.ch == '>' || sc.ch == '&' || sc.ch == '|' || sc.ch == '!' || sc.ch == '?' || sc.ch == ':') {
				sc.SetState(SCE_POV_OPERATOR);
			} else if (sc.ch == '{' || sc.ch == '}') {
				sc.SetState(SCE_POV_BRACE);
			}
		}

	}
	sc.Complete();
}

static bool IsStreamCommentStyle(int style) {
	return style == SCE_POV_COMMENT ||
	       style == SCE_POV_COMMENTDOC;
}

static void FoldNoBoxPOVDoc(unsigned int startPos, int length, int initStyle,
                            Accessor &styler) {
	bool foldComment = styler.GetPropertyInt("fold.comment", 1) != 0;
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	unsigned int endPos = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	int styleNext = styler.StyleAt(startPos);
	int style = initStyle;
	for (unsigned int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int stylePrev = style;
		style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (foldComment && IsStreamCommentStyle(style)) {
			if (!IsStreamCommentStyle(stylePrev)) {
				levelCurrent++;
			} else if (!IsStreamCommentStyle(styleNext) && !atEOL) {
				// Comments don't end at end of line and the next character may be unstyled.
				levelCurrent--;
			}
		}
		if (style == SCE_POV_BRACE) {
			if (ch == '{') {
				levelCurrent++;
			} else if (ch == '}') {
				levelCurrent--;
			}
		}
		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0 && foldCompact)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if ((levelCurrent > levelPrev) && (visibleChars > 0))
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}
		if (!isspacechar(ch))
			visibleChars++;
	}
	// Fill in the real level of the next line, keeping the current flags as they will be filled in later
	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

static void FoldPOVDoc(unsigned int startPos, int length, int initStyle, WordList *[], Accessor &styler) {
	FoldNoBoxPOVDoc(startPos, length, initStyle, styler);
}

static const char * const POVWordLists[] = {
            "Primary keywords and identifiers",
            "Secondary keywords and identifiers",
            0,
        };

static void ColourisePOVDocSensitive(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
                                     Accessor &styler) {
	ColourisePOVDoc(startPos, length, initStyle, keywordlists, styler);
}

LexerModule lmPOV(SCLEX_POV, ColourisePOVDocSensitive, "pov", FoldPOVDoc, POVWordLists);
<|endoftext|>


<commit_before>//
// Copyright (c) 2017, Boris Popov <popov@whitekefir.ru>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//

#include "SharedMemory.hpp"
#include "MMapOptions.hpp"
#include <tuple>

#ifndef __linux_posix_MMaper__
#define __linux_posix_MMaper__

namespace linux {
     namespace posix {
//////////////////////////////////////////////////////////////////
	  using UNMAP_AFTER_DESTROY = bool;
	  using MapInfo = std::tuple<void*, size_t>;
//////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////
	  class MMaper {

	  public:
	       MMaper(const SharedMemory&,
		      const UNMAP_AFTER_DESTROY = false,
		      const MMapOptions = MMapOptions());
	       ~MMaper();

	       MapInfo map();
	       void unmap() const;

	  private:
	       const SharedMemory& memory;
	       const UNMAP_AFTER_DESTROY unmap_mode;
	       MMapOptions options;

	       void* addr;

	       void error(const int) const;
	  };
//////////////////////////////////////////////////////////////////
     }
}
#endif // __linux_posix_MMaper__
<commit_msg>work in progress<commit_after>//
// Copyright (c) 2017, Boris Popov <popov@whitekefir.ru>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//

#include "SharedMemory.hpp"
#include "MMapOptions.hpp"
#include <tuple>

#ifndef __linux_posix_MMaper__
#define __linux_posix_MMaper__

namespace linux {
     namespace posix {
//////////////////////////////////////////////////////////////////
	  using UNMAP_AFTER_DESTROY = bool;
	  using MapInfo = std::tuple<void*, size_t>;
//////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////
	  class MMaper {

	  public:
	       MMaper(const SharedMemory&,
		      const UNMAP_AFTER_DESTROY = false,
		      const MMapOptions = MMapOptions());
	       ~MMaper();

	       MMaper(const MMaper&) = delete;
	       MMaper& operator= (const MMaper&) = delete;
	       MMaper(const MMaper&&) = delete;
	       MMaper& operator= (const MMaper&&) = delete;

	       MapInfo map();
	       void unmap() const;

	  private:
	       const SharedMemory& memory;
	       const UNMAP_AFTER_DESTROY unmap_mode;
	       MMapOptions options;

	       void* addr;

	       void error(const int) const;
	  };
//////////////////////////////////////////////////////////////////
     }
}
#endif // __linux_posix_MMaper__
<|endoftext|>


<commit_before>// Copyright (C) 2014 Matteo Agostini <matteo.agostini@ph.tum.de>

// This is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This software is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

// c++ libs
#include <iostream>
#include <limits>
#include <cmath>
#include <vector>

// ROOT libs
#include <TMath.h>

// m-stats libs
#include "MSMath.h"

namespace mst {

double MSMath::LogGaus(double x, double mean, double sigma) {
   // sigma must be positive
   if (sigma <= 0.0) {
      std::cerr << "MSMath::LogGaus >> error: sigma must be positive\n";
      return 0;
   }
   const double dx = (x - mean) / sigma;
   return -0.5*dx*dx - 0.5*log(2*M_PI) - log(sigma);
}

double MSMath::LogPoisson(double x, double lambda) {

   // If the parameters are negative the Poission probability is not defined
   if (lambda < 0.0 || x < 0.0) {
      std::cerr << "MSMath::LogPoisson >> error: "
                << "function not defined for negative parameters\n";
      return -std::numeric_limits<double>::infinity();
   }

   // The expectation must be positive. Empty bins in the PSD should be avoided
   else if (lambda == 0.0) {
      if (x == 0) return 0;
      else        return -std::numeric_limits<double>::infinity();
   }

   // Copute Poission probability for positive lambda values
   else {
      if      (x == 0)       return -lambda;
      else if (lambda < 899) return x*log(lambda)-lambda-TMath::LnGamma(x+1.);
      else                   return LogGaus(x, lambda, sqrt(lambda));
   }
}

double MSMath::LogExp (double x, double limit, double quantile, double offset) {
   // the expoential function should be normalized in the range [offset, inf] and
   // have the quantile corresponding to the desidered probablity at the limit
   // value.
   //
   // Starting from the standard exp function normalized betweeen 0 and inf:
   //
   //    f(x) = a*exp(-a*x)
   //
   // the parameter a is hence fixed by:
   //
   //    int _0 ^limit f(x) dx = quantile
   //    => a = -ln(1-quantile)/limit
   //
   // and final the frame must be changed such that 0->offset
   //
   //   => a = -ln(1-quantile)/(limit-offset)
   //   f(x) = a * exp(-a* (x-offset))

   // Check that the quantile is in the range ]0,1[
   if (quantile <= 0.0 && quantile >= 1.0) {
      std::cerr << "MSMath::Logexp >> error: "
                << "quantile must be >0 && <1\n";
      return std::numeric_limits<double>::quiet_NaN();

   // Check that the limit is above the offset
   } else if (limit <= offset) {
      std::cerr << "MSModelPullExp >> error: "
                << "the limit must be larger than the offset\n";
      return std::numeric_limits<double>::quiet_NaN();

   // Check that the parameter is in the physical range
   } else if (x < offset) {
      std::cerr << "MSMath::Logexp >> error: "
                << "parameter must be larger than the offset\n";
      return std::numeric_limits<double>::quiet_NaN();

   // compute LogExp
   } else {
      const double a = -log(1.0-quantile)/(limit-offset);
      return  log(a)-a*(x-offset);
   }
}
}
<commit_msg>improved performance by computing only once fixed quantities<commit_after>// Copyright (C) 2014 Matteo Agostini <matteo.agostini@ph.tum.de>

// This is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This software is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

// c++ libs
#include <iostream>
#include <limits>
#include <cmath>
#include <vector>

// ROOT libs
#include <TMath.h>

// m-stats libs
#include "MSMath.h"

namespace mst {

double MSMath::LogGaus(double x, double mean, double sigma) {
   // sigma must be positive
   if (sigma <= 0.0) {
      std::cerr << "MSMath::LogGaus >> error: sigma must be positive\n";
      return 0;
   }
   const double dx = (x - mean) / sigma;
   const static double constant = 0.5*log(2*M_PI);
   return -0.5*dx*dx - constant - log(sigma);
}

double MSMath::LogPoisson(double x, double lambda) {

   // If the parameters are negative the Poission probability is not defined
   if (lambda < 0.0 || x < 0.0) {
      std::cerr << "MSMath::LogPoisson >> error: "
                << "function not defined for negative parameters\n";
      return -std::numeric_limits<double>::infinity();
   }

   // The expectation must be positive. Empty bins in the PSD should be avoided
   else if (lambda == 0.0) {
      if (x == 0) return 0;
      else        return -std::numeric_limits<double>::infinity();
   }

   // Copute Poission probability for positive lambda values
   else {
      if      (x == 0)       return -lambda;
      else if (lambda < 899) return x*log(lambda)-lambda-TMath::LnGamma(x+1.);
      else                   return LogGaus(x, lambda, sqrt(lambda));
   }
}

double MSMath::LogExp (double x, double limit, double quantile, double offset) {
   // the expoential function should be normalized in the range [offset, inf] and
   // have the quantile corresponding to the desidered probablity at the limit
   // value.
   //
   // Starting from the standard exp function normalized betweeen 0 and inf:
   //
   //    f(x) = a*exp(-a*x)
   //
   // the parameter a is hence fixed by:
   //
   //    int _0 ^limit f(x) dx = quantile
   //    => a = -ln(1-quantile)/limit
   //
   // and final the frame must be changed such that 0->offset
   //
   //   => a = -ln(1-quantile)/(limit-offset)
   //   f(x) = a * exp(-a* (x-offset))

   // Check that the quantile is in the range ]0,1[
   if (quantile <= 0.0 && quantile >= 1.0) {
      std::cerr << "MSMath::Logexp >> error: "
                << "quantile must be >0 && <1\n";
      return std::numeric_limits<double>::quiet_NaN();

   // Check that the limit is above the offset
   } else if (limit <= offset) {
      std::cerr << "MSModelPullExp >> error: "
                << "the limit must be larger than the offset\n";
      return std::numeric_limits<double>::quiet_NaN();

   // Check that the parameter is in the physical range
   } else if (x < offset) {
      std::cerr << "MSMath::Logexp >> error: "
                << "parameter must be larger than the offset\n";
      return std::numeric_limits<double>::quiet_NaN();

   // compute LogExp
   } else {
      const double a = -log(1.0-quantile)/(limit-offset);
      return  log(a)-a*(x-offset);
   }
}
}
<|endoftext|>


<commit_before>#ifndef matrix_hpp
#define matrix_hpp

#include <cstdlib>
#include <iostream>
#include <sstream>
#include <stdint.h>
#include "util.hpp"
#include "vector.hpp"

#define debug(X) X

#define MATRIX_FOREACH(I, J) \
            for(auto I = 0; I < this->h; I++) \
                for(auto J = 0; J < this->h; J++)
#define MATRIX_SIZE_MATCH(M) \
            ((M)->w != this->w || (M)->h != this->h)
#define MATRIX_SIZE_SHOULD_BE_SAME(M) \
            if(MATRIX_SIZE_MATCH((M))) \
                fatal("matrix size mismatch");
#define MATRIX_WIDTH_VECTOR_SIZE_MATCH_P(V) \
            (this->w == V->size)
using namespace std;

template<class T>
class Matrix
{
    private:
        T *data;

        void allocate_buffer() {
            if(this->h == 0 || this->w == 0)
                fatal("neither `h` or `w` can be zero");

            this->data = new T[this->h * this->w];
            //debug({ fprintf(stderr, "[+] Matrix allocaed at %p, Buffer allocated at %p\n", this, this->data); })
        }

        void free_buffer() {
            if(this->data == NULL)
                fatal("buffer is NULL, can not be freed");
            debug({ fprintf(stderr, "[+] Buffer freed %p\n", this->data); })

            delete [] (char *)this->data;
            this->data = NULL;
        }

    public:
        const uint32_t h, w;

        // constructor and destructor
        Matrix(uint32_t h, uint32_t w) : h(h), w(w)
        {
            this->allocate_buffer();
            this->zero();
        }

        Matrix(Matrix& m) : h(m.h), w(m.w)
        {
            this->allocate_buffer();
            this->copy_from(&m);
        }

        Matrix(Matrix *m) : h(m->h), w(m->w)
        {
            this->allocate_buffer();
            this->copy_from(m);
        }

        ~Matrix() {
            this->free_buffer();
        }

        // data accessor
        T& operator() (int x, int y) {
            return this->data[x * this->h + y];
        }

        T& cell(int x, int y) {
            return this->data[x * this->h + y];
        }

        // data manipulation
        Matrix* copy_from(Matrix *m) {
            MATRIX_SIZE_SHOULD_BE_SAME(m);
            memcpy(&this->cell(0, 0), &m->cell(0, 0), sizeof(T) * this->w * this->h);
            return this;
        }

        Matrix* add(Matrix *m) {
            MATRIX_SIZE_SHOULD_BE_SAME(m);
            MATRIX_FOREACH(x, y) {
                this->cell(x, y) += m->cell(x, y);
            }
            return this;
        }
        Matrix* add(Matrix& m) {
            return this->add(&m);
        }

        Matrix* sub(Matrix *m) {
            MATRIX_SIZE_SHOULD_BE_SAME(m);
            MATRIX_FOREACH(x, y) {
                this->cell(x, y) -= m->cell(x, y);
            }
            return this;
        }
        Matrix* sub(Matrix& m) {
            return this->sub(&m);
        }

        Matrix* mul(Matrix *m) {
            if(this->w != m->h)
                fatal("matrix size mismatch (mul)");

            // result height, result width
            auto r_h = this->h, r_w = m->w, len = this->w;
            Matrix *result = new Matrix(r_h, r_w);
            for(auto x = 0; x < r_h; x++) {
                for(auto y = 0; y < r_w; y++) {
                    T sum = 0;
                    for(auto j = 0; j < len; j++)
                        sum += this->cell(x, j) * m->cell(j, y);
                    result->cell(x, y) = sum;
                }
            }
            return result;
        }
        Matrix* mul(T v) {
            MATRIX_FOREACH(x, y) {
                this->cell(x, y) *= v;
            }
            return this;
        }

        Matrix* div(T v) {
            MATRIX_FOREACH(x, y) {
                this->cell(x, y) /= v;
            }
            return this;
        }

        // operator overloading, all size check is perfrom in named functions
        Matrix* operator= (const Matrix& m) {
            return this->copy_from(&m);
        }

        Matrix* operator+= (Matrix& m) { return this->add(m); }
        Matrix* operator+= (Matrix *m) { return this->add(m); }

        Matrix* operator-= (Matrix& m) { return this->sub(m); }
        Matrix* operator-= (Matrix *m) { return this->sub(m); }

        // these operator will return new Matrix instance
        Matrix* operator+ (Matrix& m) {
            Matrix *result = new Matrix(this);
            result->add(m);
            return result;
        }

        Matrix* fill(T value) {
            MATRIX_FOREACH(x, y) {
                this->cell(x, y) = value;
            }
            return this;
        }

        Matrix* zero() {
            MATRIX_FOREACH(x, y) {
                this->cell(x, y) = 0;
            }
            return this;
        }

        Matrix* one() {
            MATRIX_FOREACH(x, y) {
                this->cell(x, y) = x == y ? 1 : 0;
            }
            return this;
        }

        string str() {
            stringstream buffer;
            buffer << "Matrix(" << h << ", " << w << ") {\n";
            for(auto x = 0; x < this->h; x++) {
                if(x) buffer << ",\n";
                buffer << "  (";
                for(auto y = 0; y < this->w; y++) {
                    if(y) buffer << ", ";
                    buffer << this->cell(x, y);
                }
                buffer << ")";
            }
            buffer << "\n}";

            return buffer.str();
        }
        //matrix multiply vector
        myVecD * mul(myVecD * v){
            if(!MATRIX_WIDTH_VECTOR_SIZE_MATCH_P(v))
                fatal("matrix's width != vector's length");
            myVecD * result = new myVecD(this->h);
            for (int index = 0; index < this->h; index++) {
                (*result)[index] = 0.0;
            }
            for (int index = 0; index < this->h; index++) {
                for (int indexa = 0; indexa < this->w; indexa ++) {
                    (*result)[index] += (this->cell(index,indexa) * (*v)[indexa]);
                }
            }
            return result;
        }
        myVecD * mul(myVecD & v){
            return this->mul(&v);
        }
        // static method
        static Matrix* one(int h, int w) {
           return (new Matrix(h, w))->one();
        }
    //TODO
    static Matrix<double> * merge_by_vectors(int merge_type, int number, myVecD ** vectors){
        if(number <= 0)
            fatal("invalid number of vectors");
        int size = vectors[0]->size;
        for (int index = 0; index < number; index++) {
            if(vectors[index]->size != size)
                fatal("vectors with different dimension can't be merged to one matrix");
        }
        Matrix<double> * result;
        int column, row;
        switch(merge_type){
            case AS_COLUMN:
                column = number;
                row  = size;
                result = new Matrix<double>(row, column);
                for (int indexa = 0; indexa < column; indexa++) {
                    for (int indexb = 0; indexb < row; indexb++) {
                        (*result)(indexb, indexa) = 1.0;
                    }
                }
                break;
            case AS_ROW:
                break;
            default:
                fatal("invalid merge type");
        }
        return result;
    }
};

#endif<commit_msg>Revert "Revert "New API, no pointer anymore""<commit_after>#ifndef matrix_hpp
#define matrix_hpp

#include <cstdlib>
#include <iostream>
#include <sstream>
#include <stdint.h>
#include "util.hpp"
#include "vector.hpp"

#ifndef debug
#define debug(X) X
#endif

#define MATRIX_FOREACH(I, J) \
            for(auto I = 0; I < this->h; I++) \
                for(auto J = 0; J < this->h; J++)
#define MATRIX_SIZE_MATCH(M) \
            ((M)->w != this->w || (M)->h != this->h)
#define MATRIX_SIZE_SHOULD_BE_SAME(M) \
            if(MATRIX_SIZE_MATCH((M))) \
                fatal("matrix size mismatch");
#define MATRIX_WIDTH_VECTOR_SIZE_MATCH_P(V) \
            (this->w == V->size)
using namespace std;

template<class T>
class Matrix
{
    private:
        T *data;

        void allocate_buffer() {
            if(this->h == 0 || this->w == 0)
                fatal("neither `h` or `w` can be zero");

            this->data = new T[this->h * this->w];
            //debug({ fprintf(stderr, "[+] Matrix allocaed at %p, Buffer allocated at %p\n", this, this->data); })
        }

        void free_buffer() {
            if(this->data == NULL)
                fatal("buffer is NULL, can not be freed");
            debug({ fprintf(stderr, "[+] Buffer freed %p\n", this->data); })

            delete [] (char *)this->data;
            this->data = NULL;
        }

    public:
        const uint32_t h, w;

        // constructor and destructor
        Matrix(uint32_t h, uint32_t w) : h(h), w(w)
        {
            this->allocate_buffer();
            this->zero();
        }

        Matrix(Matrix& m) : h(m.h), w(m.w)
        {
            this->allocate_buffer();
            this->copy_from(&m);
        }

        Matrix(Matrix *m) : h(m->h), w(m->w)
        {
            this->allocate_buffer();
            this->copy_from(m);
        }

        ~Matrix() {
            this->free_buffer();
        }

        void copy_from(Matrix *m) {
            MATRIX_SIZE_SHOULD_BE_SAME(m);
            memcpy(&this->cell(0, 0), &m->cell(0, 0), sizeof(T) * this->w * this->h);
        }

        // data accessor
        T& operator() (int x, int y) {
            return this->data[x * this->h + y];
        }

        T& cell(int x, int y) {
            return this->data[x * this->h + y];
        }

        // data manipulation
        Matrix& add(Matrix &m) {
            MATRIX_SIZE_SHOULD_BE_SAME(&m);
            MATRIX_FOREACH(x, y) {
                this->cell(x, y) += m(x, y);
            }
            return *this;
        }

        Matrix& sub(Matrix &m) {
            MATRIX_SIZE_SHOULD_BE_SAME(&m);
            MATRIX_FOREACH(x, y) {
                this->cell(x, y) -= m(x, y);
            }
            return &this;
        }

        Matrix& mul(Matrix *m) {
            if(this->w != m->h)
                fatal("matrix size mismatch (mul)");

            // result height, result width
            auto r_h = this->h, r_w = m->w, len = this->w;
            Matrix result = Matrix(r_h, r_w);
            for(auto x = 0; x < r_h; x++) {
                for(auto y = 0; y < r_w; y++) {
                    T sum = 0;
                    for(auto j = 0; j < len; j++)
                        sum += this->cell(x, j) * m->cell(j, y);
                    result(x, y) = sum;
                }
            }
            return result;
        }
        Matrix& mul(T v) {
            MATRIX_FOREACH(x, y) {
                this->cell(x, y) *= v;
            }
            return *this;
        }

        Matrix& div(T v) {
            MATRIX_FOREACH(x, y) {
                this->cell(x, y) /= v;
            }
            return *this;
        }

        // operator overloading, all size check is perfrom in named functions
        Matrix& operator= (const Matrix& m) {
            return *this->copy_from(&m);
        }

        Matrix& operator+= (Matrix& m) { return *this->add(m); }
        Matrix& operator+= (Matrix *m) { return *this->add(m); }

        Matrix& operator-= (Matrix& m) { return *this->sub(m); }
        Matrix& operator-= (Matrix *m) { return *this->sub(m); }

        // these operator will return new Matrix instance
        Matrix& operator+ (Matrix& m) {
            Matrix result(this);
            return result.add(m);
        }

        void fill(T value) {
            MATRIX_FOREACH(x, y) {
                this->cell(x, y) = value;
            }
        }

        void zero() {
            MATRIX_FOREACH(x, y) {
                this->cell(x, y) = 0;
            }
        }

        void one() {
            MATRIX_FOREACH(x, y) {
                this->cell(x, y) = x == y ? 1 : 0;
            }
        }

        string str() {
            stringstream buffer;
            buffer << "Matrix(" << h << ", " << w << ") {\n";
            for(auto x = 0; x < this->h; x++) {
                if(x) buffer << ",\n";
                buffer << "  (";
                for(auto y = 0; y < this->w; y++) {
                    if(y) buffer << ", ";
                    buffer << this->cell(x, y);
                }
                buffer << ")";
            }
            buffer << "\n}";

            return buffer.str();
        }
        //matrix multiply vector
        myVecD * mul(myVecD * v){
            if(!MATRIX_WIDTH_VECTOR_SIZE_MATCH_P(v))
                fatal("matrix's width != vector's length");
            myVecD * result = new myVecD(this->h);
            for (int index = 0; index < this->h; index++) {
                (*result)[index] = 0.0;
            }
            for (int index = 0; index < this->h; index++) {
                for (int indexa = 0; indexa < this->w; indexa ++) {
                    (*result)[index] += (this->cell(index,indexa) * (*v)[indexa]);
                }
            }
            return result;
        }
        myVecD * mul(myVecD & v){
            return this->mul(&v);
        }

    //TODO
    static Matrix<double> * merge_by_vectors(int merge_type, int number, myVecD ** vectors){
        if(number <= 0)
            fatal("invalid number of vectors");
        int size = vectors[0]->size;
        for (int index = 0; index < number; index++) {
            if(vectors[index]->size != size)
                fatal("vectors with different dimension can't be merged to one matrix");
        }
        Matrix<double> * result;
        int column, row;
        switch(merge_type){
            case AS_COLUMN:
                column = number;
                row  = size;
                result = new Matrix<double>(row, column);
                for (int indexa = 0; indexa < column; indexa++) {
                    for (int indexb = 0; indexb < row; indexb++) {
                        (*result)(indexb, indexa) = 1.0;
                    }
                }
                break;
            case AS_ROW:
                break;
            default:
                fatal("invalid merge type");
        }
        return result;
    }
};

#endif
<|endoftext|>


<commit_before>// Module:  Log4CPLUS
// File:    property.cxx
// Created: 2/2002
// Author:  Tad E. Smith
//
//
// Copyright (C) Tad E. Smith  All rights reserved.
//
// This software is published under the terms of the Apache Software
// License version 1.1, a copy of which has been included with this
// distribution in the LICENSE.APL file.
//
// $Log: not supported by cvs2svn $
// Revision 1.8  2003/05/01 19:35:25  tcsmith
// Fixed VC++ compiler "performance warning".
//
// Revision 1.7  2003/04/19 23:04:32  tcsmith
// Fixed UNICODE support.
//
// Revision 1.6  2003/04/18 21:52:35  tcsmith
// Converted from using std::ifstream to using log4cplus::tifstream.
//
// Revision 1.5  2003/04/18 21:32:22  tcsmith
// Converted from std::string to log4cplus::tstring.
//
// Revision 1.4  2003/04/05 20:09:17  tcsmith
// Added the removeProperty() method.
//
// Revision 1.3  2003/04/03 01:23:34  tcsmith
// Standardized the formatting.
//

#include <log4cplus/helpers/property.h>
#include <log4cplus/fstreams.h>

using namespace std;
using namespace log4cplus;

#define BUFFER_SIZE 2048

///////////////////////////////////////////////////////////////////////////////
// log4cplus::helpers::Properties ctors and dtor
///////////////////////////////////////////////////////////////////////////////

log4cplus::helpers::Properties::Properties()
{
}

log4cplus::helpers::Properties::Properties(log4cplus::tistream& input)
{
    init(input);
}

log4cplus::helpers::Properties::Properties(const log4cplus::tstring& inputFile)
{
    tifstream file;
    file.open(LOG4CPLUS_TSTRING_TO_STRING(inputFile).c_str());
    if(!file) {
        return;
    }
    init(file);
}

void
log4cplus::helpers::Properties::init(log4cplus::tistream& input)
{
    if(input.fail()) {
        return;
    }

    tchar buffer[BUFFER_SIZE];
    while(!input.eof()) {
        input.getline(buffer, BUFFER_SIZE);
        tstring tmp(buffer);
        tstring::size_type idx = tmp.find('=');
        if(idx != tstring::npos) {
            setProperty(tmp.substr(0, idx), tmp.substr(idx + 1));
        }
    }
}

log4cplus::helpers::Properties::~Properties()
{
}

///////////////////////////////////////////////////////////////////////////////
// log4cplus::helpers::Properties public methods
///////////////////////////////////////////////////////////////////////////////

tstring
log4cplus::helpers::Properties::getProperty(const tstring& key) const
{
    StringMap::const_iterator it = data.find(key);
    if(it == data.end()) {
        return LOG4CPLUS_TEXT("");
    }
    else {
        return it->second;
    }
}

tstring
log4cplus::helpers::Properties::getProperty(const tstring& key,
                                            const tstring& defaultVal) const
{
    if(exists(key)) {
        return getProperty(key);
    }
    else {
        return defaultVal;
    }
}

vector<tstring>
log4cplus::helpers::Properties::propertyNames() const
{
    vector<tstring> tmp;
    for(StringMap::const_iterator it=data.begin(); it!=data.end(); ++it) {
        tmp.push_back(it->first);
    }

    return tmp;
}

void
log4cplus::helpers::Properties::setProperty(const log4cplus::tstring& key,
                                            const log4cplus::tstring& value)
{
    data[key] = value;
}

bool
log4cplus::helpers::Properties::removeProperty(const log4cplus::tstring& key)
{
    return (data.erase(key) > 0);
}

log4cplus::helpers::Properties
log4cplus::helpers::Properties::getPropertySubset(const log4cplus::tstring& prefix) const
{
    Properties ret;

    vector<tstring> keys = propertyNames();
    for(vector<tstring>::iterator it=keys.begin(); it!=keys.end(); ++it) {
        tstring::size_type pos = (*it).find(prefix);
        if(pos != tstring::npos) {
            ret.setProperty( (*it).substr(prefix.size()), getProperty(*it) );
        }
    }

    return ret;
}

<commit_msg>Added a check in the ctor for a valid filename.  If if is not valid, do not attempt to open that file.<commit_after>// Module:  Log4CPLUS
// File:    property.cxx
// Created: 2/2002
// Author:  Tad E. Smith
//
//
// Copyright (C) Tad E. Smith  All rights reserved.
//
// This software is published under the terms of the Apache Software
// License version 1.1, a copy of which has been included with this
// distribution in the LICENSE.APL file.
//
// $Log: not supported by cvs2svn $
// Revision 1.9  2003/05/01 19:54:30  tcsmith
// Fixed: "warning: comparison between signed and unsigned".
//
// Revision 1.8  2003/05/01 19:35:25  tcsmith
// Fixed VC++ compiler "performance warning".
//
// Revision 1.7  2003/04/19 23:04:32  tcsmith
// Fixed UNICODE support.
//
// Revision 1.6  2003/04/18 21:52:35  tcsmith
// Converted from using std::ifstream to using log4cplus::tifstream.
//
// Revision 1.5  2003/04/18 21:32:22  tcsmith
// Converted from std::string to log4cplus::tstring.
//
// Revision 1.4  2003/04/05 20:09:17  tcsmith
// Added the removeProperty() method.
//
// Revision 1.3  2003/04/03 01:23:34  tcsmith
// Standardized the formatting.
//

#include <log4cplus/helpers/property.h>
#include <log4cplus/fstreams.h>

using namespace std;
using namespace log4cplus;

#define BUFFER_SIZE 2048

///////////////////////////////////////////////////////////////////////////////
// log4cplus::helpers::Properties ctors and dtor
///////////////////////////////////////////////////////////////////////////////

log4cplus::helpers::Properties::Properties()
{
}

log4cplus::helpers::Properties::Properties(log4cplus::tistream& input)
{
    init(input);
}

log4cplus::helpers::Properties::Properties(const log4cplus::tstring& inputFile)
{
    if(inputFile.length() == 0) {
        return;
    }

    tifstream file;
    file.open(LOG4CPLUS_TSTRING_TO_STRING(inputFile).c_str());
    if(!file) {
        return;
    }
    init(file);
}

void
log4cplus::helpers::Properties::init(log4cplus::tistream& input)
{
    if(input.fail()) {
        return;
    }

    tchar buffer[BUFFER_SIZE];
    while(!input.eof()) {
        input.getline(buffer, BUFFER_SIZE);
        tstring tmp(buffer);
        tstring::size_type idx = tmp.find('=');
        if(idx != tstring::npos) {
            setProperty(tmp.substr(0, idx), tmp.substr(idx + 1));
        }
    }
}

log4cplus::helpers::Properties::~Properties()
{
}

///////////////////////////////////////////////////////////////////////////////
// log4cplus::helpers::Properties public methods
///////////////////////////////////////////////////////////////////////////////

tstring
log4cplus::helpers::Properties::getProperty(const tstring& key) const
{
    StringMap::const_iterator it = data.find(key);
    if(it == data.end()) {
        return LOG4CPLUS_TEXT("");
    }
    else {
        return it->second;
    }
}

tstring
log4cplus::helpers::Properties::getProperty(const tstring& key,
                                            const tstring& defaultVal) const
{
    if(exists(key)) {
        return getProperty(key);
    }
    else {
        return defaultVal;
    }
}

vector<tstring>
log4cplus::helpers::Properties::propertyNames() const
{
    vector<tstring> tmp;
    for(StringMap::const_iterator it=data.begin(); it!=data.end(); ++it) {
        tmp.push_back(it->first);
    }

    return tmp;
}

void
log4cplus::helpers::Properties::setProperty(const log4cplus::tstring& key,
                                            const log4cplus::tstring& value)
{
    data[key] = value;
}

bool
log4cplus::helpers::Properties::removeProperty(const log4cplus::tstring& key)
{
    return (data.erase(key) > 0);
}

log4cplus::helpers::Properties
log4cplus::helpers::Properties::getPropertySubset(const log4cplus::tstring& prefix) const
{
    Properties ret;

    vector<tstring> keys = propertyNames();
    for(vector<tstring>::iterator it=keys.begin(); it!=keys.end(); ++it) {
        tstring::size_type pos = (*it).find(prefix);
        if(pos != tstring::npos) {
            ret.setProperty( (*it).substr(prefix.size()), getProperty(*it) );
        }
    }

    return ret;
}

<|endoftext|>


<commit_before>/*
 * DbgRenderTarget.cpp
 *
 * This file is part of the "LLGL" project (Copyright (c) 2015-2017 by Lukas Hermanns)
 * See "LICENSE.txt" for license information.
 */

#include "DbgRenderTarget.h"
#include "DbgTexture.h"
#include "DbgCore.h"
#include "../CheckedCast.h"

namespace LLGL
{

DbgRenderTarget::DbgRenderTarget(RenderTarget& instance, RenderingDebugger* debugger, const RenderTargetDescriptor& desc) :
    instance  { instance },
    debugger_ { debugger },
    desc_     { desc     }
{
}

void DbgRenderTarget::AttachDepthBuffer(const Gs::Vector2ui& size)
{
    instance.AttachDepthBuffer(size);
}

void DbgRenderTarget::AttachStencilBuffer(const Gs::Vector2ui& size)
{
    instance.AttachStencilBuffer(size);
}

void DbgRenderTarget::AttachDepthStencilBuffer(const Gs::Vector2ui& size)
{
    instance.AttachDepthStencilBuffer(size);
}

void DbgRenderTarget::AttachTexture(Texture& texture, const RenderTargetAttachmentDescriptor& attachmentDesc)
{
    auto& textureDbg = LLGL_CAST(DbgTexture&, texture);

    if (debugger_)
    {
        LLGL_DBG_SOURCE;

        if (desc_.multiSampling.SampleCount() > 1 && desc_.customMultiSampling && !IsMultiSampleTexture(texture.GetType()))
            LLGL_DBG_ERROR(ErrorType::InvalidArgument, "attempt to attach non-multi-sample texture to render-target with custom multi-sampling");
    }

    instance.AttachTexture(textureDbg.instance, attachmentDesc);
}

void DbgRenderTarget::DetachAll()
{
    instance.DetachAll();
}

} // /namespace LLGL

// ================================================================================
<commit_msg>Fixed bug in RenderTarget of debug layer (resolution was not stored).<commit_after>/*
 * DbgRenderTarget.cpp
 *
 * This file is part of the "LLGL" project (Copyright (c) 2015-2017 by Lukas Hermanns)
 * See "LICENSE.txt" for license information.
 */

#include "DbgRenderTarget.h"
#include "DbgTexture.h"
#include "DbgCore.h"
#include "../CheckedCast.h"

namespace LLGL
{

DbgRenderTarget::DbgRenderTarget(RenderTarget& instance, RenderingDebugger* debugger, const RenderTargetDescriptor& desc) :
    instance  { instance },
    debugger_ { debugger },
    desc_     { desc     }
{
}

void DbgRenderTarget::AttachDepthBuffer(const Gs::Vector2ui& size)
{
    instance.AttachDepthBuffer(size);
}

void DbgRenderTarget::AttachStencilBuffer(const Gs::Vector2ui& size)
{
    instance.AttachStencilBuffer(size);
}

void DbgRenderTarget::AttachDepthStencilBuffer(const Gs::Vector2ui& size)
{
    instance.AttachDepthStencilBuffer(size);
}

void DbgRenderTarget::AttachTexture(Texture& texture, const RenderTargetAttachmentDescriptor& attachmentDesc)
{
    auto& textureDbg = LLGL_CAST(DbgTexture&, texture);

    if (debugger_)
    {
        LLGL_DBG_SOURCE;

        if (desc_.multiSampling.SampleCount() > 1 && desc_.customMultiSampling && !IsMultiSampleTexture(texture.GetType()))
            LLGL_DBG_ERROR(ErrorType::InvalidArgument, "attempt to attach non-multi-sample texture to render-target with custom multi-sampling");
    }

    instance.AttachTexture(textureDbg.instance, attachmentDesc);

    ApplyResolution(instance.GetResolution());
}

void DbgRenderTarget::DetachAll()
{
    instance.DetachAll();
}

} // /namespace LLGL

// ================================================================================
<|endoftext|>


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

namespace skiagm {

struct GradData {
    int             fCount;
    const SkColor*  fColors;
    const SkScalar* fPos;
};

static const SkColor gColors[] = {
    SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK
};
static const SkScalar gPos0[] = { 0, SK_Scalar1 };
static const SkScalar gPos1[] = { SK_Scalar1/4, SK_Scalar1*3/4 };
static const SkScalar gPos2[] = {
    0, SK_Scalar1/8, SK_Scalar1/2, SK_Scalar1*7/8, SK_Scalar1
};

static const GradData gGradData[] = {
    { 2, gColors, NULL },
    { 2, gColors, gPos0 },
    { 2, gColors, gPos1 },
    { 5, gColors, NULL },
    { 5, gColors, gPos2 }
};

static SkShader* MakeLinear(const SkPoint pts[2], const GradData& data,
                            SkShader::TileMode tm, SkUnitMapper* mapper) {
    return SkGradientShader::CreateLinear(pts, data.fColors, data.fPos,
                                          data.fCount, tm, mapper);
}

static SkShader* MakeRadial(const SkPoint pts[2], const GradData& data,
                            SkShader::TileMode tm, SkUnitMapper* mapper) {
    SkPoint center;
    center.set(SkScalarAve(pts[0].fX, pts[1].fX),
               SkScalarAve(pts[0].fY, pts[1].fY));
    return SkGradientShader::CreateRadial(center, center.fX, data.fColors,
                                          data.fPos, data.fCount, tm, mapper);
}

static SkShader* MakeSweep(const SkPoint pts[2], const GradData& data,
                           SkShader::TileMode tm, SkUnitMapper* mapper) {
    SkPoint center;
    center.set(SkScalarAve(pts[0].fX, pts[1].fX),
               SkScalarAve(pts[0].fY, pts[1].fY));
    return SkGradientShader::CreateSweep(center.fX, center.fY, data.fColors,
                                         data.fPos, data.fCount, mapper);
}

static SkShader* Make2Radial(const SkPoint pts[2], const GradData& data,
                             SkShader::TileMode tm, SkUnitMapper* mapper) {
    SkPoint center0, center1;
    center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
                SkScalarAve(pts[0].fY, pts[1].fY));
    center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
                SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
    return SkGradientShader::CreateTwoPointRadial(
                                                  center1, (pts[1].fX - pts[0].fX) / 7,
                                                  center0, (pts[1].fX - pts[0].fX) / 2,
                                                  data.fColors, data.fPos, data.fCount, tm, mapper);
}

typedef SkShader* (*GradMaker)(const SkPoint pts[2], const GradData& data,
                               SkShader::TileMode tm, SkUnitMapper* mapper);
static const GradMaker gGradMakers[] = {
    MakeLinear, MakeRadial, MakeSweep, Make2Radial
};

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

class GradientsGM : public GM {
public:
	GradientsGM() {
        this->setBGColor(0xFFDDDDDD);
    }

protected:
    SkString onShortName() {
        return SkString("gradients");
    }

    virtual SkISize onISize() { return make_isize(640, 510); }

    virtual void onDraw(SkCanvas* canvas) {

        SkPoint pts[2] = {
            { 0, 0 },
            { SkIntToScalar(100), SkIntToScalar(100) }
        };
        SkShader::TileMode tm = SkShader::kClamp_TileMode;
        SkRect r = { 0, 0, SkIntToScalar(100), SkIntToScalar(100) };
        SkPaint paint;
        paint.setAntiAlias(true);

        canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
        for (size_t i = 0; i < SK_ARRAY_COUNT(gGradData); i++) {
            canvas->save();
            for (size_t j = 0; j < SK_ARRAY_COUNT(gGradMakers); j++) {
                SkShader* shader = gGradMakers[j](pts, gGradData[i], tm, NULL);
                paint.setShader(shader);
                canvas->drawRect(r, paint);
                shader->unref();
                canvas->translate(0, SkIntToScalar(120));
            }
            canvas->restore();
            canvas->translate(SkIntToScalar(120), 0);
        }
    }

private:
    typedef GM INHERITED;
};

/*
 Inspired by this <canvas> javascript, where we need to detect that we are not
 solving a quadratic equation, but must instead solve a linear (since our X^2
 coefficient is 0)

 ctx.fillStyle = '#f00';
 ctx.fillRect(0, 0, 100, 50);

 var g = ctx.createRadialGradient(-80, 25, 70, 0, 25, 150);
 g.addColorStop(0, '#f00');
 g.addColorStop(0.01, '#0f0');
 g.addColorStop(0.99, '#0f0');
 g.addColorStop(1, '#f00');
 ctx.fillStyle = g;
 ctx.fillRect(0, 0, 100, 50);
 */
class GradientsDegenrate2PointGM : public GM {
public:
    GradientsDegenrate2PointGM() {}

protected:
    SkString onShortName() {
        return SkString("gradients_degenerate_2pt");
    }

	virtual SkISize onISize() { return make_isize(320, 320); }

    void drawBG(SkCanvas* canvas) {
        canvas->drawColor(SK_ColorBLUE);
    }

    virtual void onDraw(SkCanvas* canvas) {
        this->drawBG(canvas);

        SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorGREEN, SK_ColorRED };
        SkScalar pos[] = { 0, SkFloatToScalar(0.01f), SkFloatToScalar(0.99f), SK_Scalar1 };
        SkPoint c0;
        c0.iset(-80, 25);
        SkScalar r0 = SkIntToScalar(70);
        SkPoint c1;
        c1.iset(0, 25);
        SkScalar r1 = SkIntToScalar(150);
        SkShader* s = SkGradientShader::CreateTwoPointRadial(c0, r0, c1, r1, colors,
                                                             pos, SK_ARRAY_COUNT(pos),
                                                             SkShader::kClamp_TileMode);
        SkPaint paint;
        paint.setShader(s)->unref();
        canvas->drawPaint(paint);
    }

private:
    typedef GM INHERITED;
};

/// Tests correctness of *optimized* codepaths in gradients.

class ClampedGradientsGM : public GM {
public:
    ClampedGradientsGM() {}

protected:
    SkString onShortName() { return SkString("clamped_gradients"); }

    virtual SkISize onISize() { return make_isize(640, 510); }

    void drawBG(SkCanvas* canvas) {
        canvas->drawColor(0xFFDDDDDD);
    }

    virtual void onDraw(SkCanvas* canvas) {
        this->drawBG(canvas);

        SkRect r = { 0, 0, SkIntToScalar(100), SkIntToScalar(300) };
        SkPaint paint;
        paint.setAntiAlias(true);

        SkPoint center;
        center.iset(0, 300);
        canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
        SkShader* shader = SkGradientShader::CreateRadial(
            SkPoint(center),
            SkIntToScalar(200), gColors, NULL, 5,
            SkShader::kClamp_TileMode, NULL);
        paint.setShader(shader);
        canvas->drawRect(r, paint);
        shader->unref();
    }

private:
    typedef GM INHERITED;
};

/// Checks quality of large radial gradients, which may display
/// some banding.

class RadialGradientGM : public GM {
public:
    RadialGradientGM() {}

protected:
    SkString onShortName() { return SkString("radial_gradient"); }
    virtual SkISize onISize() { return make_isize(1280, 1024); }
    void drawBG(SkCanvas* canvas) {
        canvas->drawColor(0xFF000000);
    }
    virtual void onDraw(SkCanvas* canvas) {
        this->drawBG(canvas);

        SkPaint paint;
        paint.setDither(true);
        SkPoint center;
        center.set(SkIntToScalar(640), SkIntToScalar(512));
        SkScalar radius = SkIntToScalar(640);
        SkColor colors [3] = { 0x7f7f7f7f, 0x7f7f7f7f, 0xb2000000 };
        SkScalar pos [3] = { SkFloatToScalar(0.0),
                             SkFloatToScalar(0.35),
                             SkFloatToScalar(1.0) };
        SkShader* shader =
            SkGradientShader::CreateRadial(center, radius, colors,
                                           pos, 3, SkShader::kClamp_TileMode);
        paint.setShader(shader)->unref();
        SkRect r = { 0, 0, SkIntToScalar(1280), SkIntToScalar(1024) };
        canvas->drawRect(r, paint);
    }
private:
    typedef GM INHERITED;
};

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

static GM* MyFactory(void*) { return new GradientsGM; }
static GMRegistry reg(MyFactory);

static GM* MyFactory2(void*) { return new GradientsDegenrate2PointGM; }
static GMRegistry reg2(MyFactory2);

static GM* MyFactory3(void*) { return new ClampedGradientsGM; }
static GMRegistry reg3(MyFactory3);

static GM* MyFactory4(void*) { return new RadialGradientGM; }
static GMRegistry reg4(MyFactory4);
}

<commit_msg>increase height to include entire circle for large radial<commit_after>
/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "gm.h"
#include "SkGradientShader.h"

namespace skiagm {

struct GradData {
    int             fCount;
    const SkColor*  fColors;
    const SkScalar* fPos;
};

static const SkColor gColors[] = {
    SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK
};
static const SkScalar gPos0[] = { 0, SK_Scalar1 };
static const SkScalar gPos1[] = { SK_Scalar1/4, SK_Scalar1*3/4 };
static const SkScalar gPos2[] = {
    0, SK_Scalar1/8, SK_Scalar1/2, SK_Scalar1*7/8, SK_Scalar1
};

static const GradData gGradData[] = {
    { 2, gColors, NULL },
    { 2, gColors, gPos0 },
    { 2, gColors, gPos1 },
    { 5, gColors, NULL },
    { 5, gColors, gPos2 }
};

static SkShader* MakeLinear(const SkPoint pts[2], const GradData& data,
                            SkShader::TileMode tm, SkUnitMapper* mapper) {
    return SkGradientShader::CreateLinear(pts, data.fColors, data.fPos,
                                          data.fCount, tm, mapper);
}

static SkShader* MakeRadial(const SkPoint pts[2], const GradData& data,
                            SkShader::TileMode tm, SkUnitMapper* mapper) {
    SkPoint center;
    center.set(SkScalarAve(pts[0].fX, pts[1].fX),
               SkScalarAve(pts[0].fY, pts[1].fY));
    return SkGradientShader::CreateRadial(center, center.fX, data.fColors,
                                          data.fPos, data.fCount, tm, mapper);
}

static SkShader* MakeSweep(const SkPoint pts[2], const GradData& data,
                           SkShader::TileMode tm, SkUnitMapper* mapper) {
    SkPoint center;
    center.set(SkScalarAve(pts[0].fX, pts[1].fX),
               SkScalarAve(pts[0].fY, pts[1].fY));
    return SkGradientShader::CreateSweep(center.fX, center.fY, data.fColors,
                                         data.fPos, data.fCount, mapper);
}

static SkShader* Make2Radial(const SkPoint pts[2], const GradData& data,
                             SkShader::TileMode tm, SkUnitMapper* mapper) {
    SkPoint center0, center1;
    center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
                SkScalarAve(pts[0].fY, pts[1].fY));
    center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
                SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
    return SkGradientShader::CreateTwoPointRadial(
                                                  center1, (pts[1].fX - pts[0].fX) / 7,
                                                  center0, (pts[1].fX - pts[0].fX) / 2,
                                                  data.fColors, data.fPos, data.fCount, tm, mapper);
}

typedef SkShader* (*GradMaker)(const SkPoint pts[2], const GradData& data,
                               SkShader::TileMode tm, SkUnitMapper* mapper);
static const GradMaker gGradMakers[] = {
    MakeLinear, MakeRadial, MakeSweep, Make2Radial
};

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

class GradientsGM : public GM {
public:
	GradientsGM() {
        this->setBGColor(0xFFDDDDDD);
    }

protected:
    SkString onShortName() {
        return SkString("gradients");
    }

    virtual SkISize onISize() { return make_isize(640, 510); }

    virtual void onDraw(SkCanvas* canvas) {

        SkPoint pts[2] = {
            { 0, 0 },
            { SkIntToScalar(100), SkIntToScalar(100) }
        };
        SkShader::TileMode tm = SkShader::kClamp_TileMode;
        SkRect r = { 0, 0, SkIntToScalar(100), SkIntToScalar(100) };
        SkPaint paint;
        paint.setAntiAlias(true);

        canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
        for (size_t i = 0; i < SK_ARRAY_COUNT(gGradData); i++) {
            canvas->save();
            for (size_t j = 0; j < SK_ARRAY_COUNT(gGradMakers); j++) {
                SkShader* shader = gGradMakers[j](pts, gGradData[i], tm, NULL);
                paint.setShader(shader);
                canvas->drawRect(r, paint);
                shader->unref();
                canvas->translate(0, SkIntToScalar(120));
            }
            canvas->restore();
            canvas->translate(SkIntToScalar(120), 0);
        }
    }

private:
    typedef GM INHERITED;
};

/*
 Inspired by this <canvas> javascript, where we need to detect that we are not
 solving a quadratic equation, but must instead solve a linear (since our X^2
 coefficient is 0)

 ctx.fillStyle = '#f00';
 ctx.fillRect(0, 0, 100, 50);

 var g = ctx.createRadialGradient(-80, 25, 70, 0, 25, 150);
 g.addColorStop(0, '#f00');
 g.addColorStop(0.01, '#0f0');
 g.addColorStop(0.99, '#0f0');
 g.addColorStop(1, '#f00');
 ctx.fillStyle = g;
 ctx.fillRect(0, 0, 100, 50);
 */
class GradientsDegenrate2PointGM : public GM {
public:
    GradientsDegenrate2PointGM() {}

protected:
    SkString onShortName() {
        return SkString("gradients_degenerate_2pt");
    }

	virtual SkISize onISize() { return make_isize(320, 320); }

    void drawBG(SkCanvas* canvas) {
        canvas->drawColor(SK_ColorBLUE);
    }

    virtual void onDraw(SkCanvas* canvas) {
        this->drawBG(canvas);

        SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorGREEN, SK_ColorRED };
        SkScalar pos[] = { 0, SkFloatToScalar(0.01f), SkFloatToScalar(0.99f), SK_Scalar1 };
        SkPoint c0;
        c0.iset(-80, 25);
        SkScalar r0 = SkIntToScalar(70);
        SkPoint c1;
        c1.iset(0, 25);
        SkScalar r1 = SkIntToScalar(150);
        SkShader* s = SkGradientShader::CreateTwoPointRadial(c0, r0, c1, r1, colors,
                                                             pos, SK_ARRAY_COUNT(pos),
                                                             SkShader::kClamp_TileMode);
        SkPaint paint;
        paint.setShader(s)->unref();
        canvas->drawPaint(paint);
    }

private:
    typedef GM INHERITED;
};

/// Tests correctness of *optimized* codepaths in gradients.

class ClampedGradientsGM : public GM {
public:
    ClampedGradientsGM() {}

protected:
    SkString onShortName() { return SkString("clamped_gradients"); }

    virtual SkISize onISize() { return make_isize(640, 510); }

    void drawBG(SkCanvas* canvas) {
        canvas->drawColor(0xFFDDDDDD);
    }

    virtual void onDraw(SkCanvas* canvas) {
        this->drawBG(canvas);

        SkRect r = { 0, 0, SkIntToScalar(100), SkIntToScalar(300) };
        SkPaint paint;
        paint.setAntiAlias(true);

        SkPoint center;
        center.iset(0, 300);
        canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
        SkShader* shader = SkGradientShader::CreateRadial(
            SkPoint(center),
            SkIntToScalar(200), gColors, NULL, 5,
            SkShader::kClamp_TileMode, NULL);
        paint.setShader(shader);
        canvas->drawRect(r, paint);
        shader->unref();
    }

private:
    typedef GM INHERITED;
};

/// Checks quality of large radial gradients, which may display
/// some banding.

class RadialGradientGM : public GM {
public:
    RadialGradientGM() {}

protected:
    SkString onShortName() { return SkString("radial_gradient"); }
    virtual SkISize onISize() { return make_isize(1280, 1280); }
    void drawBG(SkCanvas* canvas) {
        canvas->drawColor(0xFF000000);
    }
    virtual void onDraw(SkCanvas* canvas) {
        const SkISize dim = this->getISize();

        this->drawBG(canvas);

        SkPaint paint;
        paint.setDither(true);
        SkPoint center;
        center.set(SkIntToScalar(dim.width())/2, SkIntToScalar(dim.height())/2);
        SkScalar radius = SkIntToScalar(dim.width())/2;
        const SkColor colors[] = { 0x7f7f7f7f, 0x7f7f7f7f, 0xb2000000 };
        const SkScalar pos[] = { SkFloatToScalar(0.0),
                             SkFloatToScalar(0.35),
                             SkFloatToScalar(1.0) };
        SkShader* shader =
            SkGradientShader::CreateRadial(center, radius, colors,
                                           pos, SK_ARRAY_COUNT(pos),
                                           SkShader::kClamp_TileMode);
        paint.setShader(shader)->unref();
        SkRect r = {
            0, 0, SkIntToScalar(dim.width()), SkIntToScalar(dim.height())
        };
        canvas->drawRect(r, paint);
    }
private:
    typedef GM INHERITED;
};

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

static GM* MyFactory(void*) { return new GradientsGM; }
static GMRegistry reg(MyFactory);

static GM* MyFactory2(void*) { return new GradientsDegenrate2PointGM; }
static GMRegistry reg2(MyFactory2);

static GM* MyFactory3(void*) { return new ClampedGradientsGM; }
static GMRegistry reg3(MyFactory3);

static GM* MyFactory4(void*) { return new RadialGradientGM; }
static GMRegistry reg4(MyFactory4);
}

<|endoftext|>