/*M/////////////////////////////////////////////////////////////////////////////////////// // // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. // // By downloading, copying, installing or using the software you agree to this license. // If you do not agree to this license, do not download, install, // copy or use the software. // // // License Agreement // For Open Source Computer Vision Library // // Copyright (C) 2000-2008, Intel Corporation, all rights reserved. // Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. // Third party copyrights are property of their respective owners. // // Redistribution and use in source and binary forms, with or without modification, // are permitted provided that the following conditions are met: // // * Redistribution's of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // // * Redistribution's in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // // * The name of the copyright holders may not be used to endorse or promote products // derived from this software without specific prior written permission. // // This software is provided by the copyright holders and contributors "as is" and // any express or implied warranties, including, but not limited to, the implied // warranties of merchantability and fitness for a particular purpose are disclaimed. // In no event shall the Intel Corporation or contributors be liable for any direct, // indirect, incidental, special, exemplary, or consequential damages // (including, but not limited to, procurement of substitute goods or services; // loss of use, data, or profits; or business interruption) however caused // and on any theory of liability, whether in contract, strict liability, // or tort (including negligence or otherwise) arising in any way out of // the use of this software, even if advised of the possibility of such damage. // //M*/ #include "precomp.hpp" namespace cv { using std::pair; template struct sorted_vector { sorted_vector() {} void clear() { vec.clear(); } size_t size() const { return vec.size(); } _ValueTp& operator [](size_t idx) { return vec[idx]; } const _ValueTp& operator [](size_t idx) const { return vec[idx]; } void add(const _KeyTp& k, const _ValueTp& val) { pair<_KeyTp, _ValueTp> p(k, val); vec.push_back(p); size_t i = vec.size()-1; for( ; i > 0 && vec[i].first < vec[i-1].first; i-- ) std::swap(vec[i-1], vec[i]); CV_Assert( i == 0 || vec[i].first != vec[i-1].first ); } bool find(const _KeyTp& key, _ValueTp& value) const { size_t a = 0, b = vec.size(); while( b > a ) { size_t c = (a + b)/2; if( vec[c].first < key ) a = c+1; else b = c; } if( vec[a].first == key ) { value = vec[a].second; return true; } return false; } void get_keys(vector<_KeyTp>& keys) const { size_t i = 0, n = vec.size(); keys.resize(n); for( i = 0; i < n; i++ ) keys[i] = vec[i].first; } vector > vec; }; template inline const _ValueTp* findstr(const sorted_vector& vec, const char* key) { if( !key ) return 0; size_t a = 0, b = vec.vec.size(); while( b > a ) { size_t c = (a + b)/2; if( strcmp(vec.vec[c].first.c_str(), key) < 0 ) a = c+1; else b = c; } if( strcmp(vec.vec[a].first.c_str(), key) == 0 ) return &vec.vec[a].second; return 0; } Param::Param() { type = 0; offset = 0; readonly = false; getter = 0; setter = 0; } Param::Param(int _type, bool _readonly, int _offset, Algorithm::Getter _getter, Algorithm::Setter _setter, const string& _help) { type = _type; readonly = _readonly; offset = _offset; getter = _getter; setter = _setter; help = _help; } struct CV_EXPORTS AlgorithmInfoData { sorted_vector params; string _name; }; static sorted_vector alglist; void Algorithm::getList(vector& algorithms) { alglist.get_keys(algorithms); } Ptr Algorithm::_create(const string& name) { Algorithm::Constructor c = 0; if( !alglist.find(name, c) ) return Ptr(); return c(); } Algorithm::Algorithm() { } Algorithm::~Algorithm() { } string Algorithm::name() const { return info()->name(); } string Algorithm::paramHelp(const string& name) const { return info()->paramHelp(name.c_str()); } int Algorithm::paramType(const string& name) const { return info()->paramType(name.c_str()); } int Algorithm::paramType(const char* name) const { return info()->paramType(name); } void Algorithm::getParams(vector& names) const { info()->getParams(names); } void Algorithm::write(FileStorage& fs) const { info()->write(this, fs); } void Algorithm::read(const FileNode& fn) { info()->read(this, fn); } AlgorithmInfo::AlgorithmInfo(const string& _name, Algorithm::Constructor create) { data = new AlgorithmInfoData; data->_name = _name; alglist.add(_name, create); } AlgorithmInfo::~AlgorithmInfo() { delete data; } void AlgorithmInfo::write(const Algorithm* algo, FileStorage& fs) const { size_t i = 0, n = data->params.vec.size(); cv::write(fs, "name", algo->name()); for( i = 0; i < n; i++ ) { const Param& p = data->params.vec[i].second; const string& pname = data->params.vec[i].first; if( p.type == Param::INT ) cv::write(fs, pname, algo->get(pname)); else if( p.type == Param::BOOLEAN ) cv::write(fs, pname, (int)algo->get(pname)); else if( p.type == Param::REAL ) cv::write(fs, pname, algo->get(pname)); else if( p.type == Param::STRING ) cv::write(fs, pname, algo->get(pname)); else if( p.type == Param::MAT ) cv::write(fs, pname, algo->get(pname)); else if( p.type == Param::ALGORITHM ) { WriteStructContext ws(fs, pname, CV_NODE_MAP); Ptr nestedAlgo = algo->get(pname); nestedAlgo->write(fs); } else CV_Error( CV_StsUnsupportedFormat, "unknown/unsupported parameter type"); } } void AlgorithmInfo::read(Algorithm* algo, const FileNode& fn) const { size_t i = 0, n = data->params.vec.size(); for( i = 0; i < n; i++ ) { const Param& p = data->params.vec[i].second; const string& pname = data->params.vec[i].first; FileNode n = fn[pname]; if( n.empty() ) continue; if( p.type == Param::INT ) algo->set(pname, (int)n); else if( p.type == Param::BOOLEAN ) algo->set(pname, (int)n != 0); else if( p.type == Param::REAL ) algo->set(pname, (double)n); else if( p.type == Param::STRING ) algo->set(pname, (string)n); else if( p.type == Param::MAT ) { Mat m; cv::read(fn, m); algo->set(pname, m); } else if( p.type == Param::ALGORITHM ) { Ptr nestedAlgo = Algorithm::_create((string)n["name"]); CV_Assert( !nestedAlgo.empty() ); nestedAlgo->read(n); algo->set(pname, nestedAlgo); } else CV_Error( CV_StsUnsupportedFormat, "unknown/unsupported parameter type"); } } string AlgorithmInfo::name() const { return data->_name; } union GetSetParam { int (Algorithm::*get_int)() const; bool (Algorithm::*get_bool)() const; double (Algorithm::*get_double)() const; string (Algorithm::*get_string)() const; Mat (Algorithm::*get_mat)() const; Ptr (Algorithm::*get_algo)() const; void (Algorithm::*set_int)(int); void (Algorithm::*set_bool)(bool); void (Algorithm::*set_double)(double); void (Algorithm::*set_string)(const string&); void (Algorithm::*set_mat)(const Mat&); void (Algorithm::*set_algo)(const Ptr&); }; void AlgorithmInfo::set(Algorithm* algo, const char* name, int argType, const void* value) const { const Param* p = findstr(data->params, name); if( !p ) CV_Error_( CV_StsBadArg, ("No parameter '%s' is found", name ? name : "") ); if( p->readonly ) CV_Error_( CV_StsError, ("Parameter '%s' is readonly", name)); GetSetParam f; f.set_int = p->setter; if( argType == Param::INT || argType == Param::BOOLEAN || argType == Param::REAL ) { CV_Assert( p->type == Param::INT || p->type == Param::REAL || p->type == Param::BOOLEAN ); if( p->type == Param::INT ) { int val = argType == Param::INT ? *(const int*)value : argType == Param::BOOLEAN ? (int)*(const bool*)value : saturate_cast(*(const double*)value); if( p->setter ) (algo->*f.set_int)(val); else *(int*)((uchar*)algo + p->offset) = val; } else if( p->type == Param::BOOLEAN ) { bool val = argType == Param::INT ? *(const int*)value != 0 : argType == Param::BOOLEAN ? *(const bool*)value : *(const double*)value != 0; if( p->setter ) (algo->*f.set_bool)(val); else *(bool*)((uchar*)algo + p->offset) = val; } else { double val = argType == Param::INT ? (double)*(const int*)value : argType == Param::BOOLEAN ? (double)*(const bool*)value : *(const double*)value; if( p->setter ) (algo->*f.set_double)(val); else *(double*)((uchar*)algo + p->offset) = val; } } else if( argType == Param::STRING ) { CV_Assert( p->type == Param::STRING ); const string& val = *(const string*)value; if( p->setter ) (algo->*f.set_string)(val); else *(string*)((uchar*)algo + p->offset) = val; } else if( argType == Param::MAT ) { CV_Assert( p->type == Param::MAT ); const Mat& val = *(const Mat*)value; if( p->setter ) (algo->*f.set_mat)(val); else *(Mat*)((uchar*)algo + p->offset) = val; } else if( argType == Param::ALGORITHM ) { CV_Assert( p->type == Param::ALGORITHM ); const Ptr& val = *(const Ptr*)value; if( p->setter ) (algo->*f.set_algo)(val); else *(Ptr*)((uchar*)algo + p->offset) = val; } else CV_Error(CV_StsBadArg, "Unknown/unsupported parameter type"); } void AlgorithmInfo::get(const Algorithm* algo, const char* name, int argType, void* value) const { const Param* p = findstr(data->params, name); if( !p ) CV_Error_( CV_StsBadArg, ("No parameter '%s' is found", name ? name : "") ); GetSetParam f; f.get_int = p->getter; if( argType == Param::INT || argType == Param::BOOLEAN || argType == Param::REAL ) { if( p->type == Param::INT ) { CV_Assert( argType == Param::INT || argType == Param::REAL ); int val = p->getter ? (algo->*f.get_int)() : *(int*)((uchar*)algo + p->offset); if( argType == Param::INT ) *(int*)value = val; else *(double*)value = val; } else if( p->type == Param::BOOLEAN ) { CV_Assert( argType == Param::INT || argType == Param::BOOLEAN || argType == Param::REAL ); bool val = p->getter ? (algo->*f.get_bool)() : *(bool*)((uchar*)algo + p->offset); if( argType == Param::INT ) *(int*)value = (int)val; else if( argType == Param::BOOLEAN ) *(bool*)value = val; else *(double*)value = (int)val; } else { CV_Assert( argType == Param::REAL ); double val = p->getter ? (algo->*f.get_double)() : *(double*)((uchar*)algo + p->offset); *(double*)value = val; } } else if( argType == Param::STRING ) { CV_Assert( p->type == Param::STRING ); *(string*)value = p->getter ? (algo->*f.get_string)() : *(string*)((uchar*)algo + p->offset); } else if( argType == Param::MAT ) { CV_Assert( p->type == Param::MAT ); *(Mat*)value = p->getter ? (algo->*f.get_mat)() : *(Mat*)((uchar*)algo + p->offset); } else if( argType == Param::ALGORITHM ) { CV_Assert( p->type == Param::ALGORITHM ); *(Ptr*)value = p->getter ? (algo->*f.get_algo)() : *(Ptr*)((uchar*)algo + p->offset); } else CV_Error(CV_StsBadArg, "Unknown/unsupported parameter type"); } int AlgorithmInfo::paramType(const char* name) const { const Param* p = findstr(data->params, name); if( !p ) CV_Error_( CV_StsBadArg, ("No parameter '%s' is found", name ? name : "") ); return p->type; } string AlgorithmInfo::paramHelp(const char* name) const { const Param* p = findstr(data->params, name); if( !p ) CV_Error_( CV_StsBadArg, ("No parameter '%s' is found", name ? name : "") ); return p->help; } void AlgorithmInfo::getParams(vector& names) const { data->params.get_keys(names); } void AlgorithmInfo::addParam_(const Algorithm* algo, const char* name, int argType, const void* value, bool readOnly, Algorithm::Getter getter, Algorithm::Setter setter, const string& help) { CV_Assert( argType == Param::INT || argType == Param::BOOLEAN || argType == Param::REAL || argType == Param::STRING || argType == Param::MAT || argType == Param::ALGORITHM ); data->params.add(string(name), Param(argType, readOnly, (int)((size_t)value - (size_t)(void*)algo), getter, setter, help)); } } /* End of file. */