~dhananjaysathe/nuvola-player/TelepathyExt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
/*

Fenryxo's library :-)

Copyright 2011 Jiří Janoušek <janousek.jiri@gmail.com>

* Based on code from Wingpanel <https://launchpad.net/wingpanel>,
	Copyright 2010-2011 Wingpanel developers

This program is free software: you can redistribute it and/or modify it 
under the terms of the GNU General Public License version 3, as published 
by the Free Software Foundation.

This program is distributed in the hope that it will be useful, but 
WITHOUT ANY WARRANTY; without even the implied warranties of 
MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR 
PURPOSE.  See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along 
with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

/* TODO:
 * create real shared library
 */
using Gee;

namespace Fenryxo{
/**
	 * Class parsing key-value configuration file.
	 * 
	 * Class parser configuration files which contain one key-value pair per line.
	 * Leading and traling white characters are removed.
	 * Key and value are separated by "=" (value may contain "=" character).
	 * Lines starting with a hash "#" are ignored.
	 * {{{
	 * foo = bar
	 * # nice comment
	 * apple = pear
	 * # This is also valid:
	 * comparation = <, =, >
	 * }}}
	 */
	public class ConfigFile: HashMap<string, string>{
		private File file;
		public bool readonly{get; set;}
		/**
		 * Creates new map representation of given file.
		 * 
		 * Creates new map representation of given file. Prints warning on parse errors.
		 * Note: key names are always lowercased.
		 * 
		 * @param file file to parse
		 */
		public ConfigFile(File file, bool readonly=false){
			base();
			this.file = file;
			this.readonly = readonly;
			try{
				var dis = new DataInputStream(file.read());
				string line;
				int lineno = 0;
				while ((line = dis.read_line (null)) != null){
					lineno++;
					string item = line.strip();
					// Ignore empty lines or comments
					if(item.length == 0 || item[0] == '#') continue;
					string[] parts = item.split("=", 2);
					if(parts.length != 2){
						// Implicit keys without value are not supported
						warning("ConfigFile: Parse error at %s:%i",
							file.get_uri(), lineno);
						continue;
					}
					string key = parts[0].strip();
					if(key.length == 0){
						// Empty key
						warning("ConfigFile: Parse error at %s:%i",
							file.get_uri(), lineno);
						continue;
					}
					this[key] = parts[1].strip();
				}
			}
			catch(Error e){
				debug("ConfigFile: Unable to read %s", file.get_uri());
			}
		}
		/**
		 * Returns boolean value.
		 * 
		 * @param key option identifier
		 * @return false if value is empty or "false" (case insensitive), true otherwise
		 */
		public bool get_bool(string key){
			string? val = this[key];
			return  val != null && val != "" && val.down() != "false";
		}
		
		/**
		 * Saves configuration to file.
		 * 
		 * @throw Error on failure
		 */
		public void save() throws Error{
			if(readonly) throw new IOError.READ_ONLY("Configuration file is opened read-only");
			var builder = new StringBuilder();
			foreach(var e in this.entries){
				builder.append(e.key);
				builder.append(" = ");
				builder.append(e.value);
				builder.append_c('\n');
			}
			string str = builder.str;
			try{
				file.get_parent().make_directory_with_parents();
			}
			catch(Error e){}
			file.replace_contents(str, str.length, null, false, FileCreateFlags.NONE, null);
		}
	}
	
	
	/**
	 * Search user data directory and system data directories for subdirectories.
	 * 
	 * @param name name of subdirectory
	 * @return Existing subdirectories or empty array in no subdirectory has been found.
	 */
	public static File[] get_data_dirs(string name){
		File[] dirs = {};
		File dir = File.new_for_path(Environment.get_user_data_dir()).get_child(name);
		if(dir.query_file_type(0) == FileType.DIRECTORY) dirs += dir;
		foreach(string path in Environment.get_system_data_dirs()){
			dir = File.new_for_path(path).get_child(name);
			if(dir.query_file_type(0) == FileType.DIRECTORY) dirs += dir;
		}
		return dirs;
	}
	
	/**
	 * Search user data directory and system data directories for subdirectory.
	 * 
	 * @param name name of subdirectory
	 * @return First existing subdirectory or null in no subdirectory has been found.
	 */
	public static File? get_data_dir(string name){
		File dir = File.new_for_path(Environment.get_user_data_dir()).get_child(name);
		if(dir.query_file_type(0) == FileType.DIRECTORY) return dir;
		foreach(string path in Environment.get_system_data_dirs()){
			dir = File.new_for_path(path).get_child(name);
			if(dir.query_file_type(0) == FileType.DIRECTORY) return dir;
		}
		return null;
	}
	
	/**
	 * Search user data directory and system data directories for file.
	 * 
	 * @param name name of the file
	 * @return First existing file or null in no file has been found.
	 * @todo unit testing
	 */
	public static File? get_data_file(string name){
		File f = File.new_for_path(Environment.get_user_data_dir()).get_child(name);
		if(f.query_file_type(0) == FileType.REGULAR) return f;
		foreach(string path in Environment.get_system_data_dirs()){
			f = File.new_for_path(path).get_child(name);
			if(f.query_file_type(0) == FileType.REGULAR) return f;
		}
		return null;
	}
	
	public static File get_default_config_file(string dir, string file){
		return File.new_for_path(Environment.get_user_config_dir())
			.get_child(dir).get_child(file);
	}
}