#include "DStringUtils.h" #include using namespace std; using namespace ccdb; struct DHTMLReplace { string match; string replace; } gHTMLReplaceCodes[] = { {"&", "&"}, {"<", "<"}, {">", ">"}, {"\"","""} }; std::string ccdb::DStringUtils::Decode(const string& source ) { string rs = source; // Replace each matching token in turn for ( size_t i = 0; i < array_length( gHTMLReplaceCodes ); i++ ) { // Find the first match const string& match = gHTMLReplaceCodes[i].replace; const string& repl = gHTMLReplaceCodes[i].match; string::size_type start = rs.find_first_of( match ); // Replace all matches while ( start != string::npos ) { rs.replace( start, match.size(), repl ); // Be sure to jump forward by the replacement length start = rs.find_first_of( match, start + repl.size() ); } } return rs; } std::string ccdb::DStringUtils::Encode( const string& source ) { string rs = source; // Replace each matching token in turn for ( size_t i = 0; i < array_length( gHTMLReplaceCodes ); i++ ) { // Find the first match const string& match = gHTMLReplaceCodes[i].match; const string& repl = gHTMLReplaceCodes[i].replace; string::size_type start = rs.find_first_of( match ); // Replace all matches while ( start != string::npos ) { rs.replace( start, match.size(), repl ); // Be sure to jump forward by the replacement length start = rs.find_first_of( match, start + repl.size() ); } } return rs; } std::string ccdb::DStringUtils::vFormat( const char *fmt, va_list ap) { // The function is quite similar to asprintf // but it uses its implementation that assumes, that the message is short // since it is our case... //lets assume we have less than 150 chars buffer int size = 150; int nchars; va_list ap2; char *buffer = (char*)malloc(size); if (buffer == NULL) { //Aha! It is an error! fprintf(stderr, "Error allocating memory in ccdb::DConsole::vFormat( const char *fmt, va_list ap) "); return string(); } //Try to print in the allocated space. //va_start(ap, fmt); va_copy(ap2, ap); //nchars = vsnprintf(buffer, size, fmt, ap2); nchars = vsnprintf(buffer, size, fmt, ap2); //va_end(ap); //Ok! It is some more C++ crap // in linux vsnprintf will return actual number of characters if size of buffer is smaller than needed, // moreover, the buffer could be NULL, and than the actual number of characters will be returned // in windows it return -1, so if it is -1 we have to use one more function to obtain needed chars num if(nchars<0) { #ifdef WIN32 va_end(ap2); va_copy(ap2, ap); nchars = _vscprintf(fmt, ap2); #endif } if (nchars >= size) { char *tmpbuff; // Reallocate buffer now that we know how much space is needed. size = nchars+1; tmpbuff = (char*)realloc(buffer, size); if (tmpbuff == NULL) { // we need to free it free(buffer); fprintf(stderr, "Error allocating memory ccdb::DConsole::vFormat( const char *fmt, va_list ap)"); return string(); } //ok! lets try again. va_end(ap2); //va_end(ap); va_copy(ap2, ap); buffer=tmpbuff; nchars = vsnprintf(buffer, size, fmt, ap2); //nchars = vsnprintf(buffer, size, fmt, ap); va_end(ap); } va_end(ap2); if (nchars < 0) return string(); //looks like alll is okk return string(buffer); } std::string ccdb::DStringUtils::Format( const char *fmt, ... ) { //format va_list ap; va_start(ap, fmt); string str = vFormat(fmt, ap); va_end(ap); return str; } int ccdb::DStringUtils::Replace(const string& pattern, const string& replace, const string& source, string &out) { int matches = 0; out.assign(source); string::size_type start = out.find_first_of( pattern ); // Replace all matches while ( start != string::npos ) { matches++; out.replace( start, pattern.size(), replace ); // Be sure to jump forward by the replacement length start = out.find_first_of( pattern, start + replace.size() ); } return matches; } string ccdb::DStringUtils::Replace(const string& pattern, const string& replace, const string& source) { string out(""); Replace(pattern, replace, source, out); return out; } string ccdb::DStringUtils::ExtractDirectory( const string& path ) { return path.substr( 0, path.find_last_of( '/' ) ); //will get directory without final / } string ccdb::DStringUtils::ExtractObjectname( const string& path ) { return path.substr( path.find_last_of( '/' ) +1 ); } string ccdb::DStringUtils::CombinePath( const string& left, const string& right ) { if(right.length()==0) return left; if(left.length()==0) return right; char separator = '/'; string result = left; bool needAddSeparator = false; char leftLast = left[left.length()-1]; char rightFirst = right[0]; if((leftLast == separator) && (rightFirst == separator)) { //it is a situation we have both "left/ + /right" //so eraze one of them result.erase(result.length()); //needAddSeparator should be false by default so we dont touch it } else if((leftLast != separator) && (rightFirst != separator)) { //it is a situation we have "left + right" //needs separator needAddSeparator = true; } //The last case (leftLast != separator) || (rightFirst != separator) //gives us needAddSeparator = false, but it is false by default if(needAddSeparator) result += separator; return result+right; } bool ccdb::DStringUtils::WildCardCheck( const char* pattern, const char* source ) { char *cp, *mp; while ((*source) && (*pattern != '*')) { if ((*pattern != *source) && (*pattern != '?')) { return 0; } pattern++; source++; } while (*source) { if (*pattern == '*') { if (!*++pattern) { return 1; } mp = const_cast(pattern); cp = const_cast(source+1); } else if ((*pattern == *source) || (*pattern == '?')) { pattern++; source++; } else { pattern = mp; source = cp++; } } while (*pattern == '*') { pattern++; } return !*pattern; } std::vector ccdb::DStringUtils::Split( const std::string &s, const string& delimiters /*= " "*/ ) { std::vector elems; return Split(s, elems, delimiters); } vector & ccdb::DStringUtils::Split( const string& str, vector& tokens, const string& delimiters /*= " "*/ ) { // Skip delimiters at beginning. string::size_type lastPos = str.find_first_not_of(delimiters, 0); // Find first "non-delimiter". string::size_type pos = str.find_first_of(delimiters, lastPos); while (string::npos != pos || string::npos != lastPos) { // Found a token, add it to the vector. tokens.push_back(str.substr(lastPos, pos - lastPos)); // Skip delimiters. Note the "not_of" lastPos = str.find_first_not_of(delimiters, pos); // Find next "non-delimiter" pos = str.find_first_of(delimiters, lastPos); } return tokens; } int ccdb::DStringUtils::ParseInt( const string& source, bool *result/*=NULL*/ ) { return atoi(source.c_str()); //ugly isn't it? } unsigned int ccdb::DStringUtils::ParseUInt( const string& source, bool *result/*=NULL*/ ) { return static_cast(atoi(source.c_str())); //ugly isn't it? } long ccdb::DStringUtils::ParseLong( const string& source, bool *result/*=NULL*/ ) { return atol(source.c_str()); //ugly isn't it? } unsigned long ccdb::DStringUtils::ParseULong( const string& source, bool *result/*=NULL*/ ) { return static_cast(atol(source.c_str())); //ugly isn't it? } bool ccdb::DStringUtils::ParseBool( const string& source, bool *result/*=NULL*/ ) { if(source=="true") return true; if(source=="false") return false; return static_cast(atoi(source.c_str())!=0); //ugly isn't it? } double ccdb::DStringUtils::ParseDouble( const string& source, bool *result/*=NULL*/ ) { return atof(source.c_str()); //ugly isn't it? } std::string ccdb::DStringUtils::ParseString( const string& source, bool *result/*=NULL*/ ) { return string(source); } time_t ccdb::DStringUtils::ParseUnixTime( const string& source, bool *result/*=NULL*/ ) { return static_cast(ParseULong(source, result)); }