<commit_before>#include "game.hpp"

int Game::negamax(BitBoard & b, int alpha, int beta, int depth, int real_depth, int rule, bool inNullMove, bool cut) {
	++nodesCounter;

	uint64_t hash = b.getColorHash();
	Hash* currentHash = &boardHash[hash & hash_cutter];

	int oldAlpha = alpha;

	if((currentHash->flag != EMPTY && currentHash->key == hash) && b.third_repeat[hash & hash_cutter] <= 1) {
		if(real_depth > 0 && currentHash->depth >= depth) {
			int score = currentHash->score;

			if(score > WHITE_WIN - 100) {
				score -= real_depth;
			} else if(score < -WHITE_WIN + 100) {
				score += real_depth;
			}

			if(currentHash->flag == BETA && score >= beta) {
				return beta;
			} else if(currentHash->flag == ALPHA && score <= alpha) {
				return alpha;
			} else if(currentHash->flag == EXACT && score >= alpha && score <= beta) {
				return score;
			}
		}
	}

	if(depth <= 0 || real_depth >= 100) {
		return quies(b, alpha, beta, rule, real_depth);
	}

	if(depth > 6) {
		if(is_input_available()) {
			std::string input_str;
			std::getline(std::cin, input_str);
			if(input_str == "stop") {
				stopped = true;
			} else if(input_str == "isready") {
				std::cout << "readyok" << std::endl;
			}
		}
	}

	if(real_depth) {
		max_real_depth = std::max(max_real_depth, real_depth);
	} else {
		max_real_depth = 0;
	}

	int eval = -WHITE_WIN;
	int nextDepth = depth - 1;
	int extensions = 0;

	if(depth > 2) {
		if((rule == FIXED_TIME && timer.getTime() >= time) || stopped) {
			return 0;
		}
	}

	uint8_t color = colorExtended[b.currentState.color];
	uint8_t enemyColor = colorExtended[!b.currentState.color];

	int tmp;
	bool inCheck = b.inCheck(color);
	bool onPV = (beta - alpha) > 1;
	int opposiing_pieces =  b.popcount64(b.currentState.piece_bit_mask[!b.currentState.color]);

	int num_moves = 0;

	b.bitBoardMoveGenerator(moveArray[real_depth]);
	sortAttacks(moveArray[real_depth]);
	sortMoves(moveArray[real_depth], real_depth);

	if(cut) { //Multi-Cut 82.91 +/- 24.04 (10+0.1)

		if (depth >= 4 && real_depth > 0 && !inCheck && !inNullMove && !extensions && !onPV && !b.currentState.attacked) {
			int c = 0;
			for (int i = 0; i < std::min((int)moveArray[real_depth].count, 6); ++i) {
				b.move(moveArray[real_depth].moveArray[i]);
				if(b.inCheck(color)) {
					b.goBack();
					continue;
				}

				tmp = -negamax(b, -(alpha + 1), -alpha, nextDepth - 4, real_depth + 1, rule, inNullMove, false);

				b.goBack();
				if (tmp >= beta) {
					if (++c == 2) {
						return beta;
					}
				}
			}
		}
	}

	BitMove* local_move = nullptr;

	if(moveArray[real_depth].count > 0) {
		local_move = &moveArray[real_depth].moveArray[0];
	}

	int low_moves_count = 0;

	for(unsigned int i = 0; i < moveArray[real_depth].count; ++i) {
		b.move(moveArray[real_depth].moveArray[i]);

		if(game_board.inCheck(color)) {
			b.goBack();
			continue;
		}

		if(num_moves == 0) {
			local_move = &moveArray[real_depth].moveArray[i];
		}

		++num_moves;

		if(real_depth == 0 && depth >= 12) {
			if((rule != FIXED_TIME || timer.getTime() < time) && !stopped) {
				std::cout << "info currmove " << moveArray[real_depth].moveArray[i].getMoveString() << " currmovenumber " << num_moves << " time " << (int64_t)((clock() - start_timer) / (CLOCKS_PER_SEC / 1000)) << " nodes " << nodesCounter << " nps " << (int64_t)(nodesCounter / ((clock() - start_timer) / CLOCKS_PER_SEC)) << std::endl;
			}
		}

		extensions = 0;
		if(b.inCheck(enemyColor)) {
			++extensions;
		}

		nextDepth = depth - 1;
		nextDepth += extensions;
		double reduction = 0;

		if(!extensions && !inNullMove && !moveArray[real_depth].moveArray[i].isAttack && !onPV && !inCheck) {
			++low_moves_count;

			if(low_moves_count > 3) {
				reduction = 1 + low_moves_count / 6;
				nextDepth -= reduction;
			}

			if(nextDepth <= 2) {
				if(-b.getEvaluate() + PAWN_EV.mg / 2 <= alpha) {
					++nodesCounter;
					b.goBack();
					continue;
				}
			}
		}

		if(num_moves == 1) {
			tmp = -negamax(b, -beta, -alpha, nextDepth, real_depth + 1, rule, inNullMove, true);
		} else {
			tmp = -negamax(b, -(alpha + 1), -alpha, nextDepth, real_depth + 1, rule, inNullMove, true);

			if(reduction > 0 && tmp > alpha) {
				nextDepth += reduction;
				tmp = -negamax(b, -(alpha + 1), -alpha, nextDepth, real_depth + 1, rule, inNullMove, true);
			}

			if(tmp > alpha && tmp < beta) {
				tmp = -negamax(b, -beta, -alpha, nextDepth, real_depth + 1, rule, inNullMove, true);
			}
		}

		b.goBack();

		if(tmp > eval) {
			eval = tmp;
		}

		if(tmp > alpha) {
			alpha = tmp;
			local_move = &moveArray[real_depth].moveArray[i];
			recordHash(depth, tmp, tmp<beta?EXACT:BETA, hash, moveArray[real_depth].moveArray[i], real_depth);
		}

		if(alpha >= beta) {
			if(!local_move->isAttack) {
				historySort[b.currentState.color][local_move->fromY][local_move->fromX][local_move->toY][local_move->toX] += std::pow(depth, 2);

				if(color == WHITE) {
					if(whiteKiller[real_depth].enable) {
						whiteSecondKiller[real_depth] = Killer(whiteKiller[real_depth].move);
					}
					whiteKiller[real_depth] = Killer(*local_move);
				} else {
					if(blackKiller[real_depth].enable) {
						blackSecondKiller[real_depth] = Killer(blackKiller[real_depth].move);
					}
					blackKiller[real_depth] = Killer(*local_move);
				}
			}

			break;
		}
	}

	if(num_moves == 0) {
		if(game_board.inCheck(color)) {
			return BLACK_WIN + real_depth;
		} else {
			return 0;
		}
	}

	if(alpha == oldAlpha) {
		recordHash(depth, eval, ALPHA, hash, *local_move, real_depth);
	}

	if(real_depth == 0) {
		if((rule == FIXED_TIME && timer.getTime() >= time) || stopped) {
			return 0;
		}

		bestMove = *local_move;
		bestScore = alpha;
	}

	if(real_depth == 0) {
		if(num_moves >= 0) {
			std::cout << "info depth " << max_depth << " time " << (int64_t)((clock() - start_timer) / (CLOCKS_PER_SEC / 1000)) << " nodes " << nodesCounter << " nps " << (int64_t)(nodesCounter / ((clock() - start_timer) / CLOCKS_PER_SEC)) << " hashfull " << (int)(hash_filled / max_hash_filled * 1000) << " seldepth " << max_real_depth;
			std::cout << " ";
			printScore(eval);
			std::cout << " pv ";
			printPV(depth);
		} else {
			std::cout << std::endl;
		}
	}

	return eval;
}

uint64_t Game::perft(int depth) {
	uint64_t res = 0;
	if(depth == 0) {
		++combinations;

		return 1;
	}

	game_board.bitBoardMoveGenerator(moveArray[depth]);

	for(unsigned int i = 0; i < moveArray[depth].count; ++i) {
		game_board.move(moveArray[depth].moveArray[i]);
		if(game_board.currentState.color) {
			if(game_board.inCheck(BLACK)) {
				game_board.goBack();
				continue;
			}
		} else {
			if(game_board.inCheck(WHITE)) {
				game_board.goBack();
				continue;
			}
		}

		res += perft(depth - 1);
		game_board.goBack();
	}

	return res;
}

int Game::quies(BitBoard & b, int alpha, int beta, int rule, int real_depth) {
	int val = b.getEvaluate();

	if (val < alpha - QUEEN_EV.mg) {
   		return alpha;
	}

	if(val >= beta) {
		return val;
	}

	if(alpha < val) {
		alpha = val;
	}

	b.bitBoardAttackMoveGenerator(moveArray[real_depth]);
	sortAttacks(moveArray[real_depth]);

	for(unsigned int i = 0; i < moveArray[real_depth].count; ++i) {
		++nodesCounter;
		b.move(moveArray[real_depth].moveArray[i]);

		if(game_board.inCheck(colorExtended[!game_board.currentState.color])) {
			b.goBack();
			continue;
		}

		val = -quies(b, -beta, -alpha, rule, real_depth + 1);
		b.goBack();

		if(val >= beta) {
			return beta;
		}

		if(val > alpha) {
			alpha = val;
		}
	}

	return alpha;
}

bool Game::recordHash(int depth, int score, int flag, uint64_t key, BitMove move, int real_depth) {
	Hash* hash = &boardHash[key & hash_cutter];

	if(flag == ALPHA && (hash->flag == EXACT || hash->flag == BETA)) {
		return false;
	}

	if((hash->flag != EMPTY) && hash->depth > depth && hash->age == hashAge) {
		return false;
	}

	if(score > WHITE_WIN - 100) {
		score += real_depth;
	} else if(score < -WHITE_WIN + 100) {
		score -= real_depth;
	}

	if(hash->flag == EMPTY) {
		++hash_filled;
	}

	hash->depth = depth;
	hash->score = score;
	hash->flag = flag;
	hash->key = key;
	hash->age = hashAge;

	if(flag != ALPHA) {
		hash->setMove(move);
	}

	return true;
}

std::vector<BitMove> Game::extractPV(int depth) {
	int k;
	std::vector<BitMove> result;
	MoveArray moves;
	bool stopped;
	int stack_count = 0;
	for(k = 0; k < depth + 10; ++k) {
		stopped = true;
		uint64_t hash = game_board.getColorHash();
		Hash* currentHash = &boardHash[hash & hash_cutter];

		if(currentHash->flag == EXACT || currentHash->flag == BETA) {
			game_board.bitBoardMoveGenerator(moves);

			bool enable;
			BitMove mv = game_board.getMove(currentHash->fromY, currentHash->fromX, currentHash->toY, currentHash->toX, currentHash->replaced, currentHash->replacedFigure, enable);// currentHash->getMove();

			for(int i = 0; i < moves.count; ++i) {
				if(moves.moveArray[i].equal(mv)) {
					game_board.move(mv);
					++stack_count;
					if(game_board.currentState.color) {
						if(game_board.inCheck(BLACK)) {
							stopped = true;
						} else {
							stopped = false;
						}
					} else {
						if(game_board.inCheck(WHITE)) {
							stopped = true;
						} else {
							stopped = false;
						}
					}
				}
			}

			if(stopped || !enable) {
				break;
			}

			result.emplace_back(mv);
		} else {
			break;
		}
	}

	for(int i = 0; i < stack_count; ++i) {
		game_board.goBack();
	}

	return result;
}

bool Game::testMovePossible(BitMove move) {
	MoveArray moves;
	game_board.bitBoardMoveGenerator(moves);

	for(unsigned int i = 0; i < moves.count; ++i) {
		if(move.equal(moves.moveArray[i])) {
			return true;
		}
	}

	return false;
}

void Game::printPV(int depth) {
	std::vector<BitMove> main_pv = extractPV(depth);
	for(unsigned int i = 0; i < main_pv.size(); ++i) {
		std::cout << main_pv[i].getMoveString() << " ";
	}
	std::cout << std::endl;
}<commit_msg>return razoring<commit_after>#include "game.hpp"

int Game::negamax(BitBoard & b, int alpha, int beta, int depth, int real_depth, int rule, bool inNullMove, bool cut) {
	++nodesCounter;

	uint64_t hash = b.getColorHash();
	Hash* currentHash = &boardHash[hash & hash_cutter];

	int oldAlpha = alpha;

	if((currentHash->flag != EMPTY && currentHash->key == hash) && b.third_repeat[hash & hash_cutter] <= 1) {
		if(real_depth > 0 && currentHash->depth >= depth) {
			int score = currentHash->score;

			if(score > WHITE_WIN - 100) {
				score -= real_depth;
			} else if(score < -WHITE_WIN + 100) {
				score += real_depth;
			}

			if(currentHash->flag == BETA && score >= beta) {
				return beta;
			} else if(currentHash->flag == ALPHA && score <= alpha) {
				return alpha;
			} else if(currentHash->flag == EXACT && score >= alpha && score <= beta) {
				return score;
			}
		}
	}

	if(depth <= 0 || real_depth >= 100) {
		return quies(b, alpha, beta, rule, real_depth);
	}

	if(depth > 6) {
		if(is_input_available()) {
			std::string input_str;
			std::getline(std::cin, input_str);
			if(input_str == "stop") {
				stopped = true;
			} else if(input_str == "isready") {
				std::cout << "readyok" << std::endl;
			}
		}
	}

	if(real_depth) {
		max_real_depth = std::max(max_real_depth, real_depth);
	} else {
		max_real_depth = 0;
	}

	int eval = -WHITE_WIN;
	int nextDepth = depth - 1;
	int extensions = 0;

	if(depth > 2) {
		if((rule == FIXED_TIME && timer.getTime() >= time) || stopped) {
			return 0;
		}
	}

	uint8_t color = colorExtended[b.currentState.color];
	uint8_t enemyColor = colorExtended[!b.currentState.color];

	int tmp;
	bool inCheck = b.inCheck(color);
	bool onPV = (beta - alpha) > 1;
	int opposiing_pieces =  b.popcount64(b.currentState.piece_bit_mask[!b.currentState.color]);

	if(!inCheck && !inNullMove && depth < 10 && !onPV && opposiing_pieces > 3) { //Razoring
		int evaluate = b.getEvaluate();
		if(evaluate - RAZOR_MARGIN[depth] >= beta) {
			return beta;
		}
	}

	int num_moves = 0;

	b.bitBoardMoveGenerator(moveArray[real_depth]);
	sortAttacks(moveArray[real_depth]);
	sortMoves(moveArray[real_depth], real_depth);

	if(cut) { //Multi-Cut 82.91 +/- 24.04 (10+0.1)

		if (depth >= 4 && real_depth > 0 && !inCheck && !inNullMove && !extensions && !onPV && !b.currentState.attacked) {
			int c = 0;
			for (int i = 0; i < std::min((int)moveArray[real_depth].count, 6); ++i) {
				b.move(moveArray[real_depth].moveArray[i]);
				if(b.inCheck(color)) {
					b.goBack();
					continue;
				}

				tmp = -negamax(b, -(alpha + 1), -alpha, nextDepth - 4, real_depth + 1, rule, inNullMove, false);

				b.goBack();
				if (tmp >= beta) {
					if (++c == 2) {
						return beta;
					}
				}
			}
		}
	}

	BitMove* local_move = nullptr;

	if(moveArray[real_depth].count > 0) {
		local_move = &moveArray[real_depth].moveArray[0];
	}

	int low_moves_count = 0;

	for(unsigned int i = 0; i < moveArray[real_depth].count; ++i) {
		b.move(moveArray[real_depth].moveArray[i]);

		if(game_board.inCheck(color)) {
			b.goBack();
			continue;
		}

		if(num_moves == 0) {
			local_move = &moveArray[real_depth].moveArray[i];
		}

		++num_moves;

		if(real_depth == 0 && depth >= 12) {
			if((rule != FIXED_TIME || timer.getTime() < time) && !stopped) {
				std::cout << "info currmove " << moveArray[real_depth].moveArray[i].getMoveString() << " currmovenumber " << num_moves << " time " << (int64_t)((clock() - start_timer) / (CLOCKS_PER_SEC / 1000)) << " nodes " << nodesCounter << " nps " << (int64_t)(nodesCounter / ((clock() - start_timer) / CLOCKS_PER_SEC)) << std::endl;
			}
		}

		extensions = 0;
		if(b.inCheck(enemyColor)) {
			++extensions;
		}

		nextDepth = depth - 1;
		nextDepth += extensions;
		double reduction = 0;

		if(!extensions && !inNullMove && !moveArray[real_depth].moveArray[i].isAttack && !onPV && !inCheck) {
			++low_moves_count;

			if(low_moves_count > 3) {
				reduction = 1 + low_moves_count / 6;
				nextDepth -= reduction;
			}

			if(nextDepth <= 2) {
				if(-b.getEvaluate() + PAWN_EV.mg / 2 <= alpha) {
					++nodesCounter;
					b.goBack();
					continue;
				}
			}
		}

		if(num_moves == 1) {
			tmp = -negamax(b, -beta, -alpha, nextDepth, real_depth + 1, rule, inNullMove, true);
		} else {
			tmp = -negamax(b, -(alpha + 1), -alpha, nextDepth, real_depth + 1, rule, inNullMove, true);

			if(reduction > 0 && tmp > alpha) {
				nextDepth += reduction;
				tmp = -negamax(b, -(alpha + 1), -alpha, nextDepth, real_depth + 1, rule, inNullMove, true);
			}

			if(tmp > alpha && tmp < beta) {
				tmp = -negamax(b, -beta, -alpha, nextDepth, real_depth + 1, rule, inNullMove, true);
			}
		}

		b.goBack();

		if(tmp > eval) {
			eval = tmp;
		}

		if(tmp > alpha) {
			alpha = tmp;
			local_move = &moveArray[real_depth].moveArray[i];
			recordHash(depth, tmp, tmp<beta?EXACT:BETA, hash, moveArray[real_depth].moveArray[i], real_depth);
		}

		if(alpha >= beta) {
			if(!local_move->isAttack) {
				historySort[b.currentState.color][local_move->fromY][local_move->fromX][local_move->toY][local_move->toX] += std::pow(depth, 2);

				if(color == WHITE) {
					if(whiteKiller[real_depth].enable) {
						whiteSecondKiller[real_depth] = Killer(whiteKiller[real_depth].move);
					}
					whiteKiller[real_depth] = Killer(*local_move);
				} else {
					if(blackKiller[real_depth].enable) {
						blackSecondKiller[real_depth] = Killer(blackKiller[real_depth].move);
					}
					blackKiller[real_depth] = Killer(*local_move);
				}
			}

			break;
		}
	}

	if(num_moves == 0) {
		if(game_board.inCheck(color)) {
			return BLACK_WIN + real_depth;
		} else {
			return 0;
		}
	}

	if(alpha == oldAlpha) {
		recordHash(depth, eval, ALPHA, hash, *local_move, real_depth);
	}

	if(real_depth == 0) {
		if((rule == FIXED_TIME && timer.getTime() >= time) || stopped) {
			return 0;
		}

		bestMove = *local_move;
		bestScore = alpha;
	}

	if(real_depth == 0) {
		if(num_moves >= 0) {
			std::cout << "info depth " << max_depth << " time " << (int64_t)((clock() - start_timer) / (CLOCKS_PER_SEC / 1000)) << " nodes " << nodesCounter << " nps " << (int64_t)(nodesCounter / ((clock() - start_timer) / CLOCKS_PER_SEC)) << " hashfull " << (int)(hash_filled / max_hash_filled * 1000) << " seldepth " << max_real_depth;
			std::cout << " ";
			printScore(eval);
			std::cout << " pv ";
			printPV(depth);
		} else {
			std::cout << std::endl;
		}
	}

	return eval;
}

uint64_t Game::perft(int depth) {
	uint64_t res = 0;
	if(depth == 0) {
		++combinations;

		return 1;
	}

	game_board.bitBoardMoveGenerator(moveArray[depth]);

	for(unsigned int i = 0; i < moveArray[depth].count; ++i) {
		game_board.move(moveArray[depth].moveArray[i]);
		if(game_board.currentState.color) {
			if(game_board.inCheck(BLACK)) {
				game_board.goBack();
				continue;
			}
		} else {
			if(game_board.inCheck(WHITE)) {
				game_board.goBack();
				continue;
			}
		}

		res += perft(depth - 1);
		game_board.goBack();
	}

	return res;
}

int Game::quies(BitBoard & b, int alpha, int beta, int rule, int real_depth) {
	int val = b.getEvaluate();

	if (val < alpha - QUEEN_EV.mg) {
   		return alpha;
	}

	if(val >= beta) {
		return val;
	}

	if(alpha < val) {
		alpha = val;
	}

	b.bitBoardAttackMoveGenerator(moveArray[real_depth]);
	sortAttacks(moveArray[real_depth]);

	for(unsigned int i = 0; i < moveArray[real_depth].count; ++i) {
		++nodesCounter;
		b.move(moveArray[real_depth].moveArray[i]);

		if(game_board.inCheck(colorExtended[!game_board.currentState.color])) {
			b.goBack();
			continue;
		}

		val = -quies(b, -beta, -alpha, rule, real_depth + 1);
		b.goBack();

		if(val >= beta) {
			return beta;
		}

		if(val > alpha) {
			alpha = val;
		}
	}

	return alpha;
}

bool Game::recordHash(int depth, int score, int flag, uint64_t key, BitMove move, int real_depth) {
	Hash* hash = &boardHash[key & hash_cutter];

	if(flag == ALPHA && (hash->flag == EXACT || hash->flag == BETA)) {
		return false;
	}

	if((hash->flag != EMPTY) && hash->depth > depth && hash->age == hashAge) {
		return false;
	}

	if(score > WHITE_WIN - 100) {
		score += real_depth;
	} else if(score < -WHITE_WIN + 100) {
		score -= real_depth;
	}

	if(hash->flag == EMPTY) {
		++hash_filled;
	}

	hash->depth = depth;
	hash->score = score;
	hash->flag = flag;
	hash->key = key;
	hash->age = hashAge;

	if(flag != ALPHA) {
		hash->setMove(move);
	}

	return true;
}

std::vector<BitMove> Game::extractPV(int depth) {
	int k;
	std::vector<BitMove> result;
	MoveArray moves;
	bool stopped;
	int stack_count = 0;
	for(k = 0; k < depth + 10; ++k) {
		stopped = true;
		uint64_t hash = game_board.getColorHash();
		Hash* currentHash = &boardHash[hash & hash_cutter];

		if(currentHash->flag == EXACT || currentHash->flag == BETA) {
			game_board.bitBoardMoveGenerator(moves);

			bool enable;
			BitMove mv = game_board.getMove(currentHash->fromY, currentHash->fromX, currentHash->toY, currentHash->toX, currentHash->replaced, currentHash->replacedFigure, enable);// currentHash->getMove();

			for(int i = 0; i < moves.count; ++i) {
				if(moves.moveArray[i].equal(mv)) {
					game_board.move(mv);
					++stack_count;
					if(game_board.currentState.color) {
						if(game_board.inCheck(BLACK)) {
							stopped = true;
						} else {
							stopped = false;
						}
					} else {
						if(game_board.inCheck(WHITE)) {
							stopped = true;
						} else {
							stopped = false;
						}
					}
				}
			}

			if(stopped || !enable) {
				break;
			}

			result.emplace_back(mv);
		} else {
			break;
		}
	}

	for(int i = 0; i < stack_count; ++i) {
		game_board.goBack();
	}

	return result;
}

bool Game::testMovePossible(BitMove move) {
	MoveArray moves;
	game_board.bitBoardMoveGenerator(moves);

	for(unsigned int i = 0; i < moves.count; ++i) {
		if(move.equal(moves.moveArray[i])) {
			return true;
		}
	}

	return false;
}

void Game::printPV(int depth) {
	std::vector<BitMove> main_pv = extractPV(depth);
	for(unsigned int i = 0; i < main_pv.size(); ++i) {
		std::cout << main_pv[i].getMoveString() << " ";
	}
	std::cout << std::endl;
}<|endoftext|>


<commit_before>#include "augs/misc/simple_pair.h"
#include "augs/templates/for_each_std_get.h"

#include "augs/readwrite/memory_stream.h"

#include "augs/misc/imgui/imgui_utils.h"
#include "augs/misc/imgui/imgui_scope_wrappers.h"
#include "augs/misc/imgui/imgui_control_wrappers.h"

#include "application/intercosm.h"
#include "application/setups/editor/editor_folder.h"
#include "application/setups/editor/gui/editor_all_entities_gui.h"

#include "application/setups/editor/property_editor/flavour_properties_editor.h"
#include "application/setups/editor/property_editor/entity_properties_editor.h"

#include "augs/readwrite/memory_stream.h"
#include "augs/readwrite/byte_readwrite.h"

void editor_all_entities_gui::open() {
	show = true;
	acquire_once = true;
	ImGui::SetWindowFocus("All entities");
}

void editor_all_entities_gui::interrupt_tweakers() {
	properties_gui.last_active.reset();
	properties_gui.old_description.clear();
}

void editor_all_entities_gui::perform(const editor_command_input in) {
	if (!show) {
		return;
	}

	using namespace augs::imgui;

	auto entities = scoped_window("All entities", &show);
	auto& work = *in.folder.work;
	auto& cosm = work.world;

	if (acquire_once) {
		ImGui::SetKeyboardFocusHere();
		acquire_once = false;
	}

	thread_local ImGuiTextFilter filter;
	filter.Draw();

	ImGui::Columns(2); // 4-ways, with border
	next_column_text_disabled("Details");
	ImGui::Separator();

	hovered_guid.unset();

	cosm.get_solvable().for_each_pool(
		[&](const auto& p){
			using P = decltype(p);
			using pool_type = std::decay_t<P>;

			using E = type_argument_t<typename pool_type::mapped_type>;
			using specific_handle = const_typed_entity_handle<E>;

			using flavour_id_type = typed_entity_flavour_id<E>;
			using flavour_type = entity_flavour<E>;

			const auto entity_type_label = format_field_name(get_type_name<E>());
			const auto total_entities = p.size();
			const auto total_flavours = cosm.get_common_significant().get_flavours<E>().count();

			const auto node = scoped_tree_node_ex(entity_type_label);

			next_column_text_disabled(typesafe_sprintf("%x Flavours, %x Entities", total_flavours, total_entities));

			if (node) {
				cosm.change_common_significant([&](cosmos_common_significant& common_signi){
					const auto& all_flavours = common_signi.get_flavours<E>();

					if (all_flavours.count() > 0) {
						const auto unified_flavours_node = scoped_tree_node_ex(typesafe_sprintf("%x Flavours (unified)", all_flavours.count()));

						next_column_text();

						if (unified_flavours_node) {
							auto command_maker = [&]() {
								change_flavour_property_command cmd;

								all_flavours.for_each([&](
									const flavour_id_type flavour_id,
									const flavour_type& flavour
								) {
									cmd.affected_flavours.push_back(flavour_id);
								});

								return cmd;
							};

							const auto first_flavour_id = raw_entity_flavour_id { 0 };
							const auto& first_flavour = all_flavours.get_flavour(first_flavour_id);

							edit_flavour(properties_gui, first_flavour, command_maker, in);

							ImGui::Separator();
						}
					}

					all_flavours.for_each(
						[&](
							const flavour_id_type flavour_id,
							/*
								Note: we accept flavour as const,
								because ImGUI itself should only see the immutable reference.

							   	Is the job of the change_flavour_property_command to actually alter flavour state.
							*/
						   	const flavour_type& flavour
						) {
							const auto flavour_label = flavour.template get<invariants::name>().name;

							if (!filter.PassFilter(flavour_label.c_str())) {
								return;
							}

							const auto all_having_flavour = cosm.get_solvable_inferred().name.get_entities_by_flavour_id(flavour_id);

							const auto node_label = typesafe_sprintf("%x###%x", flavour_label, flavour_id.raw);
							const auto flavour_node = scoped_tree_node_ex(node_label);

							const auto num_entities_label = typesafe_sprintf("%x Entities", all_having_flavour.size());
							next_column_text_disabled(num_entities_label);

							if (flavour_node) {
								ImGui::Separator();

								{
									auto command_maker = [&flavour_id]() {
										change_flavour_property_command cmd;
										cmd.affected_flavours = { flavour_id };
										return cmd;
									};

									edit_flavour(properties_gui, flavour, command_maker, in);
								}

								ImGui::Separator();

								{
									const auto unified_entities_node = scoped_tree_node_ex(num_entities_label + " (unified)");

									next_column_text();

									if (unified_entities_node) {
										if (all_having_flavour.size() > 0) {
											const auto first_handle = specific_handle(cosm, (*all_having_flavour.begin()).basic());

											auto command_maker = [&all_having_flavour]() {
												change_entity_property_command cmd;
												cmd.affected_entities.assign(all_having_flavour.begin(), all_having_flavour.end());
												return cmd;
											};

											edit_entity(properties_gui, first_handle, command_maker, in);
										}
									}
								}

								const auto entities_node = scoped_tree_node_ex(num_entities_label);

								next_column_text();

								if (entities_node) {
									for (const auto& e : all_having_flavour) {
										auto command_maker = [e]() {
											change_entity_property_command cmd;
											cmd.affected_entities = { e };
											return cmd;
										};

										const auto typed_handle = specific_handle(cosm, e);

										const auto guid = typed_handle.get_guid();
										const auto entity_label = typesafe_sprintf("%x", guid);

										const auto entity_node = scoped_tree_node_ex(entity_label);

										if (ImGui::IsItemHovered()) {
											hovered_guid = guid;
										}

										next_column_text();

										if (entity_node) {
											edit_entity(properties_gui, typed_handle, command_maker, in);
										}
									}
								}

								ImGui::Separator();
							}
						}
					);

					return changer_callback_result::DONT_REFRESH;
				});
			}
		}
	);
}
<commit_msg>working unified entities of unified flavours view<commit_after>#include "augs/misc/simple_pair.h"
#include "augs/templates/for_each_std_get.h"

#include "augs/readwrite/memory_stream.h"

#include "augs/misc/imgui/imgui_utils.h"
#include "augs/misc/imgui/imgui_scope_wrappers.h"
#include "augs/misc/imgui/imgui_control_wrappers.h"

#include "application/intercosm.h"
#include "application/setups/editor/editor_folder.h"
#include "application/setups/editor/gui/editor_all_entities_gui.h"

#include "application/setups/editor/property_editor/flavour_properties_editor.h"
#include "application/setups/editor/property_editor/entity_properties_editor.h"

#include "augs/readwrite/memory_stream.h"
#include "augs/readwrite/byte_readwrite.h"

void editor_all_entities_gui::open() {
	show = true;
	acquire_once = true;
	ImGui::SetWindowFocus("All entities");
}

void editor_all_entities_gui::interrupt_tweakers() {
	properties_gui.last_active.reset();
	properties_gui.old_description.clear();
}

void editor_all_entities_gui::perform(const editor_command_input in) {
	if (!show) {
		return;
	}

	using namespace augs::imgui;

	auto entities = scoped_window("All entities", &show);
	auto& work = *in.folder.work;
	auto& cosm = work.world;

	if (acquire_once) {
		ImGui::SetKeyboardFocusHere();
		acquire_once = false;
	}

	thread_local ImGuiTextFilter filter;
	filter.Draw();

	ImGui::Columns(2); // 4-ways, with border
	next_column_text_disabled("Details");
	ImGui::Separator();

	hovered_guid.unset();

	cosm.get_solvable().for_each_pool(
		[&](const auto& p){
			using P = decltype(p);
			using pool_type = std::decay_t<P>;

			using E = type_argument_t<typename pool_type::mapped_type>;
			using specific_handle = const_typed_entity_handle<E>;

			using flavour_id_type = typed_entity_flavour_id<E>;
			using flavour_type = entity_flavour<E>;

			const auto entity_type_label = format_field_name(get_type_name<E>());
			const auto total_entities = p.size();
			const auto total_flavours = cosm.get_common_significant().get_flavours<E>().count();

			const auto node = scoped_tree_node_ex(entity_type_label);

			next_column_text_disabled(typesafe_sprintf("%x Flavours, %x Entities", total_flavours, total_entities));

			if (node) {
				cosm.change_common_significant([&](cosmos_common_significant& common_signi){
					const auto& all_flavours = common_signi.get_flavours<E>();

					if (all_flavours.count() > 1) {
						const auto unified_flavours_node = scoped_tree_node_ex(typesafe_sprintf("%x Flavours (unified)", all_flavours.count()));

						next_column_text();

						if (unified_flavours_node) {
							thread_local std::vector<entity_flavour_id> all_flavour_ids;
							all_flavour_ids.clear();

							all_flavours.for_each([&](
								const flavour_id_type flavour_id,
								const flavour_type& flavour
							) {
								all_flavour_ids.push_back(flavour_id);
							});

							{
								auto command_maker = [&]() {
									change_flavour_property_command cmd;
									cmd.affected_flavours = all_flavour_ids;
									return cmd;
								};

								const auto first_flavour_id = *all_flavour_ids.begin();
								const auto& first_flavour = all_flavours.get_flavour(first_flavour_id.raw);

								edit_flavour(properties_gui, first_flavour, command_maker, in);
							}

							ImGui::Separator();

							if (total_entities > 0) {
								const auto unified_entities_node = scoped_tree_node_ex(typesafe_sprintf("%x Entities (unified)", total_entities));

								next_column_text();

								if (unified_entities_node) {
									thread_local std::vector<entity_id> all_having_flavours;
									all_having_flavours.clear();

									/*
										This could be done by just iterating over the pool and gathering all ids.
										This however will be better solution if we filter per flavours.
									*/

									for (const auto id : all_flavour_ids) {
										concatenate(
											all_having_flavours,
											cosm.get_solvable_inferred().name.get_entities_by_flavour_id(id)
										);
									}

									ensure(total_entities == all_having_flavours.size());

									auto command_maker = [&]() {
										change_entity_property_command cmd;
										cmd.affected_entities = all_having_flavours;
										return cmd;
									};

									const auto first_handle = specific_handle(cosm, (*all_having_flavours.begin()).basic());
									edit_entity(properties_gui, first_handle, command_maker, in);
								}
							}

							ImGui::Separator();
						}
					}

					all_flavours.for_each(
						[&](
							const flavour_id_type flavour_id,
							/*
								Note: we accept flavour as const,
								because ImGUI itself should only see the immutable reference.

							   	Is the job of the change_flavour_property_command to actually alter flavour state.
							*/
						   	const flavour_type& flavour
						) {
							const auto flavour_label = flavour.template get<invariants::name>().name;

							if (!filter.PassFilter(flavour_label.c_str())) {
								return;
							}

							const auto all_having_flavour = cosm.get_solvable_inferred().name.get_entities_by_flavour_id(flavour_id);

							const auto node_label = typesafe_sprintf("%x###%x", flavour_label, flavour_id.raw);
							const auto flavour_node = scoped_tree_node_ex(node_label);

							const auto num_entities_label = typesafe_sprintf("%x Entities", all_having_flavour.size());
							next_column_text_disabled(num_entities_label);

							if (flavour_node) {
								ImGui::Separator();

								{
									auto command_maker = [&flavour_id]() {
										change_flavour_property_command cmd;
										cmd.affected_flavours = { flavour_id };
										return cmd;
									};

									edit_flavour(properties_gui, flavour, command_maker, in);
								}

								ImGui::Separator();

								{
									const auto unified_entities_node = scoped_tree_node_ex(num_entities_label + " (unified)");

									next_column_text();

									if (unified_entities_node) {
										if (all_having_flavour.size() > 0) {
											const auto first_handle = specific_handle(cosm, (*all_having_flavour.begin()).basic());

											auto command_maker = [&all_having_flavour]() {
												change_entity_property_command cmd;
												cmd.affected_entities.assign(all_having_flavour.begin(), all_having_flavour.end());
												return cmd;
											};

											edit_entity(properties_gui, first_handle, command_maker, in);
										}
									}
								}

								const auto entities_node = scoped_tree_node_ex(num_entities_label);

								next_column_text();

								if (entities_node) {
									for (const auto& e : all_having_flavour) {
										auto command_maker = [e]() {
											change_entity_property_command cmd;
											cmd.affected_entities = { e };
											return cmd;
										};

										const auto typed_handle = specific_handle(cosm, e);

										const auto guid = typed_handle.get_guid();
										const auto entity_label = typesafe_sprintf("%x", guid);

										const auto entity_node = scoped_tree_node_ex(entity_label);

										if (ImGui::IsItemHovered()) {
											hovered_guid = guid;
										}

										next_column_text();

										if (entity_node) {
											edit_entity(properties_gui, typed_handle, command_maker, in);
										}
									}
								}

								ImGui::Separator();
							}
						}
					);

					return changer_callback_result::DONT_REFRESH;
				});
			}
		}
	);
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2008-2010 The QXmpp developers
 *
 * Authors:
 *  Ian Reinhart Geiser
 *
 * Source:
 *  http://code.google.com/p/qxmpp
 *
 * This file is a part of QXmpp library.
 *
 * 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.
 *
 */

#include "QXmppRemoteMethod.h"
#include "QXmppClient.h"
#include "QXmppUtils.h"
#include "QXmppConfiguration.h"

#include <QEventLoop>
#include <QTimer>
#include <qdebug.h>

QXmppRemoteMethod::QXmppRemoteMethod(const QString &jid, const QString &method, const QVariantList &args, QXmppClient *client) :
        QObject(client), m_client(client)
{
    m_payload.setTo( jid );
    m_payload.setFrom( client->configuration().jid() );
    m_payload.setMethod( method );
    m_payload.setArguments( args );
}

QXmppRemoteMethodResult QXmppRemoteMethod::call( )
{
    QEventLoop loop(this);
    connect( this, SIGNAL(callDone()), &loop, SLOT(quit()));
    QTimer::singleShot(30000,&loop, SLOT(quit())); // Timeout incase the other end hangs...

    m_client->sendPacket( m_payload );

    loop.exec( QEventLoop::ExcludeUserInputEvents | QEventLoop::WaitForMoreEvents );
    return m_result;
}

void QXmppRemoteMethod::gotError( const QXmppRpcErrorIq &iq )
{
    if ( iq.id() == m_payload.id() )
    {
        m_result.hasError = true;
        m_result.errorMessage = iq.error().text();
        m_result.code = iq.error().type();
        emit callDone();
    }
}

void QXmppRemoteMethod::gotResult( const QXmppRpcResponseIq &iq )
{
    if ( iq.id() == m_payload.id() )
    {
        m_result.hasError = false;
        // FIXME: we don't handle multiple responses
        m_result.result = iq.values().first();
        emit callDone();
    }
}
<commit_msg>add some warnings in RPC code<commit_after>/*
 * Copyright (C) 2008-2010 The QXmpp developers
 *
 * Authors:
 *  Ian Reinhart Geiser
 *
 * Source:
 *  http://code.google.com/p/qxmpp
 *
 * This file is a part of QXmpp library.
 *
 * 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.
 *
 */

#include "QXmppRemoteMethod.h"
#include "QXmppClient.h"
#include "QXmppUtils.h"

#include <QDebug>
#include <QEventLoop>
#include <QTimer>

QXmppRemoteMethod::QXmppRemoteMethod(const QString &jid, const QString &method, const QVariantList &args, QXmppClient *client) :
        QObject(client), m_client(client)
{
    m_payload.setTo( jid );
    m_payload.setFrom( client->configuration().jid() );
    m_payload.setMethod( method );
    m_payload.setArguments( args );
}

QXmppRemoteMethodResult QXmppRemoteMethod::call( )
{
    // FIXME : spinning an event loop is a VERY bad idea, it can cause
    // us to lose incoming packets
    QEventLoop loop(this);
    connect( this, SIGNAL(callDone()), &loop, SLOT(quit()));
    QTimer::singleShot(30000,&loop, SLOT(quit())); // Timeout incase the other end hangs...

    m_client->sendPacket( m_payload );

    loop.exec( QEventLoop::ExcludeUserInputEvents | QEventLoop::WaitForMoreEvents );
    return m_result;
}

void QXmppRemoteMethod::gotError( const QXmppRpcErrorIq &iq )
{
    if ( iq.id() == m_payload.id() )
    {
        m_result.hasError = true;
        m_result.errorMessage = iq.error().text();
        m_result.code = iq.error().type();
        emit callDone();
    }
}

void QXmppRemoteMethod::gotResult( const QXmppRpcResponseIq &iq )
{
    if ( iq.id() == m_payload.id() )
    {
        m_result.hasError = false;
        // FIXME: we don't handle multiple responses
        m_result.result = iq.values().first();
        emit callDone();
    }
}
<|endoftext|>


<commit_before>/*
 ================================================
 *      ######
 *    #########                            ##
 *   ####    ###                           ##
 *   ##       ##                           ##
 *  ##         ## ##   ##   ####     ### ######
 *  ##         ## ##   ##  ######  ##### ######
 *  ##         ## ##   ## ###  ## ###      ##
 *  ##    #    ## ##   ## ##  ##  #####    ##
 *   ##   ##   ## ##   ## ## ##    #####   ##
 *   ###   ## ##  ##   ## ###   #     ##   ##
 *    ##########  ####### ####### ######   ##
 *      #### ##    ######   ####   ####    ##
 *            ##
 *             ##       CREATE: 2012-09-06
 *              #
 ================================================
        QuestLAB 主启动程序
 ================================================
 */

#include "../QstLibs/QstLibs.h"

/* 应用的名称 */
#ifndef EXE_XNAME
    #define EXE_XNAME   "QuestLAB"
    #define WIN_TITLE   "QuestLAB"
    #define WIN_CLASS   "QuestLABCLSS"
    #define WIN_ICONF   "QuestLAB.ini"
    #define WIN_XCONF   "QuestLAB.xml"
#endif

/* 默认配置名称 */
#define DEF_CONF_NAME   "base"

/*
=======================================
    WinMain 程序入口
=======================================
*/
int WINAPI
WinMain (
  __CR_IN__ HINSTANCE   curt_app,
  __CR_IN__ HINSTANCE   prev_app,
  __CR_IN__ LPSTR       cmd_line,
  __CR_IN__ int         cmd_show
    )
{
    uint_t      argc;
    ansi_t**    argv;

    CR_NOUSE(curt_app);
    CR_NOUSE(prev_app);
    CR_NOUSE(cmd_show);

    /* 只允许一个例程 */
    if (misc_is_running(EXE_XNAME))
        return (QST_ERROR);

    /* 限定附加参数长度 */
    if (str_lenA(cmd_line) > 128)
        return (QST_ERROR);

    /* 建立 CrHack 系统 */
    if (!set_app_type(CR_APP_GUI))
        return (QST_ERROR);

    /* 获取命令行参数, 不包括进程文件名 */
    argv = misc_get_param(cmd_line, &argc);

    ansi_t  exec[256];
    ansi_t* conf_name;

    /* 参数解析 [配置名称] */
    if (argc == 0 || str_lenA(argv[0]) > 64)
        conf_name = DEF_CONF_NAME;
    else
        conf_name = argv[0];

    HANDLE              find;
    WIN32_FIND_DATAA    wfda;

    /* 复制指定的配置文件 */
    sprintf(exec, QST_PATH_CONFIG "%s", conf_name);
    find = FindFirstFileA(exec, &wfda);
    if ((find == INVALID_HANDLE_VALUE) ||
       !(wfda.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
        conf_name = DEF_CONF_NAME;
    sprintf(exec, "cmd.exe /c copy " QST_PATH_CONFIG
            "%s\\*.* " QST_PATH_CONFIG, conf_name);
    if (find != INVALID_HANDLE_VALUE)
        FindClose(find);
    misc_call_exe(exec, TRUE, TRUE);

    /* 复制指定的窗口布局 */
    sprintf(exec, QST_PATH_WINDOW "%s", conf_name);
    find = FindFirstFileA(exec, &wfda);
    if ((find == INVALID_HANDLE_VALUE) ||
       !(wfda.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
        conf_name = DEF_CONF_NAME;
    sprintf(exec, "cmd.exe /c copy " QST_PATH_WINDOW
            "%s\\%ux%u\\*.* " QST_PATH_WINDOW, conf_name,
                    GetSystemMetrics(SM_CXSCREEN),
                    GetSystemMetrics(SM_CYSCREEN));
    if (find != INVALID_HANDLE_VALUE)
        FindClose(find);
    misc_call_exe(exec, TRUE, TRUE);

    /* 启动广播服务器程序 */
    if (!misc_call_exe("QstServ.exe", FALSE, FALSE))
        return (QST_ERROR);
    thread_sleep(100);

    sINIu*  ini;
    ansi_t* str;

    /* 根据配置文件执行各部件 */
    str = file_load_as_strA(QST_PATH_CONFIG WIN_ICONF);
    if (str == NULL)
        return (QST_ERROR);
    ini = ini_parseU(str);
    mem_free(str);
    if (ini == NULL)
        return (QST_ERROR);
    for (leng_t idx = 0; idx < ini->count; idx++) {
        str = skip_spaceA(ini->lines[idx]);
        if (str_lenA(str) == 0 ||
            str_strIA(str, ".exe") == NULL)
            continue;
        misc_call_exe(str, FALSE, FALSE);
        thread_sleep(100);
    }
    ini_closeU(ini);
    return (QST_OKAY);
}
<commit_msg>QuestLAB: 支持在不同的 SciTE 配置之间切换<commit_after>/*
 ================================================
 *      ######
 *    #########                            ##
 *   ####    ###                           ##
 *   ##       ##                           ##
 *  ##         ## ##   ##   ####     ### ######
 *  ##         ## ##   ##  ######  ##### ######
 *  ##         ## ##   ## ###  ## ###      ##
 *  ##    #    ## ##   ## ##  ##  #####    ##
 *   ##   ##   ## ##   ## ## ##    #####   ##
 *   ###   ## ##  ##   ## ###   #     ##   ##
 *    ##########  ####### ####### ######   ##
 *      #### ##    ######   ####   ####    ##
 *            ##
 *             ##       CREATE: 2012-09-06
 *              #
 ================================================
        QuestLAB 主启动程序
 ================================================
 */

#include "../QstLibs/QstLibs.h"

/* 应用的名称 */
#ifndef EXE_XNAME
    #define EXE_XNAME   "QuestLAB"
    #define WIN_TITLE   "QuestLAB"
    #define WIN_CLASS   "QuestLABCLSS"
    #define WIN_ICONF   "QuestLAB.ini"
    #define WIN_XCONF   "QuestLAB.xml"
#endif

/* 默认配置名称 */
#define DEF_CONF_NAME   "base"

/*
=======================================
    WinMain 程序入口
=======================================
*/
int WINAPI
WinMain (
  __CR_IN__ HINSTANCE   curt_app,
  __CR_IN__ HINSTANCE   prev_app,
  __CR_IN__ LPSTR       cmd_line,
  __CR_IN__ int         cmd_show
    )
{
    uint_t      argc;
    ansi_t**    argv;

    CR_NOUSE(curt_app);
    CR_NOUSE(prev_app);
    CR_NOUSE(cmd_show);

    /* 只允许一个例程 */
    if (misc_is_running(EXE_XNAME))
        return (QST_ERROR);

    /* 限定附加参数长度 */
    if (str_lenA(cmd_line) > 128)
        return (QST_ERROR);

    /* 建立 CrHack 系统 */
    if (!set_app_type(CR_APP_GUI))
        return (QST_ERROR);

    /* 获取命令行参数, 不包括进程文件名 */
    argv = misc_get_param(cmd_line, &argc);

    ansi_t  exec[256];
    ansi_t* conf_name;

    /* 参数解析 [配置名称] */
    if (argc == 0 || str_lenA(argv[0]) > 64)
        conf_name = DEF_CONF_NAME;
    else
        conf_name = argv[0];

    HANDLE              find;
    WIN32_FIND_DATAA    wfda;

    /* 复制指定的配置文件 */
    sprintf(exec, QST_PATH_CONFIG "%s", conf_name);
    find = FindFirstFileA(exec, &wfda);
    if ((find == INVALID_HANDLE_VALUE) ||
       !(wfda.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
        conf_name = DEF_CONF_NAME;
    sprintf(exec, "cmd.exe /c copy " QST_PATH_CONFIG
            "%s\\*.* " QST_PATH_CONFIG, conf_name);
    if (find != INVALID_HANDLE_VALUE)
        FindClose(find);
    misc_call_exe(exec, TRUE, TRUE);

    /* 复制指定的窗口布局 */
    sprintf(exec, QST_PATH_WINDOW "%s", conf_name);
    find = FindFirstFileA(exec, &wfda);
    if ((find == INVALID_HANDLE_VALUE) ||
       !(wfda.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
        conf_name = DEF_CONF_NAME;
    sprintf(exec, "cmd.exe /c copy " QST_PATH_WINDOW
            "%s\\%ux%u\\*.* " QST_PATH_WINDOW, conf_name,
                    GetSystemMetrics(SM_CXSCREEN),
                    GetSystemMetrics(SM_CYSCREEN));
    if (find != INVALID_HANDLE_VALUE)
        FindClose(find);
    misc_call_exe(exec, TRUE, TRUE);

    /* 启动广播服务器程序 */
    if (!misc_call_exe("QstServ.exe", FALSE, FALSE))
        return (QST_ERROR);

    /* 复制指定的 SciTE 配置文件 */
    sprintf(exec, QST_PATH_EXT3RD "wscite\\%s", conf_name);
    find = FindFirstFileA(exec, &wfda);
    if ((find == INVALID_HANDLE_VALUE) ||
       !(wfda.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
        conf_name = DEF_CONF_NAME;
    sprintf(exec, "cmd.exe /c copy " QST_PATH_EXT3RD "wscite\\"
            "%s\\*.* " QST_PATH_EXT3RD "wscite\\", conf_name);
    if (find != INVALID_HANDLE_VALUE)
        FindClose(find);
    misc_call_exe(exec, FALSE, TRUE);

    sINIu*  ini;
    ansi_t* str;

    /* 根据配置文件执行各部件 */
    str = file_load_as_strA(QST_PATH_CONFIG WIN_ICONF);
    if (str == NULL)
        return (QST_ERROR);
    ini = ini_parseU(str);
    mem_free(str);
    if (ini == NULL)
        return (QST_ERROR);
    for (leng_t idx = 0; idx < ini->count; idx++) {
        str = skip_spaceA(ini->lines[idx]);
        if (str_lenA(str) == 0 ||
            str_strIA(str, ".exe") == NULL)
            continue;
        misc_call_exe(str, FALSE, FALSE);
    }
    ini_closeU(ini);
    return (QST_OKAY);
}
<|endoftext|>


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

#include "base/util.h"
#include "base/stringpiece.h"

namespace operations_research {

// Walltimer

#if !defined(_MSC_VER)
namespace {
static inline int64 TimevalToUsec(const timeval &tv) {
  return static_cast<int64>(1000000) * tv.tv_sec + tv.tv_usec;
}
}  // namespace
#endif

WallTimer::WallTimer() :
    start_usec_(0LL), sum_usec_(0LL), has_started_(false) {}

void WallTimer::Start() {  // Just save when we started
#if defined(_MSC_VER)
  start_usec_ = clock();
#elif defined(__GNUC__)
  struct timeval tv;
  gettimeofday(&tv, NULL);
  start_usec_ = TimevalToUsec(tv);
#endif
  has_started_ = true;
}

void WallTimer::Stop() {   // Update total time, 1st time it's called
  if ( has_started_ ) {           // so two Stop()s is safe
#if defined(_MSC_VER)
    sum_usec_ += clock() - start_usec_;
#elif defined(__GNUC__)
    struct timeval tv;
    gettimeofday(&tv, NULL);
    sum_usec_ += TimevalToUsec(tv) - start_usec_;
#endif
    has_started_ = false;
  }
}

bool WallTimer::Reset() {  // As if we had hit Stop() first
  start_usec_ = 0;
  sum_usec_ = 0;
  has_started_ = false;
  return true;
}

void WallTimer::Restart() {
  Reset(); Start();
}

bool WallTimer::IsRunning() const {
  return has_started_;
}

int64 WallTimer::GetInMs() const {
#if defined(_MSC_VER)
  int64 local_sum_usec = sum_usec_;
  if ( has_started_ ) {           // need to include current time too
    local_sum_usec += clock() - start_usec_;
  }
  return local_sum_usec;
#elif defined(__GNUC__)
  static const int64 kMilliSecInMicroSec = 1000LL;
  int64 local_sum_usec = sum_usec_;
  if ( has_started_ ) {           // need to include current time too
    struct timeval tv;
    gettimeofday(&tv, NULL);
    local_sum_usec += TimevalToUsec(tv) - start_usec_;
  }
  return local_sum_usec / kMilliSecInMicroSec;
#endif
}

// GetUsedMemory

#if defined(__APPLE__) && defined(__GNUC__)
#include <mach/mach_init.h>
#include <mach/task.h>

int64 GetMemoryUsage () {
  task_t task = MACH_PORT_NULL;
  struct task_basic_info t_info;
  mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT;

  if (KERN_SUCCESS != task_info(mach_task_self(),
                                TASK_BASIC_INFO,
                                (task_info_t)&t_info,
                                &t_info_count)) {
    return -1;
  }
  int64 resident_memory = t_info.resident_size;
  //  int64 virtual_memory = t_info.virtual_size;
  return resident_memory;
}
#else
int64 GetMemoryUsage() {
  return 0;
}
#endif

}  // namespace operations_research
<commit_msg>Display real memory usage on Windows, must be tested<commit_after>// Copyright 2010 Google
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "base/util.h"
#include "base/stringpiece.h"

namespace operations_research {

// Walltimer

#if !defined(_MSC_VER)
namespace {
static inline int64 TimevalToUsec(const timeval &tv) {
  return static_cast<int64>(1000000) * tv.tv_sec + tv.tv_usec;
}
}  // namespace
#endif

WallTimer::WallTimer() :
    start_usec_(0LL), sum_usec_(0LL), has_started_(false) {}

void WallTimer::Start() {  // Just save when we started
#if defined(_MSC_VER)
  start_usec_ = clock();
#elif defined(__GNUC__)
  struct timeval tv;
  gettimeofday(&tv, NULL);
  start_usec_ = TimevalToUsec(tv);
#endif
  has_started_ = true;
}

void WallTimer::Stop() {   // Update total time, 1st time it's called
  if ( has_started_ ) {           // so two Stop()s is safe
#if defined(_MSC_VER)
    sum_usec_ += clock() - start_usec_;
#elif defined(__GNUC__)
    struct timeval tv;
    gettimeofday(&tv, NULL);
    sum_usec_ += TimevalToUsec(tv) - start_usec_;
#endif
    has_started_ = false;
  }
}

bool WallTimer::Reset() {  // As if we had hit Stop() first
  start_usec_ = 0;
  sum_usec_ = 0;
  has_started_ = false;
  return true;
}

void WallTimer::Restart() {
  Reset(); Start();
}

bool WallTimer::IsRunning() const {
  return has_started_;
}

int64 WallTimer::GetInMs() const {
#if defined(_MSC_VER)
  int64 local_sum_usec = sum_usec_;
  if ( has_started_ ) {           // need to include current time too
    local_sum_usec += clock() - start_usec_;
  }
  return local_sum_usec;
#elif defined(__GNUC__)
  static const int64 kMilliSecInMicroSec = 1000LL;
  int64 local_sum_usec = sum_usec_;
  if ( has_started_ ) {           // need to include current time too
    struct timeval tv;
    gettimeofday(&tv, NULL);
    local_sum_usec += TimevalToUsec(tv) - start_usec_;
  }
  return local_sum_usec / kMilliSecInMicroSec;
#endif
}

// GetUsedMemory

#if defined(__APPLE__) && defined(__GNUC__)
#include <mach/mach_init.h>
#include <mach/task.h>

int64 GetMemoryUsage () {
  task_t task = MACH_PORT_NULL;
  struct task_basic_info t_info;
  mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT;

  if (KERN_SUCCESS != task_info(mach_task_self(),
                                TASK_BASIC_INFO,
                                (task_info_t)&t_info,
                                &t_info_count)) {
    return -1;
  }
  int64 resident_memory = t_info.resident_size;
  //  int64 virtual_memory = t_info.virtual_size;
  return resident_memory;
}
#elif defined(__GNUC__)   // LINUX
int64 GetMemoryUsage() {
  return 0;
}
#elif DEFINED(_MSC_VER)  // WINDOWS
#include <windows.h>
#include <stdio.h>
#include <psapi.h>

int64 GetMemoryInfo() {
  HANDLE hProcess;
  PROCESS_MEMORY_COUNTERS pmc;
  hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
                         FALSE,
                         GetCurrentProcess());
  int64 memory = 0;
  if (hProcess) {
    if (GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc))) {
      memory = pmc.WorkingSetSize;
    }
    Closehandle(hProcess);
  }
  return memory;
}
#else  // Unknown, returning 0.
int64 GetMemoryUsage() {
  return 0;
}
#endif

}  // namespace operations_research
<|endoftext|>


<commit_before>/* OskarBinReader.cpp

  Oskar 2.6.x binary file data reader.

  Reads and reshuffles amp and uvw data to the
  layout, suitable for Romein-like gridder consumption.

  Copyright (C) 2015 Braam Research, LLC.
 */

#include <cstdio>
#include <cstring>
#include <cstdlib>

#include <oskar_binary.h>

// We temporarily use private tag enums, compatible
// with oskar-2.6 revision <= 2383 used for
// test dataset generation.
//
// When oskar-2.6 is released we should remove them
// and replace with
//    #include <oskar_vis_header.h>
//    #include <oskar_vis_block.h>
// and also add
//   OSKAR_VIS_HEADER_TAG_ and OSKAR_VIS_BLOCK_TAG_
// prefixes back (we removed them for clarity).

enum OSKAR_VIS_HEADER_TAGS
{
  TELESCOPE_PATH = 1,
  NUM_TAGS_PER_BLOCK = 2,
  WRITE_AUTOCORRELATIONS = 3,
  AMP_TYPE = 4,
  MAX_TIMES_PER_BLOCK = 5,
  NUM_TIMES_TOTAL = 6,
  NUM_CHANNELS = 7,
  NUM_STATIONS = 8,
  FREQ_START_HZ = 9,
  FREQ_INC_HZ = 10,
  CHANNEL_BANDWIDTH_HZ = 11,
  TIME_START_MJD_UTC = 12,
  TIME_INC_SEC = 13,
  TIME_AVERAGE_SEC = 14,
  PHASE_CENTRE = 15,
  TELESCOPE_CENTRE = 16,
  STATION_X_OFFSET_ECEF = 17,
  STATION_Y_OFFSET_ECEF = 18,
  STATION_Z_OFFSET_ECEF = 19
};

enum OSKAR_VIS_BLOCK_TAGS
{
  DIM_START_AND_SIZE = 1,
  FREQ_REF_INC_HZ = 2,
  TIME_REF_INC_MJD_UTC = 3,
  AUTO_CORRELATIONS = 4,
  CROSS_CORRELATIONS = 5,
  BASELINE_UU = 6,
  BASELINE_VV = 7,
  BASELINE_WW = 8
};

#define DBL_SZ sizeof(double)

template <unsigned char> struct siz;
template<> struct siz<OSKAR_INT> { static const int val = sizeof(int); };
template<> struct siz<OSKAR_DOUBLE> { static const int val = sizeof(double); };
template<> struct siz<OSKAR_DOUBLE_COMPLEX_MATRIX> { static const int val = 2 * sizeof(double); };

// Variadic read
template<unsigned char data_type>
int bin_read(
  oskar_Binary* h
  , unsigned char id_group
  , int user_index
  ) {
  return 0;
}

template<unsigned char data_type, typename... Args> int bin_read(
    oskar_Binary* h
  , unsigned char id_group
  , int user_index
  // these vary
  , unsigned char id_tag
  , int n
  , void * data
  , Args... args
  ) {
  int status = 0;
  oskar_binary_read(h
    , data_type
    , id_group
    , id_tag
    , user_index
    , n * siz<data_type>::val
    , data
    , &status);
  if (status != 0) return status;
  else return bin_read<data_type>(h, id_group, user_index, args...);
};
//

#define bin_read_d bin_read<OSKAR_DOUBLE>
#define bin_read_i bin_read<OSKAR_INT>

const unsigned char vis_header_group = OSKAR_TAG_GROUP_VIS_HEADER;
const unsigned char vis_block_group = OSKAR_TAG_GROUP_VIS_BLOCK;
#define __CHECK  if (status != 0) {h = nullptr; return status;}

struct VisData {
  int mk_from_file(const char* filename) {
    int status = 0;
    h = oskar_binary_create(filename, 'r', &status);
    __CHECK

    status = bin_read_i(h, vis_header_group, 0
      , NUM_TAGS_PER_BLOCK, 1, &num_tags_per_block
      , AMP_TYPE, 1, &amp_type
      , MAX_TIMES_PER_BLOCK, 1, &max_times_per_block
      , NUM_TIMES_TOTAL, 1, &num_times_total
      , NUM_CHANNELS, 1, &num_channels
      , NUM_STATIONS, 1, &num_stations
      );
    __CHECK

    if ((amp_type & 0x0F) != OSKAR_DOUBLE) {
      printf("Invalid data !\n");
      h = nullptr;
      return int(0xdeadbeef);
    }

    status = bin_read_d(h, vis_header_group, 0
      , FREQ_START_HZ, 1, &freq_start_inc[0]
      , FREQ_INC_HZ, 1, &freq_start_inc[1]
      , CHANNEL_BANDWIDTH_HZ, 1, &channel_bandwidth_hz
      , TIME_START_MJD_UTC, 1, &time_start_inc[0]
      , TIME_INC_SEC, 1, &time_start_inc[1]
      , TIME_AVERAGE_SEC, 1, &time_average_sec
      , PHASE_CENTRE, 2, phase_centre
      , TELESCOPE_CENTRE, 3, telescope_centre
      );
    __CHECK

    num_blocks = (num_times_total + max_times_per_block - 1) /
    max_times_per_block;
    num_baselines = num_stations * (num_stations - 1) / 2;
    num_times_baselines = max_times_per_block * num_baselines;
    num_times_baselines_total = num_times_total * num_baselines;
    num_total = num_times_baselines_total * num_channels;

    /* Print header data. */
    printf("Max. number of times per block: %d\n", max_times_per_block);
    printf("Total number of times: %d\n", num_times_total);
    printf("Number of stations: %d\n", num_stations);
    return 0;
  }

  oskar_Binary* h;
  int
      amp_type
    , max_times_per_block
    , num_tags_per_block
    , num_baselines
    , num_channels
    , num_stations
    , num_times_total
    , num_blocks
    , num_times_baselines
    , num_times_baselines_total
    , num_total
    ;
  double
      phase_centre[2]
    , telescope_centre[3]
    , freq_start_inc[2]
    , time_start_inc[2]
    , channel_bandwidth_hz
    , time_average_sec
    ;
};

#define __CHECK1(s) if (status != 0) {printf("ERROR! at %s: %d\n", #s, status); return;}

static void read_reshuffle_and_write(const VisData & vd)
{
  int status = 0;

  double *u_temp, *v_temp, *w_temp, *uvws;
  double *amp_temp, *amps;
  double freq_start_inc[2], time_start_inc[2]; // local to block
  int dim_start_and_size[6];

  u_temp = (double *)calloc(vd.num_times_baselines, DBL_SZ);
  v_temp = (double *)calloc(vd.num_times_baselines, DBL_SZ);
  w_temp = (double *)calloc(vd.num_times_baselines, DBL_SZ);
  uvws = (double *)calloc(vd.num_times_baselines_total, 3 * DBL_SZ);
  amp_temp = (double *)calloc(vd.num_times_baselines * vd.num_channels, 8 * DBL_SZ);
  amps = (double *)calloc(vd.num_total, 8 * DBL_SZ);

  /* Loop over blocks and read each one. */
  for (int block = 0; block < vd.num_blocks; ++block)
  {
    int b, c, t, num_times, start_time_idx, start_channel_idx;

    /* Set search start index. */
    oskar_binary_set_query_search_start(vd.h, block * vd.num_tags_per_block, &status);

    /* Read block metadata. */
    status = bin_read_i(vd.h, vis_block_group, block
      , DIM_START_AND_SIZE, 6, dim_start_and_size
      );
    __CHECK1(DIM_START_AND_SIZE)

    status = bin_read_d(vd.h, vis_block_group, block
      , FREQ_REF_INC_HZ, 2, freq_start_inc
      , TIME_REF_INC_MJD_UTC, 2, time_start_inc
      );
    __CHECK1(FREQ_REF_INC_HZ + TIME_REF_INC_MJD_UTC)

      /* Get the number of times actually in the block. */
    start_time_idx = dim_start_and_size[0];
    start_channel_idx = dim_start_and_size[1];
    num_times = dim_start_and_size[2];

    /* Read the visibility data. */
    status = bin_read<OSKAR_DOUBLE_COMPLEX_MATRIX>(vd.h, vis_block_group, block
      , CROSS_CORRELATIONS, 4 * vd.num_times_baselines * vd.num_channels, amp_temp
      );
    __CHECK1(CROSS_CORRELATIONS)

    /* Read the baseline data. */
    status = bin_read_d(vd.h, vis_block_group, block
      , BASELINE_UU, vd.num_times_baselines, u_temp
      );
    __CHECK1(BASELINES)

    status = bin_read_d(vd.h, vis_block_group, block
      , BASELINE_VV, vd.num_times_baselines, v_temp
      );
    __CHECK1(BASELINES)

    status = bin_read_d(vd.h, vis_block_group, block
      , BASELINE_WW, vd.num_times_baselines, w_temp
      );
    __CHECK1(BASELINES)

    /* Check for errors. */
    if (status) break;

    /* Print contents of the block. */
    for (t = 0; t < num_times; ++t)
    {
      for (c = 0; c < vd.num_channels; ++c)
      {
        for (b = 0; b < vd.num_baselines; ++b)
        {
          int i, j;
          int tt, ct, it, jt, tmp;
          // Amplitudes are in row-major
          //  [timesteps][channels][baselines][polarizations] array
          // U, V and W are in row-major
          //  [timesteps][baselines] array
          // And we want to convert them to
          //  [baselines][timesteps][channels][polarizations]
          // and
          //  [baselines][timesteps]
          // correspondingly
          i = 8 * (b + vd.num_baselines * (c + vd.num_channels * t));
          j = b + vd.num_baselines * t;

          tt = start_time_idx + t;
          ct = start_channel_idx + c;
          tmp = vd.num_times_total * b + tt;

          jt = 3 * tmp;
          uvws[jt] = u_temp[j];
          uvws[jt + 1] = v_temp[j];
          uvws[jt + 2] = w_temp[j];

          it = (tmp * vd.num_channels + ct) * 8;
          for (int cc = 0; cc < 8; cc++) amps[it + cc] = amp_temp[i + cc];
        }
      }
    }
  }

  /* Close the file. */
  oskar_binary_free(vd.h);

  /* Print status message. */
  if (status != 0)
    printf("Failure reading test file.\n");
  else
    printf("Test file read successfully.\n");

  /* Free local arrays. */
  free(amp_temp);
  free(u_temp);
  free(v_temp);
  free(w_temp);

  FILE *ampf = fopen("amp.dat", "wb");
  fwrite(amps, 8 * sizeof(double), vd.num_total, ampf);
  fclose(ampf);
  free(amps);

  FILE *uvwf = fopen("uvw.dat", "wb");
  fwrite(uvws, 3 * sizeof(double), vd.num_times_baselines_total, uvwf);
  fclose(uvwf);
  free(uvws);
}

int main(int argc, const char * argv[])
{
  VisData vd;
  if (argc < 2) return -1;
  vd.mk_from_file(argv[1]);
  read_reshuffle_and_write(vd);
  return 0;
}
<commit_msg>Remove some cruft.<commit_after>/* OskarBinReader.cpp

  Oskar 2.6.x binary file data reader.

  Reads and reshuffles amp and uvw data to the
  layout, suitable for Romein-like gridder consumption.

  Copyright (C) 2015 Braam Research, LLC.
 */

#include <cstdio>
#include <cstring>
#include <cstdlib>

#include <oskar_binary.h>

// We temporarily use private tag enums, compatible
// with oskar-2.6 revision <= 2383 used for
// test dataset generation.
//
// When oskar-2.6 is released we should remove them
// and replace with
//    #include <oskar_vis_header.h>
//    #include <oskar_vis_block.h>
// and also add
//   OSKAR_VIS_HEADER_TAG_ and OSKAR_VIS_BLOCK_TAG_
// prefixes back (we removed them for clarity).

enum OSKAR_VIS_HEADER_TAGS
{
  TELESCOPE_PATH = 1,
  NUM_TAGS_PER_BLOCK = 2,
  WRITE_AUTOCORRELATIONS = 3,
  AMP_TYPE = 4,
  MAX_TIMES_PER_BLOCK = 5,
  NUM_TIMES_TOTAL = 6,
  NUM_CHANNELS = 7,
  NUM_STATIONS = 8,
  FREQ_START_HZ = 9,
  FREQ_INC_HZ = 10,
  CHANNEL_BANDWIDTH_HZ = 11,
  TIME_START_MJD_UTC = 12,
  TIME_INC_SEC = 13,
  TIME_AVERAGE_SEC = 14,
  PHASE_CENTRE = 15,
  TELESCOPE_CENTRE = 16,
  STATION_X_OFFSET_ECEF = 17,
  STATION_Y_OFFSET_ECEF = 18,
  STATION_Z_OFFSET_ECEF = 19
};

enum OSKAR_VIS_BLOCK_TAGS
{
  DIM_START_AND_SIZE = 1,
  FREQ_REF_INC_HZ = 2,
  TIME_REF_INC_MJD_UTC = 3,
  AUTO_CORRELATIONS = 4,
  CROSS_CORRELATIONS = 5,
  BASELINE_UU = 6,
  BASELINE_VV = 7,
  BASELINE_WW = 8
};

#define DBL_SZ sizeof(double)

template <unsigned char> struct siz;
template<> struct siz<OSKAR_INT> { static const int val = sizeof(int); };
template<> struct siz<OSKAR_DOUBLE> { static const int val = sizeof(double); };
template<> struct siz<OSKAR_DOUBLE_COMPLEX_MATRIX> { static const int val = 2 * sizeof(double); };

// Variadic read
template<unsigned char data_type>
int bin_read(
  oskar_Binary* h
  , unsigned char id_group
  , int user_index
  ) {
  return 0;
}

template<unsigned char data_type, typename... Args> int bin_read(
    oskar_Binary* h
  , unsigned char id_group
  , int user_index
  // these vary
  , unsigned char id_tag
  , int n
  , void * data
  , Args... args
  ) {
  int status = 0;
  oskar_binary_read(h
    , data_type
    , id_group
    , id_tag
    , user_index
    , n * siz<data_type>::val
    , data
    , &status);
  if (status != 0) return status;
  else return bin_read<data_type>(h, id_group, user_index, args...);
};
//

#define bin_read_d bin_read<OSKAR_DOUBLE>
#define bin_read_i bin_read<OSKAR_INT>

const unsigned char vis_header_group = OSKAR_TAG_GROUP_VIS_HEADER;
const unsigned char vis_block_group = OSKAR_TAG_GROUP_VIS_BLOCK;
#define __CHECK  if (status != 0) {h = nullptr; return status;}

struct VisData {
  int mk_from_file(const char* filename) {
    int status = 0;
    h = oskar_binary_create(filename, 'r', &status);
    __CHECK

    status = bin_read_i(h, vis_header_group, 0
      , NUM_TAGS_PER_BLOCK, 1, &num_tags_per_block
      , AMP_TYPE, 1, &amp_type
      , MAX_TIMES_PER_BLOCK, 1, &max_times_per_block
      , NUM_TIMES_TOTAL, 1, &num_times_total
      , NUM_CHANNELS, 1, &num_channels
      , NUM_STATIONS, 1, &num_stations
      );
    __CHECK

    if ((amp_type & 0x0F) != OSKAR_DOUBLE) {
      printf("Invalid data !\n");
      h = nullptr;
      return int(0xdeadbeef);
    }

    status = bin_read_d(h, vis_header_group, 0
      , FREQ_START_HZ, 1, &freq_start_inc[0]
      , FREQ_INC_HZ, 1, &freq_start_inc[1]
      , CHANNEL_BANDWIDTH_HZ, 1, &channel_bandwidth_hz
      , TIME_START_MJD_UTC, 1, &time_start_inc[0]
      , TIME_INC_SEC, 1, &time_start_inc[1]
      , TIME_AVERAGE_SEC, 1, &time_average_sec
      , PHASE_CENTRE, 2, phase_centre
      , TELESCOPE_CENTRE, 3, telescope_centre
      );
    __CHECK

    num_blocks = (num_times_total + max_times_per_block - 1) /
    max_times_per_block;
    num_baselines = num_stations * (num_stations - 1) / 2;
    num_times_baselines = max_times_per_block * num_baselines;
    num_times_baselines_total = num_times_total * num_baselines;
    num_total = num_times_baselines_total * num_channels;

    /* Print header data. */
    printf("Max. number of times per block: %d\n", max_times_per_block);
    printf("Total number of times: %d\n", num_times_total);
    printf("Number of stations: %d\n", num_stations);
    return 0;
  }

  oskar_Binary* h;
  int
      amp_type
    , max_times_per_block
    , num_tags_per_block
    , num_baselines
    , num_channels
    , num_stations
    , num_times_total
    , num_blocks
    , num_times_baselines
    , num_times_baselines_total
    , num_total
    ;
  double
      phase_centre[2]
    , telescope_centre[3]
    , freq_start_inc[2]
    , time_start_inc[2]
    , channel_bandwidth_hz
    , time_average_sec
    ;
};

#define __CHECK1(s) if (status != 0) {printf("ERROR! at %s: %d\n", #s, status); return;}

static void read_reshuffle_and_write(const VisData & vd)
{
  int status = 0;

  double *u_temp, *v_temp, *w_temp, *uvws;
  double *amp_temp, *amps;
  double freq_start_inc[2], time_start_inc[2]; // local to block
  int dim_start_and_size[6];

  u_temp = (double *)calloc(vd.num_times_baselines, DBL_SZ);
  v_temp = (double *)calloc(vd.num_times_baselines, DBL_SZ);
  w_temp = (double *)calloc(vd.num_times_baselines, DBL_SZ);
  uvws = (double *)calloc(vd.num_times_baselines_total, 3 * DBL_SZ);
  amp_temp = (double *)calloc(vd.num_times_baselines * vd.num_channels, 8 * DBL_SZ);
  amps = (double *)calloc(vd.num_total, 8 * DBL_SZ);

  /* Loop over blocks and read each one. */
  for (int block = 0; block < vd.num_blocks; ++block)
  {
    int b, c, t, num_times, start_time_idx, start_channel_idx;

    /* Set search start index. */
    oskar_binary_set_query_search_start(vd.h, block * vd.num_tags_per_block, &status);

    /* Read block metadata. */
    status = bin_read_i(vd.h, vis_block_group, block
      , DIM_START_AND_SIZE, 6, dim_start_and_size
      );
    __CHECK1(DIM_START_AND_SIZE)

    status = bin_read_d(vd.h, vis_block_group, block
      , FREQ_REF_INC_HZ, 2, freq_start_inc
      , TIME_REF_INC_MJD_UTC, 2, time_start_inc
      );
    __CHECK1(FREQ_REF_INC_HZ + TIME_REF_INC_MJD_UTC)

    /* Get the number of times actually in the block. */
    start_time_idx = dim_start_and_size[0];
    start_channel_idx = dim_start_and_size[1];
    num_times = dim_start_and_size[2];

    /* Read the visibility data. */
    status = bin_read<OSKAR_DOUBLE_COMPLEX_MATRIX>(vd.h, vis_block_group, block
      , CROSS_CORRELATIONS, 4 * vd.num_times_baselines * vd.num_channels, amp_temp
      );
    __CHECK1(CROSS_CORRELATIONS)

    /* Read the baseline data. */
    status = bin_read_d(vd.h, vis_block_group, block
      , BASELINE_UU, vd.num_times_baselines, u_temp
      );
    __CHECK1(BASELINES)

    status = bin_read_d(vd.h, vis_block_group, block
      , BASELINE_VV, vd.num_times_baselines, v_temp
      );
    __CHECK1(BASELINES)

    status = bin_read_d(vd.h, vis_block_group, block
      , BASELINE_WW, vd.num_times_baselines, w_temp
      );
    __CHECK1(BASELINES)

    for (t = 0; t < num_times; ++t)
    {
      for (c = 0; c < vd.num_channels; ++c)
      {
        for (b = 0; b < vd.num_baselines; ++b)
        {
          int i, j;
          int tt, ct, it, jt, tmp;
          // Amplitudes are in row-major
          //  [timesteps][channels][baselines][polarizations] array
          // U, V and W are in row-major
          //  [timesteps][baselines] array
          // And we want to convert them to
          //  [baselines][timesteps][channels][polarizations]
          // and
          //  [baselines][timesteps]
          // correspondingly
          i = 8 * (b + vd.num_baselines * (c + vd.num_channels * t));
          j = b + vd.num_baselines * t;

          tt = start_time_idx + t;
          ct = start_channel_idx + c;
          tmp = vd.num_times_total * b + tt;

          jt = 3 * tmp;
          uvws[jt] = u_temp[j];
          uvws[jt + 1] = v_temp[j];
          uvws[jt + 2] = w_temp[j];

          it = (tmp * vd.num_channels + ct) * 8;
          for (int cc = 0; cc < 8; cc++) amps[it + cc] = amp_temp[i + cc];
        }
      }
    }
  }

  /* Close the file. */
  oskar_binary_free(vd.h);

  /* Print status message. */
  if (status != 0)
    printf("Failure reading test file.\n");
  else
    printf("Test file read successfully.\n");

  /* Free local arrays. */
  free(amp_temp);
  free(u_temp);
  free(v_temp);
  free(w_temp);

  FILE *ampf = fopen("amp.dat", "wb");
  fwrite(amps, 8 * sizeof(double), vd.num_total, ampf);
  fclose(ampf);
  free(amps);

  FILE *uvwf = fopen("uvw.dat", "wb");
  fwrite(uvws, 3 * sizeof(double), vd.num_times_baselines_total, uvwf);
  fclose(uvwf);
  free(uvws);
}

int main(int argc, const char * argv[])
{
  VisData vd;
  if (argc < 2) return -1;
  vd.mk_from_file(argv[1]);
  read_reshuffle_and_write(vd);
  return 0;
}
<|endoftext|>


<commit_before>#include "DBCCFactory.h"
#include "DBCCTextureAtlas.h"
#include "DBCCSlot.h"
#include "DBCCEventDispatcher.h"
#include "DBCCArmature.h"

NAME_SPACE_DRAGON_BONES_BEGIN
DBCCFactory* DBCCFactory::_instance = nullptr;

DBCCFactory* DBCCFactory::getInstance()
{
    if (!_instance)
    {
        _instance = new DBCCFactory();
    }
    return _instance;
}

void DBCCFactory::destroyInstance()
{
    if (_instance)
    {
       CC_SAFE_DELETE(_instance);
    }
}

DBCCFactory::DBCCFactory() {}
DBCCFactory::~DBCCFactory() {}

DBCCArmature* DBCCFactory::buildArmature(const std::string &armatureName) const
{
    return (DBCCArmature*) BaseFactory::buildArmature(armatureName);
}

DBCCArmature* DBCCFactory::buildArmature(const std::string &armatureName, const std::string &dragonBonesName) const
{
    return (DBCCArmature*) BaseFactory::buildArmature(armatureName, dragonBonesName);
}

DBCCArmature* DBCCFactory::buildArmature(const std::string &armatureName, const std::string &skinName, const std::string &animationName,
                                         const std::string &dragonBonesName, const std::string &textureAtlasName) const
{
    return (DBCCArmature*) BaseFactory::buildArmature(armatureName, skinName, animationName, dragonBonesName, textureAtlasName);
}

DBCCArmatureNode* DBCCFactory::buildArmatureNode(const std::string &armatureName) const
{
    auto armature = buildArmature(armatureName);
    return DBCCArmatureNode::create(armature);
}

DBCCArmatureNode* DBCCFactory::buildArmatureNode(const std::string &armatureName, const std::string &dragonBonesName) const
{
    auto armature = buildArmature(armatureName, dragonBonesName);
    return DBCCArmatureNode::create(armature);
}

DBCCArmatureNode* DBCCFactory::buildArmatureNode(const std::string &armatureName, const std::string &skinName, const std::string &animationName,
    const std::string &dragonBonesName, const std::string &textureAtlasName) const
{
    auto armature = buildArmature(armatureName, skinName, animationName, dragonBonesName, textureAtlasName);
    return DBCCArmatureNode::create(armature);
}

DragonBonesData* DBCCFactory::loadDragonBonesData(const std::string &dragonBonesFilePath, const std::string &name)
{
    DragonBonesData *existDragonBonesData = getDragonBonesData(name);

    if (existDragonBonesData)
    {
        return existDragonBonesData;
    }

    const auto &data = cocos2d::FileUtils::getInstance()->getDataFromFile(dragonBonesFilePath);
    if (data.getSize() == 0)
    {
        return nullptr;
    }

    // armature scale
    float scale = cocos2d::Director::getInstance()->getContentScaleFactor();

    // load skeleton.xml using XML parser.
    dragonBones::XMLDocument doc;
    doc.Parse(reinterpret_cast<char*>(data.getBytes()), data.getSize());
    // paser dragonbones skeleton data.
    dragonBones::XMLDataParser parser;
    DragonBonesData *dragonBonesData = parser.parseDragonBonesData(doc.RootElement(), scale);
    addDragonBonesData(dragonBonesData, name);
    return dragonBonesData;
}

ITextureAtlas* DBCCFactory::loadTextureAtlas(const std::string &textureAtlasFile, const std::string &name)
{
    ITextureAtlas *existTextureAtlas = getTextureAtlas(name);

    if (existTextureAtlas)
    {
        refreshTextureAtlasTexture(name.empty() ? existTextureAtlas->textureAtlasData->name : name);
        return existTextureAtlas;
    }

    const auto &data = cocos2d::FileUtils::getInstance()->getDataFromFile(textureAtlasFile);
    if (data.getSize() == 0)
    {
        return nullptr;
    }

    // textureAtlas scale
    float scale = cocos2d::Director::getInstance()->getContentScaleFactor();

    dragonBones::XMLDocument doc;
    doc.Parse(reinterpret_cast<char*>(data.getBytes()), data.getSize());
    dragonBones::XMLDataParser parser;
    DBCCTextureAtlas *textureAtlas = new DBCCTextureAtlas();
    textureAtlas->textureAtlasData = parser.parseTextureAtlasData(doc.RootElement(), scale);

    int pos = textureAtlasFile.find_last_of("/");

    if (std::string::npos != pos)
    {
        std::string base_path = textureAtlasFile.substr(0, pos + 1);
        textureAtlas->textureAtlasData->imagePath = base_path + textureAtlas->textureAtlasData->imagePath;
    }

    //
    addTextureAtlas(textureAtlas, name);
    refreshTextureAtlasTexture(name.empty() ? textureAtlas->textureAtlasData->name : name);
    return textureAtlas;
}

void DBCCFactory::refreshTextureAtlasTexture(const std::string &name)
{
    for (auto iterator = _textureAtlasMap.begin(); iterator != _textureAtlasMap.end(); ++iterator)
    {
        DBCCTextureAtlas *textureAtlas = static_cast<DBCCTextureAtlas*>(iterator->second);
        const TextureAtlasData *textureAtlasData = textureAtlas->textureAtlasData;

        if (iterator->first == name)
        {
            textureAtlas->reloadTexture();
        }
    }
}

void DBCCFactory::refreshAllTextureAtlasTexture()
{
    for (auto iterator = _textureAtlasMap.begin(); iterator != _textureAtlasMap.end(); ++iterator)
    {
        DBCCTextureAtlas *textureAtlas = static_cast<DBCCTextureAtlas*>(iterator->second);
        const TextureAtlasData *textureAtlasData = textureAtlas->textureAtlasData;
        textureAtlas->reloadTexture();
    }
}

bool DBCCFactory::hasDragonBones(const std::string &skeletonName, const std::string &armatureName, const std::string &animationName)
{
    auto dragonbonesData = getDragonBonesData(skeletonName);

    if (!dragonbonesData) { return false; }

    if (!armatureName.empty())
    {
        auto armatureData = dragonbonesData->getArmatureData(armatureName);

        if (!armatureData) { return false; }

        if (!animationName.empty())
        {
            auto animationData = armatureData->getAnimationData(animationName);
            return animationData != nullptr;
        }
    }

    return true;
}

DBCCArmature* DBCCFactory::generateArmature(const ArmatureData *armatureData) const
{
    Animation *animation = new Animation();
    // sprite
    cocos2d::Node *display = cocos2d::Node::create();
    display->setCascadeColorEnabled(true);
    display->setCascadeOpacityEnabled(true);
    display->retain();
    // eventDispatcher
    DBCCEventDispatcher *eventDispatcher = new DBCCEventDispatcher();
    eventDispatcher->eventDispatcher = new cocos2d::EventDispatcher();
    eventDispatcher->eventDispatcher->setEnabled(true);
    // armature
    return new DBCCArmature((ArmatureData*)(armatureData), animation, eventDispatcher, display);
}

DBCCSlot* DBCCFactory::generateSlot(const SlotData *slotData) const
{
    return new DBCCSlot((SlotData*)(slotData));
}

void* DBCCFactory::generateDisplay(const ITextureAtlas *textureAtlas, const TextureData *textureData, const DisplayData *displayData) const
{
    DBCCTextureAtlas *dbccTextureAtlas = (DBCCTextureAtlas*)(textureAtlas);

    if (!dbccTextureAtlas || !textureData) return nullptr;

    auto texture = dbccTextureAtlas->getTexture();
    assert(texture);

    const float x = textureData->region.x;
    const float y = textureData->region.y;
    const bool rotated = textureData->rotated;
    const float width = rotated ? textureData->region.height : textureData->region.width;
    const float height = rotated ? textureData->region.width : textureData->region.height;
    cocos2d::Rect rect(x, y, width, height);
    cocos2d::Vec2 offset;
    cocos2d::Size originSize(width, height);

    if (textureData->frame)
    {
        float frameX = textureData->frame->x;
        float frameY = textureData->frame->y;
        originSize.width = textureData->frame->width;
        originSize.height = textureData->frame->height;
        // offset = trimed center - origin center
        offset.x = (width - originSize.width) / 2 - frameX;
        offset.y = (height - originSize.height) / 2 - frameY;
    }
    // sprite
    auto spriteFrame = cocos2d::SpriteFrame::createWithTexture(texture, rect,
        textureData->rotated, offset, originSize);
    cocos2d::Node *display = cocos2d::Sprite::createWithSpriteFrame(spriteFrame);
    display->setCascadeColorEnabled(true);
    display->setCascadeOpacityEnabled(true);
    display->retain();
    float pivotX = 0.f;
    float pivotY = 0.f;

    if (displayData)
    {
        pivotX = displayData->pivot.x;
        pivotY = displayData->pivot.y;
    }
    display->setAnchorPoint(cocos2d::Vec2(pivotX / originSize.width, 1.f - pivotY / originSize.height));
    display->setContentSize(originSize);
    return display;
}
NAME_SPACE_DRAGON_BONES_END
<commit_msg>remove spriteframe when no trim<commit_after>#include "DBCCFactory.h"
#include "DBCCTextureAtlas.h"
#include "DBCCSlot.h"
#include "DBCCEventDispatcher.h"
#include "DBCCArmature.h"

NAME_SPACE_DRAGON_BONES_BEGIN
DBCCFactory* DBCCFactory::_instance = nullptr;

DBCCFactory* DBCCFactory::getInstance()
{
    if (!_instance)
    {
        _instance = new DBCCFactory();
    }
    return _instance;
}

void DBCCFactory::destroyInstance()
{
    if (_instance)
    {
       CC_SAFE_DELETE(_instance);
    }
}

DBCCFactory::DBCCFactory() {}
DBCCFactory::~DBCCFactory() {}

DBCCArmature* DBCCFactory::buildArmature(const std::string &armatureName) const
{
    return (DBCCArmature*) BaseFactory::buildArmature(armatureName);
}

DBCCArmature* DBCCFactory::buildArmature(const std::string &armatureName, const std::string &dragonBonesName) const
{
    return (DBCCArmature*) BaseFactory::buildArmature(armatureName, dragonBonesName);
}

DBCCArmature* DBCCFactory::buildArmature(const std::string &armatureName, const std::string &skinName, const std::string &animationName,
                                         const std::string &dragonBonesName, const std::string &textureAtlasName) const
{
    return (DBCCArmature*) BaseFactory::buildArmature(armatureName, skinName, animationName, dragonBonesName, textureAtlasName);
}

DBCCArmatureNode* DBCCFactory::buildArmatureNode(const std::string &armatureName) const
{
    auto armature = buildArmature(armatureName);
    return DBCCArmatureNode::create(armature);
}

DBCCArmatureNode* DBCCFactory::buildArmatureNode(const std::string &armatureName, const std::string &dragonBonesName) const
{
    auto armature = buildArmature(armatureName, dragonBonesName);
    return DBCCArmatureNode::create(armature);
}

DBCCArmatureNode* DBCCFactory::buildArmatureNode(const std::string &armatureName, const std::string &skinName, const std::string &animationName,
    const std::string &dragonBonesName, const std::string &textureAtlasName) const
{
    auto armature = buildArmature(armatureName, skinName, animationName, dragonBonesName, textureAtlasName);
    return DBCCArmatureNode::create(armature);
}

DragonBonesData* DBCCFactory::loadDragonBonesData(const std::string &dragonBonesFilePath, const std::string &name)
{
    DragonBonesData *existDragonBonesData = getDragonBonesData(name);

    if (existDragonBonesData)
    {
        return existDragonBonesData;
    }

    const auto &data = cocos2d::FileUtils::getInstance()->getDataFromFile(dragonBonesFilePath);
    if (data.getSize() == 0)
    {
        return nullptr;
    }

    // armature scale
    float scale = cocos2d::Director::getInstance()->getContentScaleFactor();

    // load skeleton.xml using XML parser.
    dragonBones::XMLDocument doc;
    doc.Parse(reinterpret_cast<char*>(data.getBytes()), data.getSize());
    // paser dragonbones skeleton data.
    dragonBones::XMLDataParser parser;
    DragonBonesData *dragonBonesData = parser.parseDragonBonesData(doc.RootElement(), scale);
    addDragonBonesData(dragonBonesData, name);
    return dragonBonesData;
}

ITextureAtlas* DBCCFactory::loadTextureAtlas(const std::string &textureAtlasFile, const std::string &name)
{
    ITextureAtlas *existTextureAtlas = getTextureAtlas(name);

    if (existTextureAtlas)
    {
        refreshTextureAtlasTexture(name.empty() ? existTextureAtlas->textureAtlasData->name : name);
        return existTextureAtlas;
    }

    const auto &data = cocos2d::FileUtils::getInstance()->getDataFromFile(textureAtlasFile);
    if (data.getSize() == 0)
    {
        return nullptr;
    }

    // textureAtlas scale
    float scale = cocos2d::Director::getInstance()->getContentScaleFactor();

    dragonBones::XMLDocument doc;
    doc.Parse(reinterpret_cast<char*>(data.getBytes()), data.getSize());
    dragonBones::XMLDataParser parser;
    DBCCTextureAtlas *textureAtlas = new DBCCTextureAtlas();
    textureAtlas->textureAtlasData = parser.parseTextureAtlasData(doc.RootElement(), scale);

    int pos = textureAtlasFile.find_last_of("/");

    if (std::string::npos != pos)
    {
        std::string base_path = textureAtlasFile.substr(0, pos + 1);
        textureAtlas->textureAtlasData->imagePath = base_path + textureAtlas->textureAtlasData->imagePath;
    }

    //
    addTextureAtlas(textureAtlas, name);
    refreshTextureAtlasTexture(name.empty() ? textureAtlas->textureAtlasData->name : name);
    return textureAtlas;
}

void DBCCFactory::refreshTextureAtlasTexture(const std::string &name)
{
    for (auto iterator = _textureAtlasMap.begin(); iterator != _textureAtlasMap.end(); ++iterator)
    {
        DBCCTextureAtlas *textureAtlas = static_cast<DBCCTextureAtlas*>(iterator->second);
        const TextureAtlasData *textureAtlasData = textureAtlas->textureAtlasData;

        if (iterator->first == name)
        {
            textureAtlas->reloadTexture();
        }
    }
}

void DBCCFactory::refreshAllTextureAtlasTexture()
{
    for (auto iterator = _textureAtlasMap.begin(); iterator != _textureAtlasMap.end(); ++iterator)
    {
        DBCCTextureAtlas *textureAtlas = static_cast<DBCCTextureAtlas*>(iterator->second);
        const TextureAtlasData *textureAtlasData = textureAtlas->textureAtlasData;
        textureAtlas->reloadTexture();
    }
}

bool DBCCFactory::hasDragonBones(const std::string &skeletonName, const std::string &armatureName, const std::string &animationName)
{
    auto dragonbonesData = getDragonBonesData(skeletonName);

    if (!dragonbonesData) { return false; }

    if (!armatureName.empty())
    {
        auto armatureData = dragonbonesData->getArmatureData(armatureName);

        if (!armatureData) { return false; }

        if (!animationName.empty())
        {
            auto animationData = armatureData->getAnimationData(animationName);
            return animationData != nullptr;
        }
    }

    return true;
}

DBCCArmature* DBCCFactory::generateArmature(const ArmatureData *armatureData) const
{
    Animation *animation = new Animation();
    // sprite
    cocos2d::Node *display = cocos2d::Node::create();
    display->setCascadeColorEnabled(true);
    display->setCascadeOpacityEnabled(true);
    display->retain();
    // eventDispatcher
    DBCCEventDispatcher *eventDispatcher = new DBCCEventDispatcher();
    eventDispatcher->eventDispatcher = new cocos2d::EventDispatcher();
    eventDispatcher->eventDispatcher->setEnabled(true);
    // armature
    return new DBCCArmature((ArmatureData*)(armatureData), animation, eventDispatcher, display);
}

DBCCSlot* DBCCFactory::generateSlot(const SlotData *slotData) const
{
    return new DBCCSlot((SlotData*)(slotData));
}

void* DBCCFactory::generateDisplay(const ITextureAtlas *textureAtlas, const TextureData *textureData, const DisplayData *displayData) const
{
    DBCCTextureAtlas *dbccTextureAtlas = (DBCCTextureAtlas*)(textureAtlas);

    if (!dbccTextureAtlas || !textureData) return nullptr;

    auto texture = dbccTextureAtlas->getTexture();
    assert(texture);

    const float x = textureData->region.x;
    const float y = textureData->region.y;
    const bool rotated = textureData->rotated;
    const float width = rotated ? textureData->region.height : textureData->region.width;
    const float height = rotated ? textureData->region.width : textureData->region.height;
    cocos2d::Rect rect(x, y, width, height);
    cocos2d::Vec2 offset;
    cocos2d::Size originSize(width, height);

    cocos2d::Node *display = nullptr;

    if (textureData->frame)
    {
        float frameX = textureData->frame->x;
        float frameY = textureData->frame->y;
        originSize.width = textureData->frame->width;
        originSize.height = textureData->frame->height;
        // offset = trimed center - origin center
        offset.x = (width - originSize.width) / 2 - frameX;
        offset.y = (height - originSize.height) / 2 - frameY;

        auto spriteFrame = cocos2d::SpriteFrame::createWithTexture(texture, rect,
            textureData->rotated, offset, originSize);
        display = cocos2d::Sprite::createWithSpriteFrame(spriteFrame);
    }
    else
    {
        display = cocos2d::Sprite::createWithTexture(texture, rect, rotated);
    }
    // sprite

    display->setCascadeColorEnabled(true);
    display->setCascadeOpacityEnabled(true);
    display->retain();
    float pivotX = 0.f;
    float pivotY = 0.f;

    if (displayData)
    {
        pivotX = displayData->pivot.x;
        pivotY = displayData->pivot.y;
    }
    display->setAnchorPoint(cocos2d::Vec2(pivotX / originSize.width, 1.f - pivotY / originSize.height));
    display->setContentSize(originSize);
    return display;
}
NAME_SPACE_DRAGON_BONES_END
<|endoftext|>


<commit_before>// This file is part of the ustl library, an STL implementation.
//
// Copyright (C) 2006 by Mike Sharov <msharov@users.sourceforge.net>
// This file is free software, distributed under the MIT License.
//
// bktrace.cc
//

#include "bktrace.h"
#include "sostream.h"
#include "mistream.h"
#if linux && __GNUC__
    #include <execinfo.h>
#else
    #define backtrace(a,n)		0
    #define backtrace_symbols(a,n)	NULL
#endif
#if __GNUC__ >= 3
    #include <cxxabi.h>
#endif

#if SIZE_OF_LONG == 8
    #define ADDRESS_FMT	"%16p  "
#else
    #define ADDRESS_FMT	"%8p  "
#endif

namespace ustl {

/// Default constructor. The backtrace is obtained here.
CBacktrace::CBacktrace (void)
: m_Text (NULL),
  m_nFrames (0)
{
    try {
	m_nFrames = backtrace (m_Addresses, VectorSize(m_Addresses));
	GetSymbols();
    } catch (...) {}
}

/// Copy constructor.
CBacktrace::CBacktrace (const CBacktrace& v)
: m_Text (NULL),
  m_nFrames (0)
{
    operator= (v);
}

/// Copy operator.
const CBacktrace& CBacktrace::operator= (const CBacktrace& v)
{
    memcpy (m_Addresses, v.m_Addresses, sizeof(m_Addresses));
    m_Text = strdup (v.m_Text);
    return (*this);
}

/// Tries to get symbol information for the addresses.
void CBacktrace::GetSymbols (void)
{
    auto_ptr<char*> symbols (backtrace_symbols (m_Addresses, m_nFrames));
    if (!symbols.get())
	return;
    ostringstream os;
    char nmbuf [256];
    char dmbuf [256];
    for (uoff_t i = 0; i < m_nFrames; ++ i) {
	// Address first
	os.format (ADDRESS_FMT, m_Addresses[i]);
	const char* isym = symbols.get()[i];
	if (!isym) {
	    os << endl;
	    continue;
	}
	// Copy out the name; the strings are: "file(function+0x42) [0xAddress]"
	const char* mnStart = strchr (isym, '(');
	const char* mnEnd = strchr (isym, '+');
	size_t nmSize = 0;
	if (mnStart && mnEnd) {
	    ++ mnStart;
	    nmSize = min (size_t(distance (mnStart, mnEnd)), VectorSize(nmbuf));
	    memcpy (nmbuf, mnStart, nmSize);
	}
	nmbuf[nmSize] = 0;
	// And the demangled name
	#if __GNUC__ >= 3
	    int dmFailed = 0;
	    size_t dmSize = VectorSize (dmbuf);
	    abi::__cxa_demangle (nmbuf, dmbuf, &dmSize, &dmFailed);
	#else
	    int dmFailed = -1;
	#endif
	os << (dmFailed ? nmbuf : dmbuf);
	os << endl;
    }
    m_Text = strdup (os.str().c_str());
}

/// Default destructor.
CBacktrace::~CBacktrace (void)
{
    free_nullok (m_Text);
}

/// Prints the backtrace to \p os.
void CBacktrace::text_write (ostringstream& os) const
{
    if (m_Text)
	os << m_Text;
}

/// Reads the object from stream \p is.
void CBacktrace::read (istream& is)
{
    is.read (m_Addresses, sizeof(m_Addresses));
    is >> m_nFrames;
    size_t tlen = 0;
    is >> tlen;
    free_nullok (m_Text);
    m_Text = (char*) malloc (tlen + 1);
    is.read (m_Text, tlen);
    m_Text[tlen] = 0;
}

/// Writes the object to stream \p os.
void CBacktrace::write (ostream& os) const
{
    os.write (m_Addresses, sizeof(m_Addresses));
    os << m_nFrames;
    size_t tlen = 0;
    if (m_Text) {
	tlen = strlen (m_Text);
	os << tlen;
	os.write (m_Text, tlen);
    } else
	os << tlen;
    os.align();
}

/// Returns the size of the written object.
size_t CBacktrace::stream_size (void) const
{
    return (Align (sizeof(m_Addresses) +
		   stream_size_of (m_nFrames) +
		   stream_size_of (size_t()) +
		   m_Text ? strlen (m_Text) : 0));
}

} // namespace ustl

<commit_msg>Print malformed symbols as is instead of a blank<commit_after>// This file is part of the ustl library, an STL implementation.
//
// Copyright (C) 2006 by Mike Sharov <msharov@users.sourceforge.net>
// This file is free software, distributed under the MIT License.
//
// bktrace.cc
//

#include "bktrace.h"
#include "sostream.h"
#include "mistream.h"
#if linux && __GNUC__
    #include <execinfo.h>
#else
    #define backtrace(a,n)		0
    #define backtrace_symbols(a,n)	NULL
#endif
#if __GNUC__ >= 3
    #include <cxxabi.h>
#endif

#if SIZE_OF_LONG == 8
    #define ADDRESS_FMT	"%16p  %s\n"
#else
    #define ADDRESS_FMT	"%8p  %s\n"
#endif

namespace ustl {

/// Default constructor. The backtrace is obtained here.
CBacktrace::CBacktrace (void)
: m_Text (NULL),
  m_nFrames (0)
{
    try {
	m_nFrames = backtrace (m_Addresses, VectorSize(m_Addresses));
	GetSymbols();
    } catch (...) {}
}

/// Copy constructor.
CBacktrace::CBacktrace (const CBacktrace& v)
: m_Text (NULL),
  m_nFrames (0)
{
    operator= (v);
}

/// Copy operator.
const CBacktrace& CBacktrace::operator= (const CBacktrace& v)
{
    memcpy (m_Addresses, v.m_Addresses, sizeof(m_Addresses));
    m_Text = strdup (v.m_Text);
    return (*this);
}

/// Tries to get symbol information for the addresses.
void CBacktrace::GetSymbols (void)
{
    auto_ptr<char*> symbols (backtrace_symbols (m_Addresses, m_nFrames));
    if (!symbols.get())
	return;
    ostringstream os;
    char nmbuf [256];
    char dmbuf [256];
    for (uoff_t i = 0; i < m_nFrames; ++ i) {
	// Prepare the demangled name, if possible
	size_t nmSize = 0;
	const char* isym = symbols.get()[i];
	if (isym) {
	    // Copy out the name; the strings are: "file(function+0x42) [0xAddress]"
	    const char* mnStart = strchr (isym, '(');
	    if (++mnStart == (const char*)(1))
		mnStart = isym;
	    const char* mnEnd = strchr (isym, '+');
	    const char* isymEnd = isym + strlen (isym);
	    if (!mnEnd)
		mnEnd = isymEnd;
	    nmSize = min (size_t (distance (mnStart, mnEnd)), VectorSize(nmbuf));
	    memcpy (nmbuf, mnStart, nmSize);
	}
	nmbuf[nmSize] = 0;
	// Demangle
	#if __GNUC__ >= 3
	    int dmFailed = 0;
	    size_t dmSize = VectorSize (dmbuf);
	    abi::__cxa_demangle (nmbuf, dmbuf, &dmSize, &dmFailed);
	#else
	    int dmFailed = -1;
	#endif
	// Print the result with the address
	os.format (ADDRESS_FMT, m_Addresses[i], dmFailed ? nmbuf : dmbuf);
    }
    m_Text = strdup (os.str().c_str());
}

/// Default destructor.
CBacktrace::~CBacktrace (void)
{
    free_nullok (m_Text);
}

/// Prints the backtrace to \p os.
void CBacktrace::text_write (ostringstream& os) const
{
    if (m_Text)
	os << m_Text;
}

/// Reads the object from stream \p is.
void CBacktrace::read (istream& is)
{
    is.read (m_Addresses, sizeof(m_Addresses));
    is >> m_nFrames;
    size_t tlen = 0;
    is >> tlen;
    free_nullok (m_Text);
    m_Text = (char*) malloc (tlen + 1);
    is.read (m_Text, tlen);
    m_Text[tlen] = 0;
}

/// Writes the object to stream \p os.
void CBacktrace::write (ostream& os) const
{
    os.write (m_Addresses, sizeof(m_Addresses));
    os << m_nFrames;
    size_t tlen = 0;
    if (m_Text) {
	tlen = strlen (m_Text);
	os << tlen;
	os.write (m_Text, tlen);
    } else
	os << tlen;
    os.align();
}

/// Returns the size of the written object.
size_t CBacktrace::stream_size (void) const
{
    return (Align (sizeof(m_Addresses) +
		   stream_size_of (m_nFrames) +
		   stream_size_of (size_t()) +
		   m_Text ? strlen (m_Text) : 0));
}

} // namespace ustl

<|endoftext|>


<commit_before>/*
 * Copyright 2015 Cloudius Systems
 */

#include "api/api-doc/lsa.json.hh"
#include "api/lsa.hh"
#include "api/api.hh"

#include "http/exception.hh"
#include "utils/logalloc.hh"
#include "log.hh"

namespace api {

static logging::logger logger("lsa-api");

void set_lsa(http_context& ctx, routes& r) {
    httpd::lsa_json::lsa_compact.set(r, [&ctx](std::unique_ptr<request> req) {
        logger.info("Triggering compaction");
        logalloc::shard_tracker().reclaim(std::numeric_limits<size_t>::max());
        return make_ready_future<json::json_return_type>(0);
    });
}

}
<commit_msg>api: lsa: Invoke compaction on all shards<commit_after>/*
 * Copyright 2015 Cloudius Systems
 */

#include "api/api-doc/lsa.json.hh"
#include "api/lsa.hh"
#include "api/api.hh"

#include "http/exception.hh"
#include "utils/logalloc.hh"
#include "log.hh"

namespace api {

static logging::logger logger("lsa-api");

void set_lsa(http_context& ctx, routes& r) {
    httpd::lsa_json::lsa_compact.set(r, [&ctx](std::unique_ptr<request> req) {
        logger.info("Triggering compaction");
        return ctx.db.invoke_on_all([] (database&) {
            logalloc::shard_tracker().reclaim(std::numeric_limits<size_t>::max());
        }).then([] {
            return json::json_return_type(0);
        });
    });
}

}
<|endoftext|>