23 #ifndef Properties_hpp
24 #define Properties_hpp
92 void load(
const char* filename)
93 throw (ios_base::failure);
99 void load(istream& is)
100 throw (ios_base::failure);
111 void load(streambuf& ib)
112 throw (ios_base::failure);
137 void store(
const char* filename,
const wstring* header = NULL)
const
138 throw (ios_base::failure);
143 void store(ostream& os,
const wstring* header = NULL)
const
144 throw (ios_base::failure);
158 void store(streambuf& ob,
const wstring* header = NULL)
const
159 throw (ios_base::failure);
185 static bool isWS(
int c);
186 static bool isNL(
int c);
187 static bool isComment(
int c);
188 static bool isAssign(
int c);
189 static bool isKeyTerminator(
int c);
190 static bool isEsc(
int c);
191 static void skipWS(streambuf& ib);
192 static void skipComment(streambuf& ib);
193 static void readIgnored(streambuf& ib);
194 static void readEsc(wstring& s, streambuf& ib);
195 static void readKey(wstring& s, streambuf& ib);
196 static void readValue(wstring& s, streambuf& ib);
197 static bool isPrintableAscii(
wchar_t c);
198 static void writeAsciiEsc(streambuf& os,
wchar_t c);
199 static void writeUnicodeEsc(streambuf& os,
wchar_t c);
200 static void writeKey(streambuf& os,
const wstring& s);
201 static void writeValue(streambuf& os,
const wstring& s);
202 static void writeChar(streambuf& os,
char c);
249 using std::streambuf;
250 using std::stringbuf;
267 Properties::isNL(
int c)
278 Properties::isComment(
int c)
289 Properties::isAssign(
int c)
300 Properties::isKeyTerminator(
int c)
302 return isWS(c) || isAssign(c) || isNL(c);
306 Properties::isEsc(
int c)
316 Properties::skipWS(streambuf& ib)
319 while ((c = ib.snextc()) != EOF &&
isWS(c));
323 Properties::skipComment(streambuf& ib)
327 while ((c = ib.snextc()) != EOF && !isNL(c));
332 Properties::readIgnored(streambuf& ib)
335 while ((c = ib.sgetc()) != EOF) {
354 Properties::readEsc(wstring& s, streambuf& ib)
363 if ((c = ib.snextc()) != 0x0a)
382 for (
int i = 0;
i < 4;
i++) {
385 raw +=
static_cast<wchar_t>(c);
387 case 0x30:
case 0x31:
case 0x32:
case 0x33:
case 0x34:
388 case 0x35:
case 0x36:
case 0x37:
case 0x38:
case 0x39:
392 case 0x41:
case 0x42:
case 0x43:
case 0x44:
case 0x45:
case 0x46:
396 case 0x61:
case 0x62:
case 0x63:
case 0x64:
case 0x65:
case 0x66:
403 s +=
static_cast<wchar_t>(c);
407 s +=
static_cast<wchar_t>(d);
414 s +=
static_cast<wchar_t>(c);
419 Properties::readKey(wstring& s, streambuf& ib)
422 while ((c = ib.sgetc()) != EOF) {
423 if (isKeyTerminator(c)) {
441 s +=
static_cast<wchar_t>(c);
447 Properties::readValue(wstring& s, streambuf& ib)
450 while ((c = ib.sgetc()) != EOF) {
459 s +=
static_cast<wchar_t>(c);
465 Properties::isPrintableAscii(
wchar_t c)
467 return (L
'\x20' <= c && c <= L
'\x7e');
471 Properties::writeChar(streambuf& os,
char c)
475 throw ios_base::failure(
"Error writing to streambuf");
479 Properties::writeAsciiEsc(streambuf& os,
wchar_t c)
481 assert(L
'\x20' <= c && c <= L
'\x7e');
502 d =
static_cast<char>(c);
506 writeChar(os, static_cast<char>(c));
509 writeChar(os,
'\x5c');
514 Properties::writeUnicodeEsc(streambuf& os,
wchar_t c)
516 assert(c < L
'\x20' || L
'\x7e' < c);
520 const int w =
sizeof(wchar_t);
521 assert(w == 2 || w == 4);
522 assert(CHAR_BIT == 8);
525 writeChar(os,
'\x5c');
526 writeChar(os, w == 2 ?
'\x75' :
'\x55');
527 static const char ascii[] = {
'\x30',
'\x31',
'\x32',
'\x33',
528 '\x34',
'\x35',
'\x36',
'\x37',
529 '\x38',
'\x39',
'\x41',
'\x42',
530 '\x43',
'\x44',
'\x45',
'\x46' };
531 for (
unsigned int i = w * 8 - 4;
i >= 0;
i -= 4) {
532 writeChar(os, ascii[(c>>
i) & 0xF]);
537 Properties::writeKey(streambuf& os,
const wstring& s)
539 for (wstring::const_iterator
i = s.begin();
i != s.end(); ++
i) {
540 const wchar_t c = *
i;
541 if (isPrintableAscii(c))
542 writeAsciiEsc(os, c);
544 writeUnicodeEsc(os, c);
549 Properties::writeValue(streambuf& os,
const wstring& s)
551 wstring::const_iterator
i = s.begin();
552 for (; i != s.end() && *i == L
'\x20'; ++
i) {
554 writeAsciiEsc(os, *i);
556 for (; i != s.end(); ++
i) {
557 const wchar_t c = *
i;
560 writeChar(os,
'\x20');
561 }
else if (isPrintableAscii(c)) {
562 writeAsciiEsc(os, c);
564 writeUnicodeEsc(os, c);
573 throw (ios_base::failure)
577 ifs.exceptions(ifstream::failbit | ifstream::badbit);
586 throw (ios_base::failure)
588 istream::iostate exceptions = is.exceptions();
589 is.exceptions(istream::failbit | istream::badbit);
590 streambuf* ib = is.rdbuf();
593 is.exceptions(exceptions);
598 throw (ios_base::failure)
600 while (ib.sgetc() != EOF) {
602 if (ib.sgetc() == EOF)
618 throw (ios_base::failure)
622 ofs.exceptions(ifstream::failbit | ifstream::badbit);
631 throw (ios_base::failure)
633 ostream::iostate exceptions = os.exceptions();
634 os.exceptions(istream::failbit | istream::badbit);
635 streambuf* ob = os.rdbuf();
638 os.exceptions(exceptions);
643 throw (ios_base::failure)
647 const int w =
sizeof(wchar_t);
648 assert(w == 2 || w == 4);
649 assert(CHAR_BIT == 8);
650 assert(L
'!' ==
'\x21');
651 assert(L
'A' ==
'\x41');
652 assert(L
'a' ==
'\x61');
653 assert(L
'~' ==
'\x7e');
656 if (header != NULL) {
657 writeChar(os,
'\x23');
658 writeKey(os, *header);
659 writeChar(os,
'\x0a');
662 for (const_iterator i = begin(); i != end(); ++
i) {
663 const wstring& key = i->first;
664 const wstring& value = i->second;
666 writeChar(os,
'\x3d');
667 writeValue(os, value);
668 writeChar(os,
'\x0a');
676 #endif // Properties_hpp