From 60a0ebbd6c208f5485d3dea723295923a483246e Mon Sep 17 00:00:00 2001 From: Vadim Pisarevsky Date: Mon, 30 May 2011 12:36:07 +0000 Subject: [PATCH] added optional encoding parameter to cvOpenFileStorage() and FileStorage::open() (ticket #976). moved some implementation parts of CommandLineParser to cmdparser.cpp. --- modules/core/include/opencv2/core/core.hpp | 50 ++++++------------------------ modules/core/include/opencv2/core/core_c.h | 5 ++- modules/core/src/cmdparser.cpp | 36 +++++++++++++++++---- modules/core/src/persistence.cpp | 32 ++++++++++++++----- 4 files changed, 65 insertions(+), 58 deletions(-) diff --git a/modules/core/include/opencv2/core/core.hpp b/modules/core/include/opencv2/core/core.hpp index c03e4ed..1ee3416 100644 --- a/modules/core/include/opencv2/core/core.hpp +++ b/modules/core/include/opencv2/core/core.hpp @@ -3804,14 +3804,14 @@ public: //! the default constructor CV_WRAP FileStorage(); //! the full constructor that opens file storage for reading or writing - CV_WRAP FileStorage(const string& filename, int flags); + CV_WRAP FileStorage(const string& filename, int flags, const string& encoding=string()); //! the constructor that takes pointer to the C FileStorage structure FileStorage(CvFileStorage* fs); //! the destructor. calls release() virtual ~FileStorage(); //! opens file storage for reading or writing. The previous storage is closed with release() - CV_WRAP virtual bool open(const string& filename, int flags); + CV_WRAP virtual bool open(const string& filename, int flags, const string& encoding=string()); //! returns true if the object is associated with currently opened file. CV_WRAP virtual bool isOpened() const; //! closes the file and releases all the memory buffers @@ -4193,7 +4193,7 @@ class CV_EXPORTS CommandLineParser std::string str = getString(name); if (!has(name)) return default_value; - return analizeValue<_Tp>(str); + return analyzeValue<_Tp>(str); } protected: @@ -4201,55 +4201,23 @@ class CV_EXPORTS CommandLineParser std::string getString(const std::string& name) const; template - _Tp analizeValue(const std::string& str); - - template - static _Tp getData(const std::string& str) - { - _Tp res; - std::stringstream s1(str); - s1 >> res; - return res; - } - - template - static _Tp fromStringNumber(const std::string& str)//the default conversion function for numbers - { - - if (str.empty()) - CV_Error(CV_StsParseError, "Empty string cannot be converted to a number"); - - const char* c_str=str.c_str(); - if((!isdigit(c_str[0])) - && - ( - (c_str[0]!='-') || (strlen(c_str) <= 1) || ( !isdigit(c_str[1]) ) - ) - ) - - { - CV_Error(CV_StsParseError, "The string '"+ str +"' cannot be converted to a number"); - } - - return getData<_Tp>(str); - } - + _Tp analyzeValue(const std::string& str); }; template<> CV_EXPORTS - std::string CommandLineParser::analizeValue(const std::string& str); + std::string CommandLineParser::analyzeValue(const std::string& str); template<> CV_EXPORTS - int CommandLineParser::analizeValue(const std::string& str); + int CommandLineParser::analyzeValue(const std::string& str); template<> CV_EXPORTS - unsigned CommandLineParser::analizeValue(const std::string& str); + unsigned CommandLineParser::analyzeValue(const std::string& str); template<> CV_EXPORTS - float CommandLineParser::analizeValue(const std::string& str); + float CommandLineParser::analyzeValue(const std::string& str); template<> CV_EXPORTS - double CommandLineParser::analizeValue(const std::string& str); + double CommandLineParser::analyzeValue(const std::string& str); } diff --git a/modules/core/include/opencv2/core/core_c.h b/modules/core/include/opencv2/core/core_c.h index 8e0b770..05d8c72 100644 --- a/modules/core/include/opencv2/core/core_c.h +++ b/modules/core/include/opencv2/core/core_c.h @@ -1525,9 +1525,8 @@ CVAPI(void) cvSetIPLAllocators( Cv_iplCreateImageHeader create_header, /********************************** High-level functions ********************************/ /* opens existing or creates new file storage */ -CVAPI(CvFileStorage*) cvOpenFileStorage( const char* filename, - CvMemStorage* memstorage, - int flags ); +CVAPI(CvFileStorage*) cvOpenFileStorage( const char* filename, CvMemStorage* memstorage, + int flags, const char* encoding CV_DEFAULT(NULL) ); /* closes file storage and deallocates buffers */ CVAPI(void) cvReleaseFileStorage( CvFileStorage** fs ); diff --git a/modules/core/src/cmdparser.cpp b/modules/core/src/cmdparser.cpp index e69a694..9cecb8d 100644 --- a/modules/core/src/cmdparser.cpp +++ b/modules/core/src/cmdparser.cpp @@ -32,7 +32,7 @@ void PreprocessArgs(int _argc, const char* _argv[], int& argc, char**& argv) find_symbol = buffer_string.find('='); if (find_symbol == -1) buffer_vector.push_back(buffer_string); - else if (find_symbol == 0 || find_symbol == (buffer_string.length() - 1)) + else if (find_symbol == 0 || find_symbol == (int)(buffer_string.length() - 1)) { buffer_string.erase(find_symbol, (find_symbol + 1)); if(!buffer_string.empty()) @@ -135,32 +135,56 @@ std::string CommandLineParser::getString(const std::string& keys) const } +template +static _Tp getData(const std::string& str) +{ + _Tp res; + std::stringstream s1(str); + s1 >> res; + return res; +} + +template +static _Tp fromStringNumber(const std::string& str)//the default conversion function for numbers +{ + + if (str.empty()) + CV_Error(CV_StsParseError, "Empty string cannot be converted to a number"); + + const char* c_str=str.c_str(); + if( !isdigit(c_str[0]) && + (c_str[0] != '-' || strlen(c_str) <= 1 || !isdigit(c_str[1]) )) + CV_Error(CV_StsParseError, "The string '"+ str +"' cannot be converted to a number"); + + return getData<_Tp>(str); +} + template<> -std::string CommandLineParser::analizeValue(const std::string& str) +std::string CommandLineParser::analyzeValue(const std::string& str) { return str; } template<> -int CommandLineParser::analizeValue(const std::string& str) +int CommandLineParser::analyzeValue(const std::string& str) { return fromStringNumber(str); } template<> -unsigned int CommandLineParser::analizeValue(const std::string& str) +unsigned int CommandLineParser::analyzeValue(const std::string& str) { return fromStringNumber(str); } template<> -float CommandLineParser::analizeValue(const std::string& str) +float CommandLineParser::analyzeValue(const std::string& str) { return fromStringNumber(str); } template<> -double CommandLineParser::analizeValue(const std::string& str) +double CommandLineParser::analyzeValue(const std::string& str) { return fromStringNumber(str); } diff --git a/modules/core/src/persistence.cpp b/modules/core/src/persistence.cpp index 7fd8fdd..6558b42 100644 --- a/modules/core/src/persistence.cpp +++ b/modules/core/src/persistence.cpp @@ -2167,13 +2167,15 @@ icvXMLParse( CvFileStorage* fs ) if( version && strncmp( version, "1.", 2 ) != 0 ) CV_Error( CV_StsParseError, "Unsupported version of XML" ); }*/ - { + // we support any 8-bit encoding, so we do not need to check the actual encoding. + // we do not support utf-16, but in the case of utf-16 we will not get here anyway. + /*{ const char* encoding = cvAttrValue( list, "encoding" ); if( encoding && strcmp( encoding, "ASCII" ) != 0 && strcmp( encoding, "UTF-8" ) != 0 && strcmp( encoding, "utf-8" ) != 0 ) CV_PARSE_ERROR( "Unsupported encoding" ); - } + }*/ while( *ptr != '\0' ) { @@ -2587,7 +2589,7 @@ icvXMLWriteComment( CvFileStorage* fs, const char* comment, int eol_comment ) \****************************************************************************************/ CV_IMPL CvFileStorage* -cvOpenFileStorage( const char* filename, CvMemStorage* dststorage, int flags ) +cvOpenFileStorage( const char* filename, CvMemStorage* dststorage, int flags, const char* encoding ) { CvFileStorage* fs = 0; char* xml_buf = 0; @@ -2673,7 +2675,20 @@ cvOpenFileStorage( const char* filename, CvMemStorage* dststorage, int flags ) fs->strstorage = cvCreateChildMemStorage( fs->memstorage ); if( !append || file_size == 0 ) { - icvPuts( fs, "\n" ); + if( encoding ) + { + if( strcmp( encoding, "UTF-16" ) == 0 || + strcmp( encoding, "utf-16" ) == 0 || + strcmp( encoding, "Utf-16" ) == 0 ) + CV_Error( CV_StsBadArg, "UTF-16 XML encoding is not supported! Use 8-bit encoding\n"); + + CV_Assert( strlen(encoding) < 1000 ); + char buf[1100]; + sprintf(buf, "\n", encoding); + icvPuts( fs, buf ); + } + else + icvPuts( fs, "\n" ); icvPuts( fs, "\n" ); } else @@ -4995,10 +5010,10 @@ FileStorage::FileStorage() state = UNDEFINED; } -FileStorage::FileStorage(const string& filename, int flags) +FileStorage::FileStorage(const string& filename, int flags, const string& encoding) { state = UNDEFINED; - open( filename, flags ); + open( filename, flags, encoding ); } FileStorage::FileStorage(CvFileStorage* _fs) @@ -5016,10 +5031,11 @@ FileStorage::~FileStorage() } } -bool FileStorage::open(const string& filename, int flags) +bool FileStorage::open(const string& filename, int flags, const string& encoding) { release(); - fs = Ptr(cvOpenFileStorage( filename.c_str(), 0, flags )); + fs = Ptr(cvOpenFileStorage( filename.c_str(), 0, flags, + !encoding.empty() ? encoding.c_str() : 0)); bool ok = isOpened(); state = ok ? NAME_EXPECTED + INSIDE_MAP : UNDEFINED; return ok; -- 2.7.4