<commit_before>#include "ofxGuiInputField.h"
#include "ofGraphics.h"

template<typename Type>
ofxGuiInputField<Type>::ofxGuiInputField(){

	setup();

}

template<typename Type>
ofxGuiInputField<Type>::ofxGuiInputField(const ofJson &config)
	:ofxGuiInputField(){

	_setConfig(config);

}

template<typename Type>
ofxGuiInputField<Type>::ofxGuiInputField(ofParameter<Type>& _val, const ofJson &config)
	:ofxGuiInputField(){

	value.makeReferenceTo(_val);
	input = ofToString(value);
	inputWidth = getTextBoundingBox(input,0,0).width;
	value.addListener(this,&ofxGuiInputField::valueChanged);
	pressCounter = 0;
	_setConfig(config);

}

template<typename Type>
ofxGuiInputField<Type>::ofxGuiInputField(const std::string& _name, Type _val, Type _min, Type _max, const ofJson &config)
	:ofxGuiInputField(value.set(_name,_val,_min,_max), config){
}

template<typename Type>
ofxGuiInputField<Type>::~ofxGuiInputField(){
	value.removeListener(this,&ofxGuiInputField::valueChanged);
	unregisterKeyEvents();
}

template<typename Type>
void ofxGuiInputField<Type>::setup(){

	bChangedInternally = false;
	bMousePressed = false;
	mouseInside = false;
	bRegisteredForKeyEvents = false;
	hasFocus = false;
	mousePressedPos = -1;
	selectStartX = -1;
	selectStartPos = -1;
	selectEndPos = -1;
	pressCounter = 0;
	inputWidth = 0;
	selectionWidth = 0;
	setTheme();
	registerMouseEvents();
	registerKeyEvents();

}

template<typename Type>
void ofxGuiInputField<Type>::setMin(Type min){
	value.setMin(min);
}

template<typename Type>
Type ofxGuiInputField<Type>::getMin(){
	return value.getMin();
}

template<typename Type>
void ofxGuiInputField<Type>::setMax(Type max){
	value.setMax(max);
}

template<typename Type>
Type ofxGuiInputField<Type>::getMax(){
	return value.getMax();
}

template<typename Type>
void ofxGuiInputField<Type>::calculateSelectionArea(int selectIdx1, int selectIdx2){
	std::string preSelectStr, selectStr;

	if(selectIdx1 <= selectIdx2){
		selectStartPos = selectIdx1;
		selectEndPos = selectIdx2;
	}else{
		selectStartPos = selectIdx2;
		selectEndPos = selectIdx1;
	}

	float preSelectWidth = 0;
	if(selectStartPos > 0){
		preSelectStr.assign(input,0,selectStartPos);
		preSelectWidth = getTextBoundingBox(preSelectStr,0,0).width;
	}
	selectStartX = getWidth() - textPadding - inputWidth + preSelectWidth;

	if(hasSelectedText()){
		selectStr.assign(input,selectStartPos,selectEndPos-selectStartPos);
		selectionWidth = getTextBoundingBox(selectStr,0,0).width;
	}
}

template<typename Type>
float ofxGuiInputField<Type>::getMinWidth(){
	std::string text = ofToString(value.get());
	if(showName){
		if(!getName().empty()){
			text = getName() + ": ";
		}
	}

	return ofxGuiElement::getTextWidth(text);
}

template<typename Type>
float ofxGuiInputField<Type>::getMinHeight(){
	std::string text = ofToString(value.get());
	if(showName){
		if(!getName().empty()){
			text = getName() + ": ";
		}
	}
	return ofxGuiElement::getTextHeight(text);
}

template<typename Type>
bool ofxGuiInputField<Type>::mouseMoved(ofMouseEventArgs & args){

	ofxGuiElement::mouseMoved(args);

	mouseInside = !isHidden() && isMouseOver();
	return mouseInside;
}

template<typename Type>
bool ofxGuiInputField<Type>::mousePressed(ofMouseEventArgs & args){

	ofxGuiElement::mousePressed(args);

	if(isMouseOver()){
		bMousePressed = true;
		hasFocus = true;

		float cursorX = args.x - (localToScreen(getShape()).getRight() - textPadding - inputWidth);
		int cursorPos = ofMap(cursorX,0,inputWidth,0,input.size(),true);
		mousePressedPos = cursorPos;

		calculateSelectionArea(cursorPos, cursorPos);

		pressCounter++;

	}else{
		if(hasFocus){
			leaveFocus();
		}
	}
	return false;
}

template<typename Type>
bool ofxGuiInputField<Type>::mouseDragged(ofMouseEventArgs & args){

	ofxGuiElement::mouseDragged(args);

	if(!hasFocus || !bMousePressed)
		return false;

	float cursorX = args.x - (localToScreen(getShape()).getRight() - textPadding - inputWidth);
	int cursorPos = ofMap(cursorX,0,inputWidth,0,input.size(),true);
	calculateSelectionArea(mousePressedPos,cursorPos);
	return false;
}

template<typename Type>
bool ofxGuiInputField<Type>::mouseReleased(ofMouseEventArgs & args){

	ofxGuiElement::mouseReleased(args);

	//	if(bUpdateOnEnterOnly){ //TODO not implemented yet
	//		value.enableEvents();
	//	}

	if(hasFocus){
		if(pressCounter == 1 && !hasSelectedText()){
			//activated panel without selecting an area => select all
			calculateSelectionArea(0, input.size());
		}
	}

	bMousePressed = false;
	return false;
}

template<typename Type>
typename std::enable_if<std::is_integral<Type>::value, Type>::type
getRange(Type min, Type max, float width){
	double range = max - min;
	range /= width*4;
	return std::max(range,1.0);
}

template<typename Type>
typename std::enable_if<std::is_floating_point<Type>::value, Type>::type
getRange(Type min, Type max, float width){
	double range = max - min;
	range /= width*4;
	return range;
}

template<typename Type>
bool ofxGuiInputField<Type>::mouseScrolled(ofMouseEventArgs & args){

	ofxGuiElement::mouseScrolled(args);

	if(mouseInside || hasFocus){
		if(args.y>0 || args.y<0){
			double range = getRange(value.getMin(),value.getMax(),getWidth());
			Type newValue = value + ofMap(args.y,-1,1,-range, range);
			newValue = ofClamp(newValue,value.getMin(),value.getMax());
			value = newValue;
		}
		return true;
	}else{
		return false;
	}
}

template<>
bool ofxGuiInputField<std::string>::mouseScrolled(ofMouseEventArgs & args){
	if(mouseInside || hasFocus){
		return true;
	}else{
		return false;
	}
}

template<typename Type>
void ofxGuiInputField<Type>::registerKeyEvents(){
	if(bRegisteredForKeyEvents == true){
		return; // already registered.
	}
	bRegisteredForKeyEvents = true;
	ofRegisterKeyEvents(this, OF_EVENT_ORDER_BEFORE_APP);
}

template<typename Type>
void ofxGuiInputField<Type>::unregisterKeyEvents(){
	if(bRegisteredForKeyEvents == false){
		return; // not registered.
	}
	ofUnregisterKeyEvents(this, OF_EVENT_ORDER_BEFORE_APP);
	bRegisteredForKeyEvents = false;
}

template<typename Type>
bool ofxGuiInputField<Type>::keyPressed(ofKeyEventArgs & args){
	if(hasFocus && !bMousePressed){

		int newCursorIdx = -1;
		if(args.key >= '0' && args.key <= '9'){
			int digit = args.key - '0';
			newCursorIdx = insertKeystroke(ofToString(digit));
		}else if(args.key == '.' ){
			newCursorIdx = insertKeystroke(".");
		}else if(args.key == OF_KEY_BACKSPACE || args.key == OF_KEY_DEL){
			if(hasSelectedText()){
				input.erase(selectStartPos,selectEndPos-selectStartPos);
				newCursorIdx = selectStartPos;
				parseInput();
			}else{
				int deleteIdx = -1;
				if(args.key == OF_KEY_BACKSPACE){
					deleteIdx = selectStartPos-1;
				}else if(args.key == OF_KEY_DEL){
					deleteIdx = selectStartPos;
				}

				//erase char if valid deleteIdx
				if(deleteIdx >= 0 && deleteIdx < (int)input.size()){
					input.erase(deleteIdx,1);
					newCursorIdx = deleteIdx;
					parseInput();
				}
			}
		}else if(args.key == OF_KEY_LEFT){
			if(hasSelectedText()){
				newCursorIdx = selectStartPos;
			}else{
				newCursorIdx = selectStartPos == 0 ? 0 : selectStartPos-1;
			}
		}else if(args.key == OF_KEY_RIGHT){
			if(hasSelectedText()){
				newCursorIdx = selectEndPos;
			}else{
				newCursorIdx = selectStartPos == (int)input.size() ? (int)input.size() : selectStartPos+1;
			}
		}else if(args.key == OF_KEY_RETURN){
			leaveFocus();
		}else if((args.key >= '!' && args.key <= '~')
				 || (args.key <= 'a' && args.key >= 'Z')
				 || (args.key == ' ')){
			newCursorIdx = insertAlphabetic(ofToString((char)args.key));
		}

		if(newCursorIdx != -1){
			//set cursor
			calculateSelectionArea(newCursorIdx,newCursorIdx);
		}
		return true;
	}
	return false;
}

template<typename Type>
bool ofxGuiInputField<Type>::keyReleased(ofKeyEventArgs & args){
	return hasFocus && !bMousePressed;
}

template<typename Type>
int ofxGuiInputField<Type>::insertKeystroke(const std::string & character){
	if(hasSelectedText()){
		input.erase(selectStartPos,selectEndPos-selectStartPos);
	}
	input.insert(selectStartPos,character);
	parseInput();
	return selectStartPos + 1;
}

template<typename Type>
int ofxGuiInputField<Type>::insertAlphabetic(const std::string &){
	return -1; //do nothing for numeric types, cursor/selection area stays the same
}

template<>
int ofxGuiInputField<std::string>::insertAlphabetic(const std::string & character){
	return insertKeystroke(character);
}

template<typename Type>
Type ofxGuiInputField<Type>::operator=(Type v){
	value = v;
	return v;
}

template<typename Type>
ofxGuiInputField<Type>::operator const Type & (){
	return value;
}

template<typename Type>
void ofxGuiInputField<Type>::generateDraw(){

	ofxGuiElement::generateDraw();

	generateText();
}

template<typename Type>
void ofxGuiInputField<Type>::generateText(){
	std::string valStr = input;
	textMesh = getTextMesh(getName(), textPadding, getShape().height / 2 + 4);
	textMesh.append(getTextMesh(valStr, getShape().width - textPadding - getTextBoundingBox(valStr,0,0).width, getShape().height / 2 + 4));
}

template<typename Type>
void ofxGuiInputField<Type>::render(){
	ofxGuiElement::render();

	if(hasFocus){
		drawFocusedBB();

		if(hasSelectedText()){
			drawSelectedArea();
		}else{
			drawCursor();
		}
	}

	drawMesh();
}

template<typename Type>
bool ofxGuiInputField<Type>::hasSelectedText(){
	return selectStartPos != selectEndPos;
}

template<typename Type>
void ofxGuiInputField<Type>::drawMesh(){
	ofBlendMode blendMode = ofGetStyle().blendingMode;
	if(blendMode!=OF_BLENDMODE_ALPHA){
		ofEnableAlphaBlending();
	}
	ofSetColor(textColor);

	bindFontTexture();
	textMesh.draw();
	unbindFontTexture();

	ofColor c = ofGetStyle().color;
	ofSetColor(c);
	if(blendMode!=OF_BLENDMODE_ALPHA){
		ofEnableBlendMode(blendMode);
	}
}

template<typename Type>
void ofxGuiInputField<Type>::drawSelectedArea(){
	ofPushStyle();
	ofSetColor(fillColor);
	ofFill();
	ofDrawRectangle( selectStartX, 1, selectionWidth, getShape().height-2 );
	ofPopStyle();
}

template<typename Type>
void ofxGuiInputField<Type>::drawCursor(){
	ofPushStyle();
	ofSetColor(textColor);
	ofDrawLine( selectStartX, 0, selectStartX, getShape().getHeight() );
	ofPopStyle();
}

template<typename Type>
void ofxGuiInputField<Type>::drawFocusedBB(){
	ofPushStyle();
	ofSetColor(textColor);
	ofDrawLine( selectStartX, 0, selectStartX, getShape().getHeight() );
	ofPopStyle();
}

template<typename Type>
bool ofxGuiInputField<Type>::setValue(float mx, float my, bool bCheck){
	return false;
}

template<typename Type>
ofAbstractParameter & ofxGuiInputField<Type>::getParameter(){
	return value;
}

template<typename Type>
void ofxGuiInputField<Type>::parseInput(){
	bChangedInternally = true;
	Type tmpVal = ofToFloat(input);
	if(tmpVal < getMin()){
		tmpVal = getMin();
	}else if(tmpVal > getMax()){
		tmpVal = getMax();
	}
	value = tmpVal;
}

template<>
void ofxGuiInputField<std::string>::parseInput(){
	bChangedInternally = true;
	value = input;
}

template<typename Type>
void ofxGuiInputField<Type>::valueChanged(Type & value){
	if(bChangedInternally){
		bChangedInternally = false;
		inputWidth = getTextBoundingBox(input,0,0).width;
	}else{
		input = ofToString(value);
		inputWidth = getTextBoundingBox(input,0,0).width;
		if(hasFocus){
			int cursorPos = input.size();
			calculateSelectionArea(cursorPos,cursorPos);
		}
	}
	setNeedsRedraw();
}

template<typename Type>
void ofxGuiInputField<Type>::leaveFocus(){
	pressCounter = 0;
	input = ofToString(value);
	inputWidth = getTextBoundingBox(input,0,0).width;
	hasFocus = false;
	setNeedsRedraw();
}

template<typename Type>
std::string ofxGuiInputField<Type>::getClassType(){
	return "input";
}

template<typename Type>
std::vector<std::string> ofxGuiInputField<Type>::getClassTypes(){
	std::vector<std::string> types = ofxGuiElement::getClassTypes();
	types.push_back(getClassType());
	return types;
}

template class ofxGuiInputField<int8_t>;
template class ofxGuiInputField<uint8_t>;
template class ofxGuiInputField<int16_t>;
template class ofxGuiInputField<uint16_t>;
template class ofxGuiInputField<int32_t>;
template class ofxGuiInputField<uint32_t>;
template class ofxGuiInputField<int64_t>;
template class ofxGuiInputField<uint64_t>;
template class ofxGuiInputField<float>;
template class ofxGuiInputField<double>;
template class ofxGuiInputField<std::string>;
<commit_msg>fixed missed negative character for inputfields<commit_after>#include "ofxGuiInputField.h"
#include "ofGraphics.h"

template<typename Type>
ofxGuiInputField<Type>::ofxGuiInputField(){

	setup();

}

template<typename Type>
ofxGuiInputField<Type>::ofxGuiInputField(const ofJson &config)
	:ofxGuiInputField(){

	_setConfig(config);

}

template<typename Type>
ofxGuiInputField<Type>::ofxGuiInputField(ofParameter<Type>& _val, const ofJson &config)
	:ofxGuiInputField(){

	value.makeReferenceTo(_val);
	input = ofToString(value);
	inputWidth = getTextBoundingBox(input,0,0).width;
	value.addListener(this,&ofxGuiInputField::valueChanged);
	pressCounter = 0;
	_setConfig(config);

}

template<typename Type>
ofxGuiInputField<Type>::ofxGuiInputField(const std::string& _name, Type _val, Type _min, Type _max, const ofJson &config)
	:ofxGuiInputField(value.set(_name,_val,_min,_max), config){
}

template<typename Type>
ofxGuiInputField<Type>::~ofxGuiInputField(){
	value.removeListener(this,&ofxGuiInputField::valueChanged);
	unregisterKeyEvents();
}

template<typename Type>
void ofxGuiInputField<Type>::setup(){

	bChangedInternally = false;
	bMousePressed = false;
	mouseInside = false;
	bRegisteredForKeyEvents = false;
	hasFocus = false;
	mousePressedPos = -1;
	selectStartX = -1;
	selectStartPos = -1;
	selectEndPos = -1;
	pressCounter = 0;
	inputWidth = 0;
	selectionWidth = 0;
	setTheme();
	registerMouseEvents();
	registerKeyEvents();

}

template<typename Type>
void ofxGuiInputField<Type>::setMin(Type min){
	value.setMin(min);
}

template<typename Type>
Type ofxGuiInputField<Type>::getMin(){
	return value.getMin();
}

template<typename Type>
void ofxGuiInputField<Type>::setMax(Type max){
	value.setMax(max);
}

template<typename Type>
Type ofxGuiInputField<Type>::getMax(){
	return value.getMax();
}

template<typename Type>
void ofxGuiInputField<Type>::calculateSelectionArea(int selectIdx1, int selectIdx2){
	std::string preSelectStr, selectStr;

	if(selectIdx1 <= selectIdx2){
		selectStartPos = selectIdx1;
		selectEndPos = selectIdx2;
	}else{
		selectStartPos = selectIdx2;
		selectEndPos = selectIdx1;
	}

	float preSelectWidth = 0;
	if(selectStartPos > 0){
		preSelectStr.assign(input,0,selectStartPos);
		preSelectWidth = getTextBoundingBox(preSelectStr,0,0).width;
	}
	selectStartX = getWidth() - textPadding - inputWidth + preSelectWidth;

	if(hasSelectedText()){
		selectStr.assign(input,selectStartPos,selectEndPos-selectStartPos);
		selectionWidth = getTextBoundingBox(selectStr,0,0).width;
	}
}

template<typename Type>
float ofxGuiInputField<Type>::getMinWidth(){
	std::string text = ofToString(value.get());
	if(showName){
		if(!getName().empty()){
			text = getName() + ": ";
		}
	}

	return ofxGuiElement::getTextWidth(text);
}

template<typename Type>
float ofxGuiInputField<Type>::getMinHeight(){
	std::string text = ofToString(value.get());
	if(showName){
		if(!getName().empty()){
			text = getName() + ": ";
		}
	}
	return ofxGuiElement::getTextHeight(text);
}

template<typename Type>
bool ofxGuiInputField<Type>::mouseMoved(ofMouseEventArgs & args){

	ofxGuiElement::mouseMoved(args);

	mouseInside = !isHidden() && isMouseOver();
	return mouseInside;
}

template<typename Type>
bool ofxGuiInputField<Type>::mousePressed(ofMouseEventArgs & args){

	ofxGuiElement::mousePressed(args);

	if(isMouseOver()){
		bMousePressed = true;
		hasFocus = true;

		float cursorX = args.x - (localToScreen(getShape()).getRight() - textPadding - inputWidth);
		int cursorPos = ofMap(cursorX,0,inputWidth,0,input.size(),true);
		mousePressedPos = cursorPos;

		calculateSelectionArea(cursorPos, cursorPos);

		pressCounter++;

	}else{
		if(hasFocus){
			leaveFocus();
		}
	}
	return false;
}

template<typename Type>
bool ofxGuiInputField<Type>::mouseDragged(ofMouseEventArgs & args){

	ofxGuiElement::mouseDragged(args);

	if(!hasFocus || !bMousePressed)
		return false;

	float cursorX = args.x - (localToScreen(getShape()).getRight() - textPadding - inputWidth);
	int cursorPos = ofMap(cursorX,0,inputWidth,0,input.size(),true);
	calculateSelectionArea(mousePressedPos,cursorPos);
	return false;
}

template<typename Type>
bool ofxGuiInputField<Type>::mouseReleased(ofMouseEventArgs & args){

	ofxGuiElement::mouseReleased(args);

	//	if(bUpdateOnEnterOnly){ //TODO not implemented yet
	//		value.enableEvents();
	//	}

	if(hasFocus){
		if(pressCounter == 1 && !hasSelectedText()){
			//activated panel without selecting an area => select all
			calculateSelectionArea(0, input.size());
		}
	}

	bMousePressed = false;
	return false;
}

template<typename Type>
typename std::enable_if<std::is_integral<Type>::value, Type>::type
getRange(Type min, Type max, float width){
	double range = max - min;
	range /= width*4;
	return std::max(range,1.0);
}

template<typename Type>
typename std::enable_if<std::is_floating_point<Type>::value, Type>::type
getRange(Type min, Type max, float width){
	double range = max - min;
	range /= width*4;
	return range;
}

template<typename Type>
bool ofxGuiInputField<Type>::mouseScrolled(ofMouseEventArgs & args){

	ofxGuiElement::mouseScrolled(args);

	if(mouseInside || hasFocus){
		if(args.y>0 || args.y<0){
			double range = getRange(value.getMin(),value.getMax(),getWidth());
			Type newValue = value + ofMap(args.y,-1,1,-range, range);
			newValue = ofClamp(newValue,value.getMin(),value.getMax());
			value = newValue;
		}
		return true;
	}else{
		return false;
	}
}

template<>
bool ofxGuiInputField<std::string>::mouseScrolled(ofMouseEventArgs & args){
	if(mouseInside || hasFocus){
		return true;
	}else{
		return false;
	}
}

template<typename Type>
void ofxGuiInputField<Type>::registerKeyEvents(){
	if(bRegisteredForKeyEvents == true){
		return; // already registered.
	}
	bRegisteredForKeyEvents = true;
	ofRegisterKeyEvents(this, OF_EVENT_ORDER_BEFORE_APP);
}

template<typename Type>
void ofxGuiInputField<Type>::unregisterKeyEvents(){
	if(bRegisteredForKeyEvents == false){
		return; // not registered.
	}
	ofUnregisterKeyEvents(this, OF_EVENT_ORDER_BEFORE_APP);
	bRegisteredForKeyEvents = false;
}

template<typename Type>
bool ofxGuiInputField<Type>::keyPressed(ofKeyEventArgs & args){
	if(hasFocus && !bMousePressed){

		int newCursorIdx = -1;
		if(args.key >= '0' && args.key <= '9'){
			int digit = args.key - '0';
			newCursorIdx = insertKeystroke(ofToString(digit));
		}else if(args.key == '-' ){
			newCursorIdx = insertKeystroke("-");
		}else if(args.key == '.' ){
			newCursorIdx = insertKeystroke(".");
		}else if(args.key == OF_KEY_BACKSPACE || args.key == OF_KEY_DEL){
			if(hasSelectedText()){
				input.erase(selectStartPos,selectEndPos-selectStartPos);
				newCursorIdx = selectStartPos;
				parseInput();
			}else{
				int deleteIdx = -1;
				if(args.key == OF_KEY_BACKSPACE){
					deleteIdx = selectStartPos-1;
				}else if(args.key == OF_KEY_DEL){
					deleteIdx = selectStartPos;
				}

				//erase char if valid deleteIdx
				if(deleteIdx >= 0 && deleteIdx < (int)input.size()){
					input.erase(deleteIdx,1);
					newCursorIdx = deleteIdx;
					parseInput();
				}
			}
		}else if(args.key == OF_KEY_LEFT){
			if(hasSelectedText()){
				newCursorIdx = selectStartPos;
			}else{
				newCursorIdx = selectStartPos == 0 ? 0 : selectStartPos-1;
			}
		}else if(args.key == OF_KEY_RIGHT){
			if(hasSelectedText()){
				newCursorIdx = selectEndPos;
			}else{
				newCursorIdx = selectStartPos == (int)input.size() ? (int)input.size() : selectStartPos+1;
			}
		}else if(args.key == OF_KEY_RETURN){
			leaveFocus();
		}else if((args.key >= '!' && args.key <= '~')
				 || (args.key <= 'a' && args.key >= 'Z')
				 || (args.key == ' ')){
			newCursorIdx = insertAlphabetic(ofToString((char)args.key));
		}

		if(newCursorIdx != -1){
			//set cursor
			calculateSelectionArea(newCursorIdx,newCursorIdx);
		}
		return true;
	}
	return false;
}

template<typename Type>
bool ofxGuiInputField<Type>::keyReleased(ofKeyEventArgs & args){
	return hasFocus && !bMousePressed;
}

template<typename Type>
int ofxGuiInputField<Type>::insertKeystroke(const std::string & character){
	if(hasSelectedText()){
		input.erase(selectStartPos,selectEndPos-selectStartPos);
	}
	input.insert(selectStartPos,character);
	parseInput();
	return selectStartPos + 1;
}

template<typename Type>
int ofxGuiInputField<Type>::insertAlphabetic(const std::string &){
	return -1; //do nothing for numeric types, cursor/selection area stays the same
}

template<>
int ofxGuiInputField<std::string>::insertAlphabetic(const std::string & character){
	return insertKeystroke(character);
}

template<typename Type>
Type ofxGuiInputField<Type>::operator=(Type v){
	value = v;
	return v;
}

template<typename Type>
ofxGuiInputField<Type>::operator const Type & (){
	return value;
}

template<typename Type>
void ofxGuiInputField<Type>::generateDraw(){

	ofxGuiElement::generateDraw();

	generateText();
}

template<typename Type>
void ofxGuiInputField<Type>::generateText(){
	std::string valStr = input;
	textMesh = getTextMesh(getName(), textPadding, getShape().height / 2 + 4);
	textMesh.append(getTextMesh(valStr, getShape().width - textPadding - getTextBoundingBox(valStr,0,0).width, getShape().height / 2 + 4));
}

template<typename Type>
void ofxGuiInputField<Type>::render(){
	ofxGuiElement::render();

	if(hasFocus){
		drawFocusedBB();

		if(hasSelectedText()){
			drawSelectedArea();
		}else{
			drawCursor();
		}
	}

	drawMesh();
}

template<typename Type>
bool ofxGuiInputField<Type>::hasSelectedText(){
	return selectStartPos != selectEndPos;
}

template<typename Type>
void ofxGuiInputField<Type>::drawMesh(){
	ofBlendMode blendMode = ofGetStyle().blendingMode;
	if(blendMode!=OF_BLENDMODE_ALPHA){
		ofEnableAlphaBlending();
	}
	ofSetColor(textColor);

	bindFontTexture();
	textMesh.draw();
	unbindFontTexture();

	ofColor c = ofGetStyle().color;
	ofSetColor(c);
	if(blendMode!=OF_BLENDMODE_ALPHA){
		ofEnableBlendMode(blendMode);
	}
}

template<typename Type>
void ofxGuiInputField<Type>::drawSelectedArea(){
	ofPushStyle();
	ofSetColor(fillColor);
	ofFill();
	ofDrawRectangle( selectStartX, 1, selectionWidth, getShape().height-2 );
	ofPopStyle();
}

template<typename Type>
void ofxGuiInputField<Type>::drawCursor(){
	ofPushStyle();
	ofSetColor(textColor);
	ofDrawLine( selectStartX, 0, selectStartX, getShape().getHeight() );
	ofPopStyle();
}

template<typename Type>
void ofxGuiInputField<Type>::drawFocusedBB(){
	ofPushStyle();
	ofSetColor(textColor);
	ofDrawLine( selectStartX, 0, selectStartX, getShape().getHeight() );
	ofPopStyle();
}

template<typename Type>
bool ofxGuiInputField<Type>::setValue(float mx, float my, bool bCheck){
	return false;
}

template<typename Type>
ofAbstractParameter & ofxGuiInputField<Type>::getParameter(){
	return value;
}

template<typename Type>
void ofxGuiInputField<Type>::parseInput(){
	bChangedInternally = true;
	Type tmpVal = ofToFloat(input);
	if(tmpVal < getMin()){
		tmpVal = getMin();
	}else if(tmpVal > getMax()){
		tmpVal = getMax();
	}
	value = tmpVal;
}

template<>
void ofxGuiInputField<std::string>::parseInput(){
	bChangedInternally = true;
	value = input;
}

template<typename Type>
void ofxGuiInputField<Type>::valueChanged(Type & value){
	if(bChangedInternally){
		bChangedInternally = false;
		inputWidth = getTextBoundingBox(input,0,0).width;
	}else{
		input = ofToString(value);
		inputWidth = getTextBoundingBox(input,0,0).width;
		if(hasFocus){
			int cursorPos = input.size();
			calculateSelectionArea(cursorPos,cursorPos);
		}
	}
	setNeedsRedraw();
}

template<typename Type>
void ofxGuiInputField<Type>::leaveFocus(){
	pressCounter = 0;
	input = ofToString(value);
	inputWidth = getTextBoundingBox(input,0,0).width;
	hasFocus = false;
	setNeedsRedraw();
}

template<typename Type>
std::string ofxGuiInputField<Type>::getClassType(){
	return "input";
}

template<typename Type>
std::vector<std::string> ofxGuiInputField<Type>::getClassTypes(){
	std::vector<std::string> types = ofxGuiElement::getClassTypes();
	types.push_back(getClassType());
	return types;
}

template class ofxGuiInputField<int8_t>;
template class ofxGuiInputField<uint8_t>;
template class ofxGuiInputField<int16_t>;
template class ofxGuiInputField<uint16_t>;
template class ofxGuiInputField<int32_t>;
template class ofxGuiInputField<uint32_t>;
template class ofxGuiInputField<int64_t>;
template class ofxGuiInputField<uint64_t>;
template class ofxGuiInputField<float>;
template class ofxGuiInputField<double>;
template class ofxGuiInputField<std::string>;
<|endoftext|>


<commit_before>#include "sketchlistwidget.h"
#include "ui_sketchlistwidget.h"
#include "../imaging/phnimage.h"
#include <QDebug>

SketchListWidget::SketchListWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::SketchListWidget)
{
    ui->setupUi(this);
    setStyleSheet("QListWidget::item { border: 5px solid black; }");

    loadIcon = QIcon(":/icons/sketchloading.png");

    stopLoadingIcons();
}

SketchListWidget::~SketchListWidget()
{
    delete ui;
}

void SketchListWidget::setItemSketch(QListWidgetItem *item, const SketchInfo &sketch) {
    QVariant var;
    var.setValue(sketch);
    item->setData(Qt::UserRole, var);
    item->setText(sketch.name);
    item->setIcon(sketch.hasIcon ? sketch.icon : this->loadIcon);
}

SketchInfo SketchListWidget::getItemSketch(const QListWidgetItem *item) {
    return qvariant_cast<SketchInfo>(item->data(Qt::UserRole));
}

void SketchListWidget::refreshSketches() {
    stk500ListSketches task;
    serial->execute(task);

    // Synchronize the items in the list widget with the sketches
    QListWidgetItem *selected = NULL;
    for (int i = 0; i < task.sketches.length(); i++) {
        SketchInfo sketch = task.sketches[i];
        QString sketchName = sketch.name;

        // First attempt to find the sketch icon in the list
        QListWidgetItem *itemFound = NULL;
        for (int j = i; j < ui->list->count(); j++) {
            QListWidgetItem *item = ui->list->item(j);
            if (item->text() == sketchName) {
                SketchInfo existing = getItemSketch(item);
                itemFound = item;
                memcpy(sketch.iconData, existing.iconData, sizeof(sketch.iconData));
                sketch.icon = existing.icon;
                sketch.hasIcon = existing.hasIcon;
                sketch.iconDirty = existing.iconDirty;
                break;
            }
        }

        // Add a new item at the current position if not found
        if (itemFound == NULL) {
            itemFound = new QListWidgetItem(sketchName);
            ui->list->insertItem(i, itemFound);

        } else if (itemFound != ui->list->item(i)) {
            // Move the item position
            ui->list->removeItemWidget(itemFound);
            ui->list->addItem(itemFound);
        }

        // Reset the item icon loading state
        if (sketch.iconBlock == 0) {
            // No icon available; use default
            sketch.hasIcon = true;
            sketch.iconDirty = false;
            sketch.setIcon(SKETCH_DEFAULT_ICON);
        } else {
            // Schedule for loading
            sketch.iconDirty = true;
        }

        // Check if current sketch
        if (sketchName == task.currentSketch) {
            selected = itemFound;
        }

        // Store sketch information in item
        setItemSketch(itemFound, sketch);
    }

    // Remove any items past the count limit
    while (ui->list->count() > task.sketches.length()) {
        delete ui->list->item(ui->list->count() - 1);
    }

    // Select the selected item
    if (selected != NULL) {
        selected->setSelected(true);
    }

    // Connect the signal fired when a task is finished
    connect(serial, SIGNAL(taskFinished(stk500Task*)),
            this, SLOT(serialTaskFinished(stk500Task*)), Qt::UniqueConnection);

    // Initiate icon load processing
    startLoadingIcons();
}

void SketchListWidget::stopLoadingIcons() {
    lastTask = NULL;
}

void SketchListWidget::startLoadingIcons() {
    // Find the first icon that requires loading
    SketchInfo sketch;
    bool foundSketch = false;
    for (int i = 0; i < ui->list->count(); i++) {
        QListWidgetItem *item = ui->list->item(i);
        SketchInfo itemSketch = getItemSketch(item);
        if (itemSketch.iconDirty) {
            if (itemSketch.hasIcon) {
                // Low priority, take first
                if (!foundSketch) sketch = itemSketch;
                foundSketch = true;
            } else {
                // High priority, take it now
                sketch = itemSketch;
                foundSketch = true;
                break;
            }
        }
    }
    if (foundSketch) {
        lastTask = new stk500LoadIcon(sketch);
        serial->execute(*lastTask, true);
    } else {
        stopLoadingIcons();
    }
}

void SketchListWidget::serialTaskFinished(stk500Task *task) {
    // Filter out the requested task
    if (lastTask != task) return;

    // Find the item belonging to this task
    SketchInfo &sketch = lastTask->sketch;
    QString sketchName = sketch.name;
    for (int i = 0; i < ui->list->count(); i++) {
        QListWidgetItem *item = ui->list->item(i);
        if (item->text() == sketchName) {
            setItemSketch(item, sketch);
            break;
        }
    }

    // Memory management: need to delete this when done
    delete lastTask;

    // If not aborted, continue with the next task
    startLoadingIcons();
}

QList<QString> SketchListWidget::getSketchNames() {
    QList<QString> names;
    for (int i = 0; i < ui->list->count(); i++) {
        names.append(ui->list->item(i)->text());
    }
    return names;
}

void SketchListWidget::deleteSketch(const SketchInfo &sketch) {
    if ((sketch.index >= 0) && (sketch.index < ui->list->count())) {
        delete ui->list->item(sketch.index);
    }
}

void SketchListWidget::updateSketch(SketchInfo sketch) {
    QListWidgetItem* item;
    if ((sketch.index < 0) || (sketch.index >= ui->list->count())) {
        // Add the item
        sketch.index = ui->list->count();
        item = new QListWidgetItem(sketch.name);
        ui->list->addItem(item);
    } else {
        // Update existing item
        item = ui->list->item(sketch.index);
    }
    setItemSketch(item, sketch);
}

bool SketchListWidget::hasSelectedSketch() {
    return getSelectedName() != "";
}

QString SketchListWidget::getSelectedName() {
    QList<QListWidgetItem*> items = ui->list->selectedItems();
    if (items.isEmpty()) return "";
    return items[0]->text();
}

SketchInfo SketchListWidget::getSelectedSketch() {
    SketchInfo sketch;
    QList<QListWidgetItem*> items = ui->list->selectedItems();
    if (!items.isEmpty()) {
        sketch = getItemSketch(items[0]);

        // If icon not yet loaded, load it now.
        if (sketch.iconDirty) {
            stk500LoadIcon task(sketch);
            serial->execute(task);
            sketch = task.sketch;
            setItemSketch(items[0], sketch);
        }
    }
    return sketch;
}

void SketchListWidget::setSelectedSketch(const SketchInfo &sketch) {
    QList<QListWidgetItem*> items = ui->list->selectedItems();
    if (!items.isEmpty()) {
        setItemSketch(items[0], sketch);
    }
}

void SketchListWidget::on_list_itemDoubleClicked(QListWidgetItem*) {
    emit sketchDoubleClicked();
}
<commit_msg>Fix sketch list items bugging out<commit_after>#include "sketchlistwidget.h"
#include "ui_sketchlistwidget.h"
#include "../imaging/phnimage.h"
#include <QDebug>

SketchListWidget::SketchListWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::SketchListWidget)
{
    ui->setupUi(this);
    setStyleSheet("QListWidget::item { border: 5px solid black; }");

    loadIcon = QIcon(":/icons/sketchloading.png");

    stopLoadingIcons();
}

SketchListWidget::~SketchListWidget()
{
    delete ui;
}

void SketchListWidget::setItemSketch(QListWidgetItem *item, const SketchInfo &sketch) {
    QVariant var;
    var.setValue(sketch);
    item->setData(Qt::UserRole, var);
    item->setText(sketch.name);
    item->setIcon(sketch.hasIcon ? sketch.icon : this->loadIcon);
}

SketchInfo SketchListWidget::getItemSketch(const QListWidgetItem *item) {
    return qvariant_cast<SketchInfo>(item->data(Qt::UserRole));
}

void SketchListWidget::refreshSketches() {
    stk500ListSketches task;
    serial->execute(task);

    // Synchronize the items in the list widget with the sketches
    QListWidgetItem *selected = NULL;
    for (int i = 0; i < task.sketches.length(); i++) {
        SketchInfo sketch = task.sketches[i];
        QString sketchName = sketch.name;

        // First attempt to find the sketch icon in the list
        QListWidgetItem *itemFound = NULL;
        for (int j = i; j < ui->list->count(); j++) {
            QListWidgetItem *item = ui->list->item(j);
            if (item->text() == sketchName) {
                SketchInfo existing = getItemSketch(item);
                itemFound = item;
                memcpy(sketch.iconData, existing.iconData, sizeof(sketch.iconData));
                sketch.icon = existing.icon;
                sketch.hasIcon = existing.hasIcon;
                sketch.iconDirty = existing.iconDirty;
                break;
            }
        }

        // Add a new item at the current position if not found
        if (itemFound == NULL) {
            itemFound = new QListWidgetItem(sketchName);
            ui->list->insertItem(i, itemFound);

        } else if (itemFound != ui->list->item(i)) {
            // Move the item position; make a clone
            QListWidgetItem *itemFoundClone = itemFound->clone();
            delete itemFound;
            itemFound = itemFoundClone;
            ui->list->insertItem(i, itemFound);
        }

        // Reset the item icon loading state
        if (sketch.iconBlock == 0) {
            // No icon available; use default
            sketch.hasIcon = true;
            sketch.iconDirty = false;
            sketch.setIcon(SKETCH_DEFAULT_ICON);
        } else {
            // Schedule for loading
            sketch.iconDirty = true;
        }

        // Check if current sketch
        if (sketchName == task.currentSketch) {
            selected = itemFound;
        }

        // Store sketch information in item
        setItemSketch(itemFound, sketch);
    }

    // Remove any items past the count limit
    while (ui->list->count() > task.sketches.length()) {
        delete ui->list->item(ui->list->count() - 1);
    }

    // Select the selected item
    if (selected != NULL) {
        selected->setSelected(true);
    }

    // Connect the signal fired when a task is finished
    connect(serial, SIGNAL(taskFinished(stk500Task*)),
            this, SLOT(serialTaskFinished(stk500Task*)), Qt::UniqueConnection);

    // Initiate icon load processing
    startLoadingIcons();
}

void SketchListWidget::stopLoadingIcons() {
    lastTask = NULL;
}

void SketchListWidget::startLoadingIcons() {
    // Find the first icon that requires loading
    SketchInfo sketch;
    bool foundSketch = false;
    for (int i = 0; i < ui->list->count(); i++) {
        QListWidgetItem *item = ui->list->item(i);
        SketchInfo itemSketch = getItemSketch(item);
        if (itemSketch.iconDirty) {
            if (itemSketch.hasIcon) {
                // Low priority, take first
                if (!foundSketch) sketch = itemSketch;
                foundSketch = true;
            } else {
                // High priority, take it now
                sketch = itemSketch;
                foundSketch = true;
                break;
            }
        }
    }
    if (foundSketch) {
        lastTask = new stk500LoadIcon(sketch);
        serial->execute(*lastTask, true);
    } else {
        stopLoadingIcons();
    }
}

void SketchListWidget::serialTaskFinished(stk500Task *task) {
    // Filter out the requested task
    if (lastTask != task) return;

    // Find the item belonging to this task
    SketchInfo &sketch = lastTask->sketch;
    QString sketchName = sketch.name;
    for (int i = 0; i < ui->list->count(); i++) {
        QListWidgetItem *item = ui->list->item(i);
        if (item->text() == sketchName) {
            setItemSketch(item, sketch);
            break;
        }
    }

    // Memory management: need to delete this when done
    delete lastTask;

    // If not aborted, continue with the next task
    startLoadingIcons();
}

QList<QString> SketchListWidget::getSketchNames() {
    QList<QString> names;
    for (int i = 0; i < ui->list->count(); i++) {
        names.append(ui->list->item(i)->text());
    }
    return names;
}

void SketchListWidget::deleteSketch(const SketchInfo &sketch) {
    if ((sketch.index >= 0) && (sketch.index < ui->list->count())) {
        delete ui->list->item(sketch.index);
    }
}

void SketchListWidget::updateSketch(SketchInfo sketch) {
    QListWidgetItem* item;
    if ((sketch.index < 0) || (sketch.index >= ui->list->count())) {
        // Add the item
        sketch.index = ui->list->count();
        item = new QListWidgetItem(sketch.name);
        ui->list->addItem(item);
    } else {
        // Update existing item
        item = ui->list->item(sketch.index);
    }
    setItemSketch(item, sketch);
}

bool SketchListWidget::hasSelectedSketch() {
    return getSelectedName() != "";
}

QString SketchListWidget::getSelectedName() {
    QList<QListWidgetItem*> items = ui->list->selectedItems();
    if (items.isEmpty()) return "";
    return items[0]->text();
}

SketchInfo SketchListWidget::getSelectedSketch() {
    SketchInfo sketch;
    QList<QListWidgetItem*> items = ui->list->selectedItems();
    if (!items.isEmpty()) {
        sketch = getItemSketch(items[0]);

        // If icon not yet loaded, load it now.
        if (sketch.iconDirty) {
            stk500LoadIcon task(sketch);
            serial->execute(task);
            sketch = task.sketch;
            setItemSketch(items[0], sketch);
        }
    }
    return sketch;
}

void SketchListWidget::setSelectedSketch(const SketchInfo &sketch) {
    QList<QListWidgetItem*> items = ui->list->selectedItems();
    if (!items.isEmpty()) {
        setItemSketch(items[0], sketch);
    }
}

void SketchListWidget::on_list_itemDoubleClicked(QListWidgetItem*) {
    emit sketchDoubleClicked();
}
<|endoftext|>


<commit_before>/* vim: set ai et ts=4 sw=4: */

#include <stdexcept>
#include <pthread.h>
#include <defer.h>
#include <InMemoryStorage.h>

InMemoryStorage::InMemoryStorage() {
    if(pthread_rwlock_init(&_rwlock, NULL) != 0)
        throw std::runtime_error("InMemoryStorage::InMemoryStorage() - pthread_rwlock_init() failed");
}

InMemoryStorage::~InMemoryStorage() {
    if(pthread_rwlock_destroy(&_rwlock) != 0) {
        // suppress 'throw will always call terminate() [-Wterminate]' warning
        // see https://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Pragmas.html
        #pragma GCC diagnostic push
        #pragma GCC diagnostic ignored "-Wterminate"
        throw std::runtime_error("InMemoryStorage::~InMemoryStorage() - pthread_rwlock_destroy() failed");
        #pragma GCC diagnostic pop
    }
}

void InMemoryStorage::set(const std::string& key, const std::string& value) {
    pthread_rwlock_wrlock(&_rwlock);
    defer( pthread_rwlock_unlock(&_rwlock) );

    _kv[key] = value; /* insert or update */
}

std::string InMemoryStorage::get(const std::string& key, bool* found) {
    pthread_rwlock_rdlock(&_rwlock);
    defer( pthread_rwlock_unlock(&_rwlock) );

    auto it = _kv.find(key);
    if(it == _kv.end()) {
        *found = false;
        return "";
    } else {
        *found = true;
        return it->second;
    }
}

void InMemoryStorage::del(const std::string& key, bool* found) {
    pthread_rwlock_wrlock(&_rwlock);
    defer( pthread_rwlock_unlock(&_rwlock) );

    *found = (_kv.erase(key) > 0);
}

<commit_msg>Get rid of GCC-specific pragmas for better portability<commit_after>/* vim: set ai et ts=4 sw=4: */

#include <stdexcept>
#include <pthread.h>
#include <defer.h>
#include <InMemoryStorage.h>

InMemoryStorage::InMemoryStorage() {
    if(pthread_rwlock_init(&_rwlock, NULL) != 0)
        throw std::runtime_error("InMemoryStorage::InMemoryStorage() - pthread_rwlock_init() failed");
}

InMemoryStorage::~InMemoryStorage() {
    pthread_rwlock_destroy(&_rwlock);
}

void InMemoryStorage::set(const std::string& key, const std::string& value) {
    pthread_rwlock_wrlock(&_rwlock);
    defer( pthread_rwlock_unlock(&_rwlock) );

    _kv[key] = value; /* insert or update */
}

std::string InMemoryStorage::get(const std::string& key, bool* found) {
    pthread_rwlock_rdlock(&_rwlock);
    defer( pthread_rwlock_unlock(&_rwlock) );

    auto it = _kv.find(key);
    if(it == _kv.end()) {
        *found = false;
        return "";
    } else {
        *found = true;
        return it->second;
    }
}

void InMemoryStorage::del(const std::string& key, bool* found) {
    pthread_rwlock_wrlock(&_rwlock);
    defer( pthread_rwlock_unlock(&_rwlock) );

    *found = (_kv.erase(key) > 0);
}

<|endoftext|>


<commit_before>/*
 * GameKeeper Framework
 *
 * Copyright (C) 2013 Karol Herbst <gamekeeper@karolherbst.de>
 *
 * 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.
 *
 * 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 <gamekeeper/core/log4cppLogger.h>
#include <gamekeeper/core/log4cpploggerFactory.h>
#include <gamekeeper/core/userpaths.h>

#include <string>
#include <vector>

#include <boost/algorithm/string/erase.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/filesystem/operations.hpp>

#include <log4cpp/Category.hh>
#include <log4cpp/Configurator.hh>
#include <log4cpp/OstreamAppender.hh>
#include <log4cpp/PatternLayout.hh>
#include <log4cpp/Priority.hh>
#include <log4cpp/PropertyConfigurator.hh>

namespace balgo = boost::algorithm;
namespace bfs = boost::filesystem;

GAMEKEEPER_NAMESPACE_START(core)

static std::string
parseLine(std::string line, std::shared_ptr<UserPaths> & userpaths)
{
	balgo::erase_all(line, " ");
	std::string::size_type pos = line.find(".fileName=");

	if(pos != std::string::npos)
	{
		std::string filename = line.substr(pos + 10);
		bfs::path logfile = userpaths->getDataFile(std::string("log/") + filename);
		bfs::create_directories(logfile.parent_path());
		line.replace(pos + 10, std::string::npos, logfile.string());
	}

	if(line.find_first_of("rootCategory") != 0)
	{
		balgo::replace_all(line, "category.", "category.GameKeeper.");
	}
	return line;
}

class Log4cppLoggerFactory::PImpl
{
public:
	PImpl(std::shared_ptr<UserPaths>);
	~PImpl();

	Logger& getComponentLogger(const char * const);

	Logger * rootLogger = nullptr;
	log4cpp::Appender * appender;
	std::unordered_map<const char *, Logger *> loggers;
};

Log4cppLoggerFactory::PImpl::PImpl(std::shared_ptr<UserPaths> userpaths)
:	appender(new log4cpp::OstreamAppender("console", &std::cout))
{
	log4cpp::Category & rootCategory = log4cpp::Category::getInstance("GameKeeper");

	// add default appender
	log4cpp::PatternLayout * layout = new log4cpp::PatternLayout();
	layout->setConversionPattern("%d{%Y-%m-%d %H:%M:%S} [%c] %p: %m%n");
	this->appender->setLayout(layout);

	// start with DEBUG level until the file is loaded, so that we get all errors
	rootCategory.setPriority(log4cpp::Priority::DEBUG);
	rootCategory.addAppender(this->appender);

	this->rootLogger = new Log4cppLogger(rootCategory);

	// read configuration file if exists
	bfs::path cFile = userpaths->getConfigFile("log.conf");
	if(!bfs::exists(cFile))
	{
		return;
	}

	Logger& logger = this->getComponentLogger("logger");
	logger << LogLevel::Debug << "parse config file at: " << cFile.string() << endl;

	bfs::ifstream ifstream(cFile);
	bfs::path cFileGen = userpaths->getConfigFile("log.conf.gen");
	bfs::remove(cFileGen);
	bfs::ofstream ofstream(cFileGen);
	std::string line;
	std::string parsedLine;

	while(!ifstream.eof())
	{
		std::getline(ifstream, line);
		// ignore empty lines
		if(line.empty())
		{
			continue;
		}

		parsedLine = parseLine(line, userpaths);
		logger << LogLevel::Debug << "parsed line \"" << line << "\" to: \"" << parsedLine << "\"" << endl;
		ofstream << parsedLine << std::endl;
	}

	// ignore the file if nothing was parsed
	if(ofstream.tellp() <= 0)
	{
		return;
	}

	logger << LogLevel::Info << "moving to new configuration" << endl;

	log4cpp::PropertyConfigurator pci;
	pci.configure(cFileGen.string());
	bfs::remove(cFileGen);

	// we have another logger noew
	log4cpp::Category::getInstance("GameKeeper").removeAppender(this->appender);
	this->appender = nullptr;
	delete this->rootLogger;
	this->rootLogger = new Log4cppLogger(log4cpp::Category::getInstance("GameKeeper"));
}

Logger&
Log4cppLoggerFactory::getDefaultLogger()
{
	return getComponentLogger("GameKeeper.Default");
}

Logger&
Log4cppLoggerFactory::PImpl::getComponentLogger(const char * const id)
{
	if(this->loggers.find(id) == this->loggers.end())
	{
		std::string log4cppname = "GameKeeper.";
		log4cppname += id;
		Logger * newLogger = new Log4cppLogger(log4cpp::Category::getInstance(log4cppname));
		this->loggers.insert(std::make_pair(id, newLogger));
		return *newLogger;
	}
	return *this->loggers.at(id);
}

Log4cppLoggerFactory::PImpl::~PImpl()
{
	if(this->appender != nullptr)
	{
		log4cpp::Category::getInstance("GameKeeper").removeAppender(this->appender);
	}

	if(this->rootLogger != nullptr)
	{
		delete this->rootLogger;
	}

	for(auto entry : this->loggers)
	{
		delete entry.second;
	}
}

Log4cppLoggerFactory::Log4cppLoggerFactory(std::shared_ptr<UserPaths> userpaths)
:	data(new Log4cppLoggerFactory::PImpl(userpaths)){}

Logger&
Log4cppLoggerFactory::getComponentLogger(const char * const id)
{
	return this->data->getComponentLogger(id);
}

Log4cppLoggerFactory::~Log4cppLoggerFactory(){}

GAMEKEEPER_NAMESPACE_END(core)
<commit_msg>core/log4cpplogger: store rootCategory so that we save some method calls<commit_after>/*
 * GameKeeper Framework
 *
 * Copyright (C) 2013 Karol Herbst <gamekeeper@karolherbst.de>
 *
 * 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.
 *
 * 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 <gamekeeper/core/log4cppLogger.h>
#include <gamekeeper/core/log4cpploggerFactory.h>
#include <gamekeeper/core/userpaths.h>

#include <string>
#include <vector>

#include <boost/algorithm/string/erase.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/filesystem/operations.hpp>

#include <log4cpp/Category.hh>
#include <log4cpp/Configurator.hh>
#include <log4cpp/OstreamAppender.hh>
#include <log4cpp/PatternLayout.hh>
#include <log4cpp/Priority.hh>
#include <log4cpp/PropertyConfigurator.hh>

namespace balgo = boost::algorithm;
namespace bfs = boost::filesystem;

GAMEKEEPER_NAMESPACE_START(core)

static std::string
parseLine(std::string line, std::shared_ptr<UserPaths> & userpaths)
{
	balgo::erase_all(line, " ");
	std::string::size_type pos = line.find(".fileName=");

	if(pos != std::string::npos)
	{
		std::string filename = line.substr(pos + 10);
		bfs::path logfile = userpaths->getDataFile(std::string("log/") + filename);
		bfs::create_directories(logfile.parent_path());
		line.replace(pos + 10, std::string::npos, logfile.string());
	}

	if(line.find_first_of("rootCategory") != 0)
	{
		balgo::replace_all(line, "category.", "category.GameKeeper.");
	}
	return line;
}

class Log4cppLoggerFactory::PImpl
{
public:
	PImpl(std::shared_ptr<UserPaths>);
	~PImpl();

	Logger& getComponentLogger(const char * const);

	Logger * rootLogger = nullptr;
	log4cpp::Appender * appender;
	log4cpp::Category & rootCategory;
	std::unordered_map<const char *, Logger *> loggers;
};

Log4cppLoggerFactory::PImpl::PImpl(std::shared_ptr<UserPaths> userpaths)
:	appender(new log4cpp::OstreamAppender("console", &std::cout)),
	rootCategory(log4cpp::Category::getInstance("GameKeeper"))
{
	// add default appender
	log4cpp::PatternLayout * layout = new log4cpp::PatternLayout();
	layout->setConversionPattern("%d{%Y-%m-%d %H:%M:%S} [%c] %p: %m%n");
	this->appender->setLayout(layout);

	// start with DEBUG level until the file is loaded, so that we get all errors
	this->rootCategory.setPriority(log4cpp::Priority::DEBUG);
	this->rootCategory.addAppender(this->appender);

	this->rootLogger = new Log4cppLogger(this->rootCategory);

	// read configuration file if exists
	bfs::path cFile = userpaths->getConfigFile("log.conf");
	if(!bfs::exists(cFile))
	{
		return;
	}

	Logger& logger = this->getComponentLogger("logger");
	logger << LogLevel::Debug << "parse config file at: " << cFile.string() << endl;

	bfs::ifstream ifstream(cFile);
	bfs::path cFileGen = userpaths->getConfigFile("log.conf.gen");
	bfs::remove(cFileGen);
	bfs::ofstream ofstream(cFileGen);
	std::string line;
	std::string parsedLine;

	while(!ifstream.eof())
	{
		std::getline(ifstream, line);
		// ignore empty lines
		if(line.empty())
		{
			continue;
		}

		parsedLine = parseLine(line, userpaths);
		logger << LogLevel::Debug << "parsed line \"" << line << "\" to: \"" << parsedLine << "\"" << endl;
		ofstream << parsedLine << std::endl;
	}

	// ignore the file if nothing was parsed
	if(ofstream.tellp() <= 0)
	{
		return;
	}

	logger << LogLevel::Info << "moving to new configuration" << endl;

	log4cpp::PropertyConfigurator pci;
	pci.configure(cFileGen.string());
	bfs::remove(cFileGen);

	// we have another logger noew
	this->rootCategory.removeAppender(this->appender);
	this->appender = nullptr;
	delete this->rootLogger;
	this->rootLogger = new Log4cppLogger(this->rootCategory);
}

Logger&
Log4cppLoggerFactory::getDefaultLogger()
{
	return getComponentLogger("GameKeeper.Default");
}

Logger&
Log4cppLoggerFactory::PImpl::getComponentLogger(const char * const id)
{
	if(this->loggers.find(id) == this->loggers.end())
	{
		std::string log4cppname = "GameKeeper.";
		log4cppname += id;
		Logger * newLogger = new Log4cppLogger(log4cpp::Category::getInstance(log4cppname));
		this->loggers.insert(std::make_pair(id, newLogger));
		return *newLogger;
	}
	return *this->loggers.at(id);
}

Log4cppLoggerFactory::PImpl::~PImpl()
{
	if(this->appender != nullptr)
	{
		this->rootCategory.removeAppender(this->appender);
	}

	if(this->rootLogger != nullptr)
	{
		delete this->rootLogger;
	}

	for(auto entry : this->loggers)
	{
		delete entry.second;
	}
}

Log4cppLoggerFactory::Log4cppLoggerFactory(std::shared_ptr<UserPaths> userpaths)
:	data(new Log4cppLoggerFactory::PImpl(userpaths)){}

Logger&
Log4cppLoggerFactory::getComponentLogger(const char * const id)
{
	return this->data->getComponentLogger(id);
}

Log4cppLoggerFactory::~Log4cppLoggerFactory(){}

GAMEKEEPER_NAMESPACE_END(core)
<|endoftext|>


<commit_before>/*=========================================================================
 *
 *  Copyright The University of North Carolina at Chapel Hill
 *  All rights reserved.
 *
 *  Licensed under the MADAI Software License. You may obtain a copy of
 *  this license at
 *
 *         https://madai-public.cs.unc.edu/visualization/software-license/
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/

#include "LangevinSampler.h"

#include <cassert>
#include <algorithm>
#include <cmath>

namespace madai {

LangevinSampler
::LangevinSampler() :
  Sampler(),
  m_TimeStep( 1.0e-2 ),
  m_MeanTime( 1 ),
  m_KickStrength( 1 ),
  m_DragCoefficient( 1.0e-2 ),
  m_MassScale( 1 )
{
}

LangevinSampler
::~LangevinSampler()
{
}

void
LangevinSampler
::Initialize( const Model * model )
{
  assert( model != NULL );
  m_Model = model;

  Sampler::Initialize( model );

  // Random initial starting point
  const std::vector< Parameter > & params = m_Model->GetParameters();
  for ( unsigned int i = 0; i < m_Model->GetNumberOfParameters(); i++ ) {
    const Distribution * priorDist = params[i].GetPriorDistribution();
    m_CurrentParameters[i] = priorDist->GetSample(m_Random);
    m_CurrentVelocities.push_back(0.0);
  }

  m_TimeBeforeNextKick = m_Random.Gaussian( m_MeanTime, m_MeanTime / 10.0 );
}

Sample
LangevinSampler
::NextSample()
{
  Model * m = const_cast< Model * >(m_Model);
  double TimeLeft = m_TimeStep;

  unsigned int numberOfActiveParameters = this->GetNumberOfActiveParameters();

  assert( static_cast<unsigned int> (
              std::count( m_ActiveParameterIndices.begin(),
                          m_ActiveParameterIndices.end(), true ))
          == numberOfActiveParameters);

  // Get the gradient of the Log Likelihood at the current point
  std::vector< double > Gradient;
  m->GetScalarAndGradientOutputs(
    m_CurrentParameters, m_ActiveParameterIndices,
    m_CurrentOutputs, Gradient );

  // Get loglikelihood at the current parameters
  double LogLikelihood;
  m->GetScalarOutputsAndLogLikelihood(
    m_CurrentParameters, m_CurrentOutputs, LogLikelihood );
  // Check for NaN
  assert( LogLikelihood == LogLikelihood );

  std::vector< double > Accel = Gradient;
  for ( unsigned int i = 0; i < Accel.size(); i++ ) {
    Accel[i] -= m_DragCoefficient * m_CurrentVelocities[i];
    Accel[i] /= m_MassScale;
  }
  if ( m_TimeBeforeNextKick < m_TimeStep ) { // Check if kick happens
    // Take step up to m_TimeBeforeNextKick
    for ( unsigned int i = 0; i < m_CurrentParameters.size(); i++ ) {
      m_CurrentParameters[i] += m_CurrentVelocities[i] * m_TimeBeforeNextKick;
      m_CurrentParameters[i] += 0.5 * Accel[i] * m_TimeBeforeNextKick * m_TimeBeforeNextKick;
      m_CurrentVelocities[i] += Accel[i] * m_TimeBeforeNextKick;
    }
    // Get m_CurrentVelocities.size() number of random numbers
    std::vector< double > r(m_CurrentVelocities.size());
    double temp = 0;
    for ( unsigned int i = 0; i < m_CurrentVelocities.size(); i++ ) {
      r[i] = m_Random.Uniform( -1, 1 );
      temp += r[i] * r[i];
    }
    temp = sqrt( temp );
    temp /= m_KickStrength;
    for ( unsigned int i = 0; i < m_CurrentVelocities.size(); i++ ) {
     m_CurrentVelocities[i] += r[i] / temp;
     Accel[i] -= m_DragCoefficient * r[i] / temp;
    }
    TimeLeft -= m_TimeBeforeNextKick;
    m_TimeBeforeNextKick += m_Random.Gaussian( m_MeanTime, m_MeanTime / 10.0 );
  }

  for ( unsigned int i = 0; i < m_CurrentParameters.size(); i++ ) {
    m_CurrentParameters[i] += m_CurrentVelocities[i] * TimeLeft;
    m_CurrentParameters[i] += 0.5 * Accel[i] * TimeLeft * TimeLeft;
    m_CurrentVelocities[i] += Accel[i] * TimeLeft;
  }

  m_TimeBeforeNextKick -= m_TimeStep;

  return Sample( m_CurrentParameters,
                 m_CurrentOutputs,
                 LogLikelihood );

}

void LangevinSampler
::SetTimeStep( double TimeStep )
{
  m_TimeStep = TimeStep;
}

void LangevinSampler
::SetKickStrength( double KickStrength )
{
  m_KickStrength = KickStrength;
}

void LangevinSampler
::SetMeanTimeBetweenKicks( double MeanTime )
{
  m_MeanTime = MeanTime;
}

void LangevinSampler
::SetDragCoefficient( double DragCoefficient )
{
  m_DragCoefficient = DragCoefficient;
}

void LangevinSampler
::SetMassScale( double MassScale )
{
  m_MassScale = MassScale;
}

Sampler::ErrorType
LangevinSampler
::SetVelocity( const std::string & parameterName, double Velocity )
{
  unsigned int parameterIndex = this->GetParameterIndex( parameterName );

  if ( parameterIndex == static_cast< unsigned int >( -1 ) ) {
    return INVALID_PARAMETER_INDEX_ERROR;
  }

  m_CurrentVelocities[parameterIndex] = Velocity;

  return NO_ERROR;
}

} // end namespace madai
<commit_msg>NDEBUG unused-variable fixes - LangevinSampler<commit_after>/*=========================================================================
 *
 *  Copyright The University of North Carolina at Chapel Hill
 *  All rights reserved.
 *
 *  Licensed under the MADAI Software License. You may obtain a copy of
 *  this license at
 *
 *         https://madai-public.cs.unc.edu/visualization/software-license/
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/

#include "LangevinSampler.h"

#include <cassert>
#include <algorithm>
#include <cmath>

namespace madai {

LangevinSampler
::LangevinSampler() :
  Sampler(),
  m_TimeStep( 1.0e-2 ),
  m_MeanTime( 1 ),
  m_KickStrength( 1 ),
  m_DragCoefficient( 1.0e-2 ),
  m_MassScale( 1 )
{
}

LangevinSampler
::~LangevinSampler()
{
}

void
LangevinSampler
::Initialize( const Model * model )
{
  assert( model != NULL );
  m_Model = model;

  Sampler::Initialize( model );

  // Random initial starting point
  const std::vector< Parameter > & params = m_Model->GetParameters();
  for ( unsigned int i = 0; i < m_Model->GetNumberOfParameters(); i++ ) {
    const Distribution * priorDist = params[i].GetPriorDistribution();
    m_CurrentParameters[i] = priorDist->GetSample(m_Random);
    m_CurrentVelocities.push_back(0.0);
  }

  m_TimeBeforeNextKick = m_Random.Gaussian( m_MeanTime, m_MeanTime / 10.0 );
}

Sample
LangevinSampler
::NextSample()
{
  Model * m = const_cast< Model * >(m_Model);
  double TimeLeft = m_TimeStep;

  assert( static_cast<unsigned int> (
              std::count( m_ActiveParameterIndices.begin(),
                          m_ActiveParameterIndices.end(), true ))
          == this->GetNumberOfActiveParameters());

  // Get the gradient of the Log Likelihood at the current point
  std::vector< double > Gradient;
  m->GetScalarAndGradientOutputs(
    m_CurrentParameters, m_ActiveParameterIndices,
    m_CurrentOutputs, Gradient );

  // Get loglikelihood at the current parameters
  double LogLikelihood;
  m->GetScalarOutputsAndLogLikelihood(
    m_CurrentParameters, m_CurrentOutputs, LogLikelihood );
  // Check for NaN
  assert( LogLikelihood == LogLikelihood );

  std::vector< double > Accel = Gradient;
  for ( unsigned int i = 0; i < Accel.size(); i++ ) {
    Accel[i] -= m_DragCoefficient * m_CurrentVelocities[i];
    Accel[i] /= m_MassScale;
  }
  if ( m_TimeBeforeNextKick < m_TimeStep ) { // Check if kick happens
    // Take step up to m_TimeBeforeNextKick
    for ( unsigned int i = 0; i < m_CurrentParameters.size(); i++ ) {
      m_CurrentParameters[i] += m_CurrentVelocities[i] * m_TimeBeforeNextKick;
      m_CurrentParameters[i] += 0.5 * Accel[i] * m_TimeBeforeNextKick * m_TimeBeforeNextKick;
      m_CurrentVelocities[i] += Accel[i] * m_TimeBeforeNextKick;
    }
    // Get m_CurrentVelocities.size() number of random numbers
    std::vector< double > r(m_CurrentVelocities.size());
    double temp = 0;
    for ( unsigned int i = 0; i < m_CurrentVelocities.size(); i++ ) {
      r[i] = m_Random.Uniform( -1, 1 );
      temp += r[i] * r[i];
    }
    temp = sqrt( temp );
    temp /= m_KickStrength;
    for ( unsigned int i = 0; i < m_CurrentVelocities.size(); i++ ) {
     m_CurrentVelocities[i] += r[i] / temp;
     Accel[i] -= m_DragCoefficient * r[i] / temp;
    }
    TimeLeft -= m_TimeBeforeNextKick;
    m_TimeBeforeNextKick += m_Random.Gaussian( m_MeanTime, m_MeanTime / 10.0 );
  }

  for ( unsigned int i = 0; i < m_CurrentParameters.size(); i++ ) {
    m_CurrentParameters[i] += m_CurrentVelocities[i] * TimeLeft;
    m_CurrentParameters[i] += 0.5 * Accel[i] * TimeLeft * TimeLeft;
    m_CurrentVelocities[i] += Accel[i] * TimeLeft;
  }

  m_TimeBeforeNextKick -= m_TimeStep;

  return Sample( m_CurrentParameters,
                 m_CurrentOutputs,
                 LogLikelihood );

}

void LangevinSampler
::SetTimeStep( double TimeStep )
{
  m_TimeStep = TimeStep;
}

void LangevinSampler
::SetKickStrength( double KickStrength )
{
  m_KickStrength = KickStrength;
}

void LangevinSampler
::SetMeanTimeBetweenKicks( double MeanTime )
{
  m_MeanTime = MeanTime;
}

void LangevinSampler
::SetDragCoefficient( double DragCoefficient )
{
  m_DragCoefficient = DragCoefficient;
}

void LangevinSampler
::SetMassScale( double MassScale )
{
  m_MassScale = MassScale;
}

Sampler::ErrorType
LangevinSampler
::SetVelocity( const std::string & parameterName, double Velocity )
{
  unsigned int parameterIndex = this->GetParameterIndex( parameterName );

  if ( parameterIndex == static_cast< unsigned int >( -1 ) ) {
    return INVALID_PARAMETER_INDEX_ERROR;
  }

  m_CurrentVelocities[parameterIndex] = Velocity;

  return NO_ERROR;
}

} // end namespace madai
<|endoftext|>


<commit_before>//
//  TapeParser.hpp
//  Clock Signal
//
//  Created by Thomas Harte on 05/09/2016.
//  Copyright © 2016 Thomas Harte. All rights reserved.
//

#ifndef TapeParser_hpp
#define TapeParser_hpp

#include "../Tape.hpp"

#include <memory>
#include <vector>

namespace Storage {
namespace Tape {

/*!
	A partly-abstract base class to help in the authorship of tape format parsers;
	provides hooks for pulse classification from pulses to waves and for symbol identification from
	waves.

	Very optional, not intended to box in the approaches taken for analysis.
*/
template <typename WaveType, typename SymbolType> class Parser {
	public:
		/// Instantiates a new parser with the supplied @c tape.
		Parser() : _has_next_symbol(false), _error_flag(false) {}

		/// Resets the error flag.
		void reset_error_flag()		{	_error_flag = false;		}
		/// @returns @c true if an error has occurred since the error flag was last reset; @c false otherwise.
		bool get_error_flag()		{	return _error_flag;			}

		/*!
			Asks the parser to continue taking pulses from the tape until either the subclass next declares a symbol
			or the tape runs out, returning the most-recently declared symbol.
		*/
		SymbolType get_next_symbol(const std::shared_ptr<Storage::Tape::Tape> &tape) {
			while(!_has_next_symbol && !tape->is_at_end()) {
				process_pulse(tape->get_next_pulse());
			}
			_has_next_symbol = false;
			return _next_symbol;
		}

		/*!
			Should be implemented by subclasses. Consumes @c pulse. Is likely either to call @c push_wave
			or to take no action.
		*/
		virtual void process_pulse(Storage::Tape::Tape::Pulse pulse) = 0;

	protected:

		/*!
			Adds @c wave to the back of the list of recognised waves and calls @c inspect_waves to check for a new symbol.

			Expected to be called by subclasses from @c process_pulse as and when recognised waves arise.
		*/
		void push_wave(WaveType wave) {
			_wave_queue.push_back(wave);
			inspect_waves(_wave_queue);
		}

		/*!
			Removes @c nunber_of_waves waves from the front of the list.

			Expected to be called by subclasses from @c process_pulse if it is recognised that the first set of waves
			do not form a valid symbol.
		*/
		void remove_waves(int number_of_waves) {
			_wave_queue.erase(_wave_queue.begin(), _wave_queue.begin()+number_of_waves);
		}

		/*!
			Sets @c symbol as the newly-recognised symbol and removes @c nunber_of_waves waves from the front of the list.

			Expected to be called by subclasses from @c process_pulse when it recognises that the first @c number_of_waves
			waves together represent @c symbol.
		*/
		void push_symbol(SymbolType symbol, int number_of_waves) {
			_has_next_symbol = true;
			_next_symbol = symbol;
			remove_waves(number_of_waves);
		}

		void set_error_flag() {
			_error_flag = true;
		}

	private:
		bool _error_flag;

		/*!
			Should be implemented by subclasses. Inspects @c waves for a potential new symbol. If one is
			found should call @c push_symbol. May wish alternatively to call @c remove_waves to have entries
			removed from the start of @c waves that cannot form a valid symbol. Need not do anything while
			the waves at the start of @c waves may end up forming a symbol but the symbol is not yet complete.
		*/
		virtual void inspect_waves(const std::vector<WaveType> &waves) = 0;

		std::vector<WaveType> _wave_queue;
		SymbolType _next_symbol;
		bool _has_next_symbol;
};

}
}

#endif /* TapeParser_hpp */
<commit_msg>Extended explicitly to support a token of lookahead, which is pretty much what was on offer anyway. Also corrected instance variable names, as per better adoption of C++ norms.<commit_after>//
//  TapeParser.hpp
//  Clock Signal
//
//  Created by Thomas Harte on 05/09/2016.
//  Copyright © 2016 Thomas Harte. All rights reserved.
//

#ifndef TapeParser_hpp
#define TapeParser_hpp

#include "../Tape.hpp"

#include <memory>
#include <vector>
#include <assert.h>

namespace Storage {
namespace Tape {

/*!
	A partly-abstract base class to help in the authorship of tape format parsers;
	provides hooks for pulse classification from pulses to waves and for symbol identification from
	waves.

	Very optional, not intended to box in the approaches taken for analysis.
*/
template <typename WaveType, typename SymbolType> class Parser {
	public:
		/// Instantiates a new parser with the supplied @c tape.
		Parser() : has_next_symbol_(false), error_flag_(false) {}

		/// Resets the error flag.
		void reset_error_flag()		{	error_flag_ = false;		}
		/// @returns @c true if an error has occurred since the error flag was last reset; @c false otherwise.
		bool get_error_flag()		{	return error_flag_;			}

		/*!
			Asks the parser to continue taking pulses from the tape until either the subclass next declares a symbol
			or the tape runs out, returning the most-recently declared symbol.
		*/
		SymbolType get_next_symbol(const std::shared_ptr<Storage::Tape::Tape> &tape) {
			while(!has_next_symbol_ && !tape->is_at_end()) {
				process_pulse(tape->get_next_pulse());
			}
			has_next_symbol_ = false;
			return next_symbol_;
		}

		/*!
			This class provides a single token of lookahead; return_symbol allows the single previous
			token supplied by get_next_symbol to be returned, in which case it will be the thing returned
			by the next call to get_next_symbol.
		*/
		void return_symbol(SymbolType symbol) {
			assert(!has_next_symbol_);
			has_next_symbol_ = true;
			next_symbol_ = symbol;
		}

		/*!
			Should be implemented by subclasses. Consumes @c pulse. Is likely either to call @c push_wave
			or to take no action.
		*/
		virtual void process_pulse(Storage::Tape::Tape::Pulse pulse) = 0;

	protected:

		/*!
			Adds @c wave to the back of the list of recognised waves and calls @c inspect_waves to check for a new symbol.

			Expected to be called by subclasses from @c process_pulse as and when recognised waves arise.
		*/
		void push_wave(WaveType wave) {
			wave_queue_.push_back(wave);
			inspect_waves(wave_queue_);
		}

		/*!
			Removes @c nunber_of_waves waves from the front of the list.

			Expected to be called by subclasses from @c process_pulse if it is recognised that the first set of waves
			do not form a valid symbol.
		*/
		void remove_waves(int number_of_waves) {
			wave_queue_.erase(wave_queue_.begin(), wave_queue_.begin()+number_of_waves);
		}

		/*!
			Sets @c symbol as the newly-recognised symbol and removes @c nunber_of_waves waves from the front of the list.

			Expected to be called by subclasses from @c process_pulse when it recognises that the first @c number_of_waves
			waves together represent @c symbol.
		*/
		void push_symbol(SymbolType symbol, int number_of_waves) {
			has_next_symbol_ = true;
			next_symbol_ = symbol;
			remove_waves(number_of_waves);
		}

		void set_error_flag() {
			error_flag_ = true;
		}

	private:
		bool error_flag_;

		/*!
			Should be implemented by subclasses. Inspects @c waves for a potential new symbol. If one is
			found should call @c push_symbol. May wish alternatively to call @c remove_waves to have entries
			removed from the start of @c waves that cannot form a valid symbol. Need not do anything while
			the waves at the start of @c waves may end up forming a symbol but the symbol is not yet complete.
		*/
		virtual void inspect_waves(const std::vector<WaveType> &waves) = 0;

		std::vector<WaveType> wave_queue_;
		SymbolType next_symbol_;
		bool has_next_symbol_;
};

}
}

#endif /* TapeParser_hpp */
<|endoftext|>


<commit_before>#include "PrologInterface.h"

void PrologLifetime::begin(int argc, char *argv[]) {
  if (!PL_initialise(argc, argv)) {
    PL_halt(EXIT_FAILURE);
  }
}

void PrologLifetime::end() {
  PL_halt(EXIT_SUCCESS);
}

<commit_msg>Use PL_cleanup instead of PL_halt<commit_after>#include "PrologInterface.h"

void PrologLifetime::begin(int argc, char *argv[]) {
  if (!PL_initialise(argc, argv)) {
    PL_halt(EXIT_FAILURE);
  }
}

void PrologLifetime::end() {
  PL_cleanup(EXIT_SUCCESS);
}

<|endoftext|>


<commit_before>#include <sch/S_Object/S_Cone.h>

using namespace sch;

const Point3 S_Cone::origin_(0,0,0);

S_Cone::S_Cone(const Scalar& angle, const Scalar &  height)

{

  angle_=angle;
  height_=height;
  angleTan_=tan(angle);
  baseRadius_=height*angleTan_;

  slices_ = 100;
  stacks_ = 4; /// we don't need many stacks to display a cone
}

S_Cone::~S_Cone(void)
{
}

Point3 S_Cone::l_Support(const Vector3& v, int& /*lastFeature*/)const
{

  Scalar norm = sqrt(v[0] * v[0] + v[1] * v[1]);
  if (norm < sch::epsilon)
  {
    if (v[2] >= 0)
    {
      return Point3(0, baseRadius_, height_);
    }
    else
    {
      return origin_;
    }
  }
  else
  {
    if ( v[2] < - angleTan_ * norm)
    {
      return origin_;
    }
    else
    {
      Scalar normInverse = 1 / norm;
      return Point3(normInverse * v[0]*baseRadius_, normInverse * v[1]*baseRadius_, height_);
    }
  }

}

S_Object::S_ObjectType S_Cone::getType() const
{
  return S_Object::TCone;
}

Scalar S_Cone::getAngle() const
{
  return angle_;
}

Scalar S_Cone::getHeight() const
{
  return height_;
}<commit_msg>Add EoL at the end of the file<commit_after>#include <sch/S_Object/S_Cone.h>

using namespace sch;

const Point3 S_Cone::origin_(0,0,0);

S_Cone::S_Cone(const Scalar& angle, const Scalar &  height)

{

  angle_=angle;
  height_=height;
  angleTan_=tan(angle);
  baseRadius_=height*angleTan_;

  slices_ = 100;
  stacks_ = 4; /// we don't need many stacks to display a cone
}

S_Cone::~S_Cone(void)
{
}

Point3 S_Cone::l_Support(const Vector3& v, int& /*lastFeature*/)const
{

  Scalar norm = sqrt(v[0] * v[0] + v[1] * v[1]);
  if (norm < sch::epsilon)
  {
    if (v[2] >= 0)
    {
      return Point3(0, baseRadius_, height_);
    }
    else
    {
      return origin_;
    }
  }
  else
  {
    if ( v[2] < - angleTan_ * norm)
    {
      return origin_;
    }
    else
    {
      Scalar normInverse = 1 / norm;
      return Point3(normInverse * v[0]*baseRadius_, normInverse * v[1]*baseRadius_, height_);
    }
  }

}

S_Object::S_ObjectType S_Cone::getType() const
{
  return S_Object::TCone;
}

Scalar S_Cone::getAngle() const
{
  return angle_;
}

Scalar S_Cone::getHeight() const
{
  return height_;
}
<|endoftext|>


<commit_before>// Copyright 2018 The SwiftShader Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef VK_CONFIG_HPP_
#define VK_CONFIG_HPP_

#include "Version.hpp"
#include "Device/Config.hpp"
#include "Vulkan/VulkanPlatform.hpp"
#include "spirv-tools/libspirv.h"

namespace vk {

// Note: Constant array initialization requires a string literal.
//       constexpr char* or char[] does not work for that purpose.
#define SWIFTSHADER_DEVICE_NAME "SwiftShader Device"  // Max length: VK_MAX_PHYSICAL_DEVICE_NAME_SIZE
#define SWIFTSHADER_UUID "SwiftShaderUUID"            // Max length: VK_UUID_SIZE (16)

constexpr spv_target_env SPIRV_VERSION = SPV_ENV_VULKAN_1_3;

constexpr uint32_t API_VERSION = VK_API_VERSION_1_3;
constexpr uint32_t DRIVER_VERSION = VK_MAKE_VERSION(MAJOR_VERSION, MINOR_VERSION, PATCH_VERSION);
constexpr uint32_t VENDOR_ID = 0x1AE0;  // Google, Inc.: https://pcisig.com/google-inc-1
constexpr uint32_t DEVICE_ID = 0xC0DE;  // SwiftShader (placeholder)

// "Allocations returned by vkAllocateMemory are guaranteed to meet any alignment requirement of the implementation."
constexpr VkDeviceSize DEVICE_MEMORY_ALLOCATION_ALIGNMENT = 256;

constexpr VkDeviceSize MIN_MEMORY_MAP_ALIGNMENT = 64;
static_assert(DEVICE_MEMORY_ALLOCATION_ALIGNMENT >= MIN_MEMORY_MAP_ALIGNMENT);

constexpr VkDeviceSize MIN_IMPORTED_HOST_POINTER_ALIGNMENT = 4096;
static_assert(MIN_IMPORTED_HOST_POINTER_ALIGNMENT >= DEVICE_MEMORY_ALLOCATION_ALIGNMENT);

// Vulkan 1.2 requires buffer offset alignment to be at most 256.
constexpr VkDeviceSize MIN_TEXEL_BUFFER_OFFSET_ALIGNMENT = 256;
constexpr VkDeviceSize MIN_UNIFORM_BUFFER_OFFSET_ALIGNMENT = 256;
constexpr VkDeviceSize MIN_STORAGE_BUFFER_OFFSET_ALIGNMENT = 256;
static_assert(DEVICE_MEMORY_ALLOCATION_ALIGNMENT >= MIN_TEXEL_BUFFER_OFFSET_ALIGNMENT);
static_assert(DEVICE_MEMORY_ALLOCATION_ALIGNMENT >= MIN_UNIFORM_BUFFER_OFFSET_ALIGNMENT);
static_assert(DEVICE_MEMORY_ALLOCATION_ALIGNMENT >= MIN_STORAGE_BUFFER_OFFSET_ALIGNMENT);

// Alignment of all other Vulkan resources.
constexpr VkDeviceSize MEMORY_REQUIREMENTS_OFFSET_ALIGNMENT = 16;  // 16 bytes for 128-bit vector types.
static_assert(DEVICE_MEMORY_ALLOCATION_ALIGNMENT >= MEMORY_REQUIREMENTS_OFFSET_ALIGNMENT);

constexpr VkDeviceSize HOST_MEMORY_ALLOCATION_ALIGNMENT = 16;  // 16 bytes for 128-bit vector types.

constexpr uint32_t MEMORY_TYPE_GENERIC_BIT = 0x1;  // Generic system memory.

constexpr uint32_t MAX_IMAGE_LEVELS_1D = 15;
constexpr uint32_t MAX_IMAGE_LEVELS_2D = 15;
constexpr uint32_t MAX_IMAGE_LEVELS_3D = 12;
constexpr uint32_t MAX_IMAGE_LEVELS_CUBE = 15;
constexpr uint32_t MAX_IMAGE_ARRAY_LAYERS = 2048;
constexpr float MAX_SAMPLER_LOD_BIAS = 15.0;

static_assert(MAX_IMAGE_LEVELS_1D <= sw::MIPMAP_LEVELS);
static_assert(MAX_IMAGE_LEVELS_2D <= sw::MIPMAP_LEVELS);
static_assert(MAX_IMAGE_LEVELS_3D <= sw::MIPMAP_LEVELS);
static_assert(MAX_IMAGE_LEVELS_CUBE <= sw::MIPMAP_LEVELS);

constexpr uint32_t MAX_BOUND_DESCRIPTOR_SETS = 4;
constexpr uint32_t MAX_VERTEX_INPUT_BINDINGS = 16;
constexpr uint32_t MAX_PUSH_CONSTANT_SIZE = 128;
constexpr uint32_t MAX_UPDATE_AFTER_BIND_DESCRIPTORS = 500000;

constexpr uint32_t MAX_DESCRIPTOR_SET_UNIFORM_BUFFERS_DYNAMIC = 8;
constexpr uint32_t MAX_DESCRIPTOR_SET_STORAGE_BUFFERS_DYNAMIC = 4;
constexpr uint32_t MAX_DESCRIPTOR_SET_COMBINED_BUFFERS_DYNAMIC =
    MAX_DESCRIPTOR_SET_UNIFORM_BUFFERS_DYNAMIC +
    MAX_DESCRIPTOR_SET_STORAGE_BUFFERS_DYNAMIC;

constexpr uint32_t MAX_COMPUTE_WORKGROUP_INVOCATIONS = 256;

constexpr size_t MAX_INLINE_UNIFORM_BLOCK_SIZE = 256;

constexpr float MAX_POINT_SIZE = 1023.0;

constexpr int MAX_SAMPLER_ALLOCATION_COUNT = 4000;

constexpr int SUBPIXEL_PRECISION_BITS = 4;
constexpr float SUBPIXEL_PRECISION_FACTOR = static_cast<float>(1 << SUBPIXEL_PRECISION_BITS);
constexpr int SUBPIXEL_PRECISION_MASK = 0xFFFFFFFF >> (32 - SUBPIXEL_PRECISION_BITS);

constexpr int MAX_VIEWPORTS = 16;

// TODO: The heap size should be configured based on available RAM.
constexpr VkDeviceSize PHYSICAL_DEVICE_HEAP_SIZE = 0x80000000ull;   // 0x80000000 = 2 GiB
constexpr VkDeviceSize MAX_MEMORY_ALLOCATION_SIZE = 0x40000000ull;  // 0x40000000 = 1 GiB

// Memory offset calculations in 32-bit SIMD elements limit us to addressing at most 4 GiB.
// Signed arithmetic further restricts it to 2 GiB.
static_assert(MAX_MEMORY_ALLOCATION_SIZE <= 0x80000000ull, "maxMemoryAllocationSize must not exceed 2 GiB");

}  // namespace vk

#if defined(__linux__) && !defined(__ANDROID__)
#	define SWIFTSHADER_EXTERNAL_MEMORY_OPAQUE_FD 1
#	define SWIFTSHADER_EXTERNAL_SEMAPHORE_OPAQUE_FD 1
#elif defined(__ANDROID__)
#	define SWIFTSHADER_EXTERNAL_SEMAPHORE_OPAQUE_FD 1
#endif
#if defined(__APPLE__)
#	define SWIFTSHADER_EXTERNAL_MEMORY_OPAQUE_FD 1
#endif

#endif  // VK_CONFIG_HPP_
<commit_msg>Increase subPixelPrecisionBits from 4 to 8<commit_after>// Copyright 2018 The SwiftShader Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef VK_CONFIG_HPP_
#define VK_CONFIG_HPP_

#include "Version.hpp"
#include "Device/Config.hpp"
#include "Vulkan/VulkanPlatform.hpp"
#include "spirv-tools/libspirv.h"

namespace vk {

// Note: Constant array initialization requires a string literal.
//       constexpr char* or char[] does not work for that purpose.
#define SWIFTSHADER_DEVICE_NAME "SwiftShader Device"  // Max length: VK_MAX_PHYSICAL_DEVICE_NAME_SIZE
#define SWIFTSHADER_UUID "SwiftShaderUUID"            // Max length: VK_UUID_SIZE (16)

constexpr spv_target_env SPIRV_VERSION = SPV_ENV_VULKAN_1_3;

constexpr uint32_t API_VERSION = VK_API_VERSION_1_3;
constexpr uint32_t DRIVER_VERSION = VK_MAKE_VERSION(MAJOR_VERSION, MINOR_VERSION, PATCH_VERSION);
constexpr uint32_t VENDOR_ID = 0x1AE0;  // Google, Inc.: https://pcisig.com/google-inc-1
constexpr uint32_t DEVICE_ID = 0xC0DE;  // SwiftShader (placeholder)

// "Allocations returned by vkAllocateMemory are guaranteed to meet any alignment requirement of the implementation."
constexpr VkDeviceSize DEVICE_MEMORY_ALLOCATION_ALIGNMENT = 256;

constexpr VkDeviceSize MIN_MEMORY_MAP_ALIGNMENT = 64;
static_assert(DEVICE_MEMORY_ALLOCATION_ALIGNMENT >= MIN_MEMORY_MAP_ALIGNMENT);

constexpr VkDeviceSize MIN_IMPORTED_HOST_POINTER_ALIGNMENT = 4096;
static_assert(MIN_IMPORTED_HOST_POINTER_ALIGNMENT >= DEVICE_MEMORY_ALLOCATION_ALIGNMENT);

// Vulkan 1.2 requires buffer offset alignment to be at most 256.
constexpr VkDeviceSize MIN_TEXEL_BUFFER_OFFSET_ALIGNMENT = 256;
constexpr VkDeviceSize MIN_UNIFORM_BUFFER_OFFSET_ALIGNMENT = 256;
constexpr VkDeviceSize MIN_STORAGE_BUFFER_OFFSET_ALIGNMENT = 256;
static_assert(DEVICE_MEMORY_ALLOCATION_ALIGNMENT >= MIN_TEXEL_BUFFER_OFFSET_ALIGNMENT);
static_assert(DEVICE_MEMORY_ALLOCATION_ALIGNMENT >= MIN_UNIFORM_BUFFER_OFFSET_ALIGNMENT);
static_assert(DEVICE_MEMORY_ALLOCATION_ALIGNMENT >= MIN_STORAGE_BUFFER_OFFSET_ALIGNMENT);

// Alignment of all other Vulkan resources.
constexpr VkDeviceSize MEMORY_REQUIREMENTS_OFFSET_ALIGNMENT = 16;  // 16 bytes for 128-bit vector types.
static_assert(DEVICE_MEMORY_ALLOCATION_ALIGNMENT >= MEMORY_REQUIREMENTS_OFFSET_ALIGNMENT);

constexpr VkDeviceSize HOST_MEMORY_ALLOCATION_ALIGNMENT = 16;  // 16 bytes for 128-bit vector types.

constexpr uint32_t MEMORY_TYPE_GENERIC_BIT = 0x1;  // Generic system memory.

constexpr uint32_t MAX_IMAGE_LEVELS_1D = 15;
constexpr uint32_t MAX_IMAGE_LEVELS_2D = 15;
constexpr uint32_t MAX_IMAGE_LEVELS_3D = 12;
constexpr uint32_t MAX_IMAGE_LEVELS_CUBE = 15;
constexpr uint32_t MAX_IMAGE_ARRAY_LAYERS = 2048;
constexpr float MAX_SAMPLER_LOD_BIAS = 15.0;

static_assert(MAX_IMAGE_LEVELS_1D <= sw::MIPMAP_LEVELS);
static_assert(MAX_IMAGE_LEVELS_2D <= sw::MIPMAP_LEVELS);
static_assert(MAX_IMAGE_LEVELS_3D <= sw::MIPMAP_LEVELS);
static_assert(MAX_IMAGE_LEVELS_CUBE <= sw::MIPMAP_LEVELS);

constexpr uint32_t MAX_BOUND_DESCRIPTOR_SETS = 4;
constexpr uint32_t MAX_VERTEX_INPUT_BINDINGS = 16;
constexpr uint32_t MAX_PUSH_CONSTANT_SIZE = 128;
constexpr uint32_t MAX_UPDATE_AFTER_BIND_DESCRIPTORS = 500000;

constexpr uint32_t MAX_DESCRIPTOR_SET_UNIFORM_BUFFERS_DYNAMIC = 8;
constexpr uint32_t MAX_DESCRIPTOR_SET_STORAGE_BUFFERS_DYNAMIC = 4;
constexpr uint32_t MAX_DESCRIPTOR_SET_COMBINED_BUFFERS_DYNAMIC =
    MAX_DESCRIPTOR_SET_UNIFORM_BUFFERS_DYNAMIC +
    MAX_DESCRIPTOR_SET_STORAGE_BUFFERS_DYNAMIC;

constexpr uint32_t MAX_COMPUTE_WORKGROUP_INVOCATIONS = 256;

constexpr size_t MAX_INLINE_UNIFORM_BLOCK_SIZE = 256;

constexpr float MAX_POINT_SIZE = 1023.0;

constexpr int MAX_SAMPLER_ALLOCATION_COUNT = 4000;

constexpr int SUBPIXEL_PRECISION_BITS = 8;
constexpr float SUBPIXEL_PRECISION_FACTOR = static_cast<float>(1 << SUBPIXEL_PRECISION_BITS);
constexpr int SUBPIXEL_PRECISION_MASK = 0xFFFFFFFF >> (32 - SUBPIXEL_PRECISION_BITS);

constexpr int MAX_VIEWPORTS = 16;

// TODO: The heap size should be configured based on available RAM.
constexpr VkDeviceSize PHYSICAL_DEVICE_HEAP_SIZE = 0x80000000ull;   // 0x80000000 = 2 GiB
constexpr VkDeviceSize MAX_MEMORY_ALLOCATION_SIZE = 0x40000000ull;  // 0x40000000 = 1 GiB

// Memory offset calculations in 32-bit SIMD elements limit us to addressing at most 4 GiB.
// Signed arithmetic further restricts it to 2 GiB.
static_assert(MAX_MEMORY_ALLOCATION_SIZE <= 0x80000000ull, "maxMemoryAllocationSize must not exceed 2 GiB");

}  // namespace vk

#if defined(__linux__) && !defined(__ANDROID__)
#	define SWIFTSHADER_EXTERNAL_MEMORY_OPAQUE_FD 1
#	define SWIFTSHADER_EXTERNAL_SEMAPHORE_OPAQUE_FD 1
#elif defined(__ANDROID__)
#	define SWIFTSHADER_EXTERNAL_SEMAPHORE_OPAQUE_FD 1
#endif
#if defined(__APPLE__)
#	define SWIFTSHADER_EXTERNAL_MEMORY_OPAQUE_FD 1
#endif

#endif  // VK_CONFIG_HPP_
<|endoftext|>


<commit_before>//
// Created by Sam on 9/25/2017.
//

#include "../include/Game/Core/Game.h"
#include "../include/Game/Core/Player.h"
#include "../include/Network/Server.h"
#include "../include/Game/Python/Factory.h"
#include "../include/Game/Core/Card.h"
#include "../include/Game/Core/Mana.h"
#include "../include/Game/Derived/Card/Creature.h"

#include <iostream>
#include <pybind11/embed.h>

namespace py = pybind11;

int main()
{
    auto* server = new Server(8888);
    server->Start();
    Factory factory;

    // Exit if the user enters quit
    std::string line;
    while (std::getline(std::cin, line) && line != "quit")
    {
        if (line == "memes")
        {
            py::object card = factory.createCard("Azar");
            auto base = card.cast<Card*>();
            auto creature = dynamic_cast<Creature*>(base);

            std::cout << "Name: " << creature->name << std::endl;
            std::cout << "Tag: " << creature->tag << std::endl;
            std::cout << "Text: " << creature->text << std::endl;
            std::cout << "Attack: " << creature->attackStat << std::endl;
            std::cout << "Defense: " << creature->defenseStat << std::endl;
            std::cout << "Black: " << creature->mana.black << std::endl;
            std::cout << "Blue: " << creature->mana.blue << std::endl;
            std::cout << "Brown: " << creature->mana.brown << std::endl;
            std::cout << "Red: " << creature->mana.red << std::endl;
            std::cout << "Green: " << creature->mana.green << std::endl;
            std::cout << "White: " << creature->mana.white << std::endl;
        }
        else if (line == "list")
        {
            std::cout << server->clients.size() << " client(s) connected" << std::endl;
        }
        else
        {
            std::cout << "Unknown command: '" << line << "'" << std::endl;
        }
    }

    std::cout << "Shutting down..." << std::endl;
    server->Stop();
    std::cout << "Bye!" << std::endl;
}
<commit_msg>Added a list of names for the clients when using the list command.<commit_after>//
// Created by Sam on 9/25/2017.
//

#include "../include/Game/Core/Game.h"
#include "../include/Game/Core/Player.h"
#include "../include/Network/Server.h"
#include "../include/Game/Python/Factory.h"
#include "../include/Game/Core/Card.h"
#include "../include/Game/Core/Mana.h"
#include "../include/Game/Derived/Card/Creature.h"

#include <iostream>
#include <pybind11/embed.h>

namespace py = pybind11;

int main()
{
    auto* server = new Server(8888);
    server->Start();
    Factory factory;

    // Exit if the user enters quit
    std::string line;
    while (std::getline(std::cin, line) && line != "quit")
    {
        if (line == "memes")
        {
            py::object card = factory.createCard("Azar");
            auto base = card.cast<Card*>();
            auto creature = dynamic_cast<Creature*>(base);

            std::cout << "Name: " << creature->name << std::endl;
            std::cout << "Tag: " << creature->tag << std::endl;
            std::cout << "Text: " << creature->text << std::endl;
            std::cout << "Attack: " << creature->attackStat << std::endl;
            std::cout << "Defense: " << creature->defenseStat << std::endl;
            std::cout << "Black: " << creature->mana.black << std::endl;
            std::cout << "Blue: " << creature->mana.blue << std::endl;
            std::cout << "Brown: " << creature->mana.brown << std::endl;
            std::cout << "Red: " << creature->mana.red << std::endl;
            std::cout << "Green: " << creature->mana.green << std::endl;
            std::cout << "White: " << creature->mana.white << std::endl;
        }
        else if (line == "list")
        {
            for(const auto &client : server->clients)
            {
                if (!client->name.empty())
                {
                    std::cout << client->name << std::endl;
                }
            }
            std::cout << server->clients.size() << " client(s) connected" << std::endl;
        }
        else
        {
            std::cout << "Unknown command: '" << line << "'" << std::endl;
        }
    }

    std::cout << "Shutting down..." << std::endl;
    server->Stop();
    std::cout << "Bye!" << std::endl;
}
<|endoftext|>


<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
#if !defined(NAMESPACE_HEADER_GUARD_1357924680)
#define NAMESPACE_HEADER_GUARD_1357924680

// Base header file.  Must be first.
#include <XPath/XPathDefinitions.hpp>

#include <XalanDOM/XalanDOMString.hpp>

/**
 * A representation of a namespace.  One of these will be pushed on the
 * namespace stack for each element.
 */
class XALAN_XPATH_EXPORT NameSpace
{
public:

	/**
	 * Construct a namespace for placement on the
	 * result tree namespace stack.
	 *
	 * @param prefix namespace prefix
	 * @param uri    URI of namespace
	 */
	NameSpace(
			const XalanDOMString&	prefix = XalanDOMString(),
			const XalanDOMString&	uri = XalanDOMString()) :
    m_prefix(prefix),
    m_uri(uri),
	m_resultCandidate(true)
	{
	}

	/**
	 * Retrieve the prefix for namespace
	 *
	 * @return prefix string
	 */
	const XalanDOMString&
	getPrefix() const
	{
		return m_prefix;
	}

	/**
	 * Retrieve the URI for namespace
	 *
	 * @return URI string
	 */
	const XalanDOMString&
	getURI() const
	{
		return m_uri;
	}

	/**
	 * Whether the namespace is a candidate for result namespace.
	 *
	 * @return true if it is a candidate
	 */
	bool
	getResultCandidate() const
	{
		return m_resultCandidate;
	}

	/**
	 * Set whether the namespace is a candidate for result namespace.
	 *
	 * @param fResultCandidate true to set namespace as candidate
	 */
	void
	setResultCandidate(bool		fResultCandidate)
	{
		m_resultCandidate = fResultCandidate;
	}

	/**
	 * Assignment operator, required for STL vector.
	 *
	 * @param theRHS namespace to assign
	 */
	NameSpace&
	operator=(const NameSpace&	theRHS)
	{
		if (&theRHS != this)
		{
			m_prefix = theRHS.m_prefix;
			m_uri = theRHS.m_uri;
			m_resultCandidate = theRHS.m_resultCandidate;
		}

		return *this;
	}

private:

	XalanDOMString	m_prefix;
	XalanDOMString	m_uri; // if length is 0, then Element namespace is empty.
	bool			m_resultCandidate;
};

#endif	// NAMESPACE_HEADER_GUARD_1357924680
<commit_msg>Removed unused member.  Add set accessors.<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
#if !defined(NAMESPACE_HEADER_GUARD_1357924680)
#define NAMESPACE_HEADER_GUARD_1357924680

// Base header file.  Must be first.
#include <XPath/XPathDefinitions.hpp>

#include <PlatformSupport/DOMStringHelper.hpp>

/**
 * A representation of a namespace.  One of these will be pushed on the
 * namespace stack for each element.
 */
class XALAN_XPATH_EXPORT NameSpace
{
public:

	/**
	 * Construct a namespace for placement on the
	 * result tree namespace stack.
	 *
	 * @param prefix namespace prefix
	 * @param uri    URI of namespace
	 */
	NameSpace(
			const XalanDOMString&	prefix = XalanDOMString(),
			const XalanDOMString&	uri = XalanDOMString()) :
    m_prefix(prefix),
    m_uri(uri)
	{
	}

	/**
	 * Retrieve the prefix for namespace
	 *
	 * @return prefix string
	 */
	const XalanDOMString&
	getPrefix() const
	{
		return m_prefix;
	}

	/**
	 * Set the prefix for namespace
	 *
	 * @param prefix The new prefix value
	 */
	void
	setPrefix(const XalanDOMString&		prefix)
	{
		m_prefix = prefix;
	}

	/**
	 * Retrieve the URI for namespace
	 *
	 * @return URI string
	 */
	const XalanDOMString&
	getURI() const
	{
		return m_uri;
	}

	/**
	 * Set the URI for namespace
	 *
	 * @param uri The new uri value
	 */
	void
	setURI(const XalanDOMString&	uri)
	{
		m_uri = uri;
	}

	/**
	 * Equality operator, necessary because DOMString::==()
	 * has screwy semantics.
	 *
	 * @param theRHS namespace to compare
	 */
	bool
	operator==(const NameSpace&		theRHS) const
	{
		return equals(m_prefix, theRHS.m_prefix) &&
			   equals(m_uri, theRHS.m_uri);
	}

private:

	XalanDOMString	m_prefix;

	XalanDOMString	m_uri; // if length is 0, then Element namespace is empty.
};

#endif	// NAMESPACE_HEADER_GUARD_1357924680
<|endoftext|>