/*
    PIP - Platform Independent Primitives
    Dynamic library
    Copyright (C) 2015  Ivan Pelipenko peri4ko@gmail.com

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "pilibrary.h"
#ifndef WINDOWS
#  include <dlfcn.h>
#endif


PRIVATE_DEFINITION_START(PILibrary)
#ifdef WINDOWS
	HMODULE
#else
	void *
#endif
			hLib;
PRIVATE_DEFINITION_END(PILibrary)


PILibrary::PILibrary(const PIString & path_) {
	PRIVATE->hLib = 0;
	load(path_);
}


PILibrary::~PILibrary() {
	unload();
}


bool PILibrary::load(const PIString & path_) {
	libpath = path_;
	return loadInternal();
}


bool PILibrary::load() {
	return loadInternal();
}


void PILibrary::unload() {
	if (PRIVATE->hLib == 0) return;
#ifdef WINDOWS
	FreeLibrary(PRIVATE->hLib);
#else
	dlclose(PRIVATE->hLib);
#endif
	PRIVATE->hLib = 0;
}


bool PILibrary::isLoaded() const {
	return PRIVATE->hLib;
}


void * PILibrary::resolve(const char * symbol) {
	if (!isLoaded()) return 0;
	void * ret;
#ifdef WINDOWS
	ret = (void*)GetProcAddress(PRIVATE->hLib, symbol);
#else
	ret = dlsym(PRIVATE->hLib, symbol);
#endif
	getLastError();
	return ret;
}


bool PILibrary::loadInternal() {
	unload();
	if (libpath.isEmpty()) return false;
#ifdef WINDOWS
	PRIVATE->hLib = LoadLibrary(libpath.data());
#else
	PRIVATE->hLib = dlopen(libpath.data(), RTLD_LAZY);
#endif
	getLastError();
	return PRIVATE->hLib;
}


void PILibrary::getLastError() {
#ifdef WINDOWS
	liberror = errorString();
#else
	const char * e = dlerror();
	if (e) liberror = e;
	else liberror.clear();
#endif
}
