{
out.flags(((base==HEX) ? ios_base::hex : (base==OCT) ? ios_base::oct : ios_base::dec)
| ((fmode==SCI) ? ios_base::scientific : (fmode==FIXED) ? ios_base::fixed : ios_base::fmtflags(0))
- | (fillc ? ios_base::internal : (align==LEFT) ? ios_base::left : ios_base::right)
+ | (fillc=='0' ? ios_base::internal : (align==LEFT) ? ios_base::left : ios_base::right)
| (sbase ? ios_base::showbase : ios_base::fmtflags(0))
| (spoint ? ios_base::showpoint : ios_base::fmtflags(0))
| (spos ? ios_base::showpos : ios_base::fmtflags(0))
else if(*f=='o')
base=OCT;
else if(*f=='e' || *f=='E')
- fmode=EXP;
+ fmode=SCI;
else if(*f=='f' || *f=='F')
fmode=FIXED;
else if(*f=='g' || *f=='G')
- fmode=SCI;
+ fmode=EXP;
else if(*f=='p')
{
base=HEX;
--- /dev/null
+#include <list>
+#include "utils.h"
+
+using namespace std;
+
+namespace Msp {
+
+/**
+Compares two strings, ignoring case.
+
+@param s1 First string
+@param s2 Second string
+
+@return -1 if s1<s2, 0 if s1==s2, 1 if s1>s2
+*/
+int strcasecmp(const string &s1, const string &s2)
+{
+ string::const_iterator i1=s1.begin();
+ string::const_iterator i2=s2.begin();
+ for(; (i1!=s1.end() && i2!=s2.end()); ++i1, ++i2)
+ {
+ const char c1=::tolower(*i1);
+ const char c2=::tolower(*i2);
+ if(c1!=c2) return c1-c2;
+ }
+ if(i1!=s1.end()) return *i1;
+ if(i2!=s2.end()) return -*i2;
+ return 0;
+}
+
+/**
+Returns a lowercase copy of the given string.
+*/
+string tolower(const string &str)
+{
+ string result(str);
+ transform(result.begin(), result.end(), result.begin(), ::tolower);
+ return result;
+}
+
+/**
+Returns an uppercase copy of the given string.
+*/
+string toupper(const string &str)
+{
+ string result(str);
+ transform(result.begin(), result.end(), result.begin(), ::toupper);
+ return result;
+}
+
+/**
+Splits a string to parts.
+
+@param str String to be split
+@param sep A set of separator characters
+@param allow_empty Whether or not to produce empty parts for sequences of
+ more than one separator character
+*/
+vector<string> split(const string &str, const string &sep, bool allow_empty)
+{
+ vector<string> result;
+ unsigned start=str.find_first_not_of(sep);
+ while(start<str.size())
+ {
+ unsigned end=str.find_first_of(sep, start);
+ result.push_back(str.substr(start, end-start));
+ if(end==string::npos) break;
+ if(allow_empty)
+ start=end+1;
+ else
+ start=str.find_first_not_of(sep, end);
+ }
+ return result;
+}
+
+vector<string> 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.
+
+@param seq A sequence of strings
+@param sep Separator to be inserted between strings
+*/
+template<typename T>
+string join(const T &seq, const string &sep)
+{
+ string result;
+ for(typename T::const_iterator i=seq.begin(); i!=seq.end(); ++i)
+ {
+ if(i!=seq.begin())
+ result+=sep;
+ result+=*i;
+ }
+
+ return result;
+}
+template string join<list<string> >(const list<string> &, const string &);
+template string join<vector<string> >(const vector<string> &, const string &);
+
+/**
+Returns a copy of the given string with leading and trailing whitespace
+removed.
+*/
+string strip(const string &s)
+{
+ string result=s;
+ if(!result.erase(0, result.find_first_not_of(" \t\n")).empty())
+ result.erase(result.find_last_not_of(" \t\n")+1);
+ return result;
+}
+
+} // namespace Msp
--- /dev/null
+#ifndef MSP_STRINGS_UTILS_H_
+#define MSP_STRINGS_UTILS_H_
+
+#include <string>
+#include <vector>
+
+namespace Msp {
+
+int strcasecmp(const std::string &, const std::string &);
+std::string tolower(const std::string &);
+std::string toupper(const std::string &);
+std::vector<std::string> split(const std::string &, const std::string & =" \t\r\n", bool =false);
+std::vector<std::string> split(const std::string &, char, bool =false);
+template<typename T>
+std::string join(const T &, const std::string & =" ");
+std::string strip(const std::string &);
+
+} // namespace Msp
+
+#endif