<commit_before>#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <direct.h>
#ifndef strcasecmp
#define strcasecmp _stricmp
#endif
#else
#include <dirent.h>
#include <unistd.h>
#include <errno.h>
#endif
#include <cstring>
#include <string>
#include <set>
#include <algorithm>
#include <cstdio>
#include <sys/stat.h>
#include <ctype.h>

#include "base/logging.h"
#include "base/basictypes.h"
#include "file/file_util.h"
#include "util/text/utf8.h"

#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__SYMBIAN32__)
#define stat64 stat
#endif

// Hack
#ifdef __SYMBIAN32__
static inline int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result) {
	struct dirent *readdir_entry;

	readdir_entry = readdir(dirp);
	if (readdir_entry == NULL) {
		*result = NULL;
		return errno;
	}

	*entry = *readdir_entry;
	*result = entry;
	return 0;
}
#endif

bool writeStringToFile(bool text_file, const std::string &str, const char *filename)
{
	FILE *f = fopen(filename, text_file ? "w" : "wb");
	if (!f)
		return false;
	size_t len = str.size();
	if (len != fwrite(str.data(), 1, str.size(), f))
	{
		fclose(f);
		return false;
	}
	fclose(f);
	return true;
}

bool writeDataToFile(bool text_file, const void* data, const unsigned int size, const char *filename)
{
	FILE *f = fopen(filename, text_file ? "w" : "wb");
	if (!f)
		return false;
	size_t len = size;
	if (len != fwrite(data, 1, len, f))
	{
		fclose(f);
		return false;
	}
	fclose(f);
	return true;
}

uint64_t GetSize(FILE *f)
{
	// can't use off_t here because it can be 32-bit
	uint64_t pos = ftell(f);
	if (fseek(f, 0, SEEK_END) != 0) {
		return 0;
	}
	uint64_t size = ftell(f);
	// Reset the seek position to where it was when we started.
	if ((size != pos) && (fseek(f, pos, SEEK_SET) != 0)) {
		// Should error here
		return 0;
	}
	return size;
}

bool ReadFileToString(bool text_file, const char *filename, std::string &str)
{
	FILE *f = fopen(filename, text_file ? "r" : "rb");
	if (!f)
		return false;
	size_t len = (size_t)GetSize(f);
	char *buf = new char[len + 1];
	buf[fread(buf, 1, len, f)] = 0;
	str = std::string(buf, len);
	fclose(f);
	delete [] buf;
	return true;
}

bool readDataFromFile(bool text_file, unsigned char* &data, const unsigned int size, const char *filename)
{
	FILE *f = fopen(filename, text_file ? "r" : "rb");
	if (!f)
		return false;
	size_t len = (size_t)GetSize(f);
	if(len < size) {
		fclose(f);
		return false;
	}
	data[fread(data, 1, size, f)] = 0;
	fclose(f);
	return true;
}

#define DIR_SEP "/"
#define DIR_SEP_CHR '\\'

#ifndef METRO

// Remove any ending forward slashes from directory paths
// Modifies argument.
static void stripTailDirSlashes(std::string &fname)
{
	if (fname.length() > 1)
	{
		size_t i = fname.length() - 1;
		while (fname[i] == DIR_SEP_CHR)
			fname[i--] = '\0';
	}
	return;
}

// Returns true if file filename exists
bool exists(const std::string &filename) {
#ifdef _WIN32
	std::wstring wstr = ConvertUTF8ToWString(filename);
	return GetFileAttributes(wstr.c_str()) != 0xFFFFFFFF;
#else
	struct stat64 file_info;

	std::string copy(filename);
	stripTailDirSlashes(copy);

	int result = stat64(copy.c_str(), &file_info);

	return (result == 0);
#endif
}

// Returns true if filename is a directory
bool isDirectory(const std::string &filename) {
	FileInfo info;
	getFileInfo(filename.c_str(), &info);
	return info.isDirectory;
}

bool getFileInfo(const char *path, FileInfo *fileInfo) {
	// TODO: Expand relative paths?
	fileInfo->fullName = path;

#ifdef _WIN32
	WIN32_FILE_ATTRIBUTE_DATA attrs;
	if (!GetFileAttributesExA(path, GetFileExInfoStandard, &attrs)) {
		fileInfo->size = 0;
		fileInfo->isDirectory = false;
		fileInfo->exists = false;
		return false;
	}
	fileInfo->size = (uint64_t)attrs.nFileSizeLow | ((uint64_t)attrs.nFileSizeHigh << 32);
	fileInfo->isDirectory = (attrs.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
	fileInfo->isWritable = (attrs.dwFileAttributes & FILE_ATTRIBUTE_READONLY) == 0;
	fileInfo->exists = true;
#else
	struct stat64 file_info;

	std::string copy(path);
	stripTailDirSlashes(copy);

	int result = stat64(copy.c_str(), &file_info);

	if (result < 0) {
		WLOG("IsDirectory: stat failed on %s", path);
		fileInfo->exists = false;
		return false;
	}

	fileInfo->isDirectory = S_ISDIR(file_info.st_mode);
	fileInfo->isWritable = false;
	fileInfo->size = file_info.st_size;
	fileInfo->exists = true;
	// HACK: approximation
	if (file_info.st_mode & 0200)
		fileInfo->isWritable = true;
#endif
	return true;
}

std::string getFileExtension(const std::string &fn) {
	int pos = (int)fn.rfind(".");
	if (pos < 0) return "";
	std::string ext = fn.substr(pos+1);
	for (size_t i = 0; i < ext.size(); i++) {
		ext[i] = tolower(ext[i]);
	}
	return ext;
}

bool FileInfo::operator <(const FileInfo &other) const {
	if (isDirectory && !other.isDirectory)
		return true;
	else if (!isDirectory && other.isDirectory)
		return false;
	if (strcasecmp(name.c_str(), other.name.c_str()) < 0)
		return true;
	else
		return false;
}

size_t getFilesInDir(const char *directory, std::vector<FileInfo> *files, const char *filter) {
	size_t foundEntries = 0;
	std::set<std::string> filters;
	std::string tmp;
	if (filter) {
		while (*filter) {
			if (*filter == ':') {
				filters.insert(tmp);
				tmp = "";
			} else {
				tmp.push_back(*filter);
			}
			filter++;
		}
	}
	if (tmp.size())
		filters.insert(tmp);
#ifdef _WIN32
	// Find the first file in the directory.
	WIN32_FIND_DATA ffd;
#ifdef UNICODE

	HANDLE hFind = FindFirstFile((ConvertUTF8ToWString(directory) + L"\\*").c_str(), &ffd);
#else
	HANDLE hFind = FindFirstFile((std::string(directory) + "\\*").c_str(), &ffd);
#endif
	if (hFind == INVALID_HANDLE_VALUE) {
		FindClose(hFind);
		return 0;
	}
	// windows loop
	do
	{
		const std::string virtualName = ConvertWStringToUTF8(ffd.cFileName);
#else
	struct dirent_large { struct dirent entry; char padding[FILENAME_MAX+1]; };
	struct dirent_large diren;
	struct dirent *result = NULL;

	//std::string directoryWithSlash = directory;
	//if (directoryWithSlash.back() != '/')
	//	directoryWithSlash += "/";

	DIR *dirp = opendir(directory);
	if (!dirp)
		return 0;
	// non windows loop
	while (!readdir_r(dirp, (dirent*) &diren, &result) && result)
	{
		const std::string virtualName(result->d_name);
#endif
		// check for "." and ".."
		if (((virtualName[0] == '.') && (virtualName[1] == '\0')) ||
			((virtualName[0] == '.') && (virtualName[1] == '.') &&
			(virtualName[2] == '\0')))
			continue;

		// Remove dotfiles (should be made optional?)
		if (virtualName[0] == '.')
			continue;

		FileInfo info;
		info.name = virtualName;
		info.fullName = std::string(directory) + "/" + virtualName;
		info.isDirectory = isDirectory(info.fullName);
		info.exists = true;
		info.size = 0;
		if (!info.isDirectory) {
			std::string ext = getFileExtension(info.fullName);
			if (filter) {
				if (filters.find(ext) == filters.end())
					continue;
			}
		}

		files->push_back(info);
#ifdef _WIN32
	} while (FindNextFile(hFind, &ffd) != 0);
	FindClose(hFind);
#else
	}
	closedir(dirp);
#endif
	std::sort(files->begin(), files->end());
	return foundEntries;
}

void deleteFile(const char *file)
{
#ifdef _WIN32
	if (!DeleteFile(ConvertUTF8ToWString(file).c_str())) {
		ELOG("Error deleting %s: %i", file, GetLastError());
	}
#else
	int err = unlink(file);
	if (err) {
		ELOG("Error unlinking %s: %i", file, err);
	}
#endif
}

void deleteDir(const char *dir)
{
#ifdef _WIN32
	if (!RemoveDirectory(ConvertUTF8ToWString(dir).c_str())) {
		ELOG("Error deleting directory %s: %i", dir, GetLastError());
	}
#else
	rmdir(dir);
#endif
}

#endif

std::string getDir(const std::string &path)
{
	if (path == "/")
		return path;
	int n = (int)path.size() - 1;
	while (n >= 0 && path[n] != '\\' && path[n] != '/')
		n--;
	std::string cutpath = n > 0 ? path.substr(0, n) : "";
	for (size_t i = 0; i < cutpath.size(); i++)
	{
		if (cutpath[i] == '\\') cutpath[i] = '/';
	}
#ifndef _WIN32
	if (!cutpath.size()) {
		return "/";
	}
#endif
	return cutpath;
}

std::string getFilename(std::string path) {
	size_t off = getDir(path).size() + 1;
	if (off < path.size())
		return path.substr(off);
	else
		return path;
}

void mkDir(const std::string &path)
{
#ifdef _WIN32
	mkdir(path.c_str());
#else
	mkdir(path.c_str(), 0777);
#endif
}

#ifdef _WIN32
// Returns a vector with the device names
std::vector<std::string> getWindowsDrives()
{
	std::vector<std::string> drives;

	const DWORD buffsize = GetLogicalDriveStrings(0, NULL);
	std::vector<TCHAR> buff(buffsize);
	if (GetLogicalDriveStrings(buffsize, buff.data()) == buffsize - 1)
	{
		auto drive = buff.data();
		while (*drive)
		{
			std::string str(ConvertWStringToUTF8(drive));
			str.pop_back();	// we don't want the final backslash
			str += "/";
			drives.push_back(str);

			// advance to next drive
			while (*drive++) {}
		}
	}
	return drives;
}
#endif
<commit_msg>Open filenames using wide functions on win32.<commit_after>#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <direct.h>
#ifndef strcasecmp
#define strcasecmp _stricmp
#endif
#else
#include <dirent.h>
#include <unistd.h>
#include <errno.h>
#endif
#include <cstring>
#include <string>
#include <set>
#include <algorithm>
#include <cstdio>
#include <sys/stat.h>
#include <ctype.h>

#include "base/logging.h"
#include "base/basictypes.h"
#include "file/file_util.h"
#include "util/text/utf8.h"

#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__SYMBIAN32__)
#define stat64 stat
#endif

// Hack
#ifdef __SYMBIAN32__
static inline int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result) {
	struct dirent *readdir_entry;

	readdir_entry = readdir(dirp);
	if (readdir_entry == NULL) {
		*result = NULL;
		return errno;
	}

	*entry = *readdir_entry;
	*result = entry;
	return 0;
}
#endif

FILE *openCFile(const std::string &filename, const char *mode)
{
#if defined(_WIN32) && defined(UNICODE)
	return _wfopen(ConvertUTF8ToWString(filename).c_str(), ConvertUTF8ToWString(mode).c_str());
#else
	return fopen(filename.c_str(), mode);
#endif
}

bool writeStringToFile(bool text_file, const std::string &str, const char *filename)
{
	FILE *f = openCFile(filename, text_file ? "w" : "wb");
	if (!f)
		return false;
	size_t len = str.size();
	if (len != fwrite(str.data(), 1, str.size(), f))
	{
		fclose(f);
		return false;
	}
	fclose(f);
	return true;
}

bool writeDataToFile(bool text_file, const void* data, const unsigned int size, const char *filename)
{
	FILE *f = openCFile(filename, text_file ? "w" : "wb");
	if (!f)
		return false;
	size_t len = size;
	if (len != fwrite(data, 1, len, f))
	{
		fclose(f);
		return false;
	}
	fclose(f);
	return true;
}

uint64_t GetSize(FILE *f)
{
	// can't use off_t here because it can be 32-bit
	uint64_t pos = ftell(f);
	if (fseek(f, 0, SEEK_END) != 0) {
		return 0;
	}
	uint64_t size = ftell(f);
	// Reset the seek position to where it was when we started.
	if ((size != pos) && (fseek(f, pos, SEEK_SET) != 0)) {
		// Should error here
		return 0;
	}
	return size;
}

bool ReadFileToString(bool text_file, const char *filename, std::string &str)
{
	FILE *f = openCFile(filename, text_file ? "r" : "rb");
	if (!f)
		return false;
	size_t len = (size_t)GetSize(f);
	char *buf = new char[len + 1];
	buf[fread(buf, 1, len, f)] = 0;
	str = std::string(buf, len);
	fclose(f);
	delete [] buf;
	return true;
}

bool readDataFromFile(bool text_file, unsigned char* &data, const unsigned int size, const char *filename)
{
	FILE *f = openCFile(filename, text_file ? "r" : "rb");
	if (!f)
		return false;
	size_t len = (size_t)GetSize(f);
	if(len < size) {
		fclose(f);
		return false;
	}
	data[fread(data, 1, size, f)] = 0;
	fclose(f);
	return true;
}

#define DIR_SEP "/"
#define DIR_SEP_CHR '\\'

#ifndef METRO

// Remove any ending forward slashes from directory paths
// Modifies argument.
static void stripTailDirSlashes(std::string &fname)
{
	if (fname.length() > 1)
	{
		size_t i = fname.length() - 1;
		while (fname[i] == DIR_SEP_CHR)
			fname[i--] = '\0';
	}
	return;
}

// Returns true if file filename exists
bool exists(const std::string &filename) {
#ifdef _WIN32
	std::wstring wstr = ConvertUTF8ToWString(filename);
	return GetFileAttributes(wstr.c_str()) != 0xFFFFFFFF;
#else
	struct stat64 file_info;

	std::string copy(filename);
	stripTailDirSlashes(copy);

	int result = stat64(copy.c_str(), &file_info);

	return (result == 0);
#endif
}

// Returns true if filename is a directory
bool isDirectory(const std::string &filename) {
	FileInfo info;
	getFileInfo(filename.c_str(), &info);
	return info.isDirectory;
}

bool getFileInfo(const char *path, FileInfo *fileInfo) {
	// TODO: Expand relative paths?
	fileInfo->fullName = path;

#ifdef _WIN32
	WIN32_FILE_ATTRIBUTE_DATA attrs;
	if (!GetFileAttributesExW(ConvertUTF8ToWString(path).c_str(), GetFileExInfoStandard, &attrs)) {
		fileInfo->size = 0;
		fileInfo->isDirectory = false;
		fileInfo->exists = false;
		return false;
	}
	fileInfo->size = (uint64_t)attrs.nFileSizeLow | ((uint64_t)attrs.nFileSizeHigh << 32);
	fileInfo->isDirectory = (attrs.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
	fileInfo->isWritable = (attrs.dwFileAttributes & FILE_ATTRIBUTE_READONLY) == 0;
	fileInfo->exists = true;
#else
	struct stat64 file_info;

	std::string copy(path);
	stripTailDirSlashes(copy);

	int result = stat64(copy.c_str(), &file_info);

	if (result < 0) {
		WLOG("IsDirectory: stat failed on %s", path);
		fileInfo->exists = false;
		return false;
	}

	fileInfo->isDirectory = S_ISDIR(file_info.st_mode);
	fileInfo->isWritable = false;
	fileInfo->size = file_info.st_size;
	fileInfo->exists = true;
	// HACK: approximation
	if (file_info.st_mode & 0200)
		fileInfo->isWritable = true;
#endif
	return true;
}

std::string getFileExtension(const std::string &fn) {
	int pos = (int)fn.rfind(".");
	if (pos < 0) return "";
	std::string ext = fn.substr(pos+1);
	for (size_t i = 0; i < ext.size(); i++) {
		ext[i] = tolower(ext[i]);
	}
	return ext;
}

bool FileInfo::operator <(const FileInfo &other) const {
	if (isDirectory && !other.isDirectory)
		return true;
	else if (!isDirectory && other.isDirectory)
		return false;
	if (strcasecmp(name.c_str(), other.name.c_str()) < 0)
		return true;
	else
		return false;
}

size_t getFilesInDir(const char *directory, std::vector<FileInfo> *files, const char *filter) {
	size_t foundEntries = 0;
	std::set<std::string> filters;
	std::string tmp;
	if (filter) {
		while (*filter) {
			if (*filter == ':') {
				filters.insert(tmp);
				tmp = "";
			} else {
				tmp.push_back(*filter);
			}
			filter++;
		}
	}
	if (tmp.size())
		filters.insert(tmp);
#ifdef _WIN32
	// Find the first file in the directory.
	WIN32_FIND_DATA ffd;
#ifdef UNICODE

	HANDLE hFind = FindFirstFile((ConvertUTF8ToWString(directory) + L"\\*").c_str(), &ffd);
#else
	HANDLE hFind = FindFirstFile((std::string(directory) + "\\*").c_str(), &ffd);
#endif
	if (hFind == INVALID_HANDLE_VALUE) {
		FindClose(hFind);
		return 0;
	}
	// windows loop
	do
	{
		const std::string virtualName = ConvertWStringToUTF8(ffd.cFileName);
#else
	struct dirent_large { struct dirent entry; char padding[FILENAME_MAX+1]; };
	struct dirent_large diren;
	struct dirent *result = NULL;

	//std::string directoryWithSlash = directory;
	//if (directoryWithSlash.back() != '/')
	//	directoryWithSlash += "/";

	DIR *dirp = opendir(directory);
	if (!dirp)
		return 0;
	// non windows loop
	while (!readdir_r(dirp, (dirent*) &diren, &result) && result)
	{
		const std::string virtualName(result->d_name);
#endif
		// check for "." and ".."
		if (((virtualName[0] == '.') && (virtualName[1] == '\0')) ||
			((virtualName[0] == '.') && (virtualName[1] == '.') &&
			(virtualName[2] == '\0')))
			continue;

		// Remove dotfiles (should be made optional?)
		if (virtualName[0] == '.')
			continue;

		FileInfo info;
		info.name = virtualName;
		info.fullName = std::string(directory) + "/" + virtualName;
		info.isDirectory = isDirectory(info.fullName);
		info.exists = true;
		info.size = 0;
		if (!info.isDirectory) {
			std::string ext = getFileExtension(info.fullName);
			if (filter) {
				if (filters.find(ext) == filters.end())
					continue;
			}
		}

		files->push_back(info);
#ifdef _WIN32
	} while (FindNextFile(hFind, &ffd) != 0);
	FindClose(hFind);
#else
	}
	closedir(dirp);
#endif
	std::sort(files->begin(), files->end());
	return foundEntries;
}

void deleteFile(const char *file)
{
#ifdef _WIN32
	if (!DeleteFile(ConvertUTF8ToWString(file).c_str())) {
		ELOG("Error deleting %s: %i", file, GetLastError());
	}
#else
	int err = unlink(file);
	if (err) {
		ELOG("Error unlinking %s: %i", file, err);
	}
#endif
}

void deleteDir(const char *dir)
{
#ifdef _WIN32
	if (!RemoveDirectory(ConvertUTF8ToWString(dir).c_str())) {
		ELOG("Error deleting directory %s: %i", dir, GetLastError());
	}
#else
	rmdir(dir);
#endif
}

#endif

std::string getDir(const std::string &path)
{
	if (path == "/")
		return path;
	int n = (int)path.size() - 1;
	while (n >= 0 && path[n] != '\\' && path[n] != '/')
		n--;
	std::string cutpath = n > 0 ? path.substr(0, n) : "";
	for (size_t i = 0; i < cutpath.size(); i++)
	{
		if (cutpath[i] == '\\') cutpath[i] = '/';
	}
#ifndef _WIN32
	if (!cutpath.size()) {
		return "/";
	}
#endif
	return cutpath;
}

std::string getFilename(std::string path) {
	size_t off = getDir(path).size() + 1;
	if (off < path.size())
		return path.substr(off);
	else
		return path;
}

void mkDir(const std::string &path)
{
#ifdef _WIN32
	mkdir(path.c_str());
#else
	mkdir(path.c_str(), 0777);
#endif
}

#ifdef _WIN32
// Returns a vector with the device names
std::vector<std::string> getWindowsDrives()
{
	std::vector<std::string> drives;

	const DWORD buffsize = GetLogicalDriveStrings(0, NULL);
	std::vector<TCHAR> buff(buffsize);
	if (GetLogicalDriveStrings(buffsize, buff.data()) == buffsize - 1)
	{
		auto drive = buff.data();
		while (*drive)
		{
			std::string str(ConvertWStringToUTF8(drive));
			str.pop_back();	// we don't want the final backslash
			str += "/";
			drives.push_back(str);

			// advance to next drive
			while (*drive++) {}
		}
	}
	return drives;
}
#endif
<|endoftext|>


<commit_before>#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
#include <utility>
#include <algorithm>

using namespace std;

template<typename T>
void show(T a){
  for(auto i : a){ cout << i.first << " " << i.second << " "; }
  cout << endl;
}
template<typename T>
void showmatrix(T a){
  for(auto j: a){for(auto i : j){ cout << i; }cout << endl;}
  cout << endl;
}
void check(long i = 0){
  cout << "checkpoint:[" << i << "]" << endl;
}
void check(int i = 0){
  cout << "checkpoint:[" << i << "]" << endl;
}
void check(char i = ' '){
  cout << "checkpoint:[" << i << "]" << endl;
}
void check(char i = ' ', int j = 0){
  cout << "checkpoint:[" << i <<","<<j<< "]" << endl;
}

unordered_map<char, int> map;

void add(char c){
  if(map.count(c) > 0){
    map[c] +=1;
  }
  else{
    map[c] = 1;
  }
}

long sum(char c){
  int csum = map[c];
  int real_sum = 0;
  for(auto i : map){
    real_sum += i.second;
  }
  return real_sum - csum;
}

long operate(char c){
  long counter = 0;
  for(auto i = map.begin(); i != map.end(); ++i){
    if(i->first == c) continue;
    map[c] += i->second;
    counter += i->second;
    i->second = 0;
  }
  return counter;
}

int main(int argc, char *argv[]){
  ios::sync_with_stdio(false);
  cin.tie(NULL);

  string str;
  cin >> str;

  // show(map);

  // map = {{'a', 2}, {'b', 3}, {'c', 0}};
  // operate('c');

  // show(map);

  long res = 0;

  char tmp = str[str.size() - 1];
  add(tmp);
  for(long i = str.size() - 2; i >= 0; i--){
    char t2 = str[i];
    if(t2 == tmp){
      res += operate(t2);
    }
    else{
      add(t2);
      tmp = t2;
    }
    check(t2, res);
  }

  cout << res <<endl;
}
<commit_msg>test: 💍 temp save<commit_after>#include <algorithm>
#include <iostream>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>

using namespace std;

template <typename T>
void show(T a) {
  for (auto i : a) {
    cout << i.first << " " << i.second << " ";
  }
  cout << endl;
}
template <typename T>
void showmatrix(T a) {
  for (auto j : a) {
    for (auto i : j) {
      cout << i;
    }
    cout << endl;
  }
  cout << endl;
}
void check(long i = 0) { cout << "checkpoint:[" << i << "]" << endl; }
void check(int i = 0) { cout << "checkpoint:[" << i << "]" << endl; }
void check(char i = ' ') { cout << "checkpoint:[" << i << "]" << endl; }
void check(char i = ' ', int j = 0) {
  cout << "checkpoint:[" << i << "," << j << "]" << endl;
}

unordered_map<char, int> map;

void add(char c) {
  if (map.count(c) > 0) {
    map[c] += 1;
  } else {
    map[c] = 1;
  }
}

long sum(char c) {
  int csum = map[c];
  int real_sum = 0;
  for (auto i : map) {
    real_sum += i.second;
  }
  return real_sum - csum;
}

long operate(char c) {
  long counter = 0;
  for (auto i = map.begin(); i != map.end(); ++i) {
    if (i->first == c) continue;
    map[c] += i->second;
    counter += i->second;
    i->second = 0;
  }
  return counter;
}

int main(int argc, char *argv[]) {
  ios::sync_with_stdio(false);
  cin.tie(NULL);

  string str;
  cin >> str;

  // show(map);

  // map = {{'a', 2}, {'b', 3}, {'c', 0}};
  // operate('c');

  // show(map);

  long res = 0;

  char tmp = str[str.size() - 1];
  add(tmp);
  for (long i = str.size() - 2; i >= 0; i--) {
    char t2 = str[i];
    if (t2 == tmp) {
      res += operate(t2);
    } else {
      add(t2);
      tmp = t2;
    }
    check(t2, res);
  }

  cout << res << endl;
}
<|endoftext|>


<commit_before>// Utility functions

#include "SAMdisk.h"
#include "utils.h"

namespace util
{

std::ofstream log;
LogHelper cout(&std::cout);

std::string fmt(const char* fmt, ...)
{
    va_list args;
    va_start(args, fmt);
    auto len = std::vsnprintf(nullptr, 0, fmt, args);
    va_end(args);

    std::vector<char> bytes(len + 1); // +1 for \0

    va_start(args, fmt);
    std::vsnprintf(&bytes[0], bytes.size(), fmt, args);
    va_end(args);

    return std::string(bytes.data(), len);
}

std::vector<std::string> split(const std::string& str, char delim, bool skip_empty)
{
    std::vector<std::string> items;
    std::stringstream ss(str);
    std::string s;

    while (std::getline(ss, s, delim))
    {
        if (!skip_empty || !s.empty())
            items.emplace_back(std::move(s));
    }

    return items;
}

std::string trim(const std::string& str)
{
    std::string s(str.c_str());
    s.erase(0, s.find_first_not_of(" \t\r\n"));
    s.erase(s.find_last_not_of(" \t\r\n") + 1);
    return s;
}

void bit_reverse(uint8_t* pb, int len)
{
    while (len-- > 0)
    {
        auto& b = *pb++;
        b = ((b & 1) << 7) |
            ((b & 2) << 5) |
            ((b & 4) << 3) |
            ((b & 8) << 1) |
            ((b & 16) >> 1) |
            ((b & 32) >> 3) |
            ((b & 64) >> 5) |
            ((b & 128) >> 7);
    }
}

std::string resource_dir()
{
#ifdef RESOURCE_DIR
    return RESOURCE_DIR;
#elif defined(_WIN32)
    char sz[MAX_PATH];
    if (GetModuleFileName(NULL, sz, arraysize(sz)))
    {
        auto s = std::string(sz);
        s.erase(s.find_last_of('\\') + 1);
        return s;

    }
#endif

    return "";
}

bool is_stdout_a_tty()
{
#ifdef _WIN32
    static bool ret = _isatty(_fileno(stdout)) != 0;
#else
    static bool ret = isatty(fileno(stdout)) != 0;
#endif
    return ret;
}

std::string lowercase(const std::string& str)
{
    std::string ret = str;
    ret.reserve(str.length());
    std::transform(str.cbegin(), str.cend(), ret.begin(), [](char c) {
        return static_cast<uint8_t>(std::tolower(static_cast<int>(c)));
        });
    return ret;
}

LogHelper& operator<<(LogHelper& h, colour c)
{
    // Colours are screen only
    if (util::is_stdout_a_tty())
    {
#ifdef _WIN32
        h.screen->flush();
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), static_cast<int>(c));
#else
        auto val = static_cast<int>(c);
        if (val & 0x80)
            *h.screen << "\x1b[" << (val & 0x7f) << ";1m";
        else
            *h.screen << "\x1b[0;" << (val & 0x7f) << 'm';
#endif
    }
    return h;
}

LogHelper& operator<<(LogHelper& h, ttycmd cmd)
{
    if (util::is_stdout_a_tty())
    {
        switch (cmd)
        {
        case ttycmd::statusbegin:
            h.statusmsg = true;
            break;

        case ttycmd::statusend:
            h.statusmsg = false;
            h.clearline = true;
            break;

        case ttycmd::clearline:
            h << "\r" << ttycmd::cleartoeol;
            h.clearline = false;
            break;

        case ttycmd::cleartoeol:
#ifdef _WIN32
            h.screen->flush();

            DWORD dwWritten;
            CONSOLE_SCREEN_BUFFER_INFO csbi{};
            HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);

            if (GetConsoleScreenBufferInfo(hConsole, &csbi))
                FillConsoleOutputCharacter(hConsole, ' ', csbi.dwSize.X - csbi.dwCursorPosition.X, csbi.dwCursorPosition, &dwWritten);
#else
            * h.screen << "\x1b[0K";
#endif
            break;
        }
    }
    return h;
}

} // namespace util
<commit_msg>Changed Win32 to use EXE location for resources<commit_after>// Utility functions

#include "SAMdisk.h"
#include "utils.h"

namespace util
{

std::ofstream log;
LogHelper cout(&std::cout);

std::string fmt(const char* fmt, ...)
{
    va_list args;
    va_start(args, fmt);
    auto len = std::vsnprintf(nullptr, 0, fmt, args);
    va_end(args);

    std::vector<char> bytes(len + 1); // +1 for \0

    va_start(args, fmt);
    std::vsnprintf(&bytes[0], bytes.size(), fmt, args);
    va_end(args);

    return std::string(bytes.data(), len);
}

std::vector<std::string> split(const std::string& str, char delim, bool skip_empty)
{
    std::vector<std::string> items;
    std::stringstream ss(str);
    std::string s;

    while (std::getline(ss, s, delim))
    {
        if (!skip_empty || !s.empty())
            items.emplace_back(std::move(s));
    }

    return items;
}

std::string trim(const std::string& str)
{
    std::string s(str.c_str());
    s.erase(0, s.find_first_not_of(" \t\r\n"));
    s.erase(s.find_last_not_of(" \t\r\n") + 1);
    return s;
}

void bit_reverse(uint8_t* pb, int len)
{
    while (len-- > 0)
    {
        auto& b = *pb++;
        b = ((b & 1) << 7) |
            ((b & 2) << 5) |
            ((b & 4) << 3) |
            ((b & 8) << 1) |
            ((b & 16) >> 1) |
            ((b & 32) >> 3) |
            ((b & 64) >> 5) |
            ((b & 128) >> 7);
    }
}

std::string resource_dir()
{
#if defined(_WIN32)
    char sz[MAX_PATH];
    if (GetModuleFileName(NULL, sz, arraysize(sz)))
    {
        auto s = std::string(sz);
        s.erase(s.find_last_of('\\') + 1);
        return s;
    }
#elif defined(RESOURCE_DIR)
    return RESOURCE_DIR;
#endif

    return "";
}

bool is_stdout_a_tty()
{
#ifdef _WIN32
    static bool ret = _isatty(_fileno(stdout)) != 0;
#else
    static bool ret = isatty(fileno(stdout)) != 0;
#endif
    return ret;
}

std::string lowercase(const std::string& str)
{
    std::string ret = str;
    ret.reserve(str.length());
    std::transform(str.cbegin(), str.cend(), ret.begin(), [](char c) {
        return static_cast<uint8_t>(std::tolower(static_cast<int>(c)));
        });
    return ret;
}

LogHelper& operator<<(LogHelper& h, colour c)
{
    // Colours are screen only
    if (util::is_stdout_a_tty())
    {
#ifdef _WIN32
        h.screen->flush();
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), static_cast<int>(c));
#else
        auto val = static_cast<int>(c);
        if (val & 0x80)
            *h.screen << "\x1b[" << (val & 0x7f) << ";1m";
        else
            *h.screen << "\x1b[0;" << (val & 0x7f) << 'm';
#endif
    }
    return h;
}

LogHelper& operator<<(LogHelper& h, ttycmd cmd)
{
    if (util::is_stdout_a_tty())
    {
        switch (cmd)
        {
        case ttycmd::statusbegin:
            h.statusmsg = true;
            break;

        case ttycmd::statusend:
            h.statusmsg = false;
            h.clearline = true;
            break;

        case ttycmd::clearline:
            h << "\r" << ttycmd::cleartoeol;
            h.clearline = false;
            break;

        case ttycmd::cleartoeol:
#ifdef _WIN32
            h.screen->flush();

            DWORD dwWritten;
            CONSOLE_SCREEN_BUFFER_INFO csbi{};
            HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);

            if (GetConsoleScreenBufferInfo(hConsole, &csbi))
                FillConsoleOutputCharacter(hConsole, ' ', csbi.dwSize.X - csbi.dwCursorPosition.X, csbi.dwCursorPosition, &dwWritten);
#else
            * h.screen << "\x1b[0K";
#endif
            break;
        }
    }
    return h;
}

} // namespace util
<|endoftext|>


<commit_before>#include <cmath>
#include <limits>
#include <stdexcept>
#include <iostream>
#include <boost/filesystem.hpp>
#include <sstream>
#include <cstdlib>
#include <fstream>
#include <cfenv>
#include <X11/xpm.h>
#include <iomanip>
#include <FL/x.H>
#include "utils.hpp"
#include "florb.xpm"

#define CLIPLEFT   (1)  // 0001
#define CLIPRIGHT  (2)  // 0010
#define CLIPBOTTOM (4)  // 0100
#define CLIPTOP    (8)  // 1000

#define CIRCUMFERENCEKM (2*M_PI*6372.7982)

florb::point2d<double> florb::utils::wsg842merc(const florb::point2d<double> &wsg84)
{
    if ((wsg84.x() > 180.0) || (wsg84.x() < -180.0))
        throw std::out_of_range(_("Invalid longitude"));
    if ((wsg84.y() > 90.0) || (wsg84.y() < -90.0))
        throw std::out_of_range(_("Invalid latitude"));

    // Anything above 85 degrees N or S is infinity in the mercator projection,
    // clip here.
    double lat = wsg84.y();
    if (lat > 85.0)
        lat = 85.0;
    else if (lat < -85)
        lat = -85.0;

    // Project to Mercator (360 by 360 square)
    return florb::point2d<double>(
            180.0 + wsg84.x(),
            180.0 - ((180.0/M_PI) * log(tan(M_PI/4.0+lat*(M_PI/180.0)/2.0))));
}

florb::point2d<unsigned long> florb::utils::merc2px(unsigned int z, const florb::point2d<double> &merc)
{
    unsigned long dimxy = dim(z);

    return florb::point2d<unsigned long>(
        (unsigned long)(((double)(dimxy-1)/360.0) * merc.x()),
        (unsigned long)(((double)(dimxy-1)/360.0) * merc.y()));
}

florb::point2d<unsigned long> florb::utils::wsg842px(unsigned int z, const florb::point2d<double> &wsg84)
{
    // Mercator projection
    florb::point2d<double> merc(wsg842merc(wsg84));

    // Unit conversion
    return merc2px(z, merc);
}

florb::point2d<double> florb::utils::px2wsg84(unsigned int z, const florb::point2d<unsigned long> &px)
{
    // Get map dimensions
    unsigned long dimxy = dim(z);

    // Make sure the coordinate is on the map
    if ((px.x() > dimxy) || (px.y() > dimxy))
        throw std::out_of_range(_("Invalid pixel position"));

    // Unit conversion
    florb::point2d<double> mdeg(
            (360.0/((double)dimxy/(double)px.x())),
            (360.0/((double)dimxy/(double)px.y())));

    // Convert mercator to GPS coordinate
    return merc2wsg84(mdeg);
}

florb::point2d<double> florb::utils::merc2wsg84(const florb::point2d<double>& wsg84)
{
    return florb::point2d<double>(
            wsg84.x() - 180.0,
            -((180.0/M_PI) * (2.0 * atan(exp((wsg84.y()-180.0)*M_PI/180.0)) - M_PI/2.0)));
}

florb::point2d<double> florb::utils::px2merc(unsigned int z, const florb::point2d<unsigned long> &px)
{
    unsigned long dimxy = dim(z);

    // Make sure the coordinate is on the map
    if ((px.x() >= dimxy) || (px.y() >= dimxy))
    {
        throw std::out_of_range(_("Invalid pixel position"));
    }

    double x = (px.x() == 0) ? 0.0 : (360.0/((double)(dimxy-1)/(double)px.x()));
    double y = (px.y() == 0) ? 0.0 : (360.0/((double)(dimxy-1)/(double)px.y()));
    return florb::point2d<double>(x,y);
}

unsigned long florb::utils::dim(unsigned int z)
{
    return pow(2.0, z) * 256;
}

double florb::utils::dist(const florb::point2d<double> &p1, const florb::point2d<double> &p2)
{
    if (p1 == p2)
        return 0.0;

    double d2r = (M_PI/180.0);
    double lon1 = p1.x()*d2r;
    double lat1 = p1.y()*d2r;
    double lon2 = p2.x()*d2r;
    double lat2 = p2.y()*d2r;

    double ret = (6378.388 * acos(sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2) * cos(lon2 - lon1)));

    return (isnan(ret) > 0) ? 0.0 : ret;
}

double florb::utils::dist_merc(const florb::point2d<double> &p1, const florb::point2d<double> &p2)
{
    if (p1 == p2)
        return 0.0;

    double dstmerc = sqrt( pow(std::abs(p1.x()-p2.x()), 2.0) + pow(std::abs(p1.y()-p2.y()), 2.0)*0.9444444 );
    return (dstmerc * (CIRCUMFERENCEKM/360.0));
}

double florb::utils::meters_per_pixel(unsigned int z, double lat)
{
    return (CIRCUMFERENCEKM * cos(lat*(M_PI/180.0)) / pow(2.0,(z+8))) * 1000.0;
}

time_t florb::utils::iso8601_2timet(const std::string& iso)
{
    struct tm stm;
    strptime(iso.c_str(), "%FT%T%z", &stm);

    return mktime(&stm);
}

std::string florb::utils::timet2iso8601(time_t t)
{
    char buf[sizeof "2011-10-08T07:07:09Z"];
    strftime(buf, sizeof buf, "%FT%TZ", gmtime(&t));

    return std::string(buf);
}

std::string florb::utils::pathsep()
{
#if defined(WIN32) || defined(_WIN32)
return std::string("\\");
#else
return std::string("/");
#endif
}

std::string florb::utils::userdir()
{
    char *home = getenv("HOME");
    if (!home)
        throw 0;

    return std::string(home);
}

std::string florb::utils::appdir()
{
    std::ostringstream oss;
    oss << userdir();
    oss << pathsep();
    oss << ".florb";

    return oss.str();
}

bool florb::utils::mkdir(const std::string& path)
{
    bool ret = true;

    try {
        boost::filesystem::create_directory(path);
    } catch (...) {
        ret = false;
    }

    return ret;
}

void florb::utils::rm(const std::string& path)
{
    boost::filesystem::remove_all(path);
}

bool florb::utils::exists(const std::string& path)
{
    return boost::filesystem::exists(path);
}

std::string florb::utils::filestem(const std::string& path)
{
    return boost::filesystem::path(path).stem().string();
}

std::string florb::utils::extension(const std::string& path)
{
    return boost::filesystem::path(path).extension().string();
}

void florb::utils::touch(const std::string& path)
{
    std::fstream f(path, std::ios::out|std::ios::app);
	f.close();
}

void florb::utils::set_window_icon(Fl_Window *w)
{
    fl_open_display();
    Pixmap p, mask;
    XpmCreatePixmapFromData(fl_display, DefaultRootWindow(fl_display), const_cast<char**>(florb_xpm), &p, &mask, NULL);
    w->icon((char *)p);
}

std::vector<std::string> florb::utils::str_split(const std::string& str, const std::string& delimiter)
{
    std::size_t offs = 0, p1 = 0, p2 = std::string::npos;
    std::size_t len = str.length();

    std::vector<std::string> ret;
    while ((offs < len) && (p2 = str.find(delimiter, offs)) != std::string::npos)
    {
        std::string token(str.substr(p1, p2-p1));

        if (token.length() > 0)
            ret.push_back(str.substr(p1, p2-p1));

        p1 = p2 + delimiter.length();
        offs = p1;
    }

    if ((p1 != len))
        ret.push_back(str.substr(p1, len-p1));

    return ret;
}

std::size_t florb::utils::str_count(const std::string& str, const std::string& token)
{
    if (token.length() == 0)
        return 0;

    std::size_t ret = 0, offs = 0;

    while ((offs = str.find(token, offs)) != std::string::npos)
    {
        offs += token.length();
        ret++;
    }

    return ret;
}

void florb::utils::str_replace(std::string& str, const std::string& s, const std::string& r)
{
    std::size_t offs = 0;
    while ((offs = str.find(s, 0)) != std::string::npos)
    {
        str.replace(offs, s.length(), r);
    }
}

// Cohen–Sutherland clipping algorithm
bool florb::utils::clipline(
        florb::point2d<double> &p1,
        florb::point2d<double> &p2,
        const florb::point2d<double> &r1,
        const florb::point2d<double> &r2,
        bool &p1clip,
        bool &p2clip)
{
    bool ret = false;
    double xmin, xmax, ymin, ymax;
    p1clip = false;
    p2clip = false;

    if (r1.x() > r2.x())
    {
        xmin = r2.x();
        xmax = r1.x();
    }
    else
    {
        xmin = r1.x();
        xmax = r2.x();
    }

    if (r1.y() > r2.y())
    {
        ymin = r2.y();
        ymax = r1.y();
    }
    else
    {
        ymin = r1.y();
        ymax = r2.y();
    }

    bool overflowa = false;

    // Catch arithmetic overflow when calculating m and n
    double n = 0, m = 0;
    for (;;)
    {
        std::feclearexcept(FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);

        m = (p2.y() - p1.y()) / (p2.x() - p1.x());
        if (std::fetestexcept(FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO) != 0)
        {
            overflowa = true;
            break;
        }

        std::feclearexcept(FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);

        n = p1.y() - (m * p1.x());
        if (std::fetestexcept(FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO) != 0)
        {
            overflowa = true;
            break;
        }

        break;
    }

    // Max 2 clipping operations per point and one last check operation.
    for (int i=0;i<5;i++)
    {
        // Compute code for both points
        int code1 = 0, code2 = 0;

        if (p1.x() < xmin)
            code1 |= CLIPLEFT;
        if (p1.x() > xmax)
            code1 |= CLIPRIGHT;
        if (p1.y() < ymin)
            code1 |= CLIPTOP;
        if (p1.y() > ymax)
            code1 |= CLIPBOTTOM;

        if (p2.x() < xmin)
            code2 |= CLIPLEFT;
        if (p2.x() > xmax)
            code2 |= CLIPRIGHT;
        if (p2.y() < ymin)
            code2 |= CLIPTOP;
        if (p2.y() > ymax)
            code2 |= CLIPBOTTOM;

        // Both inside, draw line
        if ((code1 | code2) == 0)
        {
            ret = true;
            break;
        }

        // Both top, bottom, left or right outside, line need not be drawn
        if ((code1 & code2) != 0)
        {
            ret = false;
            break;
        }

        // Pick an endpoint for clipping
        florb::point2d<double> &ptmp = (code1 != 0) ? p1 : p2;
        int codetmp;
        if (code1 != 0)
        {
            codetmp = code1;
            p1clip = true;
        }
        else
        {
            codetmp = code2;
            p2clip = true;
        }

        // Clip top
        if (codetmp & CLIPTOP)
        {
            // This is what the following code does with just a little overflow
            // protection:
            // ptmp[0] = (ymin - n) / m;

            double cx;
            for (;!overflowa;)
            {
                std::feclearexcept(FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
                cx = (ymin - n) / m;

                if (std::fetestexcept(FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO) != 0)
                {
                    overflowa = true;
                    break;
                }

                break;
            }

            // In case of an arithmetic exception we assume a vertical line and
            // keep the original x coordinate
            if (!overflowa)
                ptmp[0] = cx;

            ptmp[1] = ymin;
        }
        // Clip Bottom
        else if (codetmp & CLIPBOTTOM)
        {
            // This is what the following code does with just a little overflow
            // protection:
            // ptmp[0] = (ymax - n) / m;

            double cx;
            for (;!overflowa;)
            {
                std::feclearexcept(FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
                cx = (ymax - n) / m;

                if (std::fetestexcept(FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO) != 0)
                {
                    overflowa = true;
                    break;
                }

                break;
            }

            // In case of an arithmetic exception we assume a vertical line and
            // keep the original x coordinate
            if (!overflowa)
                ptmp[0] = cx;

            ptmp[1] = ymax;
        }
        // Clip Left
        else if (codetmp & CLIPLEFT)
        {
            // Vertical line left outside
            if (overflowa)
            {
                ret = false;
                break;
            }

            ptmp[0] = xmin;
            ptmp[1] = m * xmin + n;
        }
        // Clip Right
        else if (codetmp & CLIPRIGHT)
        {
            // Vertical line right outside
            if (overflowa)
            {
                ret = false;
                break;
            }

            ptmp[0] = xmax;
            ptmp[1] = m * xmax + n;
        }
    }

    return ret;
}

<commit_msg>std::isnan()<commit_after>#include <cmath>
#include <limits>
#include <stdexcept>
#include <iostream>
#include <boost/filesystem.hpp>
#include <sstream>
#include <cstdlib>
#include <fstream>
#include <cfenv>
#include <X11/xpm.h>
#include <iomanip>
#include <FL/x.H>
#include "utils.hpp"
#include "florb.xpm"

#define CLIPLEFT   (1)  // 0001
#define CLIPRIGHT  (2)  // 0010
#define CLIPBOTTOM (4)  // 0100
#define CLIPTOP    (8)  // 1000

#define CIRCUMFERENCEKM (2*M_PI*6372.7982)

florb::point2d<double> florb::utils::wsg842merc(const florb::point2d<double> &wsg84)
{
    if ((wsg84.x() > 180.0) || (wsg84.x() < -180.0))
        throw std::out_of_range(_("Invalid longitude"));
    if ((wsg84.y() > 90.0) || (wsg84.y() < -90.0))
        throw std::out_of_range(_("Invalid latitude"));

    // Anything above 85 degrees N or S is infinity in the mercator projection,
    // clip here.
    double lat = wsg84.y();
    if (lat > 85.0)
        lat = 85.0;
    else if (lat < -85)
        lat = -85.0;

    // Project to Mercator (360 by 360 square)
    return florb::point2d<double>(
            180.0 + wsg84.x(),
            180.0 - ((180.0/M_PI) * log(tan(M_PI/4.0+lat*(M_PI/180.0)/2.0))));
}

florb::point2d<unsigned long> florb::utils::merc2px(unsigned int z, const florb::point2d<double> &merc)
{
    unsigned long dimxy = dim(z);

    return florb::point2d<unsigned long>(
        (unsigned long)(((double)(dimxy-1)/360.0) * merc.x()),
        (unsigned long)(((double)(dimxy-1)/360.0) * merc.y()));
}

florb::point2d<unsigned long> florb::utils::wsg842px(unsigned int z, const florb::point2d<double> &wsg84)
{
    // Mercator projection
    florb::point2d<double> merc(wsg842merc(wsg84));

    // Unit conversion
    return merc2px(z, merc);
}

florb::point2d<double> florb::utils::px2wsg84(unsigned int z, const florb::point2d<unsigned long> &px)
{
    // Get map dimensions
    unsigned long dimxy = dim(z);

    // Make sure the coordinate is on the map
    if ((px.x() > dimxy) || (px.y() > dimxy))
        throw std::out_of_range(_("Invalid pixel position"));

    // Unit conversion
    florb::point2d<double> mdeg(
            (360.0/((double)dimxy/(double)px.x())),
            (360.0/((double)dimxy/(double)px.y())));

    // Convert mercator to GPS coordinate
    return merc2wsg84(mdeg);
}

florb::point2d<double> florb::utils::merc2wsg84(const florb::point2d<double>& wsg84)
{
    return florb::point2d<double>(
            wsg84.x() - 180.0,
            -((180.0/M_PI) * (2.0 * atan(exp((wsg84.y()-180.0)*M_PI/180.0)) - M_PI/2.0)));
}

florb::point2d<double> florb::utils::px2merc(unsigned int z, const florb::point2d<unsigned long> &px)
{
    unsigned long dimxy = dim(z);

    // Make sure the coordinate is on the map
    if ((px.x() >= dimxy) || (px.y() >= dimxy))
    {
        throw std::out_of_range(_("Invalid pixel position"));
    }

    double x = (px.x() == 0) ? 0.0 : (360.0/((double)(dimxy-1)/(double)px.x()));
    double y = (px.y() == 0) ? 0.0 : (360.0/((double)(dimxy-1)/(double)px.y()));
    return florb::point2d<double>(x,y);
}

unsigned long florb::utils::dim(unsigned int z)
{
    return pow(2.0, z) * 256;
}

double florb::utils::dist(const florb::point2d<double> &p1, const florb::point2d<double> &p2)
{
    if (p1 == p2)
        return 0.0;

    double d2r = (M_PI/180.0);
    double lon1 = p1.x()*d2r;
    double lat1 = p1.y()*d2r;
    double lon2 = p2.x()*d2r;
    double lat2 = p2.y()*d2r;

    double ret = (6378.388 * acos(sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2) * cos(lon2 - lon1)));

    return (std::isnan(ret) > 0) ? 0.0 : ret;
}

double florb::utils::dist_merc(const florb::point2d<double> &p1, const florb::point2d<double> &p2)
{
    if (p1 == p2)
        return 0.0;

    double dstmerc = sqrt( pow(std::abs(p1.x()-p2.x()), 2.0) + pow(std::abs(p1.y()-p2.y()), 2.0)*0.9444444 );
    return (dstmerc * (CIRCUMFERENCEKM/360.0));
}

double florb::utils::meters_per_pixel(unsigned int z, double lat)
{
    return (CIRCUMFERENCEKM * cos(lat*(M_PI/180.0)) / pow(2.0,(z+8))) * 1000.0;
}

time_t florb::utils::iso8601_2timet(const std::string& iso)
{
    struct tm stm;
    strptime(iso.c_str(), "%FT%T%z", &stm);

    return mktime(&stm);
}

std::string florb::utils::timet2iso8601(time_t t)
{
    char buf[sizeof "2011-10-08T07:07:09Z"];
    strftime(buf, sizeof buf, "%FT%TZ", gmtime(&t));

    return std::string(buf);
}

std::string florb::utils::pathsep()
{
#if defined(WIN32) || defined(_WIN32)
return std::string("\\");
#else
return std::string("/");
#endif
}

std::string florb::utils::userdir()
{
    char *home = getenv("HOME");
    if (!home)
        throw 0;

    return std::string(home);
}

std::string florb::utils::appdir()
{
    std::ostringstream oss;
    oss << userdir();
    oss << pathsep();
    oss << ".florb";

    return oss.str();
}

bool florb::utils::mkdir(const std::string& path)
{
    bool ret = true;

    try {
        boost::filesystem::create_directory(path);
    } catch (...) {
        ret = false;
    }

    return ret;
}

void florb::utils::rm(const std::string& path)
{
    boost::filesystem::remove_all(path);
}

bool florb::utils::exists(const std::string& path)
{
    return boost::filesystem::exists(path);
}

std::string florb::utils::filestem(const std::string& path)
{
    return boost::filesystem::path(path).stem().string();
}

std::string florb::utils::extension(const std::string& path)
{
    return boost::filesystem::path(path).extension().string();
}

void florb::utils::touch(const std::string& path)
{
    std::fstream f(path, std::ios::out|std::ios::app);
	f.close();
}

void florb::utils::set_window_icon(Fl_Window *w)
{
    fl_open_display();
    Pixmap p, mask;
    XpmCreatePixmapFromData(fl_display, DefaultRootWindow(fl_display), const_cast<char**>(florb_xpm), &p, &mask, NULL);
    w->icon((char *)p);
}

std::vector<std::string> florb::utils::str_split(const std::string& str, const std::string& delimiter)
{
    std::size_t offs = 0, p1 = 0, p2 = std::string::npos;
    std::size_t len = str.length();

    std::vector<std::string> ret;
    while ((offs < len) && (p2 = str.find(delimiter, offs)) != std::string::npos)
    {
        std::string token(str.substr(p1, p2-p1));

        if (token.length() > 0)
            ret.push_back(str.substr(p1, p2-p1));

        p1 = p2 + delimiter.length();
        offs = p1;
    }

    if ((p1 != len))
        ret.push_back(str.substr(p1, len-p1));

    return ret;
}

std::size_t florb::utils::str_count(const std::string& str, const std::string& token)
{
    if (token.length() == 0)
        return 0;

    std::size_t ret = 0, offs = 0;

    while ((offs = str.find(token, offs)) != std::string::npos)
    {
        offs += token.length();
        ret++;
    }

    return ret;
}

void florb::utils::str_replace(std::string& str, const std::string& s, const std::string& r)
{
    std::size_t offs = 0;
    while ((offs = str.find(s, 0)) != std::string::npos)
    {
        str.replace(offs, s.length(), r);
    }
}

// Cohen–Sutherland clipping algorithm
bool florb::utils::clipline(
        florb::point2d<double> &p1,
        florb::point2d<double> &p2,
        const florb::point2d<double> &r1,
        const florb::point2d<double> &r2,
        bool &p1clip,
        bool &p2clip)
{
    bool ret = false;
    double xmin, xmax, ymin, ymax;
    p1clip = false;
    p2clip = false;

    if (r1.x() > r2.x())
    {
        xmin = r2.x();
        xmax = r1.x();
    }
    else
    {
        xmin = r1.x();
        xmax = r2.x();
    }

    if (r1.y() > r2.y())
    {
        ymin = r2.y();
        ymax = r1.y();
    }
    else
    {
        ymin = r1.y();
        ymax = r2.y();
    }

    bool overflowa = false;

    // Catch arithmetic overflow when calculating m and n
    double n = 0, m = 0;
    for (;;)
    {
        std::feclearexcept(FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);

        m = (p2.y() - p1.y()) / (p2.x() - p1.x());
        if (std::fetestexcept(FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO) != 0)
        {
            overflowa = true;
            break;
        }

        std::feclearexcept(FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);

        n = p1.y() - (m * p1.x());
        if (std::fetestexcept(FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO) != 0)
        {
            overflowa = true;
            break;
        }

        break;
    }

    // Max 2 clipping operations per point and one last check operation.
    for (int i=0;i<5;i++)
    {
        // Compute code for both points
        int code1 = 0, code2 = 0;

        if (p1.x() < xmin)
            code1 |= CLIPLEFT;
        if (p1.x() > xmax)
            code1 |= CLIPRIGHT;
        if (p1.y() < ymin)
            code1 |= CLIPTOP;
        if (p1.y() > ymax)
            code1 |= CLIPBOTTOM;

        if (p2.x() < xmin)
            code2 |= CLIPLEFT;
        if (p2.x() > xmax)
            code2 |= CLIPRIGHT;
        if (p2.y() < ymin)
            code2 |= CLIPTOP;
        if (p2.y() > ymax)
            code2 |= CLIPBOTTOM;

        // Both inside, draw line
        if ((code1 | code2) == 0)
        {
            ret = true;
            break;
        }

        // Both top, bottom, left or right outside, line need not be drawn
        if ((code1 & code2) != 0)
        {
            ret = false;
            break;
        }

        // Pick an endpoint for clipping
        florb::point2d<double> &ptmp = (code1 != 0) ? p1 : p2;
        int codetmp;
        if (code1 != 0)
        {
            codetmp = code1;
            p1clip = true;
        }
        else
        {
            codetmp = code2;
            p2clip = true;
        }

        // Clip top
        if (codetmp & CLIPTOP)
        {
            // This is what the following code does with just a little overflow
            // protection:
            // ptmp[0] = (ymin - n) / m;

            double cx;
            for (;!overflowa;)
            {
                std::feclearexcept(FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
                cx = (ymin - n) / m;

                if (std::fetestexcept(FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO) != 0)
                {
                    overflowa = true;
                    break;
                }

                break;
            }

            // In case of an arithmetic exception we assume a vertical line and
            // keep the original x coordinate
            if (!overflowa)
                ptmp[0] = cx;

            ptmp[1] = ymin;
        }
        // Clip Bottom
        else if (codetmp & CLIPBOTTOM)
        {
            // This is what the following code does with just a little overflow
            // protection:
            // ptmp[0] = (ymax - n) / m;

            double cx;
            for (;!overflowa;)
            {
                std::feclearexcept(FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
                cx = (ymax - n) / m;

                if (std::fetestexcept(FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO) != 0)
                {
                    overflowa = true;
                    break;
                }

                break;
            }

            // In case of an arithmetic exception we assume a vertical line and
            // keep the original x coordinate
            if (!overflowa)
                ptmp[0] = cx;

            ptmp[1] = ymax;
        }
        // Clip Left
        else if (codetmp & CLIPLEFT)
        {
            // Vertical line left outside
            if (overflowa)
            {
                ret = false;
                break;
            }

            ptmp[0] = xmin;
            ptmp[1] = m * xmin + n;
        }
        // Clip Right
        else if (codetmp & CLIPRIGHT)
        {
            // Vertical line right outside
            if (overflowa)
            {
                ret = false;
                break;
            }

            ptmp[0] = xmax;
            ptmp[1] = m * xmax + n;
        }
    }

    return ret;
}

<|endoftext|>


<commit_before>// Chemfiles, a modern library for chemistry file reading and writing
// Copyright (C) Guillaume Fraux and contributors -- BSD license

#include "chemfiles/utils.hpp"
#include "chemfiles/config.hpp"
#include "chemfiles/warnings.hpp"

#include <algorithm>

#ifdef CHEMFILES_WINDOWS
#include <windows.h>
#include <lmcons.h>
#include <direct.h>
#define getcwd _getcwd
#else
#include <unistd.h>
#include <pwd.h>
#endif

std::string chemfiles::user_name() {
#ifdef CHEMFILES_WINDOWS
    char name[UNLEN + 1];
    DWORD size = sizeof(name);
    if (!GetUserName(name, &size)) {
        return "";
    }
    return name;
#else
    auto user = getpwuid(getuid());
    return user ? user->pw_name : "";
#endif
}

std::string chemfiles::hostname() {
#ifdef CHEMFILES_WINDOWS
    char name[MAX_COMPUTERNAME_LENGTH + 1];
    DWORD size = sizeof(name);
    if (!GetComputerName(name, &size)) {
        return "";
    }
    return name;
#else
    #if defined(_POSIX_HOST_NAME_MAX)
    #define BUFFSIZE _POSIX_HOST_NAME_MAX
    #elif defined(MAXHOSTNAMELEN)
    #define BUFFSIZE MAXHOSTNAMELEN
    #else
    #define BUFFSIZE 1024
    #endif

    char name[BUFFSIZE];
    if (gethostname(name, sizeof(name))) {
        return "";
    }
    return name;
#endif
}

std::string chemfiles::current_directory() {
    // loop util buffer large enough
    for (size_t size = 128;; size *=2) {
        std::vector<char> buffer(size, '\0');
#ifdef CHEMFILES_WINDOWS
        auto result = getcwd(buffer.data(), static_cast<int>(size));
#else
        auto result = getcwd(buffer.data(), size);
#endif
        if (result == nullptr) {
            if (errno == ERANGE) {
                continue;
            } else {
                return std::string("");
            }
        }
        // Get the first null character, and stop the copy there
        auto end = std::find(buffer.begin(), buffer.end(), '\0');
        return std::string(buffer.begin(), end);
    }
}
<commit_msg>Use DNS hostname instead of NetBIOS hostname on Windows<commit_after>// Chemfiles, a modern library for chemistry file reading and writing
// Copyright (C) Guillaume Fraux and contributors -- BSD license

#include "chemfiles/utils.hpp"
#include "chemfiles/config.hpp"
#include "chemfiles/warnings.hpp"

#include <algorithm>

#ifdef CHEMFILES_WINDOWS
#include <windows.h>  // GetUserName & GetComputerNameEx
#include <direct.h>  // _getcwd
#define getcwd _getcwd
#else
#include <unistd.h>
#include <pwd.h>
#endif

std::string chemfiles::user_name() {
#ifdef CHEMFILES_WINDOWS
    char name[1024] = {0};
    DWORD size = 1024;
    if (!GetUserName(name, &size)) {
        return "";
    }
    return name;
#else
    auto user = getpwuid(getuid());
    return user ? user->pw_name : "";
#endif
}

std::string chemfiles::hostname() {
#ifdef CHEMFILES_WINDOWS
    char name[1024] = {0};
    DWORD size = 1024;
    if (!GetComputerNameEx(ComputerNameDnsHostname, name, &size)) {
        return "";
    }
    return name;
#else
    #if defined(_POSIX_HOST_NAME_MAX)
    #define BUFFSIZE _POSIX_HOST_NAME_MAX
    #elif defined(MAXHOSTNAMELEN)
    #define BUFFSIZE MAXHOSTNAMELEN
    #else
    #define BUFFSIZE 1024
    #endif

    char name[BUFFSIZE];
    if (gethostname(name, sizeof(name))) {
        return "";
    }
    return name;
#endif
}

std::string chemfiles::current_directory() {
    // loop util buffer large enough
    for (size_t size = 128;; size *=2) {
        std::vector<char> buffer(size, '\0');
#ifdef CHEMFILES_WINDOWS
        auto result = getcwd(buffer.data(), static_cast<int>(size));
#else
        auto result = getcwd(buffer.data(), size);
#endif
        if (result == nullptr) {
            if (errno == ERANGE) {
                continue;
            } else {
                return "";
            }
        }
        // Remove additional '\0' from the string
        return std::string(buffer.data());
    }
}
<|endoftext|>


<commit_before>#include "LEDClock.h"

Display *disp;
static ss_t **ss;

/**
 * SS:
 * 48, 46, 49, 47, 45, 43, 41, 39
 * 36, 34, 32, 30, 28, 26, 24, 22
 * 37, 35, 33, 31, 29, 27, 25, 23
 */
static ss_t** setupSS() {
	ss_t **ss = new ss_t*[3];
	for (int i = 0; i < 8; i++) {
		ss[i] = new ss_t[8];
	}

	// first row
	ss[0][0] = 48;
	ss[0][1] = 46;
	ss[0][2] = 49;
	ss[0][3] = 47;
	ss[0][4] = 45;
	ss[0][5] = 43;
	ss[0][6] = 41;
	ss[0][7] = 39;

	// second row
	ss[1][0] = 36;
	ss[1][1] = 34;
	ss[1][2] = 32;
	ss[1][3] = 30;
	ss[1][4] = 28;
	ss[1][5] = 26;
	ss[1][6] = 24;
	ss[1][7] = 22;

	// third row
	ss[2][0] = 37;
	ss[2][1] = 35;
	ss[2][2] = 33;
	ss[2][3] = 31;
	ss[2][4] = 29;
	ss[2][5] = 27;
	ss[2][6] = 25;
	ss[2][7] = 23;

	return ss;
}

Scrolling8x8TextArea *sca;
char *text;
void setup() {
	util_setup();
	log_setup();

	ss = setupSS();
	disp = new Display(8, 3, ss);
	disp->setup();

	sca = new Scrolling8x8TextArea(disp, 48, 100, 1);
	sca->init();
	text = "Hallo Artur i Daniel";
	sca->scroll(0, 0, true, text);
}

void loop() {
	util_cycle();
	log_cycle();
	sca->cycle();
	disp->flush();
	delay(50);
}

void loop_() {
	util_cycle();
	log_cycle();
	Static8x8TextArea sta = Static8x8TextArea(disp, 48);
//	sta.box(0, 0, 6, 68, 97, 110, 105, 101, 108);
//	disp->flush();

	for (uint8_t y = 0; y < 24; y++) {
		for (uint8_t x = 0; x < 70; x++) {
			sta.box(x, y, 6, 68, 97, 110, 105, 101, 108);
			disp->flush();
			disp->clear(x, y, 48, 8);
		}
	}
}

<commit_msg>scrolling works<commit_after>#include "LEDClock.h"

Display *disp;
static ss_t **ss;

/**
 * SS:
 * 48, 46, 49, 47, 45, 43, 41, 39
 * 36, 34, 32, 30, 28, 26, 24, 22
 * 37, 35, 33, 31, 29, 27, 25, 23
 */
static ss_t** setupSS() {
	ss_t **ss = new ss_t*[3];
	for (int i = 0; i < 8; i++) {
		ss[i] = new ss_t[8];
	}

	// first row
	ss[0][0] = 48;
	ss[0][1] = 46;
	ss[0][2] = 49;
	ss[0][3] = 47;
	ss[0][4] = 45;
	ss[0][5] = 43;
	ss[0][6] = 41;
	ss[0][7] = 39;

	// second row
	ss[1][0] = 36;
	ss[1][1] = 34;
	ss[1][2] = 32;
	ss[1][3] = 30;
	ss[1][4] = 28;
	ss[1][5] = 26;
	ss[1][6] = 24;
	ss[1][7] = 22;

	// third row
	ss[2][0] = 37;
	ss[2][1] = 35;
	ss[2][2] = 33;
	ss[2][3] = 31;
	ss[2][4] = 29;
	ss[2][5] = 27;
	ss[2][6] = 25;
	ss[2][7] = 23;

	return ss;
}

Scrolling8x8TextArea *sca1;
char *text1;

Scrolling8x8TextArea *sca2;
char *text2;

Scrolling8x8TextArea *sca3;
char *text3;

void setup() {
	util_setup();
	log_setup();

	ss = setupSS();
	disp = new Display(8, 3, ss);
	disp->setup();
	disp->clear();

	sca1 = new Scrolling8x8TextArea(disp, 64, 50, 1);
	sca1->init();
	text1 = "Danielowi i Arturkowi zyczymy Wesolych Swiat Bozego Narodzenia";
	sca1->scroll(0, 0, true, text1);

	sca2 = new Scrolling8x8TextArea(disp, 64, 0, 2);
	sca2->init();
	text2 = "Wlazl kotek na plotek i mruga - ladna to piosenka nie dluga ;)";
	sca2->scroll(0, 8, true, text2);
}

void loop() {
	util_cycle();
	log_cycle();
	sca1->cycle();
	sca2->cycle();

	disp->flush();
}

<|endoftext|>


<commit_before>/*
 * Trace.cpp
 *
 * Copyright (C) 2006 by Universitaet Stuttgart (VIS). Alle Rechte vorbehalten.
 * Copyright (C) 2005 by Christoph Mueller (christoph.mueller@vis.uni-stuttgart.de). Alle Rechte vorbehalten.
 */

#include "vislib/Trace.h"

#include <climits>
#include <ctime>
#include <stdexcept>

#include "vislib/assert.h"
#include "vislib/IllegalParamException.h"
#include "vislib/memutils.h"
#include "vislib/UnsupportedOperationException.h"

/*
 * vislib::Trace::GetInstance
 */
vislib::Trace& vislib::Trace::GetInstance(void) {
	return vislib::Trace::instance;
}

/*
 * vislib::Trace::LEVEL_ALL
 */
const UINT vislib::Trace::LEVEL_ALL = UINT_MAX;

/*
 * vislib::Trace::LEVEL_ERROR
 */
const UINT vislib::Trace::LEVEL_ERROR = 1;

/*
 * vislib::Trace::LEVEL_INFO
 */
const UINT vislib::Trace::LEVEL_INFO = 200;

/*
 * vislib::Trace::LEVEL_NONE
 */
const UINT vislib::Trace::LEVEL_NONE = 0;

/*
 * vislib::Trace::LEVEL_VL
 */
const UINT vislib::Trace::LEVEL_VL = 0x80000000;

/*
 * vislib::Trace::LEVEL_VL_ERROR
 */
const UINT vislib::Trace::LEVEL_VL_ERROR = vislib::Trace::LEVEL_VL;

/*
 * vislib::Trace::LEVEL_VL_INFO
 */
const UINT vislib::Trace::LEVEL_VL_INFO = vislib::Trace::LEVEL_VL + 200;

/*
 * vislib::Trace::LEVEL_VL_WARN
 */
const UINT vislib::Trace::LEVEL_VL_WARN = vislib::Trace::LEVEL_VL + 100;

/*
 * vislib::Trace::LEVEL_WARN
 */
const UINT vislib::Trace::LEVEL_WARN = 100;

/*
 * vislib::Trace::~Trace
 */
vislib::Trace::~Trace(void) {
    ARY_SAFE_DELETE(this->filename);

    if (this->fp != NULL) {
        ::fclose(this->fp);
        this->fp = NULL;
    }
}

/*
 * vislib::Trace::EnableDebuggerOutput
 */
bool vislib::Trace::EnableDebuggerOutput(const bool useDebugger) {
    this->useDebugger = useDebugger;
    return true;
}

/*
 * vislib::Trace::EnableFileOutput
 */
bool vislib::Trace::EnableFileOutput(const char *filename) {
    bool retval = true;

    if (filename != NULL) {
        if ((this->filename == NULL)
                || (::strcmp(this->filename, filename) != 0)) {
            ARY_SAFE_DELETE(this->filename);
            SIZE_T len = ::strlen(filename) + 1;
            this->filename = new char[len];
            ASSERT(this->filename != NULL); // std::bad_alloc should have been thrown.
            ::memcpy(this->filename, filename, len * sizeof(char));

            if (this->fp != NULL) {
                ::fclose(this->fp);
                this->fp = NULL;
            }
        }
        /*
         * 'this->filename' is new trace file, 'this->fp' is NULL or the
         * correct file is still open.
         */

        if (this->fp == NULL) {
#ifdef _WIN32
#pragma warning(disable: 4996)
#endif /* _WIN32 */
            if ((retval = ((this->fp = ::fopen(this->filename, "w")) != NULL))) {
                time_t now;
                ::time(&now);
                ::fprintf(this->fp, "Trace file opened at %s",
                    ::asctime(::localtime(&now)));
#ifdef _WIN32
#pragma warning(default: 4996)
#endif /* _WIN32 */
            }
        }

    } else {
        /* Disable tracing to file. */
        ARY_SAFE_DELETE(this->filename);

        if (this->fp != NULL) {
            ::fclose(this->fp);
            this->fp = NULL;
        }
    } /* end if (filename != NULL) */

    return retval;
}

/*
 * vislib::Trace::SetPrefix
 */
void vislib::Trace::SetPrefix(const char *prefix) {
	ARY_SAFE_DELETE(this->prefix);
	ASSERT(this->prefix == NULL);		// Ensure potential disabling.

	if (prefix != NULL) {
		SIZE_T len = ::strlen(prefix) + 1;
		this->prefix = new char[len];
		ASSERT(this->prefix != NULL);	// std::bad_alloc or OK.
		::memcpy(this->prefix, prefix, len * sizeof(char));
	}
}

/*
 * vislib::Trace::operator ()
 */
void vislib::Trace::operator ()(const UINT level, const char *fmt, ...) {
	va_list list;
	va_start(list, fmt);
	this->trace(level, fmt, list);
	va_end(list);
}

///*
// * vislib::Trace::operator ()
// */
//void vislib::Trace::operator ()(const char *fmt, ...) {
//	va_list list;
//	va_start(list, fmt);
//	this->trace(0, fmt, list);
//	va_end(list);
//}

/*
 * vislib::Trace::DEFAULT_PREFIX
 */
const char *vislib::Trace::DEFAULT_PREFIX = "TRACE: ";

/*
 * vislib::Trace::instance
 */
vislib::Trace vislib::Trace::instance;

/*
 * vislib::Trace::Trace
 */
vislib::Trace::Trace(void) : filename(NULL), fp(NULL), prefix(NULL),
        level(LEVEL_ERROR), useDebugger(true) {
#if defined(DEBUG) || defined(_DEBUG)
    this->level = LEVEL_ALL;
#endif /* defined(DEBUG) || defined(_DEBUG) */
	this->SetPrefix(DEFAULT_PREFIX);
}

/*
 * vislib::Trace::Trace
 */
vislib::Trace::Trace(const Trace& rhs) {
    throw UnsupportedOperationException("vislib::Trace::Trace", __FILE__,
        __LINE__);
}

/*
 * vislib::Trace::trace
 */
void vislib::Trace::trace(const UINT level, const char *fmt, va_list list) {
	if ((level <= this->level) && (level > 0) && (fmt != NULL)) {
		if (this->prefix != NULL) {
			::fprintf(stderr, this->prefix);
		}
        ::vfprintf(stderr, fmt, list);
		::fflush(stderr);

        if (this->fp) {
            ::vfprintf(this->fp, fmt, list);
            ::fflush(this->fp);
        }

#ifdef _WIN32
        if (this->useDebugger) {
            try {
                int cnt = ::_vscprintf(fmt, list) + 1;
                char *tmp = new char[cnt];
#if 0 || (_MSC_VER >= 1400)
                ::_vsnprintf_s(tmp, cnt, cnt, fmt, list);
#else /* (_MSC_VER >= 1400) */
                ::vsnprintf(tmp, cnt, fmt, list);
#endif /* (_MSC_VER >= 1400) */

                ::OutputDebugStringA(tmp);
                ARY_SAFE_DELETE(tmp);
            } catch (std::bad_alloc) {
                ::fprintf(stderr, "OutputDebugStringA failed because of "
                    "insufficient system memory\n");
		        ::fflush(stderr);
            }
        }
#endif /* _WIN32 */
	}
}

/*
 * vislib::Trace::operator =
 */
vislib::Trace& vislib::Trace::operator =(const vislib::Trace &rhs) {
    if (this != &rhs) {
        throw IllegalParamException("rhs", __FILE__, __LINE__);
    }

    return *this;
}
<commit_msg>Missing throw() added.<commit_after>/*
 * Trace.cpp
 *
 * Copyright (C) 2006 by Universitaet Stuttgart (VIS). Alle Rechte vorbehalten.
 * Copyright (C) 2005 by Christoph Mueller (christoph.mueller@vis.uni-stuttgart.de). Alle Rechte vorbehalten.
 */

#include "vislib/Trace.h"

#include <climits>
#include <ctime>
#include <stdexcept>

#include "vislib/assert.h"
#include "vislib/IllegalParamException.h"
#include "vislib/memutils.h"
#include "vislib/UnsupportedOperationException.h"

/*
 * vislib::Trace::GetInstance
 */
vislib::Trace& vislib::Trace::GetInstance(void) {
	return vislib::Trace::instance;
}

/*
 * vislib::Trace::LEVEL_ALL
 */
const UINT vislib::Trace::LEVEL_ALL = UINT_MAX;

/*
 * vislib::Trace::LEVEL_ERROR
 */
const UINT vislib::Trace::LEVEL_ERROR = 1;

/*
 * vislib::Trace::LEVEL_INFO
 */
const UINT vislib::Trace::LEVEL_INFO = 200;

/*
 * vislib::Trace::LEVEL_NONE
 */
const UINT vislib::Trace::LEVEL_NONE = 0;

/*
 * vislib::Trace::LEVEL_VL
 */
const UINT vislib::Trace::LEVEL_VL = 0x80000000;

/*
 * vislib::Trace::LEVEL_VL_ERROR
 */
const UINT vislib::Trace::LEVEL_VL_ERROR = vislib::Trace::LEVEL_VL;

/*
 * vislib::Trace::LEVEL_VL_INFO
 */
const UINT vislib::Trace::LEVEL_VL_INFO = vislib::Trace::LEVEL_VL + 200;

/*
 * vislib::Trace::LEVEL_VL_WARN
 */
const UINT vislib::Trace::LEVEL_VL_WARN = vislib::Trace::LEVEL_VL + 100;

/*
 * vislib::Trace::LEVEL_WARN
 */
const UINT vislib::Trace::LEVEL_WARN = 100;

/*
 * vislib::Trace::~Trace
 */
vislib::Trace::~Trace(void) {
    ARY_SAFE_DELETE(this->filename);

    if (this->fp != NULL) {
        ::fclose(this->fp);
        this->fp = NULL;
    }
}

/*
 * vislib::Trace::EnableDebuggerOutput
 */
bool vislib::Trace::EnableDebuggerOutput(const bool useDebugger) {
    this->useDebugger = useDebugger;
    return true;
}

/*
 * vislib::Trace::EnableFileOutput
 */
bool vislib::Trace::EnableFileOutput(const char *filename) {
    bool retval = true;

    if (filename != NULL) {
        if ((this->filename == NULL)
                || (::strcmp(this->filename, filename) != 0)) {
            ARY_SAFE_DELETE(this->filename);
            SIZE_T len = ::strlen(filename) + 1;
            this->filename = new char[len];
            ASSERT(this->filename != NULL); // std::bad_alloc should have been thrown.
            ::memcpy(this->filename, filename, len * sizeof(char));

            if (this->fp != NULL) {
                ::fclose(this->fp);
                this->fp = NULL;
            }
        }
        /*
         * 'this->filename' is new trace file, 'this->fp' is NULL or the
         * correct file is still open.
         */

        if (this->fp == NULL) {
#ifdef _WIN32
#pragma warning(disable: 4996)
#endif /* _WIN32 */
            if ((retval = ((this->fp = ::fopen(this->filename, "w")) != NULL))) {
                time_t now;
                ::time(&now);
                ::fprintf(this->fp, "Trace file opened at %s",
                    ::asctime(::localtime(&now)));
#ifdef _WIN32
#pragma warning(default: 4996)
#endif /* _WIN32 */
            }
        }

    } else {
        /* Disable tracing to file. */
        ARY_SAFE_DELETE(this->filename);

        if (this->fp != NULL) {
            ::fclose(this->fp);
            this->fp = NULL;
        }
    } /* end if (filename != NULL) */

    return retval;
}

/*
 * vislib::Trace::SetPrefix
 */
void vislib::Trace::SetPrefix(const char *prefix) {
	ARY_SAFE_DELETE(this->prefix);
	ASSERT(this->prefix == NULL);		// Ensure potential disabling.

	if (prefix != NULL) {
		SIZE_T len = ::strlen(prefix) + 1;
		this->prefix = new char[len];
		ASSERT(this->prefix != NULL);	// std::bad_alloc or OK.
		::memcpy(this->prefix, prefix, len * sizeof(char));
	}
}

/*
 * vislib::Trace::operator ()
 */
void vislib::Trace::operator ()(const UINT level, const char *fmt, ...)
        throw() {
	va_list list;
	va_start(list, fmt);
	this->trace(level, fmt, list);
	va_end(list);
}

///*
// * vislib::Trace::operator ()
// */
//void vislib::Trace::operator ()(const char *fmt, ...) {
//	va_list list;
//	va_start(list, fmt);
//	this->trace(0, fmt, list);
//	va_end(list);
//}

/*
 * vislib::Trace::DEFAULT_PREFIX
 */
const char *vislib::Trace::DEFAULT_PREFIX = "TRACE: ";

/*
 * vislib::Trace::instance
 */
vislib::Trace vislib::Trace::instance;

/*
 * vislib::Trace::Trace
 */
vislib::Trace::Trace(void) : filename(NULL), fp(NULL), prefix(NULL),
        level(LEVEL_ERROR), useDebugger(true) {
#if defined(DEBUG) || defined(_DEBUG)
    this->level = LEVEL_ALL;
#endif /* defined(DEBUG) || defined(_DEBUG) */
	this->SetPrefix(DEFAULT_PREFIX);
}

/*
 * vislib::Trace::Trace
 */
vislib::Trace::Trace(const Trace& rhs) {
    throw UnsupportedOperationException("vislib::Trace::Trace", __FILE__,
        __LINE__);
}

/*
 * vislib::Trace::trace
 */
void vislib::Trace::trace(const UINT level, const char *fmt, va_list list)
        throw() {
	if ((level <= this->level) && (level > 0) && (fmt != NULL)) {
		if (this->prefix != NULL) {
			::fprintf(stderr, this->prefix);
		}
        ::vfprintf(stderr, fmt, list);
		::fflush(stderr);

        if (this->fp) {
            ::vfprintf(this->fp, fmt, list);
            ::fflush(this->fp);
        }

#ifdef _WIN32
        if (this->useDebugger) {
            try {
                int cnt = ::_vscprintf(fmt, list) + 1;
                char *tmp = new char[cnt];
#if 0 || (_MSC_VER >= 1400)
                ::_vsnprintf_s(tmp, cnt, cnt, fmt, list);
#else /* (_MSC_VER >= 1400) */
                ::vsnprintf(tmp, cnt, fmt, list);
#endif /* (_MSC_VER >= 1400) */

                ::OutputDebugStringA(tmp);
                ARY_SAFE_DELETE(tmp);
            } catch (std::bad_alloc) {
                ::fprintf(stderr, "OutputDebugStringA failed because of "
                    "insufficient system memory\n");
		        ::fflush(stderr);
            }
        }
#endif /* _WIN32 */
	}
}

/*
 * vislib::Trace::operator =
 */
vislib::Trace& vislib::Trace::operator =(const vislib::Trace &rhs) {
    if (this != &rhs) {
        throw IllegalParamException("rhs", __FILE__, __LINE__);
    }

    return *this;
}
<|endoftext|>


<commit_before>/** \brief Detect missing references in title data records
 *  \author Johannes Riedl
 *
 *  \copyright 2019-2020 Universitätsbibliothek Tübingen.  All rights reserved.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program 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 Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <iostream>
#include <unordered_map>
#include <cstdio>
#include <cstdlib>
#include "Compiler.h"
#include "FileUtil.h"
#include "StringUtil.h"
#include "MARC.h"
#include "util.h"

namespace {

static  const std::vector<MARC::Tag> REFERENCE_FIELDS{ MARC::Tag("775"), MARC::Tag("776"), MARC::Tag("780"),
                                                       MARC::Tag("785"), MARC::Tag("787") };

[[noreturn]] void Usage() {
    std::cerr << "Usage: " << ::progname << " [--patch-to-k10plus] marc_input dangling_log k10plus_concordance\n\n";
    std::exit(EXIT_FAILURE);
}

} // unnamed namespace

void CollectAllPPNs(MARC::Reader * const reader, std::unordered_set<std::string> * const all_ppns) {
   while (const auto record = reader->read())
      all_ppns->emplace(record.getControlNumber());
}

inline bool IsPartOfTitleData(const std::unordered_set<std::string> &all_ppns, const std::string &referenced_ppn) {
    return all_ppns.find(referenced_ppn) != all_ppns.cend();
}

void CheckCrossReferences(MARC::Reader * const reader, const std::unordered_set<std::string> &all_ppns,
                          std::unique_ptr<File> &dangling_log, bool patch_to_k10plus, std::unordered_map<std::string, std::string> &concordance_map) {
     int unreferenced_ppns(0);
     while (const auto record = reader->read()) {
        for (auto &field : record) {
            std::string referenced_ppn;
            if (MARC::IsCrossLinkField(field, &referenced_ppn, REFERENCE_FIELDS)) {
                if (not IsPartOfTitleData(all_ppns, referenced_ppn)) {
                    std::string ppn = record.getControlNumber();
                    if (patch_to_k10plus) {
                        auto new_ppn = concordance_map.find(ppn);
                        if (new_ppn == concordance_map.end())
                            LOG_ERROR("Could not find K10plus-PPN for PPN " + ppn);
                        auto new_referenced_ppn = concordance_map.find(referenced_ppn);
                        if (new_referenced_ppn == concordance_map.end()) {
                            LOG_WARNING("Could not find K10plus-PPN for referenced PPN " + referenced_ppn + " [PPN: " + ppn + "]");
                            *dangling_log << new_ppn->second << ", K10+ PPN DOES NOT EXIST FOR \"" << referenced_ppn + "\"\n";
                        }
                        *dangling_log << new_ppn->second << "," << new_referenced_ppn->second << '\n';
                    } else
                        *dangling_log << ppn << "," << referenced_ppn << '\n';

                    ++unreferenced_ppns;
                }
            }
        }
     }
     LOG_INFO("Detected " + std::to_string(unreferenced_ppns) + " unreferenced ppns");
}

void PopulateConcordanceMap(std::unique_ptr<File> &concordance_file, std::unordered_map<std::string, std::string> * const concordance_map) {
     unsigned int line_no(0);
     while (not concordance_file->eof()) {
         ++line_no;
         std::string line, old_val, new_val;
         concordance_file->getline(&line);
         if (not StringUtil::SplitOnString(line, " " , &old_val, &new_val))
             LOG_ERROR("Could not properly split line \"" + line + "\"");
         if (old_val.length() > 9 or new_val.length() > 10)
             LOG_ERROR("Invalid line " + std::to_string(line_no) + " in \"" + concordance_file->getPath() + "\"");
         (*concordance_map)[old_val] = new_val;
     }
     LOG_INFO("We read " + std::to_string(line_no) + " mappings from " + concordance_file->getPath());
}

int Main(int argc, char *argv[]) {
    bool patch_to_k10plus(false);

    if (argc != 3 and argc !=5)
        Usage();

    if (argc == 5) {
        if (std::strcmp(argv[1], "--patch-to-k10plus") != 0)
            Usage();
        patch_to_k10plus = true;
        ++argv;
        --argc;
    }

    auto marc_reader(MARC::Reader::Factory(argv[1]));

    std::unique_ptr<File> dangling_log;
    dangling_log = FileUtil::OpenOutputFileOrDie(argv[2]);

    std::unordered_map<std::string, std::string> swb_to_k10plus_map;
    if (patch_to_k10plus) {
        std::unique_ptr<File> swb_to_k10plus_file;
        swb_to_k10plus_file = FileUtil::OpenInputFileOrDie(argv[3]);
        PopulateConcordanceMap(swb_to_k10plus_file, &swb_to_k10plus_map);
    }

    std::unordered_set<std::string> all_ppns;
    CollectAllPPNs(marc_reader.get(), &all_ppns);
    marc_reader->rewind();
    CheckCrossReferences(marc_reader.get(), all_ppns, dangling_log, patch_to_k10plus, swb_to_k10plus_map);

    return EXIT_SUCCESS;
}
<commit_msg>Updated.<commit_after>/** \brief Detect missing references in title data records
 *  \author Johannes Riedl
 *
 *  \copyright 2019-2020 Universitätsbibliothek Tübingen.  All rights reserved.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program 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 Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <iostream>
#include <unordered_map>
#include <cstdio>
#include <cstdlib>
#include "Compiler.h"
#include "FileUtil.h"
#include "StringUtil.h"
#include "MARC.h"
#include "util.h"

namespace {

[[noreturn]] void Usage() {
    ::Usage("[--consider-only-reviews] marc_input dangling_log");
}

void CollectAllPPNs(MARC::Reader * const reader, std::unordered_set<std::string> * const all_ppns) {
   while (const auto record = reader->read())
      all_ppns->emplace(record.getControlNumber());
}

inline bool IsPartOfTitleData(const std::unordered_set<std::string> &all_ppns, const std::string &referenced_ppn) {
    return all_ppns.find(referenced_ppn) != all_ppns.cend();
}

const std::vector<MARC::Tag> REFERENCE_FIELDS{ MARC::Tag("775"), MARC::Tag("776"), MARC::Tag("780"),
                                               MARC::Tag("785"), MARC::Tag("787") };

void FindDanglingCrossReferences(MARC::Reader * const reader, const bool consider_only_reviews,
                                 const std::unordered_set<std::string> &all_ppns, File * const dangling_log)
{
     unsigned unreferenced_ppns(0);
     while (const auto record = reader->read()) {
        for (const auto &field : record) {
            std::string referenced_ppn;
            if ((not consider_only_reviews or record.isReviewArticle())
                and MARC::IsCrossLinkField(field, &referenced_ppn, REFERENCE_FIELDS)
                and not IsPartOfTitleData(all_ppns, referenced_ppn))
            {
                *dangling_log << record.getControlNumber() << "," << referenced_ppn << '\n';
                ++unreferenced_ppns;
            }
        }
     }
     LOG_INFO("Detected " + std::to_string(unreferenced_ppns) + " unreferenced ppns");
}

} // unnamed namespace

int Main(int argc, char *argv[]) {
    if (argc != 3 and argc != 4)
        Usage();

    bool consider_only_reviews(false);
    if (__builtin_strcmp(argv[1], "--consider-only-reviews") == 0) {
        consider_only_reviews = true;
        --argc, ++argv;
    }
    if (argc != 3)
        Usage();

    auto marc_reader(MARC::Reader::Factory(argv[1]));
    const auto dangling_log(FileUtil::OpenOutputFileOrDie(argv[2]));

    std::unordered_set<std::string> all_ppns;
    CollectAllPPNs(marc_reader.get(), &all_ppns);

    marc_reader->rewind();
    FindDanglingCrossReferences(marc_reader.get(), consider_only_reviews, all_ppns, dangling_log.get());

    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before><commit_msg>add:1114 print in order<commit_after><|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: scanner.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: hr $ $Date: 2001-11-02 10:50:21 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _EXT_SCANNER_HXX
#define _EXT_SCANNER_HXX

#ifndef _STREAM_HXX
#include <tools/stream.hxx>
#endif
#ifndef _VOS_MUTEX_HXX_
#include <vos/mutex.hxx>
#endif
#ifndef __RTL_USTRING_
#include <rtl/ustring>
#endif
#ifndef _CPPUHELPER_WEAK_HXX_
#include <cppuhelper/weak.hxx>
#endif
#ifndef _CPPUHELPER_WEAK_HXX_
#include <cppuhelper/weak.hxx>
#endif
#ifndef _COM_SUN_STAR_UNO_REFERENCE_H_
#include <com/sun/star/uno/Reference.h>
#endif
#ifndef _COM_SUN_STAR_UNO_SEQUENCE_H_
#include <com/sun/star/uno/Sequence.h>
#endif
#ifndef __COM_SUN_STAR_AWT_XBITMAP_HPP
#include <com/sun/star/awt/XBitmap.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XEVENTLISTENER_HPP_
#include <com/sun/star/lang/XEventListener.hpp>
#endif
#ifndef __COM_SUN_STAR_LANG_EVENTOBJECT_HPP
#include <com/sun/star/lang/EventObject.hpp>
#endif
#ifndef _COM_SUN_STAR_SCANNER_XSCANNERMANAGER_HPP_
#include <com/sun/star/scanner/XScannerManager.hpp>
#endif
#ifndef _COM_SUN_STAR_SCANNER_SCANNEREXCEPTION_HPP_
#include <com/sun/star/scanner/ScannerException.hpp>
#endif

using namespace rtl;
using namespace cppu;
using namespace com::sun::star::uno;
using namespace com::sun::star::scanner;

// -----------
// - Defines -
// -----------

#define REF( _def_Obj )                     Reference< _def_Obj >
#define SEQ( _def_Obj )                     Sequence< _def_Obj >
#define ANY                                 Any
#define AWT                                 com::sun::star::awt

// ------------------
// - ScannerManager -
// ------------------

class ScannerManager : public OWeakObject, XScannerManager, AWT::XBitmap
{
protected:

    vos::OMutex                             maProtector;
    void*                                   mpData;

    void                                    DestroyData();

public:

                                            ScannerManager();
    virtual                                 ~ScannerManager();

    // XInterface
    virtual ANY SAL_CALL                    queryInterface( const Type & rType ) throw( RuntimeException );
    virtual void SAL_CALL                   acquire() throw();
    virtual void SAL_CALL                   release() throw();

    // XScannerManager
    virtual SEQ( ScannerContext ) SAL_CALL  getAvailableScanners() throw();
    virtual BOOL SAL_CALL                   configureScanner( ScannerContext& scanner_context ) throw( ScannerException );
    virtual void SAL_CALL                   startScan( const ScannerContext& scanner_context, const REF( com::sun::star::lang::XEventListener )& rxListener ) throw( ScannerException );
    virtual ScanError SAL_CALL              getError( const ScannerContext& scanner_context ) throw( ScannerException );
    virtual REF( AWT::XBitmap ) SAL_CALL    getBitmap( const ScannerContext& scanner_context ) throw( ScannerException );

    // XBitmap
    virtual AWT::Size SAL_CALL              getSize() throw();
    virtual SEQ( sal_Int8 ) SAL_CALL        getDIB() throw();
    virtual SEQ( sal_Int8 ) SAL_CALL        getMaskDIB() throw();

    // Misc
    OUString                                getImplementationName() throw();
    static OUString                         getImplementationName_Static() throw();
    Sequence< OUString >                    getSupportedServiceNames() throw();
    static Sequence< OUString >             getSupportedServiceNames_Static() throw();
    BOOL                                    supportsService( const OUString& ServiceName ) throw();

    void                                    Lock() { maProtector.acquire(); }
    void                                    Unlock() { maProtector.release(); }

    void*                                   GetData() const { return mpData; }
    void                                    SetData( void* pData ) { DestroyData(); mpData = pData; }
};

// -----------------------------------------------------------------------------

REF( XInterface ) SAL_CALL ScannerManager_CreateInstance( const REF( com::sun::star::lang::XMultiServiceFactory )& rxFactory ) throw( Exception );

#endif
<commit_msg>INTEGRATION: CWS ooo19126 (1.3.580); FILE MERGED 2005/09/05 13:01:01 rt 1.3.580.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: scanner.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 20:38:44 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _EXT_SCANNER_HXX
#define _EXT_SCANNER_HXX

#ifndef _STREAM_HXX
#include <tools/stream.hxx>
#endif
#ifndef _VOS_MUTEX_HXX_
#include <vos/mutex.hxx>
#endif
#ifndef __RTL_USTRING_
#include <rtl/ustring>
#endif
#ifndef _CPPUHELPER_WEAK_HXX_
#include <cppuhelper/weak.hxx>
#endif
#ifndef _CPPUHELPER_WEAK_HXX_
#include <cppuhelper/weak.hxx>
#endif
#ifndef _COM_SUN_STAR_UNO_REFERENCE_H_
#include <com/sun/star/uno/Reference.h>
#endif
#ifndef _COM_SUN_STAR_UNO_SEQUENCE_H_
#include <com/sun/star/uno/Sequence.h>
#endif
#ifndef __COM_SUN_STAR_AWT_XBITMAP_HPP
#include <com/sun/star/awt/XBitmap.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XEVENTLISTENER_HPP_
#include <com/sun/star/lang/XEventListener.hpp>
#endif
#ifndef __COM_SUN_STAR_LANG_EVENTOBJECT_HPP
#include <com/sun/star/lang/EventObject.hpp>
#endif
#ifndef _COM_SUN_STAR_SCANNER_XSCANNERMANAGER_HPP_
#include <com/sun/star/scanner/XScannerManager.hpp>
#endif
#ifndef _COM_SUN_STAR_SCANNER_SCANNEREXCEPTION_HPP_
#include <com/sun/star/scanner/ScannerException.hpp>
#endif

using namespace rtl;
using namespace cppu;
using namespace com::sun::star::uno;
using namespace com::sun::star::scanner;

// -----------
// - Defines -
// -----------

#define REF( _def_Obj )                     Reference< _def_Obj >
#define SEQ( _def_Obj )                     Sequence< _def_Obj >
#define ANY                                 Any
#define AWT                                 com::sun::star::awt

// ------------------
// - ScannerManager -
// ------------------

class ScannerManager : public OWeakObject, XScannerManager, AWT::XBitmap
{
protected:

    vos::OMutex                             maProtector;
    void*                                   mpData;

    void                                    DestroyData();

public:

                                            ScannerManager();
    virtual                                 ~ScannerManager();

    // XInterface
    virtual ANY SAL_CALL                    queryInterface( const Type & rType ) throw( RuntimeException );
    virtual void SAL_CALL                   acquire() throw();
    virtual void SAL_CALL                   release() throw();

    // XScannerManager
    virtual SEQ( ScannerContext ) SAL_CALL  getAvailableScanners() throw();
    virtual BOOL SAL_CALL                   configureScanner( ScannerContext& scanner_context ) throw( ScannerException );
    virtual void SAL_CALL                   startScan( const ScannerContext& scanner_context, const REF( com::sun::star::lang::XEventListener )& rxListener ) throw( ScannerException );
    virtual ScanError SAL_CALL              getError( const ScannerContext& scanner_context ) throw( ScannerException );
    virtual REF( AWT::XBitmap ) SAL_CALL    getBitmap( const ScannerContext& scanner_context ) throw( ScannerException );

    // XBitmap
    virtual AWT::Size SAL_CALL              getSize() throw();
    virtual SEQ( sal_Int8 ) SAL_CALL        getDIB() throw();
    virtual SEQ( sal_Int8 ) SAL_CALL        getMaskDIB() throw();

    // Misc
    OUString                                getImplementationName() throw();
    static OUString                         getImplementationName_Static() throw();
    Sequence< OUString >                    getSupportedServiceNames() throw();
    static Sequence< OUString >             getSupportedServiceNames_Static() throw();
    BOOL                                    supportsService( const OUString& ServiceName ) throw();

    void                                    Lock() { maProtector.acquire(); }
    void                                    Unlock() { maProtector.release(); }

    void*                                   GetData() const { return mpData; }
    void                                    SetData( void* pData ) { DestroyData(); mpData = pData; }
};

// -----------------------------------------------------------------------------

REF( XInterface ) SAL_CALL ScannerManager_CreateInstance( const REF( com::sun::star::lang::XMultiServiceFactory )& rxFactory ) throw( Exception );

#endif
<|endoftext|>