From 5736addc04a55de10add5780d92dcb5ef8b8c390 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Tue, 7 Aug 2007 17:17:24 +0000 Subject: [PATCH] Add documentation for all functions in utils Add c_escape and c_unescape functions --- source/utils.cpp | 179 +++++++++++++++++++++++++++++++++++------------ source/utils.h | 98 +++++++++++++++++++++++--- 2 files changed, 225 insertions(+), 52 deletions(-) diff --git a/source/utils.cpp b/source/utils.cpp index 244055b..9898a07 100644 --- a/source/utils.cpp +++ b/source/utils.cpp @@ -6,6 +6,7 @@ Distributed under the LGPL */ #include +#include #include "utils.h" using namespace std; @@ -48,14 +49,6 @@ vector do_split(const string &str, const string &sep, int max_split) namespace Msp { -/** -Compares two strings, ignoring case. - -@param s1 First string -@param s2 Second string - -@return -1 if s1s2 -*/ int strcasecmp(const string &s1, const string &s2) { string::const_iterator i1=s1.begin(); @@ -71,9 +64,6 @@ int strcasecmp(const string &s1, const string &s2) return 0; } -/** -Returns a lowercase copy of the given string. -*/ string tolower(const string &str) { string result(str); @@ -81,9 +71,6 @@ string tolower(const string &str) return result; } -/** -Returns an uppercase copy of the given string. -*/ string toupper(const string &str) { string result(str); @@ -91,14 +78,14 @@ string toupper(const string &str) return result; } -vector split_fields(const string &str, const string &sep, int max_split) +vector split(const string &str, const string &sep, int max_split) { - return do_split(str, sep, max_split); + return do_split(str, sep, max_split); } -vector split_fields(const string &str, char sep, int max_split) +vector split(const string &str, char sep, int max_split) { - return split_fields(str, string(1, sep), max_split); + return split(str, string(1, sep), max_split); } vector split_long(const string &str, const string &sep, int max_split) @@ -106,14 +93,14 @@ vector split_long(const string &str, const string &sep, int max_split) return do_split(str, sep, max_split); } -vector split(const string &str, const string &sep, int max_split) +vector split_fields(const string &str, const string &sep, int max_split) { - return do_split(str, sep, max_split); + return do_split(str, sep, max_split); } -vector split(const string &str, char sep, int max_split) +vector split_fields(const string &str, char sep, int max_split) { - return split(str, string(1, sep), max_split); + return split_fields(str, string(1, sep), max_split); } /** @@ -158,38 +145,142 @@ vector split(const string &str, char sep, bool allow_empty) return split(str, string(1, sep), allow_empty); } -/** -Builds a single string from the strings in the given sequence by concatenating -them. +string strip(const string &s) +{ + string result=s; + if(!result.erase(0, result.find_first_not_of(" \t\r\n")).empty()) + result.erase(result.find_last_not_of(" \t\r\n")+1); + return result; +} -@param seq A sequence of strings -@param sep Separator to be inserted between strings -*/ -template -string join(const T &seq, const string &sep) +string c_unescape(const std::string &str) { + bool escape=false; + unsigned numeric_type=0; + unsigned numeric_pos=0; + unsigned numeric_value=0; string result; - for(typename T::const_iterator i=seq.begin(); i!=seq.end(); ++i) + for(string::const_iterator i=str.begin(); i!=str.end(); ++i) { - if(i!=seq.begin()) - result+=sep; - result+=*i; + if(numeric_type==1) + { + unsigned digit=0; + if(*i>='0' && *i<='9') + digit=*i-'0'; + else if(*i>='a' && *i<='f') + digit=*i-'a'+10; + else if(*i>='A' && *i<='F') + digit=*i-'A'+10; + else + throw InvalidParameterValue("Invalid hexadecimal digit"); + + numeric_value=(numeric_value<<4 | digit); + ++numeric_pos; + if(numeric_pos==2) + { + result+=numeric_value; + numeric_type=0; + } + } + else if(numeric_type==2) + { + unsigned digit=0; + if(*i>='0' && *i<='7') + digit=*i-'0'; + else + throw InvalidParameterValue("Invalid octal digit"); + + if(numeric_pos==0 && digit>3) + throw InvalidParameterValue("Octal escape sequence must start with [0-3]"); + + numeric_value=(numeric_value<<3 | digit); + ++numeric_pos; + if(numeric_pos==2) + { + result+=numeric_value; + numeric_type=0; + } + } + else if(escape) + { + if(*i=='x' || (*i>='0' && *i<='7')) + { + numeric_type=(*i=='x' ? 1 : 2); + numeric_pos=0; + numeric_value=0; + } + else if(*i=='n') + result+='\n'; + else if(*i=='t') + result+='\t'; + else if(*i=='r') + result+='\r'; + else if(*i=='b') + result+='\b'; + else if(*i=='v') + result+='\v'; + else if(*i=='a') + result+='\a'; + else if(*i=='f') + result+='\f'; + else if(*i=='\"') + result+='\"'; + else if(*i=='\'') + result+='\''; + else if(*i=='\\') + result+='\\'; + else + throw InvalidParameterValue("Invalid escape sequence"); + + escape=false; + } + else if(*i=='\\') + escape=true; + else + result+=*i; } + if(escape) + throw InvalidParameterValue("Stray backslash at end of string"); + return result; } -template string join >(const list &, const string &); -template string join >(const vector &, const string &); -/** -Returns a copy of the given string with leading and trailing whitespace -removed. -*/ -string strip(const string &s) +string c_escape(const string &str, bool escape_8bit) { - string result=s; - if(!result.erase(0, result.find_first_not_of(" \t\r\n")).empty()) - result.erase(result.find_last_not_of(" \t\r\n")+1); + string result; + + for(string::const_iterator i=str.begin(); i!=str.end(); ++i) + { + if(*i=='\n') + result+="\\n"; + else if(*i=='\t') + result+="\\t"; + else if(*i=='\r') + result+="\\r"; + else if(*i=='\b') + result+="\\b"; + else if(*i=='\v') + result+="\\v"; + else if(*i=='\a') + result+="\\a"; + else if(*i=='\f') + result+="\\f"; + else if(*i=='\"') + result+="\\\""; + else if(*i=='\'') + result+="\\\'"; + else if(*i=='\\') + result+="\\\\"; + else if(*i<' ' || (escape_8bit && (*i&0x80))) + { + char buf[4]={'\\', (*i>>6)&7, (*i>>3)&7, *i&7}; + result.append(buf, 4); + } + else + result+=*i; + } + return result; } diff --git a/source/utils.h b/source/utils.h index d0d8a17..5492f95 100644 --- a/source/utils.h +++ b/source/utils.h @@ -13,20 +13,102 @@ Distributed under the LGPL namespace Msp { -int strcasecmp(const std::string &, const std::string &); +/** +Compares two strings, ignoring upper/lower case. + +@param s1 First string +@param s2 Second string + +@return -1 if s1s2 +*/ +int strcasecmp(const std::string &s1, const std::string &s2); + +/** +Converts a string to lower case. +*/ std::string tolower(const std::string &); + +/** +Converts a string to upper case. +*/ std::string toupper(const std::string &); -std::vector split_fields(const std::string &, const std::string &, int =-1); -std::vector split_fields(const std::string &, char, int =-1); -std::vector split_long(const std::string &, const std::string &, int =-1); -std::vector split(const std::string &, const std::string & =" \t\r\n", int =-1); -std::vector split(const std::string &, char, int =-1); +/** +Splits a string at occurrences of any of the characters in sep. If max_split +is non-negative, at most that many split will be performed, i.e. the resulting +vector will contain at most max_split+1 elements. Two or more consecutive +separator characters will be treated as a single separator. + +@param str A string +@param sep Separator characters +@param max_split Maximum number of splits to perform +*/ +std::vector split(const std::string &str, const std::string &sep=" \t\r\n", int max_split=-1); + +/** +Splits a string on occurrences of a single character. +*/ +std::vector split(const std::string &str, char sep, int max_split=-1); + +/** +Splits a string on occurrences of another string. +*/ +std::vector split_long(const std::string &str, const std::string &sep, int max_split=-1); + +/** +Splits a string on occurrences of another string. Two consecutive separators +will cause an empty string to be placed in the result. +*/ +std::vector split_fields(const std::string &str, const std::string &sep, int max_split=-1); + +/** +Splits a string on occurrences of a single character. Two consecutive +separators will cause an empty string to be placed in the result. +*/ +std::vector split_fields(const std::string &str, char sep, int max_split=-1); + +/** +Concatenates strings from an iterator range. + +@param begin First iterator +@param end Last iterator +@param sep Separator to be inserted between strings +*/ +template +std::string join(Iter begin, Iter end, const std::string &sep=" ") +{ + std::string result; + for(Iter i=begin; i!=end; ++i) + { + if(i!=begin) + result+=sep; + result+=*i; + } + + return result; +} -template -std::string join(const T &, const std::string & =" "); +/** +Strips leading and trailing whitespace from a string. +*/ std::string strip(const std::string &); +/** +Unescapes a string with C escape sequences. +*/ +std::string c_unescape(const std::string &str); + +/** +Escapes any non-printable characters in a string with C escape sequences. + +@param str A string +@param escape_8bit If true, consider characters with high bit set as + non-printable + +@return An escaped version of the string +*/ +std::string c_escape(const std::string &str, bool escape_8bit=true); + } // namespace Msp #endif -- 2.45.2