<commit_before>// Scintilla source code edit control
/** @file LexCPP.cxx
 ** Lexer for C++, C, Java, and Javascript.
 **/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// 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"

static bool IsOKBeforeRE(const int ch) {
	return (ch == '(') || (ch == '=') || (ch == ',');
}

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

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

inline bool IsADoxygenChar(const int ch) {
	return (islower(ch) || ch == '$' || ch == '@' ||
		    ch == '\\' || ch == '&' || ch == '<' ||
			ch == '>' || ch == '#' || ch == '{' ||
			ch == '}' || ch == '[' || ch == ']');
}

inline bool IsStateComment(const int state) {
	return ((state == SCE_C_COMMENT) ||
		      (state == SCE_C_COMMENTLINE) ||
		      (state == SCE_C_COMMENTDOC) ||
		      (state == SCE_C_COMMENTDOCKEYWORD) ||
		      (state == SCE_C_COMMENTDOCKEYWORDERROR));
}

inline bool IsStateString(const int state) {
	return ((state == SCE_C_STRING) || (state == SCE_C_VERBATIM));
}

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

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

	bool stylingWithinPreprocessor = styler.GetPropertyInt("styling.within.preprocessor");

	// Do not leak onto next line
	if (initStyle == SCE_C_STRINGEOL)
		initStyle = SCE_C_DEFAULT;

	int chPrevNonWhite = ' ';
	int visibleChars = 0;
	int noDocChars = 0;
	bool lastWordWasUUID = false;

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

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

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

		// Determine if the current state should terminate.
		if (sc.state == SCE_C_OPERATOR) {
			sc.SetState(SCE_C_DEFAULT);
		} else if (sc.state == SCE_C_NUMBER) {
			if (!IsAWordChar(sc.ch)) {
				sc.SetState(SCE_C_DEFAULT);
			}
		} else if (sc.state == SCE_C_IDENTIFIER) {
			if (!IsAWordChar(sc.ch) || (sc.ch == '.')) {
				char s[100];
				sc.GetCurrent(s, sizeof(s));
				if (keywords.InList(s)) {
					lastWordWasUUID = strcmp(s, "uuid") == 0;
					sc.ChangeState(SCE_C_WORD);
				} else if (keywords2.InList(s)) {
					sc.ChangeState(SCE_C_WORD2);
				}
				sc.SetState(SCE_C_DEFAULT);
			}
		} else if (sc.state == SCE_C_PREPROCESSOR) {
			if (stylingWithinPreprocessor) {
				if (IsASpace(sc.ch)) {
					sc.SetState(SCE_C_DEFAULT);
				}
			} else {
				if (sc.atLineEnd) {
					sc.SetState(SCE_C_DEFAULT);
				}
			}
		} else if (sc.state == SCE_C_COMMENT) {
			if (sc.Match('*', '/')) {
				sc.Forward();
				sc.ForwardSetState(SCE_C_DEFAULT);
			}
		} else if (sc.state == SCE_C_COMMENTDOC) {
			if (sc.Match('*', '/')) {
				sc.Forward();
				sc.ForwardSetState(SCE_C_DEFAULT);
			} else if ((sc.ch == '@' || sc.ch == '\\') && (noDocChars == 0)) {
				sc.SetState(SCE_C_COMMENTDOCKEYWORD);
			} else if (sc.atLineEnd) {
				noDocChars = 0;
			} else if (!isspace(sc.ch) && (sc.ch != '*')) {
				noDocChars++;
			}
		} else if (sc.state == SCE_C_COMMENTLINE || sc.state == SCE_C_COMMENTLINEDOC) {
			if (sc.atLineEnd) {
				sc.SetState(SCE_C_DEFAULT);
				visibleChars = 0;
			}
		} else if (sc.state == SCE_C_COMMENTDOCKEYWORD) {
			if (sc.Match('*', '/')) {
				sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR);
				sc.Forward();
				sc.ForwardSetState(SCE_C_DEFAULT);
			} else if (!IsADoxygenChar(sc.ch)) {
				char s[100];
				sc.GetCurrent(s, sizeof(s));
				if (!isspace(sc.ch) || !keywords3.InList(s+1)) {
					sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR);
				}
				sc.SetState(SCE_C_COMMENTDOC);
			}
		} else if (sc.state == SCE_C_STRING) {
			if (sc.ch == '\\') {
				if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
					sc.Forward();
				}
			} else if (sc.ch == '\"') {
				sc.ForwardSetState(SCE_C_DEFAULT);
			} else if (sc.atLineEnd) {
				sc.ChangeState(SCE_C_STRINGEOL);
				sc.ForwardSetState(SCE_C_DEFAULT);
				visibleChars = 0;
			}
		} else if (sc.state == SCE_C_CHARACTER) {
			if (sc.atLineEnd) {
				sc.ChangeState(SCE_C_STRINGEOL);
				sc.ForwardSetState(SCE_C_DEFAULT);
				visibleChars = 0;
			} else if (sc.ch == '\\') {
				if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
					sc.Forward();
				}
			} else if (sc.ch == '\'') {
				sc.ForwardSetState(SCE_C_DEFAULT);
			}
		} else if (sc.state == SCE_C_REGEX) {
			if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == '/') {
				sc.ForwardSetState(SCE_C_DEFAULT);
			} else if (sc.ch == '\\') {
				// Gobble up the quoted character
				if (sc.chNext == '\\' || sc.chNext == '/') {
					sc.Forward();
				}
			}
		} else if (sc.state == SCE_C_VERBATIM) {
			if (sc.ch == '\"') {
				if (sc.chNext == '\"') {
					sc.Forward();
				} else {
					sc.ForwardSetState(SCE_C_DEFAULT);
				}
			}
		} else if (sc.state == SCE_C_UUID) {
			if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ')') {
				sc.SetState(SCE_C_DEFAULT);
			}
		}

		// Determine if a new state should be entered.
		if (sc.state == SCE_C_DEFAULT) {
			if (sc.Match('@', '\"')) {
				sc.SetState(SCE_C_VERBATIM);
				sc.Forward();
			} else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
				if (lastWordWasUUID) {
					sc.SetState(SCE_C_UUID);
					lastWordWasUUID = false;
				} else {
					sc.SetState(SCE_C_NUMBER);
				}
			} else if (IsAWordStart(sc.ch) || (sc.ch == '@')) {
				if (lastWordWasUUID) {
					sc.SetState(SCE_C_UUID);
					lastWordWasUUID = false;
				} else {
					sc.SetState(SCE_C_IDENTIFIER);
				}
			} else if (sc.Match('/', '*')) {
				if (sc.Match("/**") || sc.Match("/*!")) {	// Support of Qt/Doxygen doc. style
					noDocChars = 0;
					sc.SetState(SCE_C_COMMENTDOC);
				} else {
					sc.SetState(SCE_C_COMMENT);
				}
				sc.Forward();	// Eat the * so it isn't used for the end of the comment
			} else if (sc.Match('/', '/')) {
				if (sc.Match("///") || sc.Match("//!"))	// Support of Qt/Doxygen doc. style
					sc.SetState(SCE_C_COMMENTLINEDOC);
				else
					sc.SetState(SCE_C_COMMENTLINE);
			} else if (sc.ch == '/' && IsOKBeforeRE(chPrevNonWhite)) {
				sc.SetState(SCE_C_REGEX);
			} else if (sc.ch == '\"') {
				sc.SetState(SCE_C_STRING);
			} else if (sc.ch == '\'') {
				sc.SetState(SCE_C_CHARACTER);
			} else if (sc.ch == '#' && visibleChars == 0) {
				// Preprocessor commands are alone on their line
				sc.SetState(SCE_C_PREPROCESSOR);
				// Skip whitespace between # and preprocessor word
				do {
					sc.Forward();
				} while ((sc.ch == ' ') && (sc.ch == '\t') && sc.More());
				if (sc.atLineEnd) {
					sc.SetState(SCE_C_DEFAULT);
				}
			} else if (isoperator(static_cast<char>(sc.ch))) {
				sc.SetState(SCE_C_OPERATOR);
			}
		}

		if (sc.atLineEnd) {
			// Reset states to begining of colourise so no surprises
			// if different sets of lines lexed.
			chPrevNonWhite = ' ';
			visibleChars = 0;
			lastWordWasUUID = false;
		}
		if (!IsASpace(sc.ch)) {
			chPrevNonWhite = sc.ch;
			visibleChars++;
		}
	}
	sc.Complete();
}

static void FoldCppDoc(unsigned int startPos, int length, int initStyle, WordList *[],
                            Accessor &styler) {
	bool foldComment = styler.GetPropertyInt("fold.comment");
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1);
	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 &&
			(style == SCE_C_COMMENT || style == SCE_C_COMMENTDOC)) {
			if (style != stylePrev) {
				levelCurrent++;
			} else if ((style != styleNext) && !atEOL) {
				// Comments don't end at end of line and the next character may be unstyled.
				levelCurrent--;
			}
		}
		if (style == SCE_C_OPERATOR) {
			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);
}

LexerModule lmCPP(SCLEX_CPP, ColouriseCppDoc, "cpp", FoldCppDoc);
LexerModule lmTCL(SCLEX_TCL, ColouriseCppDoc, "tcl", FoldCppDoc);
<commit_msg>Patch from Philippe to make doc comment keywords work throughout doc comments.<commit_after>// Scintilla source code edit control
/** @file LexCPP.cxx
 ** Lexer for C++, C, Java, and Javascript.
 **/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// 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"

static bool IsOKBeforeRE(const int ch) {
	return (ch == '(') || (ch == '=') || (ch == ',');
}

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

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

inline bool IsADoxygenChar(const int ch) {
	return (islower(ch) || ch == '$' || ch == '@' ||
		    ch == '\\' || ch == '&' || ch == '<' ||
			ch == '>' || ch == '#' || ch == '{' ||
			ch == '}' || ch == '[' || ch == ']');
}

inline bool IsStateComment(const int state) {
	return ((state == SCE_C_COMMENT) ||
		      (state == SCE_C_COMMENTLINE) ||
		      (state == SCE_C_COMMENTDOC) ||
		      (state == SCE_C_COMMENTDOCKEYWORD) ||
		      (state == SCE_C_COMMENTDOCKEYWORDERROR));
}

inline bool IsStateString(const int state) {
	return ((state == SCE_C_STRING) || (state == SCE_C_VERBATIM));
}

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

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

	bool stylingWithinPreprocessor = styler.GetPropertyInt("styling.within.preprocessor");

	// Do not leak onto next line
	if (initStyle == SCE_C_STRINGEOL)
		initStyle = SCE_C_DEFAULT;

	int chPrevNonWhite = ' ';
	int visibleChars = 0;
	bool lastWordWasUUID = false;

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

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

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

		// Determine if the current state should terminate.
		if (sc.state == SCE_C_OPERATOR) {
			sc.SetState(SCE_C_DEFAULT);
		} else if (sc.state == SCE_C_NUMBER) {
			if (!IsAWordChar(sc.ch)) {
				sc.SetState(SCE_C_DEFAULT);
			}
		} else if (sc.state == SCE_C_IDENTIFIER) {
			if (!IsAWordChar(sc.ch) || (sc.ch == '.')) {
				char s[100];
				sc.GetCurrent(s, sizeof(s));
				if (keywords.InList(s)) {
					lastWordWasUUID = strcmp(s, "uuid") == 0;
					sc.ChangeState(SCE_C_WORD);
				} else if (keywords2.InList(s)) {
					sc.ChangeState(SCE_C_WORD2);
				}
				sc.SetState(SCE_C_DEFAULT);
			}
		} else if (sc.state == SCE_C_PREPROCESSOR) {
			if (stylingWithinPreprocessor) {
				if (IsASpace(sc.ch)) {
					sc.SetState(SCE_C_DEFAULT);
				}
			} else {
				if (sc.atLineEnd) {
					sc.SetState(SCE_C_DEFAULT);
				}
			}
		} else if (sc.state == SCE_C_COMMENT) {
			if (sc.Match('*', '/')) {
				sc.Forward();
				sc.ForwardSetState(SCE_C_DEFAULT);
			}
		} else if (sc.state == SCE_C_COMMENTDOC) {
			if (sc.Match('*', '/')) {
				sc.Forward();
				sc.ForwardSetState(SCE_C_DEFAULT);
			} else if (sc.ch == '@' || sc.ch == '\\') {
				sc.SetState(SCE_C_COMMENTDOCKEYWORD);
			}
		} else if (sc.state == SCE_C_COMMENTLINE || sc.state == SCE_C_COMMENTLINEDOC) {
			if (sc.atLineEnd) {
				sc.SetState(SCE_C_DEFAULT);
				visibleChars = 0;
			}
		} else if (sc.state == SCE_C_COMMENTDOCKEYWORD) {
			if (sc.Match('*', '/')) {
				sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR);
				sc.Forward();
				sc.ForwardSetState(SCE_C_DEFAULT);
			} else if (!IsADoxygenChar(sc.ch)) {
				char s[100];
				sc.GetCurrent(s, sizeof(s));
				if (!isspace(sc.ch) || !keywords3.InList(s+1)) {
					sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR);
				}
				sc.SetState(SCE_C_COMMENTDOC);
			}
		} else if (sc.state == SCE_C_STRING) {
			if (sc.ch == '\\') {
				if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
					sc.Forward();
				}
			} else if (sc.ch == '\"') {
				sc.ForwardSetState(SCE_C_DEFAULT);
			} else if (sc.atLineEnd) {
				sc.ChangeState(SCE_C_STRINGEOL);
				sc.ForwardSetState(SCE_C_DEFAULT);
				visibleChars = 0;
			}
		} else if (sc.state == SCE_C_CHARACTER) {
			if (sc.atLineEnd) {
				sc.ChangeState(SCE_C_STRINGEOL);
				sc.ForwardSetState(SCE_C_DEFAULT);
				visibleChars = 0;
			} else if (sc.ch == '\\') {
				if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
					sc.Forward();
				}
			} else if (sc.ch == '\'') {
				sc.ForwardSetState(SCE_C_DEFAULT);
			}
		} else if (sc.state == SCE_C_REGEX) {
			if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == '/') {
				sc.ForwardSetState(SCE_C_DEFAULT);
			} else if (sc.ch == '\\') {
				// Gobble up the quoted character
				if (sc.chNext == '\\' || sc.chNext == '/') {
					sc.Forward();
				}
			}
		} else if (sc.state == SCE_C_VERBATIM) {
			if (sc.ch == '\"') {
				if (sc.chNext == '\"') {
					sc.Forward();
				} else {
					sc.ForwardSetState(SCE_C_DEFAULT);
				}
			}
		} else if (sc.state == SCE_C_UUID) {
			if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ')') {
				sc.SetState(SCE_C_DEFAULT);
			}
		}

		// Determine if a new state should be entered.
		if (sc.state == SCE_C_DEFAULT) {
			if (sc.Match('@', '\"')) {
				sc.SetState(SCE_C_VERBATIM);
				sc.Forward();
			} else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
				if (lastWordWasUUID) {
					sc.SetState(SCE_C_UUID);
					lastWordWasUUID = false;
				} else {
					sc.SetState(SCE_C_NUMBER);
				}
			} else if (IsAWordStart(sc.ch) || (sc.ch == '@')) {
				if (lastWordWasUUID) {
					sc.SetState(SCE_C_UUID);
					lastWordWasUUID = false;
				} else {
					sc.SetState(SCE_C_IDENTIFIER);
				}
			} else if (sc.Match('/', '*')) {
				if (sc.Match("/**") || sc.Match("/*!")) {	// Support of Qt/Doxygen doc. style
					sc.SetState(SCE_C_COMMENTDOC);
				} else {
					sc.SetState(SCE_C_COMMENT);
				}
				sc.Forward();	// Eat the * so it isn't used for the end of the comment
			} else if (sc.Match('/', '/')) {
				if (sc.Match("///") || sc.Match("//!"))	// Support of Qt/Doxygen doc. style
					sc.SetState(SCE_C_COMMENTLINEDOC);
				else
					sc.SetState(SCE_C_COMMENTLINE);
			} else if (sc.ch == '/' && IsOKBeforeRE(chPrevNonWhite)) {
				sc.SetState(SCE_C_REGEX);
			} else if (sc.ch == '\"') {
				sc.SetState(SCE_C_STRING);
			} else if (sc.ch == '\'') {
				sc.SetState(SCE_C_CHARACTER);
			} else if (sc.ch == '#' && visibleChars == 0) {
				// Preprocessor commands are alone on their line
				sc.SetState(SCE_C_PREPROCESSOR);
				// Skip whitespace between # and preprocessor word
				do {
					sc.Forward();
				} while ((sc.ch == ' ') && (sc.ch == '\t') && sc.More());
				if (sc.atLineEnd) {
					sc.SetState(SCE_C_DEFAULT);
				}
			} else if (isoperator(static_cast<char>(sc.ch))) {
				sc.SetState(SCE_C_OPERATOR);
			}
		}

		if (sc.atLineEnd) {
			// Reset states to begining of colourise so no surprises
			// if different sets of lines lexed.
			chPrevNonWhite = ' ';
			visibleChars = 0;
			lastWordWasUUID = false;
		}
		if (!IsASpace(sc.ch)) {
			chPrevNonWhite = sc.ch;
			visibleChars++;
		}
	}
	sc.Complete();
}

static void FoldCppDoc(unsigned int startPos, int length, int initStyle, WordList *[],
                            Accessor &styler) {
	bool foldComment = styler.GetPropertyInt("fold.comment");
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1);
	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 &&
			(style == SCE_C_COMMENT || style == SCE_C_COMMENTDOC)) {
			if (style != stylePrev) {
				levelCurrent++;
			} else if ((style != styleNext) && !atEOL) {
				// Comments don't end at end of line and the next character may be unstyled.
				levelCurrent--;
			}
		}
		if (style == SCE_C_OPERATOR) {
			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);
}

LexerModule lmCPP(SCLEX_CPP, ColouriseCppDoc, "cpp", FoldCppDoc);
LexerModule lmTCL(SCLEX_TCL, ColouriseCppDoc, "tcl", FoldCppDoc);
<|endoftext|>


<commit_before>#pragma once

#include "ExecutorBase.hpp"

#include "ExecutorSingleTree.hpp"
#include "ExecutorDualTree.hpp"

#include "EvalUpward.hpp"
#include "EvalInteraction.hpp"
#include "EvalInteractionQueue.hpp"
#include "EvalInteractionLazy.hpp"
#include "EvalDownward.hpp"

#include "Octree.hpp"

template <typename Kernel,
	  typename SourceIter,
	  typename Options>
ExecutorBase<Kernel>* make_executor(const Kernel& K,
				    SourceIter first, SourceIter last,
				    Options& opts) {
  typedef Octree<typename Kernel::point_type> Tree;

  auto executor = make_executor<Tree>(K, first, last, opts);

  auto upward = make_upward(*executor, opts);
  executor->insert_eval(upward);
  auto inter = make_interact(*executor, opts);
  executor->insert_eval(inter);
  auto downward = make_downward(*executor, opts);
  executor->insert_eval(downward);

  return executor;
}

template <typename Kernel,
	  typename SourceIter, typename TargetIter,
	  typename Options>
ExecutorBase<Kernel>* make_executor(const Kernel& K,
				    SourceIter sfirst, SourceIter slast,
				    TargetIter tfirst, TargetIter tlast,
				    Options& opts) {
  typedef Octree<typename Kernel::point_type> Tree;

  auto executor = make_executor<Tree>(K,
				      sfirst, slast,
				      tfirst, tlast, opts);

  auto upward = make_upward(*executor, opts);
  executor->insert_eval(upward);
  auto inter = make_interact(*executor, opts);
  executor->insert_eval(inter);
  auto downward = make_downward(*executor, opts);
  executor->insert_eval(downward);

  return executor;
}
<commit_msg>make_evaluators<commit_after>#pragma once

#include "ExecutorBase.hpp"

#include "ExecutorSingleTree.hpp"
#include "ExecutorDualTree.hpp"

#include "EvalUpward.hpp"
#include "EvalInteraction.hpp"
#include "EvalInteractionQueue.hpp"
#include "EvalInteractionLazy.hpp"
#include "EvalDownward.hpp"

#include "Octree.hpp"

template <typename Executor, typename Options>
void make_evaluators(Executor& executor, Options& opts)
{
  auto upward = make_upward(executor, opts);
  executor.insert_eval(upward);
  auto inter = make_interact(executor, opts);
  executor.insert_eval(inter);
  auto downward = make_downward(executor, opts);
  executor.insert_eval(downward);
}

template <typename Kernel,
	  typename SourceIter,
	  typename Options>
ExecutorBase<Kernel>* make_executor(const Kernel& K,
				    SourceIter first, SourceIter last,
				    Options& opts) {
  typedef Octree<typename Kernel::point_type> Tree;

  auto executor = make_executor<Tree>(K, first, last, opts);
  make_evaluators(*executor, opts);

  return executor;
}

template <typename Kernel,
	  typename SourceIter, typename TargetIter,
	  typename Options>
ExecutorBase<Kernel>* make_executor(const Kernel& K,
				    SourceIter sfirst, SourceIter slast,
				    TargetIter tfirst, TargetIter tlast,
				    Options& opts) {
  typedef Octree<typename Kernel::point_type> Tree;

  auto executor = make_executor<Tree>(K,
				      sfirst, slast,
				      tfirst, tlast, opts);
  make_evaluators(*executor, opts);

  return executor;
}
<|endoftext|>


<commit_before>/**
 ******************************************************************************
 * Xenia : Xbox 360 Emulator Research Project                                 *
 ******************************************************************************
 * Copyright 2013 Ben Vanik. All rights reserved.                             *
 * Released under the BSD license - see LICENSE in the root for more details. *
 ******************************************************************************
 */

#include "xenia/kernel/xobject.h"

#include "xenia/kernel/xboxkrnl_private.h"
#include "xenia/kernel/objects/xevent.h"
#include "xenia/kernel/objects/xmutant.h"
#include "xenia/kernel/objects/xsemaphore.h"

namespace xe {
namespace kernel {

XObject::XObject(KernelState* kernel_state, Type type)
    : kernel_state_(kernel_state),
      handle_ref_count_(0),
      pointer_ref_count_(1),
      type_(type),
      handle_(X_INVALID_HANDLE_VALUE) {
  // Added pointer check to support usage without a kernel_state
  if (kernel_state != nullptr) {
    kernel_state->object_table()->AddHandle(this, &handle_);
  }
}

XObject::~XObject() {
  assert_zero(handle_ref_count_);
  assert_zero(pointer_ref_count_);
}

XObject::Type XObject::type() { return type_; }

X_HANDLE XObject::handle() const { return handle_; }

void XObject::RetainHandle() { ++handle_ref_count_; }

bool XObject::ReleaseHandle() {
  if (--handle_ref_count_ == 0) {
    return true;
  }
  return false;
}

void XObject::Retain() { ++pointer_ref_count_; }

void XObject::Release() {
  if (--pointer_ref_count_ == 0) {
    assert_true(pointer_ref_count_ >= handle_ref_count_);
    delete this;
  }
}

X_STATUS XObject::Delete() {
  if (kernel_state_ == nullptr) {
    // Fake return value for api-scanner
    return X_STATUS_SUCCESS;
  } else {
    if (!name_.empty()) {
      kernel_state_->object_table()->RemoveNameMapping(name_);
    }
    return kernel_state_->object_table()->RemoveHandle(handle_);
  }
}

void XObject::SetAttributes(const uint8_t* obj_attrs_ptr) {
  if (!obj_attrs_ptr) {
    return;
  }

  uint32_t name_str_ptr = xe::load_and_swap<uint32_t>(obj_attrs_ptr + 4);
  if (name_str_ptr) {
    X_ANSI_STRING name_str(memory()->virtual_membase(), name_str_ptr);
    name_ = name_str.to_string();
    kernel_state_->object_table()->AddNameMapping(name_, handle_);
  }
}

uint32_t XObject::TimeoutTicksToMs(int64_t timeout_ticks) {
  if (timeout_ticks > 0) {
    // Absolute time, based on January 1, 1601.
    // TODO(benvanik): convert time to relative time.
    assert_always();
    return 0;
  } else if (timeout_ticks < 0) {
    // Relative time.
    return (uint32_t)(-timeout_ticks / 10000);  // Ticks -> MS
  } else {
    return 0;
  }
}

X_STATUS XObject::Wait(uint32_t wait_reason, uint32_t processor_mode,
                       uint32_t alertable, uint64_t* opt_timeout) {
  void* wait_handle = GetWaitHandle();
  if (!wait_handle) {
    // Object doesn't support waiting.
    return X_STATUS_SUCCESS;
  }

  DWORD timeout_ms = opt_timeout ? TimeoutTicksToMs(*opt_timeout) : INFINITE;

  DWORD result = WaitForSingleObjectEx(wait_handle, timeout_ms, alertable);
  switch (result) {
    case WAIT_OBJECT_0:
      return X_STATUS_SUCCESS;
    case WAIT_IO_COMPLETION:
      // Or X_STATUS_ALERTED?
      return X_STATUS_USER_APC;
    case WAIT_TIMEOUT:
      YieldProcessor();
      return X_STATUS_TIMEOUT;
    default:
    case WAIT_FAILED:
    case WAIT_ABANDONED:
      return X_STATUS_ABANDONED_WAIT_0;
  }
}

X_STATUS XObject::SignalAndWait(XObject* signal_object, XObject* wait_object,
                                uint32_t wait_reason, uint32_t processor_mode,
                                uint32_t alertable, uint64_t* opt_timeout) {
  DWORD timeout_ms = opt_timeout ? TimeoutTicksToMs(*opt_timeout) : INFINITE;

  DWORD result = SignalObjectAndWait(signal_object->GetWaitHandle(),
                                     wait_object->GetWaitHandle(), timeout_ms,
                                     alertable ? TRUE : FALSE);

  return result;
}

X_STATUS XObject::WaitMultiple(uint32_t count, XObject** objects,
                               uint32_t wait_type, uint32_t wait_reason,
                               uint32_t processor_mode, uint32_t alertable,
                               uint64_t* opt_timeout) {
  void** wait_handles = (void**)alloca(sizeof(void*) * count);
  for (uint32_t n = 0; n < count; n++) {
    wait_handles[n] = objects[n]->GetWaitHandle();
    assert_not_null(wait_handles[n]);
  }

  DWORD timeout_ms = opt_timeout ? TimeoutTicksToMs(*opt_timeout) : INFINITE;

  DWORD result = WaitForMultipleObjectsEx(
      count, wait_handles, wait_type ? FALSE : TRUE, timeout_ms, alertable);

  return result;
}

void XObject::SetNativePointer(uint32_t native_ptr, bool uninitialized) {
  std::lock_guard<std::recursive_mutex> lock(kernel_state_->object_mutex());

  auto header =
      kernel_state_->memory()->TranslateVirtual<DISPATCH_HEADER*>(native_ptr);

  // Memory uninitialized, so don't bother with the check.
  if (!uninitialized) {
    assert_true(!(header->wait_list_blink & 0x1));
  }

  // Stash pointer in struct.
  uint64_t object_ptr = reinterpret_cast<uint64_t>(this);
  object_ptr |= 0x1;
  header->wait_list_flink = (uint32_t)(object_ptr >> 32);
  header->wait_list_blink = (uint32_t)(object_ptr & 0xFFFFFFFF);
}

XObject* XObject::GetObject(KernelState* kernel_state, void* native_ptr,
                            int32_t as_type) {
  // Unfortunately the XDK seems to inline some KeInitialize calls, meaning
  // we never see it and just randomly start getting passed events/timers/etc.
  // Luckily it seems like all other calls (Set/Reset/Wait/etc) are used and
  // we don't have to worry about PPC code poking the struct. Because of that,
  // we init on first use, store our pointer in the struct, and dereference it
  // each time.
  // We identify this by checking the low bit of wait_list_blink - if it's 1,
  // we have already put our pointer in there.

  std::lock_guard<std::recursive_mutex> lock(kernel_state->object_mutex());

  auto header = reinterpret_cast<DISPATCH_HEADER*>(native_ptr);

  if (as_type == -1) {
    as_type = (header->type_flags >> 24) & 0xFF;
  }

  if (header->wait_list_blink & 0x1) {
    // Already initialized.
    uint64_t object_ptr = ((uint64_t)header->wait_list_flink << 32) |
                          ((header->wait_list_blink) & ~0x1);
    XObject* object = reinterpret_cast<XObject*>(object_ptr);
    // TODO(benvanik): assert nothing has been changed in the struct.
    return object;
  } else {
    // First use, create new.
    // http://www.nirsoft.net/kernel_struct/vista/KOBJECTS.html
    XObject* object = NULL;
    switch (as_type) {
      case 0:  // EventNotificationObject
      case 1:  // EventSynchronizationObject
      {
        XEvent* ev = new XEvent(kernel_state);
        ev->InitializeNative(native_ptr, *header);
        object = ev;
      } break;
      case 2:  // MutantObject
      {
        XMutant* mutant = new XMutant(kernel_state);
        mutant->InitializeNative(native_ptr, *header);
        object = mutant;
      } break;
      case 5:  // SemaphoreObject
      {
        XSemaphore* sem = new XSemaphore(kernel_state);
        sem->InitializeNative(native_ptr, *header);
        object = sem;
      } break;
      case 3:   // ProcessObject
      case 4:   // QueueObject
      case 6:   // ThreadObject
      case 7:   // GateObject
      case 8:   // TimerNotificationObject
      case 9:   // TimerSynchronizationObject
      case 18:  // ApcObject
      case 19:  // DpcObject
      case 20:  // DeviceQueueObject
      case 21:  // EventPairObject
      case 22:  // InterruptObject
      case 23:  // ProfileObject
      case 24:  // ThreadedDpcObject
      default:
        assert_always();
        return NULL;
    }

    // Stash pointer in struct.
    uint64_t object_ptr = reinterpret_cast<uint64_t>(object);
    object_ptr |= 0x1;
    header->wait_list_flink = (uint32_t)(object_ptr >> 32);
    header->wait_list_blink = (uint32_t)(object_ptr & 0xFFFFFFFF);

    return object;
  }
}

}  // namespace kernel
}  // namespace xe
<commit_msg>Added an assert_not_null for native_ptr in XObject::GetObject.<commit_after>/**
 ******************************************************************************
 * Xenia : Xbox 360 Emulator Research Project                                 *
 ******************************************************************************
 * Copyright 2013 Ben Vanik. All rights reserved.                             *
 * Released under the BSD license - see LICENSE in the root for more details. *
 ******************************************************************************
 */

#include "xenia/kernel/xobject.h"

#include "xenia/kernel/xboxkrnl_private.h"
#include "xenia/kernel/objects/xevent.h"
#include "xenia/kernel/objects/xmutant.h"
#include "xenia/kernel/objects/xsemaphore.h"

namespace xe {
namespace kernel {

XObject::XObject(KernelState* kernel_state, Type type)
    : kernel_state_(kernel_state),
      handle_ref_count_(0),
      pointer_ref_count_(1),
      type_(type),
      handle_(X_INVALID_HANDLE_VALUE) {
  // Added pointer check to support usage without a kernel_state
  if (kernel_state != nullptr) {
    kernel_state->object_table()->AddHandle(this, &handle_);
  }
}

XObject::~XObject() {
  assert_zero(handle_ref_count_);
  assert_zero(pointer_ref_count_);
}

XObject::Type XObject::type() { return type_; }

X_HANDLE XObject::handle() const { return handle_; }

void XObject::RetainHandle() { ++handle_ref_count_; }

bool XObject::ReleaseHandle() {
  if (--handle_ref_count_ == 0) {
    return true;
  }
  return false;
}

void XObject::Retain() { ++pointer_ref_count_; }

void XObject::Release() {
  if (--pointer_ref_count_ == 0) {
    assert_true(pointer_ref_count_ >= handle_ref_count_);
    delete this;
  }
}

X_STATUS XObject::Delete() {
  if (kernel_state_ == nullptr) {
    // Fake return value for api-scanner
    return X_STATUS_SUCCESS;
  } else {
    if (!name_.empty()) {
      kernel_state_->object_table()->RemoveNameMapping(name_);
    }
    return kernel_state_->object_table()->RemoveHandle(handle_);
  }
}

void XObject::SetAttributes(const uint8_t* obj_attrs_ptr) {
  if (!obj_attrs_ptr) {
    return;
  }

  uint32_t name_str_ptr = xe::load_and_swap<uint32_t>(obj_attrs_ptr + 4);
  if (name_str_ptr) {
    X_ANSI_STRING name_str(memory()->virtual_membase(), name_str_ptr);
    name_ = name_str.to_string();
    kernel_state_->object_table()->AddNameMapping(name_, handle_);
  }
}

uint32_t XObject::TimeoutTicksToMs(int64_t timeout_ticks) {
  if (timeout_ticks > 0) {
    // Absolute time, based on January 1, 1601.
    // TODO(benvanik): convert time to relative time.
    assert_always();
    return 0;
  } else if (timeout_ticks < 0) {
    // Relative time.
    return (uint32_t)(-timeout_ticks / 10000);  // Ticks -> MS
  } else {
    return 0;
  }
}

X_STATUS XObject::Wait(uint32_t wait_reason, uint32_t processor_mode,
                       uint32_t alertable, uint64_t* opt_timeout) {
  void* wait_handle = GetWaitHandle();
  if (!wait_handle) {
    // Object doesn't support waiting.
    return X_STATUS_SUCCESS;
  }

  DWORD timeout_ms = opt_timeout ? TimeoutTicksToMs(*opt_timeout) : INFINITE;

  DWORD result = WaitForSingleObjectEx(wait_handle, timeout_ms, alertable);
  switch (result) {
    case WAIT_OBJECT_0:
      return X_STATUS_SUCCESS;
    case WAIT_IO_COMPLETION:
      // Or X_STATUS_ALERTED?
      return X_STATUS_USER_APC;
    case WAIT_TIMEOUT:
      YieldProcessor();
      return X_STATUS_TIMEOUT;
    default:
    case WAIT_FAILED:
    case WAIT_ABANDONED:
      return X_STATUS_ABANDONED_WAIT_0;
  }
}

X_STATUS XObject::SignalAndWait(XObject* signal_object, XObject* wait_object,
                                uint32_t wait_reason, uint32_t processor_mode,
                                uint32_t alertable, uint64_t* opt_timeout) {
  DWORD timeout_ms = opt_timeout ? TimeoutTicksToMs(*opt_timeout) : INFINITE;

  DWORD result = SignalObjectAndWait(signal_object->GetWaitHandle(),
                                     wait_object->GetWaitHandle(), timeout_ms,
                                     alertable ? TRUE : FALSE);

  return result;
}

X_STATUS XObject::WaitMultiple(uint32_t count, XObject** objects,
                               uint32_t wait_type, uint32_t wait_reason,
                               uint32_t processor_mode, uint32_t alertable,
                               uint64_t* opt_timeout) {
  void** wait_handles = (void**)alloca(sizeof(void*) * count);
  for (uint32_t n = 0; n < count; n++) {
    wait_handles[n] = objects[n]->GetWaitHandle();
    assert_not_null(wait_handles[n]);
  }

  DWORD timeout_ms = opt_timeout ? TimeoutTicksToMs(*opt_timeout) : INFINITE;

  DWORD result = WaitForMultipleObjectsEx(
      count, wait_handles, wait_type ? FALSE : TRUE, timeout_ms, alertable);

  return result;
}

void XObject::SetNativePointer(uint32_t native_ptr, bool uninitialized) {
  std::lock_guard<std::recursive_mutex> lock(kernel_state_->object_mutex());

  auto header =
      kernel_state_->memory()->TranslateVirtual<DISPATCH_HEADER*>(native_ptr);

  // Memory uninitialized, so don't bother with the check.
  if (!uninitialized) {
    assert_true(!(header->wait_list_blink & 0x1));
  }

  // Stash pointer in struct.
  uint64_t object_ptr = reinterpret_cast<uint64_t>(this);
  object_ptr |= 0x1;
  header->wait_list_flink = (uint32_t)(object_ptr >> 32);
  header->wait_list_blink = (uint32_t)(object_ptr & 0xFFFFFFFF);
}

XObject* XObject::GetObject(KernelState* kernel_state, void* native_ptr,
                            int32_t as_type) {
  assert_not_null(native_ptr);

  // Unfortunately the XDK seems to inline some KeInitialize calls, meaning
  // we never see it and just randomly start getting passed events/timers/etc.
  // Luckily it seems like all other calls (Set/Reset/Wait/etc) are used and
  // we don't have to worry about PPC code poking the struct. Because of that,
  // we init on first use, store our pointer in the struct, and dereference it
  // each time.
  // We identify this by checking the low bit of wait_list_blink - if it's 1,
  // we have already put our pointer in there.

  std::lock_guard<std::recursive_mutex> lock(kernel_state->object_mutex());

  auto header = reinterpret_cast<DISPATCH_HEADER*>(native_ptr);

  if (as_type == -1) {
    as_type = (header->type_flags >> 24) & 0xFF;
  }

  if (header->wait_list_blink & 0x1) {
    // Already initialized.
    uint64_t object_ptr = ((uint64_t)header->wait_list_flink << 32) |
                          ((header->wait_list_blink) & ~0x1);
    XObject* object = reinterpret_cast<XObject*>(object_ptr);
    // TODO(benvanik): assert nothing has been changed in the struct.
    return object;
  } else {
    // First use, create new.
    // http://www.nirsoft.net/kernel_struct/vista/KOBJECTS.html
    XObject* object = NULL;
    switch (as_type) {
      case 0:  // EventNotificationObject
      case 1:  // EventSynchronizationObject
      {
        XEvent* ev = new XEvent(kernel_state);
        ev->InitializeNative(native_ptr, *header);
        object = ev;
      } break;
      case 2:  // MutantObject
      {
        XMutant* mutant = new XMutant(kernel_state);
        mutant->InitializeNative(native_ptr, *header);
        object = mutant;
      } break;
      case 5:  // SemaphoreObject
      {
        XSemaphore* sem = new XSemaphore(kernel_state);
        sem->InitializeNative(native_ptr, *header);
        object = sem;
      } break;
      case 3:   // ProcessObject
      case 4:   // QueueObject
      case 6:   // ThreadObject
      case 7:   // GateObject
      case 8:   // TimerNotificationObject
      case 9:   // TimerSynchronizationObject
      case 18:  // ApcObject
      case 19:  // DpcObject
      case 20:  // DeviceQueueObject
      case 21:  // EventPairObject
      case 22:  // InterruptObject
      case 23:  // ProfileObject
      case 24:  // ThreadedDpcObject
      default:
        assert_always();
        return NULL;
    }

    // Stash pointer in struct.
    uint64_t object_ptr = reinterpret_cast<uint64_t>(object);
    object_ptr |= 0x1;
    header->wait_list_flink = (uint32_t)(object_ptr >> 32);
    header->wait_list_blink = (uint32_t)(object_ptr & 0xFFFFFFFF);

    return object;
  }
}

}  // namespace kernel
}  // namespace xe
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2008 by Marc Boris Duerner
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * As a special exception, you may use this file as part of a free
 * software library without restriction. Specifically, if other files
 * instantiate templates or use macros or inline functions from this
 * file, or you compile this file and link it with other files to
 * produce an executable, this file does not by itself cause the
 * resulting executable to be covered by the GNU General Public
 * License. This exception does not however invalidate any other
 * reasons why the executable file might be covered by the GNU Library
 * General Public License.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
#include "cxxtools/xml/xmldeserializer.h"
#include "cxxtools/xml/startelement.h"
#include "cxxtools/xml/endelement.h"
#include "cxxtools/xml/characters.h"
#include "cxxtools/string.h"
#include "cxxtools/utf8codec.h"
#include <stdexcept>

namespace cxxtools {

namespace xml {

XmlDeserializer::XmlDeserializer(XmlReader& reader, bool readAttributes)
  : _readAttributes(readAttributes)
{
    parse(reader);
}

XmlDeserializer::XmlDeserializer(std::istream& is, bool readAttributes)
  : _readAttributes(readAttributes)
{
    parse(is);
}

void XmlDeserializer::parse(std::istream& is)
{
    XmlReader reader(is);
    parse(reader);
}

void XmlDeserializer::parse(std::basic_istream<Char>& is)
{
    XmlReader reader(is);
    parse(reader);
}

void XmlDeserializer::parse(XmlReader& reader)
{
    begin();

    if(reader.get().type() != Node::StartElement)
        reader.nextElement();

    _processNode = &XmlDeserializer::beginDocument;

    _startDepth = reader.depth();
    for(XmlReader::Iterator it = reader.current(); it != reader.end(); ++it)
    {
        (this->*_processNode)(reader);

        if( (it->type() == Node::EndElement) && (reader.depth() < _startDepth) )
        {
            break;
        }
    }
}

void XmlDeserializer::beginDocument(XmlReader& reader)
{
    const Node& node = reader.get();
    switch( node.type() )
    {
        case Node::StartElement:
        {
            const StartElement& se =  static_cast<const StartElement&>(node);

            _nodeName = se.name();
            _nodeType = se.attribute(L"type");
            _nodeCategory = se.attribute(L"category");

            current()->setName(_nodeName.narrow());
            current()->setTypeName(_nodeType.narrow());
            current()->setCategory(nodeCategory());

            if (_readAttributes)
                processAttributes(se.attributes());

            _processNode = &XmlDeserializer::onRootElement;
            break;
        }
        default:
            throw std::logic_error("Expected start element");
    };
}

void XmlDeserializer::onRootElement(XmlReader& reader)
{
    const Node& node = reader.get();
    switch( node.type() )
    {
        case Node::Characters:
        {
            const Characters& chars = static_cast<const cxxtools::xml::Characters&>(node);
            if(cxxtools::String::npos != chars.content().find_first_not_of(L" \t\n\r") )
            {
                setValue( chars.content() );
                _processNode = &XmlDeserializer::onContent;
            }
            else
            {
                _processNode = &XmlDeserializer::onWhitespace;
            }

            break;
        }
        case Node::StartElement:
        {
            const StartElement& se =  static_cast<const StartElement&>(node);
            _nodeName = se.name();
            _nodeType = se.attribute(L"type");
            _nodeCategory = se.attribute(L"category");
            if (_readAttributes)
                _attributes = se.attributes();

            _processNode = &XmlDeserializer::onStartElement;
            break;
        }

        case Node::EndElement:
        {
            if( _nodeName != static_cast<const EndElement&>(node).name() )
                throw std::logic_error("Invalid element");
            break;
        }
        default:
            throw std::logic_error("Invalid element");
    };
}

void XmlDeserializer::onStartElement(XmlReader& reader)
{
    const Node& node = reader.get();
    switch( node.type() )
    {
        case Node::Characters:
        {
            const Characters& chars = static_cast<const cxxtools::xml::Characters&>(node);
            if(cxxtools::String::npos != chars.content().find_first_not_of(L" \t\n\r") )
            {
                std::string nodeName = _nodeName.narrow();
                std::string nodeType = _nodeType.empty() ? nodeName : _nodeType.narrow();
                beginMember(nodeName, nodeType, nodeCategory());
                if (_readAttributes)
                    processAttributes(_attributes);
                setValue( chars.content() );
                leaveMember();
                //_current->addValue( _nodeName.narrow(), chars.content() );

                _processNode = &XmlDeserializer::onContent;
            }
            else
            {
                std::string nodeName = _nodeName.narrow();
                std::string nodeType = _nodeType.empty() ? nodeName : _nodeType.narrow();
                beginMember(nodeName, nodeType, nodeCategory());
                if (_readAttributes)
                    processAttributes(_attributes);

                _processNode = &XmlDeserializer::onWhitespace;
            }

            break;
        }
        case Node::StartElement:
        {
            std::string nodeName = _nodeName.narrow();
            std::string nodeType = _nodeType.empty() ? nodeName : _nodeType.narrow();
            beginMember(nodeName, nodeType, nodeCategory());

            const StartElement& se =  static_cast<const StartElement&>(node);
            _nodeName = se.name();
            _nodeType = se.attribute(L"type");
            _nodeCategory = se.attribute(L"category");
            if (_readAttributes)
                _attributes = se.attributes();
            break;
        }
        case Node::EndElement:
        {
            if( _nodeName != static_cast<const EndElement&>(node).name() )
                throw std::logic_error("Invalid element");

            std::string nodeName = _nodeName.narrow();
            std::string nodeType = _nodeType.empty() ? nodeName : _nodeType.narrow();
            beginMember(nodeName, nodeType, nodeCategory());
            if (_readAttributes)
                processAttributes(_attributes);
            leaveMember();
            _processNode = &XmlDeserializer::onEndElement;
            break;
        }
        default:
            throw std::logic_error("Invalid element");
    };
}

void XmlDeserializer::onWhitespace(XmlReader& reader)
{
    const Node& node = reader.get();
    switch( node.type() )
    {
        case Node::StartElement:
        {
            const StartElement& se =  static_cast<const StartElement&>(node);
            _nodeName = se.name();
            _nodeType = se.attribute(L"type");
            _nodeCategory = se.attribute(L"category");
            if (_readAttributes)
                _attributes = se.attributes();

            _processNode = &XmlDeserializer::onStartElement;
            break;
        }
        case Node::EndElement:
        {
            _nodeName = static_cast<const EndElement&>(node).name();

            if(reader.depth() >= _startDepth)
                leaveMember();

            _processNode = &XmlDeserializer::onEndElement;
            break;
        }
        default:
            throw std::logic_error("Expected start element");
    };
}

void XmlDeserializer::onContent(XmlReader& reader)
{
    const Node& node = reader.get();
    switch( node.type() )
    {
        case Node::EndElement:
        {
            _processNode = &XmlDeserializer::onEndElement;
            break;
        }
        default:
            throw std::logic_error("Expected end element");
    };
}

void XmlDeserializer::onEndElement(XmlReader& reader)
{
    const Node& node = reader.get();
    switch( node.type() )
    {
        case Node::Characters:
        {
            _processNode = &XmlDeserializer::onWhitespace;
            break;
        }
        case Node::StartElement:
        {
            _nodeName = static_cast<const StartElement&>(node).name();
            _nodeType = static_cast<const StartElement&>(node).attribute(L"type");
            _nodeCategory = static_cast<const StartElement&>(node).attribute(L"category");
            _processNode = &XmlDeserializer::onStartElement;
            break;
        }
        case Node::EndElement:
        {
            _nodeName = static_cast<const EndElement&>(node).name();

            if(reader.depth() >= _startDepth)
                leaveMember();

            break;
        }
        case Node::EndDocument:
        {
            break;
        }
        default:
        {
            throw std::logic_error("Expected start element");
        }
    }

}

SerializationInfo::Category XmlDeserializer::nodeCategory() const
{
    return _nodeCategory == L"array" ? SerializationInfo::Array :
           _nodeCategory == L"struct" || _nodeCategory == L"object" ? SerializationInfo::Object :
           _nodeCategory == L"scalar" || _nodeCategory == L"value" ? SerializationInfo::Value :
           SerializationInfo::Void;
}

void XmlDeserializer::processAttributes(const Attributes& attributes)
{
    SerializationInfo& si = *current();
    for (Attributes::const_iterator it = attributes.begin(); it != attributes.end(); ++it)
    {
        SerializationInfo& m = si.addMember(cxxtools::encode<Utf8Codec>(it->name()));
        m.setValue(it->value());
        m.setTypeName("attribute");
    }
}

} // namespace xml

} // namespace cxxtools
<commit_msg>fix processing xml attributes in deserializer when a start node is followed directly by another start node<commit_after>/*
 * Copyright (C) 2008 by Marc Boris Duerner
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * As a special exception, you may use this file as part of a free
 * software library without restriction. Specifically, if other files
 * instantiate templates or use macros or inline functions from this
 * file, or you compile this file and link it with other files to
 * produce an executable, this file does not by itself cause the
 * resulting executable to be covered by the GNU General Public
 * License. This exception does not however invalidate any other
 * reasons why the executable file might be covered by the GNU Library
 * General Public License.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
#include "cxxtools/xml/xmldeserializer.h"
#include "cxxtools/xml/startelement.h"
#include "cxxtools/xml/endelement.h"
#include "cxxtools/xml/characters.h"
#include "cxxtools/string.h"
#include "cxxtools/utf8codec.h"
#include "cxxtools/log.h"
#include <stdexcept>

log_define("cxxtools.xml.deserializer");

namespace cxxtools {

namespace xml {

namespace {

    std::ostream& operator<< (std::ostream& out, Node::Type type)
    {
        switch(type)
        {
            case Node::StartDocument: out << "StartDocument"; break;
            case Node::DocType: out << "DocType"; break;
            case Node::EndDocument: out << "EndDocument"; break;
            case Node::StartElement: out << "StartElement"; break;
            case Node::EndElement: out << "EndElement"; break;
            case Node::Characters: out << "Characters"; break;
            case Node::Comment: out << "Comment"; break;
            case Node::ProcessingInstruction: out << "ProcessingInstruction"; break;
            case Node::Unknown:
            default: out << "Unknown"; break;
        }

        return out;
    }
}

XmlDeserializer::XmlDeserializer(XmlReader& reader, bool readAttributes)
  : _readAttributes(readAttributes)
{
    parse(reader);
}

XmlDeserializer::XmlDeserializer(std::istream& is, bool readAttributes)
  : _readAttributes(readAttributes)
{
    parse(is);
}

void XmlDeserializer::parse(std::istream& is)
{
    XmlReader reader(is);
    parse(reader);
}

void XmlDeserializer::parse(std::basic_istream<Char>& is)
{
    XmlReader reader(is);
    parse(reader);
}

void XmlDeserializer::parse(XmlReader& reader)
{
    begin();

    if(reader.get().type() != Node::StartElement)
        reader.nextElement();

    _processNode = &XmlDeserializer::beginDocument;

    _startDepth = reader.depth();
    for(XmlReader::Iterator it = reader.current(); it != reader.end(); ++it)
    {
        (this->*_processNode)(reader);

        if( (it->type() == Node::EndElement) && (reader.depth() < _startDepth) )
        {
            break;
        }
    }
}

void XmlDeserializer::beginDocument(XmlReader& reader)
{
    const Node& node = reader.get();

    log_debug("beginDocument; node type=" << node.type());

    switch( node.type() )
    {
        case Node::StartElement:
        {
            const StartElement& se =  static_cast<const StartElement&>(node);

            _nodeName = se.name();
            _nodeType = se.attribute(L"type");
            _nodeCategory = se.attribute(L"category");

            current()->setName(_nodeName.narrow());
            current()->setTypeName(_nodeType.narrow());
            current()->setCategory(nodeCategory());

            if (_readAttributes)
                processAttributes(se.attributes());

            _processNode = &XmlDeserializer::onRootElement;
            break;
        }
        default:
            throw std::logic_error("Expected start element");
    };
}

void XmlDeserializer::onRootElement(XmlReader& reader)
{
    const Node& node = reader.get();

    log_debug("onRootElement; node type=" << node.type());

    switch( node.type() )
    {
        case Node::Characters:
        {
            const Characters& chars = static_cast<const cxxtools::xml::Characters&>(node);
            if(cxxtools::String::npos != chars.content().find_first_not_of(L" \t\n\r") )
            {
                setValue( chars.content() );
                _processNode = &XmlDeserializer::onContent;
            }
            else
            {
                _processNode = &XmlDeserializer::onWhitespace;
            }

            break;
        }
        case Node::StartElement:
        {
            const StartElement& se =  static_cast<const StartElement&>(node);
            _nodeName = se.name();
            _nodeType = se.attribute(L"type");
            _nodeCategory = se.attribute(L"category");
            if (_readAttributes)
                _attributes = se.attributes();

            _processNode = &XmlDeserializer::onStartElement;
            break;
        }

        case Node::EndElement:
        {
            if( _nodeName != static_cast<const EndElement&>(node).name() )
                throw std::logic_error("Invalid element");
            break;
        }
        default:
            throw std::logic_error("Invalid element");
    };
}

void XmlDeserializer::onStartElement(XmlReader& reader)
{
    const Node& node = reader.get();

    log_debug("onStartElement; node type=" << node.type());

    switch( node.type() )
    {
        case Node::Characters:
        {
            const Characters& chars = static_cast<const cxxtools::xml::Characters&>(node);
            if(cxxtools::String::npos != chars.content().find_first_not_of(L" \t\n\r") )
            {
                std::string nodeName = _nodeName.narrow();
                std::string nodeType = _nodeType.empty() ? nodeName : _nodeType.narrow();
                beginMember(nodeName, nodeType, nodeCategory());
                if (_readAttributes)
                    processAttributes(_attributes);
                setValue( chars.content() );
                leaveMember();
                //_current->addValue( _nodeName.narrow(), chars.content() );

                _processNode = &XmlDeserializer::onContent;
            }
            else
            {
                std::string nodeName = _nodeName.narrow();
                std::string nodeType = _nodeType.empty() ? nodeName : _nodeType.narrow();
                beginMember(nodeName, nodeType, nodeCategory());
                if (_readAttributes)
                    processAttributes(_attributes);

                _processNode = &XmlDeserializer::onWhitespace;
            }

            break;
        }
        case Node::StartElement:
        {
            std::string nodeName = _nodeName.narrow();
            std::string nodeType = _nodeType.empty() ? nodeName : _nodeType.narrow();
            beginMember(nodeName, nodeType, nodeCategory());

            const StartElement& se =  static_cast<const StartElement&>(node);
            _nodeName = se.name();
            _nodeType = se.attribute(L"type");
            _nodeCategory = se.attribute(L"category");
            if (_readAttributes)
            {
                processAttributes(_attributes);
                _attributes = se.attributes();
            }
            break;
        }
        case Node::EndElement:
        {
            if( _nodeName != static_cast<const EndElement&>(node).name() )
                throw std::logic_error("Invalid element");

            std::string nodeName = _nodeName.narrow();
            std::string nodeType = _nodeType.empty() ? nodeName : _nodeType.narrow();
            beginMember(nodeName, nodeType, nodeCategory());
            if (_readAttributes)
                processAttributes(_attributes);
            leaveMember();
            _processNode = &XmlDeserializer::onEndElement;
            break;
        }
        default:
            throw std::logic_error("Invalid element");
    };
}

void XmlDeserializer::onWhitespace(XmlReader& reader)
{
    const Node& node = reader.get();

    log_debug("onWhitespaceElement; node type=" << node.type());

    switch( node.type() )
    {
        case Node::StartElement:
        {
            const StartElement& se =  static_cast<const StartElement&>(node);
            _nodeName = se.name();
            _nodeType = se.attribute(L"type");
            _nodeCategory = se.attribute(L"category");
            if (_readAttributes)
                _attributes = se.attributes();

            _processNode = &XmlDeserializer::onStartElement;
            break;
        }
        case Node::EndElement:
        {
            _nodeName = static_cast<const EndElement&>(node).name();

            if(reader.depth() >= _startDepth)
                leaveMember();

            _processNode = &XmlDeserializer::onEndElement;
            break;
        }
        default:
            throw std::logic_error("Expected start element");
    };
}

void XmlDeserializer::onContent(XmlReader& reader)
{
    const Node& node = reader.get();

    log_debug("onContentElement; node type=" << node.type());

    switch( node.type() )
    {
        case Node::EndElement:
        {
            _processNode = &XmlDeserializer::onEndElement;
            break;
        }
        default:
            throw std::logic_error("Expected end element");
    };
}

void XmlDeserializer::onEndElement(XmlReader& reader)
{
    const Node& node = reader.get();

    log_debug("onEndElement; node type=" << node.type());

    switch( node.type() )
    {
        case Node::Characters:
        {
            _processNode = &XmlDeserializer::onWhitespace;
            break;
        }
        case Node::StartElement:
        {
            _nodeName = static_cast<const StartElement&>(node).name();
            _nodeType = static_cast<const StartElement&>(node).attribute(L"type");
            _nodeCategory = static_cast<const StartElement&>(node).attribute(L"category");
            _processNode = &XmlDeserializer::onStartElement;
            break;
        }
        case Node::EndElement:
        {
            _nodeName = static_cast<const EndElement&>(node).name();

            if(reader.depth() >= _startDepth)
                leaveMember();

            break;
        }
        case Node::EndDocument:
        {
            break;
        }
        default:
        {
            throw std::logic_error("Expected start element");
        }
    }

}

SerializationInfo::Category XmlDeserializer::nodeCategory() const
{
    return _nodeCategory == L"array" ? SerializationInfo::Array :
           _nodeCategory == L"struct" || _nodeCategory == L"object" ? SerializationInfo::Object :
           _nodeCategory == L"scalar" || _nodeCategory == L"value" ? SerializationInfo::Value :
           SerializationInfo::Void;
}

void XmlDeserializer::processAttributes(const Attributes& attributes)
{
    log_debug("processAttributes " << attributes.size() << " attributes");
    SerializationInfo& si = *current();
    for (Attributes::const_iterator it = attributes.begin(); it != attributes.end(); ++it)
    {
        SerializationInfo& m = si.addMember(cxxtools::encode<Utf8Codec>(it->name()));
        m.setValue(it->value());
        m.setTypeName("attribute");
    }
}

} // namespace xml

} // namespace cxxtools
<|endoftext|>


<commit_before><commit_msg>Added layout support to StaticPageController<commit_after><|endoftext|>


<commit_before>#include "Wavenet/Logger.h"

namespace Wavenet {

void Logger::_print (std::string cls, std::string fun, std::string type, std::string format, ...) {

    std::string col = "\033[1m";
    if      (type == "ERROR")   { col = "\033[1;31m"; }
    else if (type == "WARNING") { col = "\033[1;31m"; }
    else if (type == "INFO")    { col = "\033[1;34m"; }

    std::cout << "\033[1m" << std::left << std::setw(25) << ("<" + cls + "::" + fun + "> ") << col << std::setw(7) << type << "\033[0m ";
    va_list args;
    va_start (args, format);
    vprintf (format.c_str(), args);
    va_end (args);
    std::cout << std::endl;
    return;
}

void Logger::_fctprint (std::string fun, std::string type, std::string format, ...) {

    std::string col = "\033[1m";
    if      (type == "ERROR")   { col = "\033[1;31m"; }
    else if (type == "WARNING") { col = "\033[1;31m"; }
    else if (type == "INFO")    { col = "\033[1;34m"; }

    std::cout << "\033[1m" << std::left << std::setw(25) << ("<" + fun + "> ") << col << std::setw(7) << type << "\033[0m ";
    va_list args;
    va_start (args, format);
    vprintf (format.c_str(), args);
    va_end (args);
    std::cout << std::endl;
    return;
}

} // namespace
<commit_msg>Update Logger field width to fit namespace.<commit_after>#include "Wavenet/Logger.h"

namespace Wavenet {

void Logger::_print (std::string cls, std::string fun, std::string type, std::string format, ...) {

    std::string col = "\033[1m";
    if      (type == "ERROR")   { col = "\033[1;31m"; }
    else if (type == "WARNING") { col = "\033[1;31m"; }
    else if (type == "INFO")    { col = "\033[1;34m"; }

    std::cout << "\033[1m" << std::left << std::setw(34) << ("<" + cls + "::" + fun + "> ") << col << std::setw(7) << type << "\033[0m ";
    va_list args;
    va_start (args, format);
    vprintf (format.c_str(), args);
    va_end (args);
    std::cout << std::endl;
    return;
}

void Logger::_fctprint (std::string fun, std::string type, std::string format, ...) {

    std::string col = "\033[1m";
    if      (type == "ERROR")   { col = "\033[1;31m"; }
    else if (type == "WARNING") { col = "\033[1;31m"; }
    else if (type == "INFO")    { col = "\033[1;34m"; }

    std::cout << "\033[1m" << std::left << std::setw(34) << ("<" + fun + "> ") << col << std::setw(7) << type << "\033[0m ";
    va_list args;
    va_start (args, format);
    vprintf (format.c_str(), args);
    va_end (args);
    std::cout << std::endl;
    return;
}

} // namespace
<|endoftext|>


<commit_before>#include <LSM303.h>
#include <Wire.h>
#include <math.h>

// Defines ////////////////////////////////////////////////////////////////

// The Arduino two-wire interface uses a 7-bit number for the address,
// and sets the last bit correctly based on reads and writes
#define MAG_ADDRESS            (0x3C >> 1)
#define ACC_ADDRESS_SA0_A_LOW  (0x30 >> 1)
#define ACC_ADDRESS_SA0_A_HIGH (0x32 >> 1)

// Constructors ////////////////////////////////////////////////////////////////

LSM303::LSM303(void)
{
  // These are just some values for a particular unit; it is recommended that
  // a calibration be done for your particular unit.
  m_max.x = +540; m_max.y = +500; m_max.z = 180;
  m_min.x = -520; m_min.y = -570; m_min.z = -770;

  _device = LSM303_DEVICE_AUTO;
  acc_address = ACC_ADDRESS_SA0_A_LOW;

  io_timeout = 0;  // 0 = no timeout
  did_timeout = false;
}

// Public Methods //////////////////////////////////////////////////////////////

bool LSM303::timeoutOccurred()
{
  return did_timeout;
}

void LSM303::setTimeout(unsigned int timeout)
{
  io_timeout = timeout;
}

unsigned int LSM303::getTimeout()
{
  return io_timeout;
}

void LSM303::init(byte device, byte sa0_a)
{
  _device = device;
  switch (_device)
  {
    case LSM303DLH_DEVICE:
    case LSM303DLM_DEVICE:
      if (sa0_a == LSM303_SA0_A_LOW)
        acc_address = ACC_ADDRESS_SA0_A_LOW;
      else if (sa0_a == LSM303_SA0_A_HIGH)
        acc_address = ACC_ADDRESS_SA0_A_HIGH;
      else
        acc_address = (detectSA0_A() == LSM303_SA0_A_HIGH) ? ACC_ADDRESS_SA0_A_HIGH : ACC_ADDRESS_SA0_A_LOW;
      break;

    case LSM303DLHC_DEVICE:
      acc_address = ACC_ADDRESS_SA0_A_HIGH;
      break;

    default:
      // try to auto-detect device
      if (detectSA0_A() == LSM303_SA0_A_HIGH)
      {
        // if device responds on 0011001b (SA0_A is high), assume DLHC
        acc_address = ACC_ADDRESS_SA0_A_HIGH;
        _device = LSM303DLHC_DEVICE;
      }
      else
      {
        // otherwise, assume DLH or DLM (pulled low by default on Pololu boards); query magnetometer WHO_AM_I to differentiate these two
        acc_address = ACC_ADDRESS_SA0_A_LOW;
        _device = (readMagReg(LSM303_WHO_AM_I_M) == 0x3C) ? LSM303DLM_DEVICE : LSM303DLH_DEVICE;
      }
  }
}

// Turns on the LSM303's accelerometer and magnetometers and places them in normal
// mode.
void LSM303::enableDefault(void)
{
  // Enable Accelerometer
  // 0x27 = 0b00100111
  // Normal power mode, all axes enabled
  writeAccReg(LSM303_CTRL_REG1_A, 0x27);

  // Enable Magnetometer
  // 0x00 = 0b00000000
  // Continuous conversion mode
  writeMagReg(LSM303_MR_REG_M, 0x00);
}

// Writes an accelerometer register
void LSM303::writeAccReg(byte reg, byte value)
{
  Wire.beginTransmission(acc_address);
  Wire.write(reg);
  Wire.write(value);
  last_status = Wire.endTransmission();
}

// Reads an accelerometer register
byte LSM303::readAccReg(byte reg)
{
  byte value;

  Wire.beginTransmission(acc_address);
  Wire.write(reg);
  last_status = Wire.endTransmission();
  Wire.requestFrom(acc_address, (byte)1);
  value = Wire.read();
  Wire.endTransmission();

  return value;
}

// Writes a magnetometer register
void LSM303::writeMagReg(byte reg, byte value)
{
  Wire.beginTransmission(MAG_ADDRESS);
  Wire.write(reg);
  Wire.write(value);
  last_status = Wire.endTransmission();
}

// Reads a magnetometer register
byte LSM303::readMagReg(int reg)
{
  byte value;

  // if dummy register address (magnetometer Y/Z), use device type to determine actual address
  if (reg < 0)
  {
    switch (reg)
    {
      case LSM303_OUT_Y_H_M:
        reg = (_device == LSM303DLH_DEVICE) ? LSM303DLH_OUT_Y_H_M : LSM303DLM_OUT_Y_H_M;
        break;
      case LSM303_OUT_Y_L_M:
        reg = (_device == LSM303DLH_DEVICE) ? LSM303DLH_OUT_Y_L_M : LSM303DLM_OUT_Y_L_M;
        break;
      case LSM303_OUT_Z_H_M:
        reg = (_device == LSM303DLH_DEVICE) ? LSM303DLH_OUT_Z_H_M : LSM303DLM_OUT_Z_H_M;
        break;
      case LSM303_OUT_Z_L_M:
        reg = (_device == LSM303DLH_DEVICE) ? LSM303DLH_OUT_Z_L_M : LSM303DLM_OUT_Z_L_M;
        break;
    }
  }

  Wire.beginTransmission(MAG_ADDRESS);
  Wire.write(reg);
  last_status = Wire.endTransmission();
  Wire.requestFrom(MAG_ADDRESS, 1);
  value = Wire.read();
  Wire.endTransmission();

  return value;
}

void LSM303::setMagGain(magGain value)
{
  Wire.beginTransmission(MAG_ADDRESS);
  Wire.write(LSM303_CRB_REG_M);
  Wire.write((byte) value);
  Wire.endTransmission();
}

// Reads the 3 accelerometer channels and stores them in vector a
void LSM303::readAcc(void)
{
  Wire.beginTransmission(acc_address);
  // assert the MSB of the address to get the accelerometer
  // to do slave-transmit subaddress updating.
  Wire.write(LSM303_OUT_X_L_A | (1 << 7));
  last_status = Wire.endTransmission();
  Wire.requestFrom(acc_address, (byte)6);

  unsigned int millis_start = millis();
  did_timeout = false;
  while (Wire.available() < 6) {
    if (io_timeout > 0 && ((unsigned int)millis() - millis_start) > io_timeout) {
      did_timeout = true;
      return;
    }
  }

  byte xla = Wire.read();
  byte xha = Wire.read();
  byte yla = Wire.read();
  byte yha = Wire.read();
  byte zla = Wire.read();
  byte zha = Wire.read();

  // combine high and low bytes, then shift right to discard lowest 4 bits (which are meaningless)
  // GCC performs an arithmetic right shift for signed negative numbers, but this code will not work
  // if you port it to a compiler that does a logical right shift instead.
  a.x = ((int16_t)(xha << 8 | xla)) >> 4;
  a.y = ((int16_t)(yha << 8 | yla)) >> 4;
  a.z = ((int16_t)(zha << 8 | zla)) >> 4;
}

// Reads the 3 magnetometer channels and stores them in vector m
void LSM303::readMag(void)
{
  Wire.beginTransmission(MAG_ADDRESS);
  Wire.write(LSM303_OUT_X_H_M);
  last_status = Wire.endTransmission();
  Wire.requestFrom(MAG_ADDRESS, 6);

  unsigned int millis_start = millis();
  did_timeout = false;
  while (Wire.available() < 6) {
    if (io_timeout > 0 && ((unsigned int)millis() - millis_start) > io_timeout) {
      did_timeout = true;
      return;
    }
  }

  byte xhm = Wire.read();
  byte xlm = Wire.read();

  byte yhm, ylm, zhm, zlm;

  if (_device == LSM303DLH_DEVICE)
  {
    // DLH: register address for Y comes before Z
    yhm = Wire.read();
    ylm = Wire.read();
    zhm = Wire.read();
    zlm = Wire.read();
  }
  else
  {
    // DLM, DLHC: register address for Z comes before Y
    zhm = Wire.read();
    zlm = Wire.read();
    yhm = Wire.read();
    ylm = Wire.read();

  }

  // combine high and low bytes
  m.x = (int16_t)(xhm << 8 | xlm);
  m.y = (int16_t)(yhm << 8 | ylm);
  m.z = (int16_t)(zhm << 8 | zlm);
}

// Reads all 6 channels of the LSM303 and stores them in the object variables
void LSM303::read(void)
{
  readAcc();
  readMag();
}

// Returns the number of degrees from the -Y axis that it
// is pointing.
int LSM303::heading(void)
{
  return heading((vector){0,-1,0});
}

// Returns the number of degrees from the From vector projected into
// the horizontal plane is away from north.
//
// Description of heading algorithm:
// Shift and scale the magnetic reading based on calibration data to
// to find the North vector. Use the acceleration readings to
// determine the Down vector. The cross product of North and Down
// vectors is East. The vectors East and North form a basis for the
// horizontal plane. The From vector is projected into the horizontal
// plane and the angle between the projected vector and north is
// returned.
int LSM303::heading(vector from)
{
    // shift and scale
    m.x = (m.x - m_min.x) / (m_max.x - m_min.x) * 2 - 1.0;
    m.y = (m.y - m_min.y) / (m_max.y - m_min.y) * 2 - 1.0;
    m.z = (m.z - m_min.z) / (m_max.z - m_min.z) * 2 - 1.0;

    vector temp_a = a;
    // normalize
    vector_normalize(&temp_a);
    //vector_normalize(&m);

    // compute E and N
    vector E;
    vector N;
    vector_cross(&m, &temp_a, &E);
    vector_normalize(&E);
    vector_cross(&temp_a, &E, &N);

    // compute heading
    int heading = round(atan2(vector_dot(&E, &from), vector_dot(&N, &from)) * 180 / M_PI);
    if (heading < 0) heading += 360;
  return heading;
}

void LSM303::vector_cross(const vector *a,const vector *b, vector *out)
{
  out->x = a->y*b->z - a->z*b->y;
  out->y = a->z*b->x - a->x*b->z;
  out->z = a->x*b->y - a->y*b->x;
}

float LSM303::vector_dot(const vector *a,const vector *b)
{
  return a->x*b->x+a->y*b->y+a->z*b->z;
}

void LSM303::vector_normalize(vector *a)
{
  float mag = sqrt(vector_dot(a,a));
  a->x /= mag;
  a->y /= mag;
  a->z /= mag;
}

// Private Methods //////////////////////////////////////////////////////////////

byte LSM303::detectSA0_A(void)
{
  Wire.beginTransmission(ACC_ADDRESS_SA0_A_LOW);
  Wire.write(LSM303_CTRL_REG1_A);
  last_status = Wire.endTransmission();
  Wire.requestFrom(ACC_ADDRESS_SA0_A_LOW, 1);
  if (Wire.available())
  {
    Wire.read();
    return LSM303_SA0_A_LOW;
  }
  else
    return LSM303_SA0_A_HIGH;
}
<commit_msg>enable high res mode on DLHC by default<commit_after>#include <LSM303.h>
#include <Wire.h>
#include <math.h>

// Defines ////////////////////////////////////////////////////////////////

// The Arduino two-wire interface uses a 7-bit number for the address,
// and sets the last bit correctly based on reads and writes
#define MAG_ADDRESS            (0x3C >> 1)
#define ACC_ADDRESS_SA0_A_LOW  (0x30 >> 1)
#define ACC_ADDRESS_SA0_A_HIGH (0x32 >> 1)

// Constructors ////////////////////////////////////////////////////////////////

LSM303::LSM303(void)
{
  // These are just some values for a particular unit; it is recommended that
  // a calibration be done for your particular unit.
  m_max.x = +540; m_max.y = +500; m_max.z = 180;
  m_min.x = -520; m_min.y = -570; m_min.z = -770;

  _device = LSM303_DEVICE_AUTO;
  acc_address = ACC_ADDRESS_SA0_A_LOW;

  io_timeout = 0;  // 0 = no timeout
  did_timeout = false;
}

// Public Methods //////////////////////////////////////////////////////////////

bool LSM303::timeoutOccurred()
{
  return did_timeout;
}

void LSM303::setTimeout(unsigned int timeout)
{
  io_timeout = timeout;
}

unsigned int LSM303::getTimeout()
{
  return io_timeout;
}

void LSM303::init(byte device, byte sa0_a)
{
  _device = device;
  switch (_device)
  {
    case LSM303DLH_DEVICE:
    case LSM303DLM_DEVICE:
      if (sa0_a == LSM303_SA0_A_LOW)
        acc_address = ACC_ADDRESS_SA0_A_LOW;
      else if (sa0_a == LSM303_SA0_A_HIGH)
        acc_address = ACC_ADDRESS_SA0_A_HIGH;
      else
        acc_address = (detectSA0_A() == LSM303_SA0_A_HIGH) ? ACC_ADDRESS_SA0_A_HIGH : ACC_ADDRESS_SA0_A_LOW;
      break;

    case LSM303DLHC_DEVICE:
      acc_address = ACC_ADDRESS_SA0_A_HIGH;
      break;

    default:
      // try to auto-detect device
      if (detectSA0_A() == LSM303_SA0_A_HIGH)
      {
        // if device responds on 0011001b (SA0_A is high), assume DLHC
        acc_address = ACC_ADDRESS_SA0_A_HIGH;
        _device = LSM303DLHC_DEVICE;
      }
      else
      {
        // otherwise, assume DLH or DLM (pulled low by default on Pololu boards); query magnetometer WHO_AM_I to differentiate these two
        acc_address = ACC_ADDRESS_SA0_A_LOW;
        _device = (readMagReg(LSM303_WHO_AM_I_M) == 0x3C) ? LSM303DLM_DEVICE : LSM303DLH_DEVICE;
      }
  }
}

// Turns on the LSM303's accelerometer and magnetometers and places them in normal
// mode.
void LSM303::enableDefault(void)
{
  // Enable Accelerometer
  // 0x27 = 0b00100111
  // Normal power mode, all axes enabled
  writeAccReg(LSM303_CTRL_REG1_A, 0x27);

  if (_device == LSM303DLHC_DEVICE)
    writeAccReg(LSM303_CTRL_REG4_A, 0x08); // DLHC: enable high resolution mode

  // Enable Magnetometer
  // 0x00 = 0b00000000
  // Continuous conversion mode
  writeMagReg(LSM303_MR_REG_M, 0x00);
}

// Writes an accelerometer register
void LSM303::writeAccReg(byte reg, byte value)
{
  Wire.beginTransmission(acc_address);
  Wire.write(reg);
  Wire.write(value);
  last_status = Wire.endTransmission();
}

// Reads an accelerometer register
byte LSM303::readAccReg(byte reg)
{
  byte value;

  Wire.beginTransmission(acc_address);
  Wire.write(reg);
  last_status = Wire.endTransmission();
  Wire.requestFrom(acc_address, (byte)1);
  value = Wire.read();
  Wire.endTransmission();

  return value;
}

// Writes a magnetometer register
void LSM303::writeMagReg(byte reg, byte value)
{
  Wire.beginTransmission(MAG_ADDRESS);
  Wire.write(reg);
  Wire.write(value);
  last_status = Wire.endTransmission();
}

// Reads a magnetometer register
byte LSM303::readMagReg(int reg)
{
  byte value;

  // if dummy register address (magnetometer Y/Z), use device type to determine actual address
  if (reg < 0)
  {
    switch (reg)
    {
      case LSM303_OUT_Y_H_M:
        reg = (_device == LSM303DLH_DEVICE) ? LSM303DLH_OUT_Y_H_M : LSM303DLM_OUT_Y_H_M;
        break;
      case LSM303_OUT_Y_L_M:
        reg = (_device == LSM303DLH_DEVICE) ? LSM303DLH_OUT_Y_L_M : LSM303DLM_OUT_Y_L_M;
        break;
      case LSM303_OUT_Z_H_M:
        reg = (_device == LSM303DLH_DEVICE) ? LSM303DLH_OUT_Z_H_M : LSM303DLM_OUT_Z_H_M;
        break;
      case LSM303_OUT_Z_L_M:
        reg = (_device == LSM303DLH_DEVICE) ? LSM303DLH_OUT_Z_L_M : LSM303DLM_OUT_Z_L_M;
        break;
    }
  }

  Wire.beginTransmission(MAG_ADDRESS);
  Wire.write(reg);
  last_status = Wire.endTransmission();
  Wire.requestFrom(MAG_ADDRESS, 1);
  value = Wire.read();
  Wire.endTransmission();

  return value;
}

void LSM303::setMagGain(magGain value)
{
  Wire.beginTransmission(MAG_ADDRESS);
  Wire.write(LSM303_CRB_REG_M);
  Wire.write((byte) value);
  Wire.endTransmission();
}

// Reads the 3 accelerometer channels and stores them in vector a
void LSM303::readAcc(void)
{
  Wire.beginTransmission(acc_address);
  // assert the MSB of the address to get the accelerometer
  // to do slave-transmit subaddress updating.
  Wire.write(LSM303_OUT_X_L_A | (1 << 7));
  last_status = Wire.endTransmission();
  Wire.requestFrom(acc_address, (byte)6);

  unsigned int millis_start = millis();
  did_timeout = false;
  while (Wire.available() < 6) {
    if (io_timeout > 0 && ((unsigned int)millis() - millis_start) > io_timeout) {
      did_timeout = true;
      return;
    }
  }

  byte xla = Wire.read();
  byte xha = Wire.read();
  byte yla = Wire.read();
  byte yha = Wire.read();
  byte zla = Wire.read();
  byte zha = Wire.read();

  // combine high and low bytes, then shift right to discard lowest 4 bits (which are meaningless)
  // GCC performs an arithmetic right shift for signed negative numbers, but this code will not work
  // if you port it to a compiler that does a logical right shift instead.
  a.x = ((int16_t)(xha << 8 | xla)) >> 4;
  a.y = ((int16_t)(yha << 8 | yla)) >> 4;
  a.z = ((int16_t)(zha << 8 | zla)) >> 4;
}

// Reads the 3 magnetometer channels and stores them in vector m
void LSM303::readMag(void)
{
  Wire.beginTransmission(MAG_ADDRESS);
  Wire.write(LSM303_OUT_X_H_M);
  last_status = Wire.endTransmission();
  Wire.requestFrom(MAG_ADDRESS, 6);

  unsigned int millis_start = millis();
  did_timeout = false;
  while (Wire.available() < 6) {
    if (io_timeout > 0 && ((unsigned int)millis() - millis_start) > io_timeout) {
      did_timeout = true;
      return;
    }
  }

  byte xhm = Wire.read();
  byte xlm = Wire.read();

  byte yhm, ylm, zhm, zlm;

  if (_device == LSM303DLH_DEVICE)
  {
    // DLH: register address for Y comes before Z
    yhm = Wire.read();
    ylm = Wire.read();
    zhm = Wire.read();
    zlm = Wire.read();
  }
  else
  {
    // DLM, DLHC: register address for Z comes before Y
    zhm = Wire.read();
    zlm = Wire.read();
    yhm = Wire.read();
    ylm = Wire.read();

  }

  // combine high and low bytes
  m.x = (int16_t)(xhm << 8 | xlm);
  m.y = (int16_t)(yhm << 8 | ylm);
  m.z = (int16_t)(zhm << 8 | zlm);
}

// Reads all 6 channels of the LSM303 and stores them in the object variables
void LSM303::read(void)
{
  readAcc();
  readMag();
}

// Returns the number of degrees from the -Y axis that it
// is pointing.
int LSM303::heading(void)
{
  return heading((vector){0,-1,0});
}

// Returns the number of degrees from the From vector projected into
// the horizontal plane is away from north.
//
// Description of heading algorithm:
// Shift and scale the magnetic reading based on calibration data to
// to find the North vector. Use the acceleration readings to
// determine the Down vector. The cross product of North and Down
// vectors is East. The vectors East and North form a basis for the
// horizontal plane. The From vector is projected into the horizontal
// plane and the angle between the projected vector and north is
// returned.
int LSM303::heading(vector from)
{
    // shift and scale
    m.x = (m.x - m_min.x) / (m_max.x - m_min.x) * 2 - 1.0;
    m.y = (m.y - m_min.y) / (m_max.y - m_min.y) * 2 - 1.0;
    m.z = (m.z - m_min.z) / (m_max.z - m_min.z) * 2 - 1.0;

    vector temp_a = a;
    // normalize
    vector_normalize(&temp_a);
    //vector_normalize(&m);

    // compute E and N
    vector E;
    vector N;
    vector_cross(&m, &temp_a, &E);
    vector_normalize(&E);
    vector_cross(&temp_a, &E, &N);

    // compute heading
    int heading = round(atan2(vector_dot(&E, &from), vector_dot(&N, &from)) * 180 / M_PI);
    if (heading < 0) heading += 360;
  return heading;
}

void LSM303::vector_cross(const vector *a,const vector *b, vector *out)
{
  out->x = a->y*b->z - a->z*b->y;
  out->y = a->z*b->x - a->x*b->z;
  out->z = a->x*b->y - a->y*b->x;
}

float LSM303::vector_dot(const vector *a,const vector *b)
{
  return a->x*b->x+a->y*b->y+a->z*b->z;
}

void LSM303::vector_normalize(vector *a)
{
  float mag = sqrt(vector_dot(a,a));
  a->x /= mag;
  a->y /= mag;
  a->z /= mag;
}

// Private Methods //////////////////////////////////////////////////////////////

byte LSM303::detectSA0_A(void)
{
  Wire.beginTransmission(ACC_ADDRESS_SA0_A_LOW);
  Wire.write(LSM303_CTRL_REG1_A);
  last_status = Wire.endTransmission();
  Wire.requestFrom(ACC_ADDRESS_SA0_A_LOW, 1);
  if (Wire.available())
  {
    Wire.read();
    return LSM303_SA0_A_LOW;
  }
  else
    return LSM303_SA0_A_HIGH;
}
<|endoftext|>


<commit_before>#include "MadCam.h"

//--------------------------------------------------------------
void MadCam::setup(){
  ofSetVerticalSync(true);
  setupMidi();
  cams.setup();

  if(ofIsGLProgrammableRenderer())
    cout << "IS A PRGRAMMABLE REMDNER" << endl;
  else
    cout << "NO NO NO IS A PRGRAMMABLE REMDNER" << endl;

  shader.load("shaders/passThru_vert.glsl", "shaders/mrt_frag.glsl");
  shader.linkProgram();
}

//--------------------------------------------------------------
void MadCam::update(){
  ofBackground(0,0,0);
  cams.update();

}

//--------------------------------------------------------------
void MadCam::draw(){
  //shader.begin();
  cams.draw();
  ofDrawBitmapString(ofGetFrameRate(),20,20);
  //shader.end();
}

//--------------------------------------------------------------
void MadCam::keyPressed(int key){
  int baseKey = 49;
  cout << "key pressed: " << key << endl;
  if(key >= baseKey && key < (baseKey + cams.getNumCameras())) {
    cams.setCamera((key % baseKey) % cams.getNumCameras());
    return;
  }

  switch(key) {
    case 113:
      cams.setArrangement(SINGLE);
      break;
    case 119:
      cams.setArrangement(DUAL_HORIZ);
      break;
    case 101:
      cams.setArrangement(TRIPLE_HORIZ);
      break;
    case 114:
      cams.setArrangement(TILED);
      break;
    case 116:
      cams.setArrangement(MONOCLE);
      break;
    case 99:
      cams.setViewMode((CROP));
      break;
    case 115:
      cams.setViewMode((SCALE));
      break;
  }
}

//--------------------------------------------------------------
void MadCam::keyReleased(int key){

}

//--------------------------------------------------------------
void MadCam::mouseMoved(int x, int y ){

}

//--------------------------------------------------------------
void MadCam::mouseDragged(int x, int y, int button){

}

//--------------------------------------------------------------
void MadCam::mousePressed(int x, int y, int button){

}

//--------------------------------------------------------------
void MadCam::mouseReleased(int x, int y, int button){

}

//--------------------------------------------------------------
void
MadCam::windowResized(int w, int h)
{
  cams.setDimensions(w, h);
}

//--------------------------------------------------------------
void
MadCam::gotMessage(ofMessage msg)
{
}

//--------------------------------------------------------------
void MadCam::dragEvent(ofDragInfo dragInfo){

}

//--------------------------------------------------------------
void MadCam::exit() {
  // clean up
  midiIn.closePort();
  midiIn.removeListener(this);
}

// MIDI
void MadCam::setupMidi()
{
  midiIn.listPorts(); // via instance

  //midiIn.openPort(1);
  //midiIn.openVirtualPort("ofxMidiIn Input"); // open a virtual port
  midiIn.openPort("FastTrack Pro 40:0");

  // don't ignore sysex, timing, & active sense messages,
  // these are ignored by default
  //midiIn.ignoreTypes(false, false, false);

  // add MadCam as a listener
  midiIn.addListener(this);
  midiIn.setVerbose(true);
}

void MadCam::newMidiMessage(ofxMidiMessage& msg)
{
  switch(msg.status) {
    case MIDI_NOTE_ON:
      //if(msg.pitch < grabbers.size())
        //selected = msg.pitch;
      cout << "pitch: " << msg.pitch << endl;
      return;
    case MIDI_CONTROL_CHANGE:
      if(msg.control == 20 && msg.value > 1)
        //tiles = msg.value;
      return;
    default:
      return;
  }
}
<commit_msg>adding some code for trying out shaders<commit_after>#include "MadCam.h"

//--------------------------------------------------------------
void MadCam::setup(){
  ofSetVerticalSync(true);
  setupMidi();
  cams.setup();
}

void MadCam::loadShader()
{
  shader.load("", "krgn.frag");
  //shader.linkProgram();
}

//--------------------------------------------------------------
void MadCam::update(){
  ofBackground(0,0,0);
  cams.update();
}

//--------------------------------------------------------------
void MadCam::draw(){
  if(shader.isLoaded())
    shader.begin();

  cams.draw();
  ofDrawBitmapString(ofGetFrameRate(),20,20);

  if(shader.isLoaded())
    shader.end();
}

//--------------------------------------------------------------
void MadCam::keyPressed(int key){
  int baseKey = 49;

  if(key == 121)
    loadShader();

  if(key >= baseKey && key < (baseKey + cams.getNumCameras())) {
    cams.setCamera((key % baseKey) % cams.getNumCameras());
    return;
  }

  switch(key) {
    case 113:
      cams.setArrangement(SINGLE);
      break;
    case 119:
      cams.setArrangement(DUAL_HORIZ);
      break;
    case 101:
      cams.setArrangement(TRIPLE_HORIZ);
      break;
    case 114:
      cams.setArrangement(TILED);
      break;
    case 116:
      cams.setArrangement(MONOCLE);
      break;
    case 99:
      cams.setViewMode((CROP));
      break;
    case 115:
      cams.setViewMode((SCALE));
      break;
  }
}

//--------------------------------------------------------------
void MadCam::keyReleased(int key){

}

//--------------------------------------------------------------
void MadCam::mouseMoved(int x, int y ){

}

//--------------------------------------------------------------
void MadCam::mouseDragged(int x, int y, int button){

}

//--------------------------------------------------------------
void MadCam::mousePressed(int x, int y, int button){

}

//--------------------------------------------------------------
void MadCam::mouseReleased(int x, int y, int button){

}

//--------------------------------------------------------------
void
MadCam::windowResized(int w, int h)
{
  cams.setDimensions(w, h);
}

//--------------------------------------------------------------
void
MadCam::gotMessage(ofMessage msg)
{
}

//--------------------------------------------------------------
void MadCam::dragEvent(ofDragInfo dragInfo){

}

//--------------------------------------------------------------
void MadCam::exit() {
  // clean up
  midiIn.closePort();
  midiIn.removeListener(this);
}

// MIDI
void MadCam::setupMidi()
{
  midiIn.listPorts(); // via instance

  //midiIn.openPort(1);
  //midiIn.openVirtualPort("ofxMidiIn Input"); // open a virtual port
  midiIn.openPort("FastTrack Pro 40:0");

  // don't ignore sysex, timing, & active sense messages,
  // these are ignored by default
  //midiIn.ignoreTypes(false, false, false);

  // add MadCam as a listener
  midiIn.addListener(this);
  midiIn.setVerbose(true);
}

void MadCam::newMidiMessage(ofxMidiMessage& msg)
{
  switch(msg.status) {
    case MIDI_NOTE_ON:
      //if(msg.pitch < grabbers.size())
        //selected = msg.pitch;
      cout << "pitch: " << msg.pitch << endl;
      return;
    case MIDI_CONTROL_CHANGE:
      if(msg.control == 20 && msg.value > 1)
        //tiles = msg.value;
      return;
    default:
      return;
  }
}
<|endoftext|>