1 : /// -*- C++ -*- (c) 2006, 2007 Petr Rockai <me@mornfall.net>
2 :
3 : #include <iostream>
4 : #include <string>
5 : #include <map>
6 :
7 : #ifndef EPT_CORE_DESKTOPFILE_H
8 : #define EPT_CORE_DESKTOPFILE_H
9 :
10 : namespace ept {
11 : namespace core {
12 : namespace desktop {
13 :
14 32 : struct File {
15 13540 : struct Entry {
16 : std::string key;
17 : std::string value;
18 : };
19 : typedef std::map< std::string, Entry > EntryMap;
20 :
21 144 : struct Group {
22 : std::string name;
23 : EntryMap entries;
24 88 : Entry &entry( std::string k ) { return entries[ k ]; }
25 : };
26 :
27 : typedef std::map< std::string, Group > GroupMap;
28 : GroupMap groups;
29 16 : Group &group( std::string k ) { return groups[ k ]; }
30 : };
31 :
32 1228 : inline std::istream &operator >>( std::istream &i, File::Entry &e )
33 : {
34 1228 : std::string spaces = ""; char c; bool started = false;
35 :
36 1228 : e.key = "";
37 : // read key
38 16056 : while ( i.peek() != EOF ) {
39 14820 : c = i.get();
40 14820 : if ( !started && c == '\n' )
41 8 : return i >> e;
42 14812 : if ( isspace( c ) ) {
43 0 : spaces += c;
44 0 : continue;
45 : }
46 14812 : if ( !started && c == '#' ) {
47 0 : while ( i.peek() != EOF && i.get() != '\n' )
48 : ; // read till eol
49 0 : return i >> e; // restart reading
50 : }
51 14812 : started = true;
52 14812 : if ( c == '=' )
53 1212 : break;
54 13600 : e.key += spaces;
55 13600 : e.key += c;
56 13600 : spaces = "";
57 : }
58 : // std::cerr << "read key: " << e.key << std::endl;
59 :
60 1220 : started = false;
61 1220 : bool backslash = false;
62 : // read value
63 37496 : while ( i.peek() != EOF ) {
64 36268 : c = i.get();
65 36268 : if ( c == '\n' ) {
66 1212 : if ( backslash )
67 0 : e.value += '\\';
68 1212 : return i;
69 : }
70 35056 : if ( !started && isspace( c ) )
71 0 : continue;
72 35056 : started = true;
73 35056 : if ( backslash ) { // interpret escape sequences
74 0 : if ( c == '\\' ) e.value += '\\';
75 0 : else if ( c == 'n' ) e.value += '\n';
76 0 : else if ( c == 't' ) e.value += '\t';
77 0 : else if ( c == 'r' ) e.value += '\r';
78 0 : else if ( c == 's' ) e.value += ' ';
79 0 : else { e.value += '\\'; e.value += c; }
80 0 : backslash = false;
81 0 : continue;
82 : }
83 35056 : if ( c == '\\' ) {
84 0 : backslash = true;
85 0 : continue;
86 : }
87 35056 : e.value += c;
88 : }
89 8 : return i;
90 : }
91 :
92 16 : inline std::istream &operator >>( std::istream &i, File::Group &g )
93 : {
94 16 : bool started = false; char c;
95 16 : g.name = "";
96 256 : while ( i.peek() != EOF ) {
97 240 : c = i.get();
98 240 : if ( !started && isspace( c ) )
99 0 : continue;
100 240 : if ( !started && c == '#' ) {
101 0 : while( i.peek() != EOF && i.get() != '\n' )
102 : ; // read till eol
103 0 : return i >> g; // restart reading
104 : }
105 240 : if ( !started && c == '[' ) {
106 16 : started = true;
107 16 : continue;
108 : }
109 224 : if ( started && c == ']' ) {
110 16 : while( i.peek() != EOF && i.get() != '\n' )
111 : ; // read till eol
112 16 : break;
113 : }
114 208 : g.name += c;
115 : }
116 1236 : while ( i.peek() != EOF ) {
117 1220 : File::Entry e;
118 1220 : i >> e;
119 1220 : g.entries[ e.key ] = e;
120 : }
121 16 : return i;
122 : }
123 :
124 16 : inline std::istream &operator >>( std::istream &i, File &f )
125 : {
126 32 : while ( i.peek() != EOF ) {
127 16 : File::Group g;
128 16 : i >> g;
129 16 : f.groups[ g.name ] = g;
130 : }
131 16 : return i;
132 : }
133 :
134 : }
135 : }
136 : }
137 :
138 : #endif
|