<commit_before>/*
 Copyright (C) 2011 by Ivan Safrin

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
*/

#include "OSBasics.h"
#ifdef _WINDOWS
	#include <windows.h>
#else
	#include <dirent.h>
	#include <sys/types.h>
	#include <sys/stat.h>
#endif

#include <vector>
#include <string>
#include "physfs.h"

using namespace std;
using namespace Polycode;

#ifdef _WINDOWS

void wtoc(char* Dest, const WCHAR* Source)
{
	int i = 0;
	while(Source[i] != '\0') {
		Dest[i] = (char)Source[i];
		++i;
	}
}
void ctow(WCHAR* Dest, const char* Source)
{
	int i = 0;
	while(Source[i] != '\0') {
		Dest[i] = (WCHAR)Source[i];
		++i;
	}
}

#endif

OSFileEntry::OSFileEntry(const Polycode::String& fullPath, int type) {
	std::vector<String> parts = fullPath.split("/");

	if(parts.size() > 0) {
		String path = parts[0];

		if(parts.size() > 1) {
			for(int i=1; i < parts.size()-1; i++) {
				path += "/" + parts[i];
			}
			init(path, parts[parts.size()-1], type);
		}
	} else {
		init("", fullPath, type);
	}

}

OSFileEntry::OSFileEntry(const String& path, const String& name, int type) {
	init(path, name, type);
}

void OSFileEntry::init(const Polycode::String& path, const Polycode::String& name, int type) {
	this->basePath = path;

	if(path == "/") {
		this->fullPath = "/" + name;
	} else {
		this->fullPath = path + "/" + name;
	}
	this->name = name;
	this->type = type;

	size_t found;
	found=this->name.rfind(".");
	if (found!=string::npos) {
		extension = this->name.substr(found+1);
		nameWithoutExtension = this->name.substr(0, found);
	} else {
		extension = "";
		nameWithoutExtension = name;
	}

}

void OSFILE::debugDump() {
	long tellval = OSBasics::tell(this);
	OSBasics::seek(this, 0, SEEK_SET);

	char buffer;
	while(OSBasics::read(&buffer, 1, 1, this)) {
		printf("%c", buffer);
	}

	OSBasics::seek(this, tellval, SEEK_SET);
}

OSFILE *OSBasics::open(const String& filename, const String& opts) {
	OSFILE *retFile = NULL;
	if(PHYSFS_exists(filename.c_str())) {
		if(!PHYSFS_isDirectory(filename.c_str())) {
			retFile = new OSFILE;
			retFile->fileType = OSFILE::TYPE_ARCHIVE_FILE;
			if(opts.find("a") !=string::npos) {
				retFile->physFSFile = PHYSFS_openAppend(filename.c_str());
				if(!retFile->physFSFile){
					printf("Error opening file from archive (%s)\n", filename.c_str());
					return NULL;
				}
			} else if(opts.find("w") !=string::npos) {
				retFile->physFSFile = PHYSFS_openWrite(filename.c_str());
				if(!retFile->physFSFile){
					printf("Error opening file from archive (%s)\n", filename.c_str());
					return NULL;
				}
			} else {
				retFile->physFSFile = PHYSFS_openRead(filename.c_str());
				if(!retFile->physFSFile){
					printf("Error opening file from archive (%s)\n", filename.c_str());
					return NULL;
				}
			}
			return retFile;
		}
	} else {
//		Logger::log("File doesn't exist in archive (%s)\n", filename.c_str());
	}

	FILE *file = fopen(filename.c_str(), opts.c_str());
	if(file) {
		retFile = new OSFILE;
		retFile->fileType = OSFILE::TYPE_FILE;
		retFile->file = file;
		return retFile;
	}

	return NULL;
}

int OSBasics::close(OSFILE *file) {
	int result = 0;
	switch(file->fileType) {
		case OSFILE::TYPE_FILE:
			result = fclose(file->file);
			break;
		case OSFILE::TYPE_ARCHIVE_FILE:
			result = PHYSFS_close(file->physFSFile);
			break;
	}
	delete file;
	return result;
}

long OSBasics::tell(OSFILE * stream) {
	switch(stream->fileType) {
		case OSFILE::TYPE_FILE:
			return ftell(stream->file);
			break;
		case OSFILE::TYPE_ARCHIVE_FILE:
			return PHYSFS_tell(stream->physFSFile);
			break;
	}
	return 0;
}

size_t OSBasics::read( void * ptr, size_t size, size_t count, OSFILE * stream ) {
	switch(stream->fileType) {
		case OSFILE::TYPE_FILE:
			return fread(ptr, size, count, stream->file);
		break;
		case OSFILE::TYPE_ARCHIVE_FILE:
			return PHYSFS_read(stream->physFSFile, ptr, size, count);
		break;
	}
	return 0;
}

size_t OSBasics::write( const void * ptr, size_t size, size_t count, OSFILE * stream ) {
	switch(stream->fileType) {
		case OSFILE::TYPE_FILE:
			fwrite(ptr, size, count, stream->file);
			break;
		case OSFILE::TYPE_ARCHIVE_FILE:
			PHYSFS_write(stream->physFSFile, ptr, size, count);
		break;
	}
	return 0;
}

int OSBasics::seek(OSFILE * stream, long int offset, int origin ) {
	switch(stream->fileType) {
		case OSFILE::TYPE_FILE:
			return fseek(stream->file, offset, origin);
			break;
		case OSFILE::TYPE_ARCHIVE_FILE:
			switch(origin) {
				case SEEK_SET:
					return PHYSFS_seek(stream->physFSFile, offset);
				break;
				case SEEK_CUR: {
					PHYSFS_sint64 curoffset = PHYSFS_tell(stream->physFSFile);
					return PHYSFS_seek(stream->physFSFile, curoffset+offset);
				}
				break;
				case SEEK_END: {
					PHYSFS_sint64 fileLength =  PHYSFS_fileLength(stream->physFSFile);
					return PHYSFS_seek(stream->physFSFile, fileLength-offset);
				}
				break;
			}
			break;
	}
	return 0;
}

vector<OSFileEntry> OSBasics::parsePhysFSFolder(const String& pathString, bool showHidden) {
	vector<OSFileEntry> returnVector;

	char **rc = PHYSFS_enumerateFiles(pathString.c_str());
	char **i;

	String fullPath;
	String fname;
	for (i = rc; *i != NULL; i++) {
		fname = string(*i);
		fullPath = pathString + "/" + fname;
		if((fname.c_str()[0] != '.' || (fname.c_str()[0] == '.'  && showHidden)) && fname != "..") {
			if(PHYSFS_isDirectory(fullPath.c_str())) {
				returnVector.push_back(OSFileEntry(pathString, fname, OSFileEntry::TYPE_FOLDER));
			} else {
				returnVector.push_back(OSFileEntry(pathString, fname, OSFileEntry::TYPE_FILE));
			}
		}
	}
	PHYSFS_freeList(rc);
	return returnVector;
}

vector<OSFileEntry> OSBasics::parseFolder(const String& pathString, bool showHidden) {
	vector<OSFileEntry> returnVector;

	if(pathString != "/") {
	if(pathString.size() < 128) {
		if(PHYSFS_exists(pathString.c_str())) {
			if(PHYSFS_isDirectory(pathString.c_str())) {
				return parsePhysFSFolder(pathString, showHidden);
			}
		}
	}
	}

#ifdef _WINDOWS

	WIN32_FIND_DATA findFileData;

	WCHAR curDir[4096];
	GetCurrentDirectory(4096, curDir);

	WCHAR tmp[4096];
	memset(tmp, 0, sizeof(WCHAR)*4096);
	ctow(tmp, pathString.c_str());

	DWORD dwAttrib = GetFileAttributes(tmp);
  if(! (dwAttrib != INVALID_FILE_ATTRIBUTES &&
         (dwAttrib & FILE_ATTRIBUTE_DIRECTORY))) {
		return returnVector;
  }

	SetCurrentDirectory(tmp);

	HANDLE hFind = FindFirstFile((LPCWSTR)"*", &findFileData);
	if(hFind  == INVALID_HANDLE_VALUE) {
		SetCurrentDirectory(curDir);
		return returnVector;
	}

	char fileName[260];
	do {
		memset(fileName, 0, 260);
		wtoc(fileName, findFileData.cFileName);
		String fname = string(fileName);

		if((fname.c_str()[0] != '.' || (fname.c_str()[0] == '.'  && showHidden)) && fname != "..") {
			if( findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
				returnVector.push_back(OSFileEntry(pathString, fname, OSFileEntry::TYPE_FOLDER));
			} else {
				returnVector.push_back(OSFileEntry(pathString, fname, OSFileEntry::TYPE_FILE));
			}
		}
    } while(FindNextFile(hFind, &findFileData));
	FindClose(hFind);
	SetCurrentDirectory(curDir);
#else
	DIR           *d;
	struct dirent *dir;

	d = opendir(pathString.c_str());
	if(d) {
		while ((dir = readdir(d)) != NULL) {
			if(dir->d_name[0] != '.' || (dir->d_name[0] == '.'  && showHidden)) {
				if(dir->d_type == DT_DIR) {
					returnVector.push_back(OSFileEntry(pathString, dir->d_name, OSFileEntry::TYPE_FOLDER));
				} else {
					returnVector.push_back(OSFileEntry(pathString, dir->d_name, OSFileEntry::TYPE_FILE));
				}
			}
		}
		closedir(d);
	}

#endif

	return returnVector;
}

void OSBasics::removeItem(const String& pathString) {
#ifdef _WINDOWS
#else
	remove(pathString.c_str());
#endif
}

void OSBasics::createFolder(const String& pathString) {
#ifdef _WINDOWS
#else
	mkdir(pathString.c_str(),  S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
#endif
}

bool OSBasics::isFolder(const String& pathString) {
	bool retVal = false;
#ifdef _WINDOWS
#else
	DIR           *d;

	d = opendir(pathString.c_str());
	if(d) {
		retVal = true;
		closedir(d);
	}
#endif
	return retVal;
}
<commit_msg>Implemented Windows OSBasics stuff<commit_after>/*
 Copyright (C) 2011 by Ivan Safrin

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
*/

#include "OSBasics.h"
#ifdef _WINDOWS
	#include <windows.h>
	#include <Shellapi.h>
#else
	#include <dirent.h>
	#include <sys/types.h>
	#include <sys/stat.h>
#endif

#include <vector>
#include <string>
#include "physfs.h"

using namespace std;
using namespace Polycode;

#ifdef _WINDOWS

void wtoc(char* Dest, const WCHAR* Source)
{
	int i = 0;
	while(Source[i] != '\0') {
		Dest[i] = (char)Source[i];
		++i;
	}
}
void ctow(WCHAR* Dest, const char* Source)
{
	int i = 0;
	while(Source[i] != '\0') {
		Dest[i] = (WCHAR)Source[i];
		++i;
	}
}

#endif

OSFileEntry::OSFileEntry(const Polycode::String& fullPath, int type) {
	std::vector<String> parts = fullPath.split("/");

	if(parts.size() > 0) {
		String path = parts[0];

		if(parts.size() > 1) {
			for(int i=1; i < parts.size()-1; i++) {
				path += "/" + parts[i];
			}
			init(path, parts[parts.size()-1], type);
		}
	} else {
		init("", fullPath, type);
	}

}

OSFileEntry::OSFileEntry(const String& path, const String& name, int type) {
	init(path, name, type);
}

void OSFileEntry::init(const Polycode::String& path, const Polycode::String& name, int type) {
	this->basePath = path;

	if(path == "/") {
		this->fullPath = "/" + name;
	} else {
		this->fullPath = path + "/" + name;
	}
	this->name = name;
	this->type = type;

	size_t found;
	found=this->name.rfind(".");
	if (found!=string::npos) {
		extension = this->name.substr(found+1);
		nameWithoutExtension = this->name.substr(0, found);
	} else {
		extension = "";
		nameWithoutExtension = name;
	}

}

void OSFILE::debugDump() {
	long tellval = OSBasics::tell(this);
	OSBasics::seek(this, 0, SEEK_SET);

	char buffer;
	while(OSBasics::read(&buffer, 1, 1, this)) {
		printf("%c", buffer);
	}

	OSBasics::seek(this, tellval, SEEK_SET);
}

OSFILE *OSBasics::open(const String& filename, const String& opts) {
	OSFILE *retFile = NULL;
	if(PHYSFS_exists(filename.c_str())) {
		if(!PHYSFS_isDirectory(filename.c_str())) {
			retFile = new OSFILE;
			retFile->fileType = OSFILE::TYPE_ARCHIVE_FILE;
			if(opts.find("a") !=string::npos) {
				retFile->physFSFile = PHYSFS_openAppend(filename.c_str());
				if(!retFile->physFSFile){
					printf("Error opening file from archive (%s)\n", filename.c_str());
					return NULL;
				}
			} else if(opts.find("w") !=string::npos) {
				retFile->physFSFile = PHYSFS_openWrite(filename.c_str());
				if(!retFile->physFSFile){
					printf("Error opening file from archive (%s)\n", filename.c_str());
					return NULL;
				}
			} else {
				retFile->physFSFile = PHYSFS_openRead(filename.c_str());
				if(!retFile->physFSFile){
					printf("Error opening file from archive (%s)\n", filename.c_str());
					return NULL;
				}
			}
			return retFile;
		}
	} else {
//		Logger::log("File doesn't exist in archive (%s)\n", filename.c_str());
	}

	FILE *file = fopen(filename.c_str(), opts.c_str());
	if(file) {
		retFile = new OSFILE;
		retFile->fileType = OSFILE::TYPE_FILE;
		retFile->file = file;
		return retFile;
	}

	return NULL;
}

int OSBasics::close(OSFILE *file) {
	int result = 0;
	switch(file->fileType) {
		case OSFILE::TYPE_FILE:
			result = fclose(file->file);
			break;
		case OSFILE::TYPE_ARCHIVE_FILE:
			result = PHYSFS_close(file->physFSFile);
			break;
	}
	delete file;
	return result;
}

long OSBasics::tell(OSFILE * stream) {
	switch(stream->fileType) {
		case OSFILE::TYPE_FILE:
			return ftell(stream->file);
			break;
		case OSFILE::TYPE_ARCHIVE_FILE:
			return PHYSFS_tell(stream->physFSFile);
			break;
	}
	return 0;
}

size_t OSBasics::read( void * ptr, size_t size, size_t count, OSFILE * stream ) {
	switch(stream->fileType) {
		case OSFILE::TYPE_FILE:
			return fread(ptr, size, count, stream->file);
		break;
		case OSFILE::TYPE_ARCHIVE_FILE:
			return PHYSFS_read(stream->physFSFile, ptr, size, count);
		break;
	}
	return 0;
}

size_t OSBasics::write( const void * ptr, size_t size, size_t count, OSFILE * stream ) {
	switch(stream->fileType) {
		case OSFILE::TYPE_FILE:
			fwrite(ptr, size, count, stream->file);
			break;
		case OSFILE::TYPE_ARCHIVE_FILE:
			PHYSFS_write(stream->physFSFile, ptr, size, count);
		break;
	}
	return 0;
}

int OSBasics::seek(OSFILE * stream, long int offset, int origin ) {
	switch(stream->fileType) {
		case OSFILE::TYPE_FILE:
			return fseek(stream->file, offset, origin);
			break;
		case OSFILE::TYPE_ARCHIVE_FILE:
			switch(origin) {
				case SEEK_SET:
					return PHYSFS_seek(stream->physFSFile, offset);
				break;
				case SEEK_CUR: {
					PHYSFS_sint64 curoffset = PHYSFS_tell(stream->physFSFile);
					return PHYSFS_seek(stream->physFSFile, curoffset+offset);
				}
				break;
				case SEEK_END: {
					PHYSFS_sint64 fileLength =  PHYSFS_fileLength(stream->physFSFile);
					return PHYSFS_seek(stream->physFSFile, fileLength-offset);
				}
				break;
			}
			break;
	}
	return 0;
}

vector<OSFileEntry> OSBasics::parsePhysFSFolder(const String& pathString, bool showHidden) {
	vector<OSFileEntry> returnVector;

	char **rc = PHYSFS_enumerateFiles(pathString.c_str());
	char **i;

	String fullPath;
	String fname;
	for (i = rc; *i != NULL; i++) {
		fname = string(*i);
		fullPath = pathString + "/" + fname;
		if((fname.c_str()[0] != '.' || (fname.c_str()[0] == '.'  && showHidden)) && fname != "..") {
			if(PHYSFS_isDirectory(fullPath.c_str())) {
				returnVector.push_back(OSFileEntry(pathString, fname, OSFileEntry::TYPE_FOLDER));
			} else {
				returnVector.push_back(OSFileEntry(pathString, fname, OSFileEntry::TYPE_FILE));
			}
		}
	}
	PHYSFS_freeList(rc);
	return returnVector;
}

vector<OSFileEntry> OSBasics::parseFolder(const String& pathString, bool showHidden) {
	vector<OSFileEntry> returnVector;

	if(pathString != "/") {
	if(pathString.size() < 128) {
		if(PHYSFS_exists(pathString.c_str())) {
			if(PHYSFS_isDirectory(pathString.c_str())) {
				return parsePhysFSFolder(pathString, showHidden);
			}
		}
	}
	}

#ifdef _WINDOWS

	WIN32_FIND_DATA findFileData;

	WCHAR curDir[4096];
	GetCurrentDirectory(4096, curDir);

	WCHAR tmp[4096];
	memset(tmp, 0, sizeof(WCHAR)*4096);
	ctow(tmp, pathString.c_str());

	DWORD dwAttrib = GetFileAttributes(tmp);
  if(! (dwAttrib != INVALID_FILE_ATTRIBUTES &&
         (dwAttrib & FILE_ATTRIBUTE_DIRECTORY))) {
		return returnVector;
  }

	SetCurrentDirectory(tmp);

	HANDLE hFind = FindFirstFile((LPCWSTR)"*", &findFileData);
	if(hFind  == INVALID_HANDLE_VALUE) {
		SetCurrentDirectory(curDir);
		return returnVector;
	}

	char fileName[260];
	do {
		memset(fileName, 0, 260);
		wtoc(fileName, findFileData.cFileName);
		String fname = string(fileName);

		if((fname.c_str()[0] != '.' || (fname.c_str()[0] == '.'  && showHidden)) && fname != "..") {
			if( findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
				returnVector.push_back(OSFileEntry(pathString, fname, OSFileEntry::TYPE_FOLDER));
			} else {
				returnVector.push_back(OSFileEntry(pathString, fname, OSFileEntry::TYPE_FILE));
			}
		}
    } while(FindNextFile(hFind, &findFileData));
	FindClose(hFind);
	SetCurrentDirectory(curDir);
#else
	DIR           *d;
	struct dirent *dir;

	d = opendir(pathString.c_str());
	if(d) {
		while ((dir = readdir(d)) != NULL) {
			if(dir->d_name[0] != '.' || (dir->d_name[0] == '.'  && showHidden)) {
				if(dir->d_type == DT_DIR) {
					returnVector.push_back(OSFileEntry(pathString, dir->d_name, OSFileEntry::TYPE_FOLDER));
				} else {
					returnVector.push_back(OSFileEntry(pathString, dir->d_name, OSFileEntry::TYPE_FILE));
				}
			}
		}
		closedir(d);
	}

#endif

	return returnVector;
}

void OSBasics::removeItem(const String& pathString) {
#ifdef _WINDOWS
	 String _tmp = pathString.replace("/", "\\");
	 DeleteFile(_tmp.getWDataWithEncoding(String::ENCODING_UTF8));
#else
	remove(pathString.c_str());
#endif
}

void OSBasics::createFolder(const String& pathString) {
#ifdef _WINDOWS
	String path = pathString;
	CreateDirectory(path.getWDataWithEncoding(String::ENCODING_UTF8), NULL);
#else
	mkdir(pathString.c_str(),  S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
#endif
}

bool OSBasics::isFolder(const String& pathString) {
	bool retVal = false;
#ifdef _WINDOWS
	String path = pathString;
	DWORD dwAttrib = GetFileAttributes(path.getWDataWithEncoding(String::ENCODING_UTF8));
  return (dwAttrib != INVALID_FILE_ATTRIBUTES &&
         (dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
#else
	DIR           *d;

	d = opendir(pathString.c_str());
	if(d) {
		retVal = true;
		closedir(d);
	}
#endif
	return retVal;
}
<|endoftext|>


<commit_before><commit_msg>Fixed warning in swapBytes, simple addded unsigned to the int loop count, since sizeof() is always an unsigned int.<commit_after><|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: dynload.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: jl $ $Date: 2001-03-28 11:02:29 $
 *
 *  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 _SALHELPER_DYNLOAD_HXX_
#include <salhelper/dynload.hxx>
#endif

#ifndef _RTL_USTRBUF_HXX_
#include <rtl/ustrbuf.hxx>
#endif

namespace salhelper
{

typedef void*   (SAL_CALL *ApiInitFunction) (void);

ORealDynamicLoader::ORealDynamicLoader(ORealDynamicLoader ** ppSetToZeroInDestructor_,
                       const rtl::OUString& moduleName,
                       const rtl::OUString& initFunction,
                       void* pApi,
                       oslModule pModule)
    : m_pApi(pApi)
    , m_refCount(1)
    , m_pModule(pModule)
    , m_strModuleName(moduleName)
    , m_strInitFunction(initFunction)
    , ppSetToZeroInDestructor( ppSetToZeroInDestructor_ )
{
}

ORealDynamicLoader* ORealDynamicLoader::newInstance(ORealDynamicLoader ** ppSetToZeroInDestructor,
                                  const rtl::OUString& moduleName,
                                  const rtl::OUString& initFunction)
{
    ApiInitFunction initFunc;
    oslModule pModule = osl_loadModule(moduleName.pData, SAL_LOADMODULE_DEFAULT);

    if ( !pModule )
    {
        return NULL;
    }

    initFunc = (ApiInitFunction)osl_getSymbol(pModule, initFunction.pData);

    if ( !initFunc )
    {
        osl_unloadModule(pModule);
        return NULL;
    }

    return(new ORealDynamicLoader(ppSetToZeroInDestructor, moduleName,
                                 initFunction,
                                 initFunc(),
                                 pModule));
}

ORealDynamicLoader::~ORealDynamicLoader()
{
    // set the address to zero
    if( ppSetToZeroInDestructor )
        *ppSetToZeroInDestructor = 0;

    if (m_pModule)
    {
        osl_unloadModule(m_pModule);
        m_pModule = NULL;
    }
}

sal_uInt32 ORealDynamicLoader::acquire()
{
    return ++m_refCount;
}

sal_uInt32 ORealDynamicLoader::release()
{
    sal_uInt32 nRet = --m_refCount;
    if( nRet == 0 )
        delete this;
    return nRet;
}

void* ORealDynamicLoader::getApi() const
{
    return m_pApi;
}

} // namespace salhelper

<commit_msg>INTEGRATION: CWS ooo19126 (1.2.136); FILE MERGED 2005/09/05 17:42:40 rt 1.2.136.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: dynload.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 17:01:02 $
 *
 *  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 _SALHELPER_DYNLOAD_HXX_
#include <salhelper/dynload.hxx>
#endif

#ifndef _RTL_USTRBUF_HXX_
#include <rtl/ustrbuf.hxx>
#endif

namespace salhelper
{

typedef void*   (SAL_CALL *ApiInitFunction) (void);

ORealDynamicLoader::ORealDynamicLoader(ORealDynamicLoader ** ppSetToZeroInDestructor_,
                       const rtl::OUString& moduleName,
                       const rtl::OUString& initFunction,
                       void* pApi,
                       oslModule pModule)
    : m_pApi(pApi)
    , m_refCount(1)
    , m_pModule(pModule)
    , m_strModuleName(moduleName)
    , m_strInitFunction(initFunction)
    , ppSetToZeroInDestructor( ppSetToZeroInDestructor_ )
{
}

ORealDynamicLoader* ORealDynamicLoader::newInstance(ORealDynamicLoader ** ppSetToZeroInDestructor,
                                  const rtl::OUString& moduleName,
                                  const rtl::OUString& initFunction)
{
    ApiInitFunction initFunc;
    oslModule pModule = osl_loadModule(moduleName.pData, SAL_LOADMODULE_DEFAULT);

    if ( !pModule )
    {
        return NULL;
    }

    initFunc = (ApiInitFunction)osl_getSymbol(pModule, initFunction.pData);

    if ( !initFunc )
    {
        osl_unloadModule(pModule);
        return NULL;
    }

    return(new ORealDynamicLoader(ppSetToZeroInDestructor, moduleName,
                                 initFunction,
                                 initFunc(),
                                 pModule));
}

ORealDynamicLoader::~ORealDynamicLoader()
{
    // set the address to zero
    if( ppSetToZeroInDestructor )
        *ppSetToZeroInDestructor = 0;

    if (m_pModule)
    {
        osl_unloadModule(m_pModule);
        m_pModule = NULL;
    }
}

sal_uInt32 ORealDynamicLoader::acquire()
{
    return ++m_refCount;
}

sal_uInt32 ORealDynamicLoader::release()
{
    sal_uInt32 nRet = --m_refCount;
    if( nRet == 0 )
        delete this;
    return nRet;
}

void* ORealDynamicLoader::getApi() const
{
    return m_pApi;
}

} // namespace salhelper

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2011-2014 Yule Fox. All rights reserved.
 * http://www.yulefox.com/
 */

#include <elf/event.h>
#include <elf/log.h>
#include <elf/memory.h>
#include <map>
#include <set>

namespace elf {
typedef std::map<oid_t, callback_t *> listener_list;
typedef std::map<int, listener_list *> listener_map;

static listener_map s_listeners;

int event_init(void)
{
    MODULE_IMPORT_SWITCH;
    return 0;
}

int event_fini(void)
{
    MODULE_IMPORT_SWITCH;
    return 0;
}

void event_regist(int evt, callback_t *cb)
{
    assert(cb);
    listener_list *lss = NULL;
    listener_map::iterator itr = s_listeners.find(evt);

    if (itr == s_listeners.end()) {
        lss = E_NEW listener_list;
        s_listeners[evt] = lss;
    } else {
        lss = itr->second;
    }
    (*lss)[cb->lid] = cb;
}

void event_unregist(oid_t lid, int evt)
{
    if (evt > 0) {
        listener_map::iterator itr = s_listeners.find(evt);

        if (itr == s_listeners.end()) {
            return;
        }

        listener_list *lss = itr->second;

        assert(lss);
        listener_list::iterator itr_l = lss->find(lid);

        if (itr_l != lss->end()) {
            E_DELETE(itr_l->second);
            lss->erase(itr_l);
        }
    } else {
        listener_map::iterator itr = s_listeners.begin();

        for (; itr != s_listeners.end(); ++itr) {
            listener_list *lss = itr->second;

            assert(lss);
            listener_list::iterator itr_l = lss->find(lid);

            if (itr_l != lss->end()) {
                E_DELETE(itr_l->second);
                lss->erase(itr_l);
            }
        }
    }
}

void event_emit(int evt, int arg, oid_t oid)
{
    listener_map::iterator itr_l = s_listeners.find(evt);

    if (itr_l == s_listeners.end()) {
        return;
    }

    listener_list *lss = itr_l->second;
    listener_list::iterator itr = lss->begin();
    for (; itr != lss->end(); ++itr) {
        callback_t *cb = itr->second;

        assert(cb);

        cb->tid = oid;
        cb->targ = arg;
        cb->func(cb);
    }
}
} // namespace elf

<commit_msg>[MOD] fix event trigger.<commit_after>/*
 * Copyright (C) 2011-2014 Yule Fox. All rights reserved.
 * http://www.yulefox.com/
 */

#include <elf/event.h>
#include <elf/log.h>
#include <elf/memory.h>
#include <map>
#include <set>

namespace elf {
typedef std::map<oid_t, callback_t *> listener_list;
typedef std::map<int, listener_list *> listener_map;

static listener_map s_listeners;

int event_init(void)
{
    MODULE_IMPORT_SWITCH;
    return 0;
}

int event_fini(void)
{
    MODULE_IMPORT_SWITCH;
    return 0;
}

void event_regist(int evt, callback_t *cb)
{
    assert(cb);
    listener_list *lss = NULL;
    listener_map::iterator itr = s_listeners.find(evt);

    if (itr == s_listeners.end()) {
        lss = E_NEW listener_list;
        s_listeners[evt] = lss;
    } else {
        lss = itr->second;
    }
    (*lss)[cb->lid] = cb;
}

void event_unregist(oid_t lid, int evt)
{
    if (evt > 0) {
        listener_map::iterator itr = s_listeners.find(evt);

        if (itr == s_listeners.end()) {
            return;
        }

        listener_list *lss = itr->second;

        assert(lss);
        listener_list::iterator itr_l = lss->find(lid);

        if (itr_l != lss->end()) {
            E_DELETE(itr_l->second);
            lss->erase(itr_l);
        }
    } else {
        listener_map::iterator itr = s_listeners.begin();

        for (; itr != s_listeners.end(); ++itr) {
            listener_list *lss = itr->second;

            assert(lss);
            listener_list::iterator itr_l = lss->find(lid);

            if (itr_l != lss->end()) {
                E_DELETE(itr_l->second);
                lss->erase(itr_l);
            }
        }
    }
}

void event_emit(int evt, int arg, oid_t oid)
{
    listener_map::iterator itr_l = s_listeners.find(evt);

    if (itr_l == s_listeners.end()) {
        return;
    }

    LOG_TRACE("event", "<%lld> emit %d:%d.",
            oid, evt, arg);

    listener_list *lss = itr_l->second;
    listener_list::iterator itr = lss->begin();
    for (; itr != lss->end(); ++itr) {
        callback_t *cb = itr->second;

        assert(cb);

        // not same owner
        if (oid != cb->oid) continue;
        cb->tid = oid;
        cb->targ = arg;
        cb->func(cb);
    }
}
} // namespace elf

<|endoftext|>


<commit_before>extern "C" {
  #include "utility/wl_definitions.h"
  #include "utility/wl_types.h"
  #include "socket.h"
  #include "string.h"
  #include "utility/debug.h"
}

#include "WiFi.h"
#include "WiFiClient.h"
#include "WiFiServer.h"
#include "server_drv.h"

uint16_t WiFiClient::_srcport = 1024;

WiFiClient::WiFiClient() : _sock(MAX_SOCK_NUM) {
}

WiFiClient::WiFiClient(uint8_t sock) : _sock(sock) {
}

int WiFiClient::connect(const char* host, uint16_t port) {
	IPAddress remote_addr;
	if (WiFi.hostByName(host, remote_addr))
	{
		return connect(remote_addr, port);
	}
	return 0;
}

int WiFiClient::connect(IPAddress ip, uint16_t port) {
    _sock = getFirstSocket();
    if (_sock != NO_SOCKET_AVAIL)
    {
    	ServerDrv::startClient(uint32_t(ip), port, _sock);
    	WiFiClass::_state[_sock] = _sock;
    	while(!connected());
    }else{
    	return 0;
    }
    return 1;
}

size_t WiFiClient::write(uint8_t b) {
	  return write(&b, 1);
}

size_t WiFiClient::write(const uint8_t *buf, size_t size) {
  if (_sock >= MAX_SOCK_NUM)
  {
	  setWriteError();
	  return 0;
  }
  if (size==0)
  {
	  setWriteError();
      return 0;
  }

  if ((!ServerDrv::sendData(_sock, buf, size)) ||
		  (!ServerDrv::checkDataSent(_sock)))
  {
	  setWriteError();
      return 0;
  }
  return size;
}

int WiFiClient::available() {
  if (_sock != 255)
  {
      return ServerDrv::availData(_sock);
  }

  return 0;
}

int WiFiClient::read() {
  uint8_t b;
  if (!available())
    return -1;

  ServerDrv::getData(_sock, &b);
  return b;
}

int WiFiClient::read(uint8_t* buf, size_t size) {
  if (!ServerDrv::getDataBuf(_sock, buf, &size))
      return -1;
  return 0;
}

int WiFiClient::peek() {
	//TODO to be implemented
	return 0;
}

void WiFiClient::flush() {
  while (available())
    read();
}

void WiFiClient::stop() {

  if (_sock == 255)
    return;

  ServerDrv::stopClient(_sock);

  unsigned long start = millis();

  // wait a second for the connection to close
  while (status() != CLOSED && millis() - start < 1000)
    delay(1);

  _sock = 255;
}

uint8_t WiFiClient::connected() {

  if (_sock == 255) {
    return 0;
  } else {
    uint8_t s = status();

    return !(s == LISTEN || s == CLOSED || s == FIN_WAIT_1 ||
    		s == FIN_WAIT_2 || s == TIME_WAIT ||
             (s == CLOSE_WAIT && !available()));
  }
}

uint8_t WiFiClient::status() {
    if (_sock == 255) {
    return CLOSED;
  } else {
    return ServerDrv::getClientState(_sock);
  }
}

WiFiClient::operator bool() {
  return _sock != 255;
}

// Private Methods
uint8_t WiFiClient::getFirstSocket()
{
    for (int i = 0; i < MAX_SOCK_NUM; i++) {
      if (WiFiClass::_state[i] == 0)
      {
          return i;
      }
    }
    return SOCK_NOT_AVAIL;
}

<commit_msg>Fix issue on Cosm sketch tahat stops after some conenctions<commit_after>extern "C" {
  #include "utility/wl_definitions.h"
  #include "utility/wl_types.h"
  #include "socket.h"
  #include "string.h"
  #include "utility/debug.h"
}

#include "WiFi.h"
#include "WiFiClient.h"
#include "WiFiServer.h"
#include "server_drv.h"

uint16_t WiFiClient::_srcport = 1024;

WiFiClient::WiFiClient() : _sock(MAX_SOCK_NUM) {
}

WiFiClient::WiFiClient(uint8_t sock) : _sock(sock) {
}

int WiFiClient::connect(const char* host, uint16_t port) {
	IPAddress remote_addr;
	if (WiFi.hostByName(host, remote_addr))
	{
		return connect(remote_addr, port);
	}
	return 0;
}

int WiFiClient::connect(IPAddress ip, uint16_t port) {
    _sock = getFirstSocket();
    if (_sock != NO_SOCKET_AVAIL)
    {
    	ServerDrv::startClient(uint32_t(ip), port, _sock);
    	WiFiClass::_state[_sock] = _sock;
    	while(!connected());
    }else{
    	return 0;
    }
    return 1;
}

size_t WiFiClient::write(uint8_t b) {
	  return write(&b, 1);
}

size_t WiFiClient::write(const uint8_t *buf, size_t size) {
  if (_sock >= MAX_SOCK_NUM)
  {
	  setWriteError();
	  return 0;
  }
  if (size==0)
  {
	  setWriteError();
      return 0;
  }

  if ((!ServerDrv::sendData(_sock, buf, size)) ||
		  (!ServerDrv::checkDataSent(_sock)))
  {
	  setWriteError();
      return 0;
  }
  return size;
}

int WiFiClient::available() {
  if (_sock != 255)
  {
      return ServerDrv::availData(_sock);
  }

  return 0;
}

int WiFiClient::read() {
  uint8_t b;
  if (!available())
    return -1;

  ServerDrv::getData(_sock, &b);
  return b;
}

int WiFiClient::read(uint8_t* buf, size_t size) {
  if (!ServerDrv::getDataBuf(_sock, buf, &size))
      return -1;
  return 0;
}

int WiFiClient::peek() {
	//TODO to be implemented
	return 0;
}

void WiFiClient::flush() {
  while (available())
    read();
}

void WiFiClient::stop() {

  if (_sock == 255)
    return;

  ServerDrv::stopClient(_sock);

  unsigned long start = millis();

  // wait a second for the connection to close
  while (status() != CLOSED && millis() - start < 1000)
    delay(1);

  _sock = 255;
}

uint8_t WiFiClient::connected() {

  if (_sock == 255) {
    return 0;
  } else {
    uint8_t s = status();

    return !(s == LISTEN || s == CLOSED || s == FIN_WAIT_1 ||
    		s == FIN_WAIT_2 || s == TIME_WAIT ||
    		s == SYN_SENT || s== SYN_RCVD ||
             (s == CLOSE_WAIT && !available()));
  }
}

uint8_t WiFiClient::status() {
    if (_sock == 255) {
    return CLOSED;
  } else {
    return ServerDrv::getClientState(_sock);
  }
}

WiFiClient::operator bool() {
  return _sock != 255;
}

// Private Methods
uint8_t WiFiClient::getFirstSocket()
{
    for (int i = 0; i < MAX_SOCK_NUM; i++) {
      if (WiFiClass::_state[i] == 0)
      {
          return i;
      }
    }
    return SOCK_NOT_AVAIL;
}

<|endoftext|>


<commit_before>/**
 * ocv_ar - OpenCV based Augmented Reality library
 *
 * Marker identification via simple template matching of binary
 * images -- implementation file.
 *
 * Author: Markus Konrad <konrad@htw-berlin.de>, June 2014.
 * INKA Research Group, HTW Berlin - http://inka.htw-berlin.de/
 *
 * See LICENSE for license.
 */

#include "ident_templ.h"

#include "tools.h"

using namespace ocv_ar;

#pragma mark constructors/deconstructor

IdentificatorTemplMatch::IdentificatorTemplMatch() :
    IdentificatorBase(IDENT_TYPE_TEMPL_MATCH, 8 * OCV_AR_CONF_MARKER_CODE_PX_PER_FIELD),
    borderSize(OCV_AR_CONF_MARKER_CODE_PX_PER_FIELD),
    minSetMarkerPixels(OCV_AR_CONF_MARKER_CODE_PX_PER_FIELD * OCV_AR_CONF_MARKER_CODE_PX_PER_FIELD / 2)
{
    // calculate defaults
    templSize = reqMarkerSize - 2 * borderSize;
    templSizeSq = templSize * templSize;

    printf("ocv_ar::IdentificatorTemplMatch - req. marker size: %d, templ. size: %d\n",
           reqMarkerSize, templSize);
}

IdentificatorTemplMatch::~IdentificatorTemplMatch() {
    // clear templates map
    for (TemplateMap::iterator it = templates.begin();
         it != templates.end();
         ++it)
    {
        cv::Mat *templArr = it->second;
        delete [] templArr;
    }
}

#pragma mark public methods

bool IdentificatorTemplMatch::readMarkerCode(const cv::Mat &area, Marker &marker) {
    assert(area.rows == area.cols && area.rows == reqMarkerSize && area.type() == CV_8UC1);   // must be quadratic and grayscale

    // check the border as "cells" first
    bool borderOk =    checkBorder(area, 0, 0)      // top row
                    && checkBorder(area, 0, 7)      // bottom row
                    && checkBorder(area, 1, 0)      // left column
                    && checkBorder(area, 1, 7);     // right column

    if (!borderOk) return false;

    printf("ocv_ar::IdentificatorTemplMatch - border checks ok\n");

    // get only the "content" of <area>, i.e. the marker without borders
    int areaContentSize = area.cols - 2 * borderSize;
    cv::Rect roi(borderSize, borderSize, areaContentSize, areaContentSize);
    cv::Mat areaContent(area, roi);

    // do the template matching for all templates we have
    for (TemplateMap::iterator it = templates.begin();
         it != templates.end();
         ++it)
    {
        int validRot;
        if (checkTemplateRotations(areaContent, it->second, &validRot)) {  // found a matching template!
            marker.setId(it->first);
            marker.rotatePoints(validRot);
            return true;
        }
    }

    return false;
}

void IdentificatorTemplMatch::addTemplateImg(int id, const cv::Mat &img, bool stripBorder, bool binarize) {
    assert(id >= 0 && img.rows == img.cols && img.type() == CV_8UC1);   // must be quadratic and grayscale

    if (templates.find(id) != templates.end()) {
        printf("ocv_ar::IdentificatorTemplMatch - template not added to library - id %d already exists\n", id);

        return;
    }

    cv::Mat templ(templSize, templSize, CV_8UC1);

    // strip border
    if (stripBorder) {
        assert(img.rows == reqMarkerSize);  // "templ" will then be of size "reqMarkerSize - 2 * borderSize"
        int imgContentSize = img.cols - 2 * borderSize;
        cv::Rect roi(borderSize, borderSize, imgContentSize, imgContentSize);
        templ = img(roi);
    } else {
        assert(img.rows == templSize);
        img.copyTo(templ);
    }

    // binarize, if necessary
    if (binarize) {
        cv::threshold(templ, templ, 127, 255, cv::THRESH_BINARY | cv::THRESH_OTSU);
    }

    // create all 4 possible rotations
    cv::Mat *templArr = new cv::Mat[4];
    templ.copyTo(templArr[0]);  // first: no rotation
    for (int r = 1; r < 4; r++) {   // all other rotations
        Tools::matRot90CW(templ);
        templ.copyTo(templArr[r]);
    }

    // add to map
    TemplateMapPair templPair(id, templArr);
    templates.insert(templPair);

    printf("ocv_ar::IdentificatorTemplMatch - added template image of size %dx%d for id %d\n",
           img.cols, img.rows, id);
}

void IdentificatorTemplMatch::removeTemplateImg(int id) {
    TemplateMap::iterator it = templates.find(id);
    if (it != templates.end()) {
        // free memory
        cv::Mat *templArr = it->second;
        delete [] templArr;

        // remove the map entry
        templates.erase(it);
    }
}

#pragma mark private methods

bool IdentificatorTemplMatch::checkBorder(const cv::Mat &img, int dir, int off) {
    const int numCells = 8;

    // init
    int x, y;
    if (dir == 0) { // horizontal
        x = 0;
        y = off;
    } else {        // vertical
        x = off;
        y = 0;
    }

    // walk
    for (int c = 0; c < numCells; c++) {
        // get abs. pixel offsets for the cell
        int cellX = x * borderSize;
        int cellY = y * borderSize;

        // select cell
        cv::Mat cell = img(cv::Rect(cellX, cellY, borderSize, borderSize));

        // count non zero values
        if (cv::countNonZero(cell) > minSetMarkerPixels) {  // we have "white" cell!
            printf("ocv_ar::IdentificatorTemplMatch - check border failed for dir %d, offset %d\n", dir, off);

            return false;
        }

        // increment
        if (dir == 0) { // horizontal
            x++;
        } else {        // vertical
            y++;
        }
    }

    return true;
}

bool IdentificatorTemplMatch::checkTemplateRotations(const cv::Mat &marker, const cv::Mat *templRotations, int *validRot) {
    cv::Mat errorMat(marker.rows, marker.cols, CV_8UC1);

    float bestResult = OCV_AR_CONF_TEMPL_MATCH_MAX_ERROR_RATE;    // init. with worst possible result
    int bestResultRot = -1;

    for (int r = 0; r < 4; r++) {   // check all four rotations
        // do a bitwise or so that we get "1"s where the two images do not fit
        cv::bitwise_xor(marker, templRotations[r], errorMat);

        // could the pixels that do not fit
        float errRate = (float)cv::countNonZero(errorMat) / (float)templSizeSq;

        if (errRate <= OCV_AR_CONF_TEMPL_MATCH_MAX_ERROR_RATE && errRate < bestResult) {
            // found the best result so far
            bestResult = errRate;
            bestResultRot = r;
        }
    }

    if (bestResultRot < 0) {
        printf("ocv_ar::IdentificatorTemplMatch - no template match\n");

        return false;
    }

    printf("ocv_ar::IdentificatorTemplMatch - template match(es) with best result %f, rotation %d\n",
           bestResult, bestResultRot);
    *validRot = bestResultRot;

    return true;
}<commit_msg>downscale input marker images for template matching<commit_after>/**
 * ocv_ar - OpenCV based Augmented Reality library
 *
 * Marker identification via simple template matching of binary
 * images -- implementation file.
 *
 * Author: Markus Konrad <konrad@htw-berlin.de>, June 2014.
 * INKA Research Group, HTW Berlin - http://inka.htw-berlin.de/
 *
 * See LICENSE for license.
 */

#include "ident_templ.h"

#include "tools.h"

using namespace ocv_ar;

#pragma mark constructors/deconstructor

IdentificatorTemplMatch::IdentificatorTemplMatch() :
    IdentificatorBase(IDENT_TYPE_TEMPL_MATCH, 8 * OCV_AR_CONF_MARKER_CODE_PX_PER_FIELD),
    borderSize(OCV_AR_CONF_MARKER_CODE_PX_PER_FIELD),
    minSetMarkerPixels(OCV_AR_CONF_MARKER_CODE_PX_PER_FIELD * OCV_AR_CONF_MARKER_CODE_PX_PER_FIELD / 2)
{
    // calculate defaults
    templSize = reqMarkerSize - 2 * borderSize;
    templSizeSq = templSize * templSize;

    printf("ocv_ar::IdentificatorTemplMatch - req. marker size: %d, templ. size: %d\n",
           reqMarkerSize, templSize);
}

IdentificatorTemplMatch::~IdentificatorTemplMatch() {
    // clear templates map
    for (TemplateMap::iterator it = templates.begin();
         it != templates.end();
         ++it)
    {
        cv::Mat *templArr = it->second;
        delete [] templArr;
    }
}

#pragma mark public methods

bool IdentificatorTemplMatch::readMarkerCode(const cv::Mat &area, Marker &marker) {
    assert(area.rows == area.cols && area.rows == reqMarkerSize && area.type() == CV_8UC1);   // must be quadratic and grayscale

    // check the border as "cells" first
    bool borderOk =    checkBorder(area, 0, 0)      // top row
                    && checkBorder(area, 0, 7)      // bottom row
                    && checkBorder(area, 1, 0)      // left column
                    && checkBorder(area, 1, 7);     // right column

    if (!borderOk) return false;

//    printf("ocv_ar::IdentificatorTemplMatch - border checks ok\n");

    // get only the "content" of <area>, i.e. the marker without borders
    int areaContentSize = area.cols - 2 * borderSize;
    cv::Rect roi(borderSize, borderSize, areaContentSize, areaContentSize);
    cv::Mat areaContent(area, roi);

    // do the template matching for all templates we have
    for (TemplateMap::iterator it = templates.begin();
         it != templates.end();
         ++it)
    {
        int validRot;
        if (checkTemplateRotations(areaContent, it->second, &validRot)) {  // found a matching template!
            marker.setId(it->first);
            marker.rotatePoints(validRot);
            return true;
        }
    }

    return false;
}

void IdentificatorTemplMatch::addTemplateImg(int id, const cv::Mat &img, bool stripBorder, bool binarize) {
    assert(id >= 0 && img.rows == img.cols && img.type() == CV_8UC1);   // must be quadratic and grayscale

    if (templates.find(id) != templates.end()) {
        printf("ocv_ar::IdentificatorTemplMatch - template not added to library - id %d already exists\n", id);

        return;
    }

    cv::Mat templ(templSize, templSize, CV_8UC1);

    // strip border
    if (stripBorder) {
        const cv::Mat *imgToUse;
        cv::Mat imgResized;

        if (img.cols != reqMarkerSize) {    // resize
            cv::resize(img, imgResized, cv::Size(reqMarkerSize, reqMarkerSize));
            imgToUse = &imgResized;
        } else {
            imgToUse = &img;
        }

        // "templ" will then be of size "reqMarkerSize - 2 * borderSize"
        int imgContentSize = imgToUse->cols - 2 * borderSize;
        cv::Rect roi(borderSize, borderSize, imgContentSize, imgContentSize);
        templ = (*imgToUse)(roi);
    } else {
        if (img.cols != templSize) {    // resize
            cv::resize(img, templ, cv::Size(templSize, templSize));
        } else {    // just copy
            img.copyTo(templ);
        }
    }

    // binarize, if necessary
    if (binarize) {
        cv::threshold(templ, templ, 127, 255, cv::THRESH_BINARY | cv::THRESH_OTSU);
    }

    // create all 4 possible rotations
    cv::Mat *templArr = new cv::Mat[4];
    templ.copyTo(templArr[0]);  // first: no rotation
    for (int r = 1; r < 4; r++) {   // all other rotations
        Tools::matRot90CW(templ);
        templ.copyTo(templArr[r]);
    }

    // add to map
    TemplateMapPair templPair(id, templArr);
    templates.insert(templPair);

    printf("ocv_ar::IdentificatorTemplMatch - added template image of size %dx%d for id %d\n",
           img.cols, img.rows, id);
}

void IdentificatorTemplMatch::removeTemplateImg(int id) {
    TemplateMap::iterator it = templates.find(id);
    if (it != templates.end()) {
        // free memory
        cv::Mat *templArr = it->second;
        delete [] templArr;

        // remove the map entry
        templates.erase(it);
    }
}

#pragma mark private methods

bool IdentificatorTemplMatch::checkBorder(const cv::Mat &img, int dir, int off) {
    const int numCells = 8;

    // init
    int x, y;
    if (dir == 0) { // horizontal
        x = 0;
        y = off;
    } else {        // vertical
        x = off;
        y = 0;
    }

    // walk
    for (int c = 0; c < numCells; c++) {
        // get abs. pixel offsets for the cell
        int cellX = x * borderSize;
        int cellY = y * borderSize;

        // select cell
        cv::Mat cell = img(cv::Rect(cellX, cellY, borderSize, borderSize));

        // count non zero values
        if (cv::countNonZero(cell) > minSetMarkerPixels) {  // we have "white" cell!
//            printf("ocv_ar::IdentificatorTemplMatch - check border failed for dir %d, offset %d\n", dir, off);

            return false;
        }

        // increment
        if (dir == 0) { // horizontal
            x++;
        } else {        // vertical
            y++;
        }
    }

    return true;
}

bool IdentificatorTemplMatch::checkTemplateRotations(const cv::Mat &marker, const cv::Mat *templRotations, int *validRot) {
    cv::Mat errorMat(marker.rows, marker.cols, CV_8UC1);

    float bestResult = OCV_AR_CONF_TEMPL_MATCH_MAX_ERROR_RATE;    // init. with worst possible result
    int bestResultRot = -1;

    for (int r = 0; r < 4; r++) {   // check all four rotations
        // do a bitwise or so that we get "1"s where the two images do not fit
        cv::bitwise_xor(marker, templRotations[r], errorMat);

        // could the pixels that do not fit
        float errRate = (float)cv::countNonZero(errorMat) / (float)templSizeSq;

        if (errRate <= OCV_AR_CONF_TEMPL_MATCH_MAX_ERROR_RATE && errRate < bestResult) {
            // found the best result so far
            bestResult = errRate;
            bestResultRot = r;
        }
    }

    if (bestResultRot < 0) {
//        printf("ocv_ar::IdentificatorTemplMatch - no template match\n");

        return false;
    }

//    printf("ocv_ar::IdentificatorTemplMatch - template match(es) with best result %f, rotation %d\n",
//           bestResult, bestResultRot);
    *validRot = bestResultRot;

    return true;
}<|endoftext|>


<commit_before>/** @file

  A brief file description

  @section license License

  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
 */

/****************************************************************************
Process arguments

****************************************************************************/

#include "libts.h"

//
//  Global variables
//

const char *file_arguments[MAX_FILE_ARGUMENTS] = { 0 };
const char *program_name = (char *) "Traffic Server";
unsigned n_file_arguments = 0;

//
//  Local variables
//

static const char *argument_types_keys = (char *) "ISDfFTL";
static const char *argument_types_descriptions[] = {
  (char *) "int  ",
  (char *) "str  ",
  (char *) "dbl  ",
  (char *) "off  ",
  (char *) "on   ",
  (char *) "tog  ",
  (char *) "i64  ",
  (char *) "     "
};

//
// Functions
//

static bool
arg_is_version_flag(const ArgumentDescription * arg)
{
  return strcmp(arg->name, "version") == 0 && arg->key == 'V';
}

static void
append_file_argument(const char * arg)
{
    if (n_file_arguments >= countof(file_arguments)) {
      ink_fatal("too many files");
    }
    file_arguments[n_file_arguments++] = arg;
    file_arguments[n_file_arguments] = NULL;
}

static void
process_arg(const AppVersionInfo * appinfo, const ArgumentDescription * argument_descriptions,
            unsigned n_argument_descriptions, int i, char ***argv, const char *usage_string)
{
  char *arg = NULL;

  if (arg_is_version_flag(&argument_descriptions[i])) {
    ink_fputln(stdout, appinfo->FullVersionInfoStr);
    exit(0);
  }

  if (argument_descriptions[i].type) {
    char type = argument_descriptions[i].type[0];
    if (type == 'F' || type == 'f')
      *(int *) argument_descriptions[i].location = type == 'F' ? 1 : 0;
    else if (type == 'T')
      *(int *) argument_descriptions[i].location = !*(int *) argument_descriptions[i].location;
    else {
      arg = *++(**argv) ? **argv : *++(*argv);
      if (!arg)
        usage(argument_descriptions, n_argument_descriptions, usage_string);
      switch (type) {
      case 'I':
        *(int *) argument_descriptions[i].location = atoi(arg);
        break;
      case 'D':
        *(double *) argument_descriptions[i].location = atof(arg);
        break;
      case 'L':
        *(int64_t *) argument_descriptions[i].location = ink_atoi64(arg);
        break;
      case 'S':
        if (argument_descriptions[i].type[1] == '*') {
          char ** out = (char **)argument_descriptions[i].location;
          *out = ats_strdup(arg);
        } else {
          ink_strlcpy((char *) argument_descriptions[i].location, arg, atoi(argument_descriptions[i].type + 1));
        }
        break;
      default:
        ink_fatal("bad argument description");
        break;
      }
      **argv += strlen(**argv) - 1;
    }
  }
  if (argument_descriptions[i].pfn)
    argument_descriptions[i].pfn(argument_descriptions, n_argument_descriptions, arg);
}

void
show_argument_configuration(const ArgumentDescription * argument_descriptions, unsigned n_argument_descriptions)
{
  printf("Argument Configuration\n");
  for (unsigned i = 0; i < n_argument_descriptions; i++) {
    if (argument_descriptions[i].type) {
      printf("  %-34s ", argument_descriptions[i].description);
      switch (argument_descriptions[i].type[0]) {
      case 'F':
      case 'f':
      case 'T':
        printf(*(int *) argument_descriptions[i].location ? "TRUE" : "FALSE");
        break;
      case 'I':
        printf("%d", *(int *) argument_descriptions[i].location);
        break;
      case 'D':
        printf("%f", *(double *) argument_descriptions[i].location);
        break;
      case 'L':
        printf("%" PRId64 "", *(int64_t *) argument_descriptions[i].location);
        break;
      case 'S':
        printf("%s", (char *) argument_descriptions[i].location);
        break;
      default:
        ink_fatal("bad argument description");
        break;
      }
      printf("\n");
    }
  }
}

void
process_args(const AppVersionInfo * appinfo, const ArgumentDescription * argument_descriptions, unsigned n_argument_descriptions, char **argv, const char *usage_string)
{
  unsigned i = 0;
  //
  // Grab Environment Variables
  //
  for (i = 0; i < n_argument_descriptions; i++)
    if (argument_descriptions[i].env) {
      char type = argument_descriptions[i].type[0];
      char *env = getenv(argument_descriptions[i].env);
      if (!env)
        continue;
      switch (type) {
      case 'f':
      case 'F':
      case 'I':
        *(int *) argument_descriptions[i].location = atoi(env);
        break;
      case 'D':
        *(double *) argument_descriptions[i].location = atof(env);
        break;
      case 'L':
        *(int64_t *) argument_descriptions[i].location = atoll(env);
        break;
      case 'S':
        ink_strlcpy((char *) argument_descriptions[i].location, env, atoi(argument_descriptions[i].type + 1));
        break;
      }
    }
  //
  // Grab Command Line Arguments
  //
  program_name = appinfo->AppStr;
  while (*++argv) {
    if (**argv == '-') {
      if ((*argv)[1] == '-') {
        for (i = 0; i < n_argument_descriptions; i++)
          if (!strcmp(argument_descriptions[i].name, (*argv) + 2)) {
            *argv += strlen(*argv) - 1;
            process_arg(appinfo, argument_descriptions, n_argument_descriptions, i, &argv, usage_string);
            break;
          }
        if (i >= n_argument_descriptions)
          usage(argument_descriptions, n_argument_descriptions, usage_string);
      } else {
        // Hack for supporting '-' as a file argument.
        if (strcmp(*argv, "-") == 0) {
          append_file_argument(*argv);
        }

        while (*++(*argv)) {
          for (i = 0; i < n_argument_descriptions; i++) {
            if (argument_descriptions[i].key == **argv) {
              process_arg(appinfo, argument_descriptions, n_argument_descriptions, i, &argv, usage_string);
              break;
            }
          }

          if (i >= n_argument_descriptions) {
            usage(argument_descriptions, n_argument_descriptions, usage_string);
          }
        }
      }
    } else {
      append_file_argument(*argv);
    }
  }
}

void
usage(const ArgumentDescription * argument_descriptions, unsigned n_argument_descriptions, const char *usage_string)
{
  (void) argument_descriptions;
  (void) n_argument_descriptions;
  (void) usage_string;
  if (usage_string)
    fprintf(stderr, "%s\n", usage_string);
  else
    fprintf(stderr, "Usage: %s [--SWITCH [ARG]]\n", program_name);
  fprintf(stderr, "  switch__________________type__default___description\n");
  for (unsigned i = 0; i < n_argument_descriptions; i++) {
    if (!argument_descriptions[i].description)
      continue;

    fprintf(stderr, "  ");

    if ('-' == argument_descriptions[i].key) fprintf(stderr, "   ");
    else fprintf(stderr, "-%c,", argument_descriptions[i].key);

    fprintf(stderr, " --%-17s %s",
            argument_descriptions[i].name,
            argument_types_descriptions[argument_descriptions[i].type ?
                                        strchr(argument_types_keys,
                                               argument_descriptions[i].type[0]) -
                                        argument_types_keys : strlen(argument_types_keys)
            ]);
    switch (argument_descriptions[i].type ? argument_descriptions[i].type[0] : 0) {
    case 0:
      fprintf(stderr, "          ");
      break;
    case 'L':
      fprintf(stderr, " %-9" PRId64 "", *(int64_t *) argument_descriptions[i].location);
      break;
    case 'S': {
      char * location;
      if (argument_descriptions[i].type[1] == '*') {
        location = *(char **)argument_descriptions[i].location;
      } else {
        location = (char *)argument_descriptions[i].location;
      }

      if (location) {
        if (strlen(location) < 10) {
          fprintf(stderr, " %-9s", location);
        } else {
          fprintf(stderr, " %-7.7s..", location);
        }
      } else {
        fprintf(stderr, " (null)   ");
      }
      break;
    }
    case 'D':
      fprintf(stderr, " %-9.3f", *(double *) argument_descriptions[i].location);
      break;
    case 'I':
      fprintf(stderr, " %-9d", *(int *) argument_descriptions[i].location);
      break;
    case 'T':
    case 'f':
    case 'F':
      if (argument_descriptions[i].location) {
        fprintf(stderr, " %-9s", *(int *) argument_descriptions[i].location ? "true " : "false");
      } else {
        fprintf(stderr, " %-9s", "false");
      }
      break;
    }
    fprintf(stderr, " %s\n", argument_descriptions[i].description);
  }
  _exit(1);
}
<commit_msg>Prevent out of bounds write in argument parsing<commit_after>/** @file

  A brief file description

  @section license License

  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
 */

/****************************************************************************
Process arguments

****************************************************************************/

#include "libts.h"

//
//  Global variables
//

const char *file_arguments[MAX_FILE_ARGUMENTS] = { 0 };
const char *program_name = (char *) "Traffic Server";
unsigned n_file_arguments = 0;

//
//  Local variables
//

static const char *argument_types_keys = (char *) "ISDfFTL";
static const char *argument_types_descriptions[] = {
  (char *) "int  ",
  (char *) "str  ",
  (char *) "dbl  ",
  (char *) "off  ",
  (char *) "on   ",
  (char *) "tog  ",
  (char *) "i64  ",
  (char *) "     "
};

//
// Functions
//

static bool
arg_is_version_flag(const ArgumentDescription * arg)
{
  return strcmp(arg->name, "version") == 0 && arg->key == 'V';
}

static void
append_file_argument(const char * arg)
{
    if (n_file_arguments >= countof(file_arguments)) {
      ink_fatal("too many files");
    }

    file_arguments[n_file_arguments++] = arg;
}

static void
process_arg(const AppVersionInfo * appinfo, const ArgumentDescription * argument_descriptions,
            unsigned n_argument_descriptions, int i, char ***argv, const char *usage_string)
{
  char *arg = NULL;

  if (arg_is_version_flag(&argument_descriptions[i])) {
    ink_fputln(stdout, appinfo->FullVersionInfoStr);
    exit(0);
  }

  if (argument_descriptions[i].type) {
    char type = argument_descriptions[i].type[0];
    if (type == 'F' || type == 'f')
      *(int *) argument_descriptions[i].location = type == 'F' ? 1 : 0;
    else if (type == 'T')
      *(int *) argument_descriptions[i].location = !*(int *) argument_descriptions[i].location;
    else {
      arg = *++(**argv) ? **argv : *++(*argv);
      if (!arg)
        usage(argument_descriptions, n_argument_descriptions, usage_string);
      switch (type) {
      case 'I':
        *(int *) argument_descriptions[i].location = atoi(arg);
        break;
      case 'D':
        *(double *) argument_descriptions[i].location = atof(arg);
        break;
      case 'L':
        *(int64_t *) argument_descriptions[i].location = ink_atoi64(arg);
        break;
      case 'S':
        if (argument_descriptions[i].type[1] == '*') {
          char ** out = (char **)argument_descriptions[i].location;
          *out = ats_strdup(arg);
        } else {
          ink_strlcpy((char *) argument_descriptions[i].location, arg, atoi(argument_descriptions[i].type + 1));
        }
        break;
      default:
        ink_fatal("bad argument description");
        break;
      }
      **argv += strlen(**argv) - 1;
    }
  }
  if (argument_descriptions[i].pfn)
    argument_descriptions[i].pfn(argument_descriptions, n_argument_descriptions, arg);
}

void
show_argument_configuration(const ArgumentDescription * argument_descriptions, unsigned n_argument_descriptions)
{
  printf("Argument Configuration\n");
  for (unsigned i = 0; i < n_argument_descriptions; i++) {
    if (argument_descriptions[i].type) {
      printf("  %-34s ", argument_descriptions[i].description);
      switch (argument_descriptions[i].type[0]) {
      case 'F':
      case 'f':
      case 'T':
        printf(*(int *) argument_descriptions[i].location ? "TRUE" : "FALSE");
        break;
      case 'I':
        printf("%d", *(int *) argument_descriptions[i].location);
        break;
      case 'D':
        printf("%f", *(double *) argument_descriptions[i].location);
        break;
      case 'L':
        printf("%" PRId64 "", *(int64_t *) argument_descriptions[i].location);
        break;
      case 'S':
        printf("%s", (char *) argument_descriptions[i].location);
        break;
      default:
        ink_fatal("bad argument description");
        break;
      }
      printf("\n");
    }
  }
}

void
process_args(const AppVersionInfo * appinfo, const ArgumentDescription * argument_descriptions, unsigned n_argument_descriptions, char **argv, const char *usage_string)
{
  unsigned i = 0;
  //
  // Grab Environment Variables
  //
  for (i = 0; i < n_argument_descriptions; i++)
    if (argument_descriptions[i].env) {
      char type = argument_descriptions[i].type[0];
      char *env = getenv(argument_descriptions[i].env);
      if (!env)
        continue;
      switch (type) {
      case 'f':
      case 'F':
      case 'I':
        *(int *) argument_descriptions[i].location = atoi(env);
        break;
      case 'D':
        *(double *) argument_descriptions[i].location = atof(env);
        break;
      case 'L':
        *(int64_t *) argument_descriptions[i].location = atoll(env);
        break;
      case 'S':
        ink_strlcpy((char *) argument_descriptions[i].location, env, atoi(argument_descriptions[i].type + 1));
        break;
      }
    }
  //
  // Grab Command Line Arguments
  //
  program_name = appinfo->AppStr;
  while (*++argv) {
    if (**argv == '-') {
      if ((*argv)[1] == '-') {
        for (i = 0; i < n_argument_descriptions; i++)
          if (!strcmp(argument_descriptions[i].name, (*argv) + 2)) {
            *argv += strlen(*argv) - 1;
            process_arg(appinfo, argument_descriptions, n_argument_descriptions, i, &argv, usage_string);
            break;
          }
        if (i >= n_argument_descriptions)
          usage(argument_descriptions, n_argument_descriptions, usage_string);
      } else {
        // Hack for supporting '-' as a file argument.
        if (strcmp(*argv, "-") == 0) {
          append_file_argument(*argv);
        }

        while (*++(*argv)) {
          for (i = 0; i < n_argument_descriptions; i++) {
            if (argument_descriptions[i].key == **argv) {
              process_arg(appinfo, argument_descriptions, n_argument_descriptions, i, &argv, usage_string);
              break;
            }
          }

          if (i >= n_argument_descriptions) {
            usage(argument_descriptions, n_argument_descriptions, usage_string);
          }
        }
      }
    } else {
      append_file_argument(*argv);
    }
  }
}

void
usage(const ArgumentDescription * argument_descriptions, unsigned n_argument_descriptions, const char *usage_string)
{
  (void) argument_descriptions;
  (void) n_argument_descriptions;
  (void) usage_string;
  if (usage_string)
    fprintf(stderr, "%s\n", usage_string);
  else
    fprintf(stderr, "Usage: %s [--SWITCH [ARG]]\n", program_name);
  fprintf(stderr, "  switch__________________type__default___description\n");
  for (unsigned i = 0; i < n_argument_descriptions; i++) {
    if (!argument_descriptions[i].description)
      continue;

    fprintf(stderr, "  ");

    if ('-' == argument_descriptions[i].key) fprintf(stderr, "   ");
    else fprintf(stderr, "-%c,", argument_descriptions[i].key);

    fprintf(stderr, " --%-17s %s",
            argument_descriptions[i].name,
            argument_types_descriptions[argument_descriptions[i].type ?
                                        strchr(argument_types_keys,
                                               argument_descriptions[i].type[0]) -
                                        argument_types_keys : strlen(argument_types_keys)
            ]);
    switch (argument_descriptions[i].type ? argument_descriptions[i].type[0] : 0) {
    case 0:
      fprintf(stderr, "          ");
      break;
    case 'L':
      fprintf(stderr, " %-9" PRId64 "", *(int64_t *) argument_descriptions[i].location);
      break;
    case 'S': {
      char * location;
      if (argument_descriptions[i].type[1] == '*') {
        location = *(char **)argument_descriptions[i].location;
      } else {
        location = (char *)argument_descriptions[i].location;
      }

      if (location) {
        if (strlen(location) < 10) {
          fprintf(stderr, " %-9s", location);
        } else {
          fprintf(stderr, " %-7.7s..", location);
        }
      } else {
        fprintf(stderr, " (null)   ");
      }
      break;
    }
    case 'D':
      fprintf(stderr, " %-9.3f", *(double *) argument_descriptions[i].location);
      break;
    case 'I':
      fprintf(stderr, " %-9d", *(int *) argument_descriptions[i].location);
      break;
    case 'T':
    case 'f':
    case 'F':
      if (argument_descriptions[i].location) {
        fprintf(stderr, " %-9s", *(int *) argument_descriptions[i].location ? "true " : "false");
      } else {
        fprintf(stderr, " %-9s", "false");
      }
      break;
    }
    fprintf(stderr, " %s\n", argument_descriptions[i].description);
  }
  _exit(1);
}
<|endoftext|>


<commit_before>#include <float.h>
#include "reductions.h"
#include "multiclass.h"
#include "cost_sensitive.h"
#include "cb.h"
#include "cb_algs.h"
#include "rand48.h"
#include "bs.h"
#include "MWT.h"

using namespace LEARNER;

namespace CBIFY {

  struct cbify {
    size_t k;

    size_t tau;

    float epsilon;

    size_t counter;

    size_t bags;
    v_array<float> count;
    v_array<uint32_t> predictions;

    CB::label cb_label;
    COST_SENSITIVE::label cs_label;
    COST_SENSITIVE::label second_cs_label;

    learner* cs;
    vw* all;
  };

  uint32_t do_uniform(cbify& data)
  {  //Draw an action
    return (uint32_t)ceil(frand48() * data.k);
  }

  uint32_t choose_bag(cbify& data)
  {  //Draw an action
    return (uint32_t)floor(frand48() * data.bags);
  }

  float loss(uint32_t label, uint32_t final_prediction)
  {
    if (label != final_prediction)
      return 1.;
    else
      return 0.;
  }

  template <bool is_learn>
  void predict_or_learn_first(cbify& data, learner& base, example& ec)
  {//Explore tau times, then act according to optimal.
    MULTICLASS::multiclass* ld = (MULTICLASS::multiclass*)ec.ld;
    //Use CB to find current prediction for remaining rounds.
    if (data.tau && is_learn)
      {
	ld->prediction = (uint32_t)do_uniform(data);
	ec.loss = loss(ld->label, ld->prediction);
	data.tau--;
	uint32_t action = ld->prediction;
	CB::cb_class l = {ec.loss, action, 1.f / data.k, 0};
	data.cb_label.costs.erase();
	data.cb_label.costs.push_back(l);
	ec.ld = &(data.cb_label);
	base.learn(ec);
	ld->prediction = action;
	ec.loss = l.cost;
      }
    else
      {
	data.cb_label.costs.erase();
	ec.ld = &(data.cb_label);
	base.predict(ec);
	ld->prediction = data.cb_label.prediction;
	ec.loss = loss(ld->label, ld->prediction);
      }
    ec.ld = ld;
  }

  u32 greedy_policy(void* context, void* application_context)
  {
	  vw_context* ctx = (vw_context*)context;
	  ctx->learner->predict(*ctx->example);
	  return (u32)(((CB::label*)ctx->example->ld)->prediction);
  }

  template <bool is_learn>
  void predict_or_learn_greedy(cbify& data, learner& base, example& ec)
  {//Explore uniform random an epsilon fraction of the time.
    MULTICLASS::multiclass* ld = (MULTICLASS::multiclass*)ec.ld;
    ec.ld = &(data.cb_label);
    data.cb_label.costs.erase();

	// TODO: ideally these call to modify the policy context are not needed,
	// however at the moment MWT::Initialize requires the policy function's argument
	// which is not available at calling time. This can be fixed if the Context object
	// allows for a void* data instance, then we can pass the argument in at the
	// time of choose_action. Or if Choose_Action takes a separate parameter for this arg.
	base.mwt_policy_context->learner = &base;
	base.mwt_policy_context->example = &ec;

	Context dummy(nullptr, 0);
    base.mwt->Choose_Action_Join_Key(dummy);

	size_t num_interactions = 0;
	Interaction** interactions = nullptr;
	base.mwt->Get_All_Interactions(num_interactions, interactions);

	if (num_interactions != 1)
	{
		throw std::exception();
	}

	u32 action = interactions[0]->Get_Action().Get_Id();
	float prob = interactions[0]->Get_Prob();

	CB::cb_class l = { loss(ld->label, ld->prediction), action, prob };
	data.cb_label.costs.push_back(l);

    if (is_learn)
      base.learn(ec);

    ld->prediction = action;
    ec.ld = ld;
    ec.loss = loss(ld->label, action);

	delete interactions[0];
	delete[] interactions;
  }

  template <bool is_learn>
  void predict_or_learn_bag(cbify& data, learner& base, example& ec)
  {//Randomize over predictions from a base set of predictors
    //Use CB to find current predictions.
    MULTICLASS::multiclass* ld = (MULTICLASS::multiclass*)ec.ld;
    ec.ld = &(data.cb_label);
    data.cb_label.costs.erase();

    for (size_t j = 1; j <= data.bags; j++)
       data.count[j] = 0;

    size_t bag = choose_bag(data);
    uint32_t action = 0;
    for (size_t i = 0; i < data.bags; i++)
      {
	base.predict(ec,i);
	data.count[data.cb_label.prediction]++;
	if (i == bag)
	  action = data.cb_label.prediction;
      }
    assert(action != 0);
    if (is_learn)
      {
	float probability = (float)data.count[action] / (float)data.bags;
	CB::cb_class l = {loss(ld->label, action),
			  action, probability};
	data.cb_label.costs.push_back(l);
	for (size_t i = 0; i < data.bags; i++)
	  {
	    uint32_t count = BS::weight_gen();
	    for (uint32_t j = 0; j < count; j++)
	      base.learn(ec,i);
	  }
      }
    ld->prediction = action;
    ec.ld = ld;
  }

  uint32_t choose_action(v_array<float>& distribution)
  {
    float value = frand48();
    for (uint32_t i = 0; i < distribution.size();i++)
      {
	if (value <= distribution[i])
	  return i+1;
	else
	  value -= distribution[i];
      }
    //some rounding problem presumably.
    return 1;
  }

  void safety(v_array<float>& distribution, float min_prob)
  {
    float added_mass = 0.;
    for (uint32_t i = 0; i < distribution.size();i++)
      if (distribution[i] > 0 && distribution[i] <= min_prob)
	{
	  added_mass += min_prob - distribution[i];
	  distribution[i] = min_prob;
	}

    float ratio = 1.f / (1.f + added_mass);
    if (ratio < 0.999)
      {
	for (uint32_t i = 0; i < distribution.size(); i++)
	  if (distribution[i] > min_prob)
	    distribution[i] = distribution[i] * ratio;
	safety(distribution, min_prob);
      }
  }

  void gen_cs_label(vw& all, CB::cb_class& known_cost, example& ec, COST_SENSITIVE::label& cs_ld, uint32_t label)
  {
    COST_SENSITIVE::wclass wc;

    //get cost prediction for this label
    wc.x = CB_ALGS::get_cost_pred<false>(all, &known_cost, ec, label, all.sd->k);
    wc.class_index = label;
    wc.partial_prediction = 0.;
    wc.wap_value = 0.;

    //add correction if we observed cost for this action and regressor is wrong
    if( known_cost.action == label )
      wc.x += (known_cost.cost - wc.x) / known_cost.probability;

    cs_ld.costs.push_back( wc );
  }

  template <bool is_learn>
  void predict_or_learn_cover(cbify& data, learner& base, example& ec)
  {//Randomize over predictions from a base set of predictors
    //Use cost sensitive oracle to cover actions to form distribution.
    MULTICLASS::multiclass* ld = (MULTICLASS::multiclass*)ec.ld;
    data.counter++;

    data.count.erase();
    data.cs_label.costs.erase();
    for (uint32_t j = 0; j < data.k; j++)
      {
	data.count.push_back(0);

	COST_SENSITIVE::wclass wc;

	//get cost prediction for this label
	wc.x = FLT_MAX;
	wc.class_index = j+1;
	wc.partial_prediction = 0.;
	wc.wap_value = 0.;
	data.cs_label.costs.push_back(wc);
      }

    float additive_probability = 1.f / (float)data.bags;

    ec.ld = &data.cs_label;
    for (size_t i = 0; i < data.bags; i++)
      { //get predicted cost-sensitive predictions
	if (i == 0)
	  data.cs->predict(ec, i);
	else
	  data.cs->predict(ec,i+1);
	data.count[data.cs_label.prediction-1] += additive_probability;
	data.predictions[i] = (uint32_t)data.cs_label.prediction;
      }

    float min_prob = data.epsilon * min (1.f / data.k, 1.f / (float)sqrt(data.counter * data.k));

    safety(data.count, min_prob);

    //compute random action
    uint32_t action = choose_action(data.count);

    if (is_learn)
      {
	data.cb_label.costs.erase();
	float probability = (float)data.count[action-1];
	CB::cb_class l = {loss(ld->label, action),
			  action, probability};
	data.cb_label.costs.push_back(l);
	ec.ld = &(data.cb_label);
	base.learn(ec);

	//Now update oracles

	//1. Compute loss vector
	data.cs_label.costs.erase();
	float norm = min_prob * data.k;
	for (uint32_t j = 0; j < data.k; j++)
	  { //data.cs_label now contains an unbiased estimate of cost of each class.
	    gen_cs_label(*data.all, l, ec, data.cs_label, j+1);
	    data.count[j] = 0;
	  }

	ec.ld = &data.second_cs_label;
	//2. Update functions
	for (size_t i = 0; i < data.bags; i++)
	  { //get predicted cost-sensitive predictions
	    for (uint32_t j = 0; j < data.k; j++)
	      {
		float pseudo_cost = data.cs_label.costs[j].x - data.epsilon * min_prob / (max(data.count[j], min_prob) / norm) + 1;
		data.second_cs_label.costs[j].class_index = j+1;
		data.second_cs_label.costs[j].x = pseudo_cost;
	      }
	    if (i != 0)
	      data.cs->learn(ec,i+1);
	    if (data.count[data.predictions[i]-1] < min_prob)
	      norm += max(0, additive_probability - (min_prob - data.count[data.predictions[i]-1]));
	    else
	      norm += additive_probability;
	    data.count[data.predictions[i]-1] += additive_probability;
	  }
      }

    ld->prediction = action;
    ec.ld = ld;
  }

  void init_driver(cbify&) {}

  void finish_example(vw& all, cbify&, example& ec)
  {
    MULTICLASS::output_example(all, ec);
    VW::finish_example(all, &ec);
  }

  learner* setup(vw& all, po::variables_map& vm)
  {//parse and set arguments
    cbify* data = (cbify*)calloc_or_die(1, sizeof(cbify));

    data->epsilon = 0.05f;
    data->counter = 0;
    data->tau = 1000;
    data->all = &all;
    po::options_description cb_opts("CBIFY options");
    cb_opts.add_options()
      ("first", po::value<size_t>(), "tau-first exploration")
      ("epsilon",po::value<float>() ,"epsilon-greedy exploration")
      ("bag",po::value<size_t>() ,"bagging-based exploration")
      ("cover",po::value<size_t>() ,"bagging-based exploration");

    vm = add_options(all, cb_opts);

    data->k = (uint32_t)vm["cbify"].as<size_t>();

    //appends nb_actions to options_from_file so it is saved to regressor later
    std::stringstream ss;
    ss << " --cbify " << data->k;
    all.file_options.append(ss.str());

    all.p->lp = MULTICLASS::mc_label;
    learner* l;
    if (vm.count("cover"))
      {
	data->bags = (uint32_t)vm["cover"].as<size_t>();
	data->cs = all.cost_sensitive;
	data->count.resize(data->k);
	data->predictions.resize(data->bags);
	data->second_cs_label.costs.resize(data->k);
	data->second_cs_label.costs.end = data->second_cs_label.costs.begin+data->k;
	if ( vm.count("epsilon") )
	  data->epsilon = vm["epsilon"].as<float>();
	l = new learner(data, all.l, data->bags + 1);
	l->set_learn<cbify, predict_or_learn_cover<true> >();
	l->set_predict<cbify, predict_or_learn_cover<false> >();
      }
    else if (vm.count("bag"))
      {
	data->bags = (uint32_t)vm["bag"].as<size_t>();
	data->count.resize(data->bags+1);
	l = new learner(data, all.l, data->bags);
	l->set_learn<cbify, predict_or_learn_bag<true> >();
	l->set_predict<cbify, predict_or_learn_bag<false> >();
      }
    else if (vm.count("first") )
      {
	data->tau = (uint32_t)vm["first"].as<size_t>();
	l = new learner(data, all.l, 1);
	l->set_learn<cbify, predict_or_learn_first<true> >();
	l->set_predict<cbify, predict_or_learn_first<false> >();
      }
    else
      {
	if ( vm.count("epsilon") )
	  data->epsilon = vm["epsilon"].as<float>();
	l = new learner(data, all.l, 1);
	all.l->mwt = new MWT(string("VW"), data->k);
	all.l->mwt_policy_context = new vw_context();
	all.l->mwt->Initialize_Epsilon_Greedy(data->epsilon, greedy_policy, all.l->mwt_policy_context);
	l->set_learn<cbify, predict_or_learn_greedy<true> >();
	l->set_predict<cbify, predict_or_learn_greedy<false> >();
      }

    l->set_finish_example<cbify,finish_example>();
    l->set_init_driver<cbify,init_driver>();

    return l;
  }
}
<commit_msg>fixes 4<commit_after>#include <float.h>
#include "reductions.h"
#include "multiclass.h"
#include "cost_sensitive.h"
#include "cb.h"
#include "cb_algs.h"
#include "rand48.h"
#include "bs.h"
#include "MWT.h"

using namespace LEARNER;

namespace CBIFY {

  struct cbify {
    size_t k;

    size_t tau;

    float epsilon;

    size_t counter;

    size_t bags;
    v_array<float> count;
    v_array<uint32_t> predictions;

    CB::label cb_label;
    COST_SENSITIVE::label cs_label;
    COST_SENSITIVE::label second_cs_label;

    learner* cs;
    vw* all;
  };

  uint32_t do_uniform(cbify& data)
  {  //Draw an action
    return (uint32_t)ceil(frand48() * data.k);
  }

  uint32_t choose_bag(cbify& data)
  {  //Draw an action
    return (uint32_t)floor(frand48() * data.bags);
  }

  float loss(uint32_t label, uint32_t final_prediction)
  {
    if (label != final_prediction)
      return 1.;
    else
      return 0.;
  }

  u32 explore_policy(void* context, void* application_context)
  {
	  vw_context* ctx = (vw_context*)context;
	  ctx->learner->predict(*ctx->example);
	  return (u32)(((CB::label*)ctx->example->ld)->prediction);
  }

  template <bool is_learn>
  void predict_or_learn_first(cbify& data, learner& base, example& ec)
  {//Explore tau times, then act according to optimal.
    MULTICLASS::multiclass* ld = (MULTICLASS::multiclass*)ec.ld;
	base.mwt_policy_context->learner = &base;
	base.mwt_policy_context->example = &ec;
	Context dummy(nullptr, 0);
    //Use CB to find current prediction for remaining rounds.
    if (data.tau && is_learn)
      {
	ld->prediction = (uint32_t)base.mwt->Choose_Action_Join_Key(dummy).first;
	ec.loss = loss(ld->label, ld->prediction);
	data.tau--;
	uint32_t action = ld->prediction;
	CB::cb_class l = {ec.loss, action, 1.f / data.k, 0};
	data.cb_label.costs.erase();
	data.cb_label.costs.push_back(l);
	ec.ld = &(data.cb_label);
	base.learn(ec);
	ld->prediction = action;
	ec.loss = l.cost;
      }
    else
      {
	data.cb_label.costs.erase();
	ec.ld = &(data.cb_label);
	ld->prediction = (uint32_t)base.mwt->Choose_Action_Join_Key(dummy).first;
	ec.loss = loss(ld->label, ld->prediction);
      }
    ec.ld = ld;
  }

  template <bool is_learn>
  void predict_or_learn_greedy(cbify& data, learner& base, example& ec)
  {//Explore uniform random an epsilon fraction of the time.
    MULTICLASS::multiclass* ld = (MULTICLASS::multiclass*)ec.ld;
    ec.ld = &(data.cb_label);
    data.cb_label.costs.erase();

	// TODO: ideally these call to modify the policy context are not needed,
	// however at the moment MWT::Initialize requires the policy function's argument
	// which is not available at calling time. This can be fixed if the Context object
	// allows for a void* data instance, then we can pass the argument in at the
	// time of choose_action. Or if Choose_Action takes a separate parameter for this arg.
	base.mwt_policy_context->learner = &base;
	base.mwt_policy_context->example = &ec;

	Context dummy(nullptr, 0);
    base.mwt->Choose_Action_Join_Key(dummy);

	size_t num_interactions = 0;
	Interaction** interactions = nullptr;
	base.mwt->Get_All_Interactions(num_interactions, interactions);

	if (num_interactions != 1)
	{
		throw std::exception();
	}

	u32 action = interactions[0]->Get_Action().Get_Id();
	float prob = interactions[0]->Get_Prob();

	CB::cb_class l = { loss(ld->label, ld->prediction), action, prob };
	data.cb_label.costs.push_back(l);

    if (is_learn)
      base.learn(ec);

    ld->prediction = action;
    ec.ld = ld;
    ec.loss = loss(ld->label, action);

	delete interactions[0];
	delete[] interactions;
  }

  template <bool is_learn>
  void predict_or_learn_bag(cbify& data, learner& base, example& ec)
  {//Randomize over predictions from a base set of predictors
    //Use CB to find current predictions.
    MULTICLASS::multiclass* ld = (MULTICLASS::multiclass*)ec.ld;
    ec.ld = &(data.cb_label);
    data.cb_label.costs.erase();

    for (size_t j = 1; j <= data.bags; j++)
       data.count[j] = 0;

    size_t bag = choose_bag(data);
    uint32_t action = 0;
    for (size_t i = 0; i < data.bags; i++)
      {
	base.predict(ec,i);
	data.count[data.cb_label.prediction]++;
	if (i == bag)
	  action = data.cb_label.prediction;
      }
    assert(action != 0);
    if (is_learn)
      {
	float probability = (float)data.count[action] / (float)data.bags;
	CB::cb_class l = {loss(ld->label, action),
			  action, probability};
	data.cb_label.costs.push_back(l);
	for (size_t i = 0; i < data.bags; i++)
	  {
	    uint32_t count = BS::weight_gen();
	    for (uint32_t j = 0; j < count; j++)
	      base.learn(ec,i);
	  }
      }
    ld->prediction = action;
    ec.ld = ld;
  }

  uint32_t choose_action(v_array<float>& distribution)
  {
    float value = frand48();
    for (uint32_t i = 0; i < distribution.size();i++)
      {
	if (value <= distribution[i])
	  return i+1;
	else
	  value -= distribution[i];
      }
    //some rounding problem presumably.
    return 1;
  }

  void safety(v_array<float>& distribution, float min_prob)
  {
    float added_mass = 0.;
    for (uint32_t i = 0; i < distribution.size();i++)
      if (distribution[i] > 0 && distribution[i] <= min_prob)
	{
	  added_mass += min_prob - distribution[i];
	  distribution[i] = min_prob;
	}

    float ratio = 1.f / (1.f + added_mass);
    if (ratio < 0.999)
      {
	for (uint32_t i = 0; i < distribution.size(); i++)
	  if (distribution[i] > min_prob)
	    distribution[i] = distribution[i] * ratio;
	safety(distribution, min_prob);
      }
  }

  void gen_cs_label(vw& all, CB::cb_class& known_cost, example& ec, COST_SENSITIVE::label& cs_ld, uint32_t label)
  {
    COST_SENSITIVE::wclass wc;

    //get cost prediction for this label
    wc.x = CB_ALGS::get_cost_pred<false>(all, &known_cost, ec, label, all.sd->k);
    wc.class_index = label;
    wc.partial_prediction = 0.;
    wc.wap_value = 0.;

    //add correction if we observed cost for this action and regressor is wrong
    if( known_cost.action == label )
      wc.x += (known_cost.cost - wc.x) / known_cost.probability;

    cs_ld.costs.push_back( wc );
  }

  template <bool is_learn>
  void predict_or_learn_cover(cbify& data, learner& base, example& ec)
  {//Randomize over predictions from a base set of predictors
    //Use cost sensitive oracle to cover actions to form distribution.
    MULTICLASS::multiclass* ld = (MULTICLASS::multiclass*)ec.ld;
    data.counter++;

    data.count.erase();
    data.cs_label.costs.erase();
    for (uint32_t j = 0; j < data.k; j++)
      {
	data.count.push_back(0);

	COST_SENSITIVE::wclass wc;

	//get cost prediction for this label
	wc.x = FLT_MAX;
	wc.class_index = j+1;
	wc.partial_prediction = 0.;
	wc.wap_value = 0.;
	data.cs_label.costs.push_back(wc);
      }

    float additive_probability = 1.f / (float)data.bags;

    ec.ld = &data.cs_label;
    for (size_t i = 0; i < data.bags; i++)
      { //get predicted cost-sensitive predictions
	if (i == 0)
	  data.cs->predict(ec, i);
	else
	  data.cs->predict(ec,i+1);
	data.count[data.cs_label.prediction-1] += additive_probability;
	data.predictions[i] = (uint32_t)data.cs_label.prediction;
      }

    float min_prob = data.epsilon * min (1.f / data.k, 1.f / (float)sqrt(data.counter * data.k));

    safety(data.count, min_prob);

    //compute random action
    uint32_t action = choose_action(data.count);

    if (is_learn)
      {
	data.cb_label.costs.erase();
	float probability = (float)data.count[action-1];
	CB::cb_class l = {loss(ld->label, action),
			  action, probability};
	data.cb_label.costs.push_back(l);
	ec.ld = &(data.cb_label);
	base.learn(ec);

	//Now update oracles

	//1. Compute loss vector
	data.cs_label.costs.erase();
	float norm = min_prob * data.k;
	for (uint32_t j = 0; j < data.k; j++)
	  { //data.cs_label now contains an unbiased estimate of cost of each class.
	    gen_cs_label(*data.all, l, ec, data.cs_label, j+1);
	    data.count[j] = 0;
	  }

	ec.ld = &data.second_cs_label;
	//2. Update functions
	for (size_t i = 0; i < data.bags; i++)
	  { //get predicted cost-sensitive predictions
	    for (uint32_t j = 0; j < data.k; j++)
	      {
		float pseudo_cost = data.cs_label.costs[j].x - data.epsilon * min_prob / (max(data.count[j], min_prob) / norm) + 1;
		data.second_cs_label.costs[j].class_index = j+1;
		data.second_cs_label.costs[j].x = pseudo_cost;
	      }
	    if (i != 0)
	      data.cs->learn(ec,i+1);
	    if (data.count[data.predictions[i]-1] < min_prob)
	      norm += max(0, additive_probability - (min_prob - data.count[data.predictions[i]-1]));
	    else
	      norm += additive_probability;
	    data.count[data.predictions[i]-1] += additive_probability;
	  }
      }

    ld->prediction = action;
    ec.ld = ld;
  }

  void init_driver(cbify&) {}

  void finish_example(vw& all, cbify&, example& ec)
  {
    MULTICLASS::output_example(all, ec);
    VW::finish_example(all, &ec);
  }

  learner* setup(vw& all, po::variables_map& vm)
  {//parse and set arguments
    cbify* data = (cbify*)calloc_or_die(1, sizeof(cbify));

    data->epsilon = 0.05f;
    data->counter = 0;
    data->tau = 1000;
    data->all = &all;
    po::options_description cb_opts("CBIFY options");
    cb_opts.add_options()
      ("first", po::value<size_t>(), "tau-first exploration")
      ("epsilon",po::value<float>() ,"epsilon-greedy exploration")
      ("bag",po::value<size_t>() ,"bagging-based exploration")
      ("cover",po::value<size_t>() ,"bagging-based exploration");

    vm = add_options(all, cb_opts);

    data->k = (uint32_t)vm["cbify"].as<size_t>();

    //appends nb_actions to options_from_file so it is saved to regressor later
    std::stringstream ss;
    ss << " --cbify " << data->k;
    all.file_options.append(ss.str());

    all.p->lp = MULTICLASS::mc_label;
    learner* l;
    if (vm.count("cover"))
      {
	data->bags = (uint32_t)vm["cover"].as<size_t>();
	data->cs = all.cost_sensitive;
	data->count.resize(data->k);
	data->predictions.resize(data->bags);
	data->second_cs_label.costs.resize(data->k);
	data->second_cs_label.costs.end = data->second_cs_label.costs.begin+data->k;
	if ( vm.count("epsilon") )
	  data->epsilon = vm["epsilon"].as<float>();
	l = new learner(data, all.l, data->bags + 1);
	l->set_learn<cbify, predict_or_learn_cover<true> >();
	l->set_predict<cbify, predict_or_learn_cover<false> >();
      }
    else if (vm.count("bag"))
      {
	data->bags = (uint32_t)vm["bag"].as<size_t>();
	data->count.resize(data->bags+1);
	l = new learner(data, all.l, data->bags);
	l->set_learn<cbify, predict_or_learn_bag<true> >();
	l->set_predict<cbify, predict_or_learn_bag<false> >();
      }
    else if (vm.count("first") )
      {
	data->tau = (uint32_t)vm["first"].as<size_t>();
	l = new learner(data, all.l, 1);
	all.l->mwt = new MWT(string("VW"), data->k);
	all.l->mwt_policy_context = new vw_context();
	all.l->mwt->Initialize_Tau_First(data->tau, explore_policy, all.l->mwt_policy_context);
	l->set_learn<cbify, predict_or_learn_first<true> >();
	l->set_predict<cbify, predict_or_learn_first<false> >();
      }
    else
      {
	if ( vm.count("epsilon") )
	  data->epsilon = vm["epsilon"].as<float>();
	l = new learner(data, all.l, 1);
	all.l->mwt = new MWT(string("VW"), data->k);
	all.l->mwt_policy_context = new vw_context();
	all.l->mwt->Initialize_Epsilon_Greedy(data->epsilon, explore_policy, all.l->mwt_policy_context);
	l->set_learn<cbify, predict_or_learn_greedy<true> >();
	l->set_predict<cbify, predict_or_learn_greedy<false> >();
      }

    l->set_finish_example<cbify,finish_example>();
    l->set_init_driver<cbify,init_driver>();

    return l;
  }
}
<|endoftext|>


<commit_before>#include <boost/python.hpp>
#include <boost/core/noncopyable.hpp>

#include <sm/PropertyTree.hpp>
#include <sm/value_store/ValueStore.hpp>
#include <functional>

void exportValueStoreRef()
{
  using namespace boost::python;
  using namespace sm::value_store;

  /// brief create a value store reference pointing to a fresh empty value store (based on @see sm::BoostPropertyTree)
  class_<ValueStoreRef>("ValueStoreRef", init<>())
    .def(init<ValueStoreRef>())
    .def(init<ValueStore::SharedPtr>())
    .def(init<sm::PropertyTree>())
    /// ValueStoreRef getChild(const std::string & key)
    .def("getChild", &ValueStoreRef::getChild)
    /// sm::ConstPropertyTree asPropertyTree() const
    .def("asPropertyTree", &ValueStoreRef::asPropertyTree)
    /// brief Create a ValueStoreRef to a BoostPropertyTree loaded from file using @see sm::BoostPropertyTree::load .
    /// static ValueStoreRef fromFile(const std::string & path)
    .def("fromFile", &ValueStoreRef::fromFile).staticmethod("fromFile")
    /// brief Create a ValueStoreRef to a BoostPropertyTree loaded from file using @see sm::BoostPropertyTree::load .
    /// static ValueStoreRef fromFile(const std::string & path)
    .def("fromString", &ValueStoreRef::fromString).staticmethod("fromString")
    /// ValueHandle<bool> getBool(const std::string & path, boost::optional<bool> def = boost::optional<bool>()) const;
    .def("getBool", +[](ValueStoreRef * vs, const std::string & path){return vs->getBool(path).get();})
    .def("getBool", +[](ValueStoreRef * vs, const std::string & path, bool defaultValue){return vs->getBool(path, defaultValue).get();})
    /// ValueHandle<int> getInt(const std::string & path, boost::optional<int> def = boost::optional<int>()) const;
    .def("getInt", +[](ValueStoreRef * vs, const std::string & path){return vs->getInt(path).get();})
    .def("getInt", +[](ValueStoreRef * vs, const std::string & path, int defaultValue){return vs->getInt(path, defaultValue).get();})
    /// ValueHandle<double> getDouble(const std::string & path, boost::optional<double> def = boost::optional<double>()) const;
    .def("getDouble", +[](ValueStoreRef * vs, const std::string & path){return vs->getDouble(path).get();})
    .def("getDouble", +[](ValueStoreRef * vs, const std::string & path, double defaultValue){return vs->getDouble(path, defaultValue).get();})
    /// ValueHandle<std::string> getString(const std::string & path, boost::optional<std::string> def = boost::optional<std::string>()) const;
    .def("getString", +[](ValueStoreRef * vs, const std::string & path){return vs->getString(path).get();})
    .def("getString", +[](ValueStoreRef * vs, const std::string & path, const std::string & defaultValue){return vs->getString(path, defaultValue).get();})
  ;
}
<commit_msg>Removed unused <boost/core/noncopyable.hpp><commit_after>#include <boost/python.hpp>

#include <sm/PropertyTree.hpp>
#include <sm/value_store/ValueStore.hpp>
#include <functional>

void exportValueStoreRef()
{
  using namespace boost::python;
  using namespace sm::value_store;

  /// brief create a value store reference pointing to a fresh empty value store (based on @see sm::BoostPropertyTree)
  class_<ValueStoreRef>("ValueStoreRef", init<>())
    .def(init<ValueStoreRef>())
    .def(init<ValueStore::SharedPtr>())
    .def(init<sm::PropertyTree>())
    /// ValueStoreRef getChild(const std::string & key)
    .def("getChild", &ValueStoreRef::getChild)
    /// sm::ConstPropertyTree asPropertyTree() const
    .def("asPropertyTree", &ValueStoreRef::asPropertyTree)
    /// brief Create a ValueStoreRef to a BoostPropertyTree loaded from file using @see sm::BoostPropertyTree::load .
    /// static ValueStoreRef fromFile(const std::string & path)
    .def("fromFile", &ValueStoreRef::fromFile).staticmethod("fromFile")
    /// brief Create a ValueStoreRef to a BoostPropertyTree loaded from file using @see sm::BoostPropertyTree::load .
    /// static ValueStoreRef fromFile(const std::string & path)
    .def("fromString", &ValueStoreRef::fromString).staticmethod("fromString")
    /// ValueHandle<bool> getBool(const std::string & path, boost::optional<bool> def = boost::optional<bool>()) const;
    .def("getBool", +[](ValueStoreRef * vs, const std::string & path){return vs->getBool(path).get();})
    .def("getBool", +[](ValueStoreRef * vs, const std::string & path, bool defaultValue){return vs->getBool(path, defaultValue).get();})
    /// ValueHandle<int> getInt(const std::string & path, boost::optional<int> def = boost::optional<int>()) const;
    .def("getInt", +[](ValueStoreRef * vs, const std::string & path){return vs->getInt(path).get();})
    .def("getInt", +[](ValueStoreRef * vs, const std::string & path, int defaultValue){return vs->getInt(path, defaultValue).get();})
    /// ValueHandle<double> getDouble(const std::string & path, boost::optional<double> def = boost::optional<double>()) const;
    .def("getDouble", +[](ValueStoreRef * vs, const std::string & path){return vs->getDouble(path).get();})
    .def("getDouble", +[](ValueStoreRef * vs, const std::string & path, double defaultValue){return vs->getDouble(path, defaultValue).get();})
    /// ValueHandle<std::string> getString(const std::string & path, boost::optional<std::string> def = boost::optional<std::string>()) const;
    .def("getString", +[](ValueStoreRef * vs, const std::string & path){return vs->getString(path).get();})
    .def("getString", +[](ValueStoreRef * vs, const std::string & path, const std::string & defaultValue){return vs->getString(path, defaultValue).get();})
  ;
}
<|endoftext|>