Skip to content

Commit 7118908

Browse files
committed
initial commit - v1.0
0 parents  commit 7118908

File tree

13 files changed

+824
-0
lines changed

13 files changed

+824
-0
lines changed

Config.sln

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 10.00
3+
# Visual Studio 2008
4+
# SharpDevelop 3.2.1.6466
5+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Config", "Config\Config.csproj", "{FF6E4113-3ABD-4E4B-AAB4-3C7073F6E0C3}"
6+
EndProject
7+
Global
8+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
9+
Debug|x86 = Debug|x86
10+
Release|x86 = Release|x86
11+
EndGlobalSection
12+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
13+
{FF6E4113-3ABD-4E4B-AAB4-3C7073F6E0C3}.Debug|x86.Build.0 = Debug|x86
14+
{FF6E4113-3ABD-4E4B-AAB4-3C7073F6E0C3}.Debug|x86.ActiveCfg = Debug|x86
15+
{FF6E4113-3ABD-4E4B-AAB4-3C7073F6E0C3}.Release|x86.Build.0 = Release|x86
16+
{FF6E4113-3ABD-4E4B-AAB4-3C7073F6E0C3}.Release|x86.ActiveCfg = Release|x86
17+
EndGlobalSection
18+
EndGlobal

Config/Config.csproj

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
2+
<PropertyGroup>
3+
<ProjectGuid>{FF6E4113-3ABD-4E4B-AAB4-3C7073F6E0C3}</ProjectGuid>
4+
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
5+
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
6+
<OutputType>Library</OutputType>
7+
<RootNamespace>Multipetros.Config</RootNamespace>
8+
<AssemblyName>Multipetros.Config</AssemblyName>
9+
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
10+
<AppDesignerFolder>Properties</AppDesignerFolder>
11+
<SourceAnalysisOverrideSettingsFile>C:\Users\petros\AppData\Roaming\ICSharpCode/SharpDevelop3.0\Settings.SourceAnalysis</SourceAnalysisOverrideSettingsFile>
12+
</PropertyGroup>
13+
<PropertyGroup Condition=" '$(Platform)' == 'x86' ">
14+
<PlatformTarget>x86</PlatformTarget>
15+
</PropertyGroup>
16+
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
17+
<OutputPath>bin\Debug\</OutputPath>
18+
<DebugSymbols>True</DebugSymbols>
19+
<DebugType>Full</DebugType>
20+
<Optimize>False</Optimize>
21+
<CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
22+
<DefineConstants>DEBUG;TRACE</DefineConstants>
23+
</PropertyGroup>
24+
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
25+
<OutputPath>bin\Release\</OutputPath>
26+
<DebugSymbols>False</DebugSymbols>
27+
<DebugType>None</DebugType>
28+
<Optimize>True</Optimize>
29+
<CheckForOverflowUnderflow>False</CheckForOverflowUnderflow>
30+
<DefineConstants>TRACE</DefineConstants>
31+
</PropertyGroup>
32+
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
33+
<ItemGroup>
34+
<Reference Include="System" />
35+
<Reference Include="System.Core">
36+
<RequiredTargetFramework>3.5</RequiredTargetFramework>
37+
</Reference>
38+
<Reference Include="System.Xml" />
39+
<Reference Include="System.Xml.Linq">
40+
<RequiredTargetFramework>3.5</RequiredTargetFramework>
41+
</Reference>
42+
</ItemGroup>
43+
<ItemGroup>
44+
<Compile Include="ConfigBase.cs" />
45+
<Compile Include="Ini.cs" />
46+
<Compile Include="Properties\AssemblyInfo.cs" />
47+
<Compile Include="RegistryIni.cs" />
48+
<Compile Include="SimpleIni.cs" />
49+
</ItemGroup>
50+
</Project>

Config/ConfigBase.cs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#region info
2+
/*
3+
* ConfigBase Class - Version 1.0
4+
* Copyright (C) 2015 Petros Kyladitis <http://www.multipetros.gr/>
5+
*
6+
* Base class with static methods for easily configuration properties manipulation.
7+
*
8+
* This is free software, distributed under the therms & conditions of the FreeBSD License. For the full License text
9+
* see at the 'license.txt' file, distributed with this project or at <http://www.multipetros.gr/freebsd-license/>
10+
*/
11+
#endregion
12+
13+
using System ;
14+
15+
namespace Multipetros.Config{
16+
/// <summary>
17+
/// Provide static methods for easily configuration properties manipulation, such as base64 encoding, add & remove double quotes, etc.
18+
/// </summary>
19+
public class ConfigBase{
20+
public ConfigBase(){ }
21+
22+
/// <summary>
23+
/// Encode unicode text to Base64
24+
/// </summary>
25+
/// <param name="val">Text to encode</param>
26+
/// <returns>Encoded text</returns>
27+
public static string EncodeB64(string val){
28+
return Convert.ToBase64String(System.Text.Encoding.Unicode.GetBytes(val)) ;
29+
}
30+
31+
/// <summary>
32+
/// Decode text from Base64 to Unicode
33+
/// </summary>
34+
/// <param name="val">Text to decode</param>
35+
/// <returns>Decoded text</returns>
36+
public static string DecodeB64(string val){
37+
return System.Text.Encoding.Unicode.GetString(Convert.FromBase64String(val)) ;
38+
}
39+
40+
/// <summary>
41+
/// Add double quotes to the text. You can use this if you want to store properites values with spaces at the begin and/or the end
42+
/// </summary>
43+
/// <param name="val">Text to add double quotes</param>
44+
/// <returns></returns>
45+
public static string AddQuotes(string val){
46+
return "\"" + val + "\"" ;
47+
}
48+
49+
/// <summary>
50+
/// Remove double quotes from the text. This is for strip double quotes from properties values stored in this way.
51+
/// </summary>
52+
/// <param name="val">Text to trim double quotes</param>
53+
/// <returns></returns>
54+
public static string RemoveQuotes(string val){
55+
return val.Trim("\"".ToCharArray()) ;
56+
}
57+
}
58+
}

Config/Ini.cs

Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
#region info
2+
/*
3+
* Ini Class - Version 1.0
4+
* Copyright (C) 2015 Petros Kyladitis <http://www.multipetros.gr/>
5+
*
6+
* Complete INI file properties manipulation class.
7+
*
8+
* This is free software, distributed under the therms & conditions of the FreeBSD License. For the full License text
9+
* see at the 'license.txt' file, distributed with this project or at <http://www.multipetros.gr/freebsd-license/>
10+
*/
11+
#endregion
12+
13+
using System ;
14+
using System.IO ;
15+
using System.Collections.Generic ;
16+
17+
namespace Multipetros.Config{
18+
/// <summary>
19+
/// Description of Ini.
20+
/// </summary>
21+
public class Ini : ConfigBase{
22+
23+
private Dictionary<string, Dictionary<string, string>> sections ; //store all file structure
24+
//with sections as keys & nested lines as values
25+
private Dictionary<string, string> properties ; //lines of each section stored in a dictionary with key-value pair
26+
private char[] separator = new char[1] ; //1-cell char array to store separator
27+
private string separatorStr ; //separator as string
28+
private char[] comments = new char[1] ; //1-cell char array to store comments start sign
29+
private string commentsStr ; //comments sign as string
30+
private string file ; //properties file path
31+
private bool autosave ; //autosave mode option
32+
private bool ignoreCase ; //ignore case filter for keys option
33+
34+
/// <summary>
35+
/// The simplest constructor, with filename only to configure. Autosave properties setted as False, ingore case as True, the Separator as "=" & Comments sign as "#".
36+
/// </summary>
37+
/// <param name="file">A valid file path, with read and write priviliges</param>
38+
public Ini(string file) : this(file, false, true, '=', '#') { }
39+
40+
/// <summary>
41+
/// Constructor with filename and autosave mode to configure. Ingore case setted as True, the Separator as "=" & Comments sign as "#".
42+
/// </summary>
43+
/// <param name="file">A valid file path, with read and write priviliges</param>
44+
/// <param name="autosave">True, to save each time a Property added or setted. False, to save manualy by calling the Save() method</param>
45+
public Ini(string file, bool autosave) : this(file, autosave, true, '=', '#') { }
46+
47+
/// <summary>
48+
/// Constructor with filename, autosave mode & ignore case to configure. Separator setted as "=" & Comments sign as "#".
49+
/// </summary>
50+
/// <param name="file">A valid file path, with read and write priviliges</param>
51+
/// <param name="autosave">True, to save each time a Property added or setted. False, to save manualy by calling the Save() method</param>
52+
/// <param name="ignoreCase">True to ignore case, False to make properties keys case sensitive</param>
53+
public Ini(string file, bool autosave, bool ignoreCase) : this(file, autosave, ignoreCase, '=', '#') { }
54+
55+
/// <summary>
56+
/// Constructor with filename, autosave mode, ignore case & the separator sign to configure. The Comments sign setted as "#".
57+
/// </summary>
58+
/// <param name="file">A valid file path, with read and write priviliges</param>
59+
/// <param name="autosave">True, to save each time a Property added or setted. False, to save manualy by calling the Save() method</param>
60+
/// <param name="ignoreCase">True to ignore case, False to make properties keys case sensitive</param>
61+
/// <param name="separator">Separator character for keys and values</param>
62+
public Ini(string file, bool autosave, bool ignoreCase, char separator) : this(file, autosave, ignoreCase, separator, '#') { }
63+
64+
/// <summary>
65+
/// Constructor with filename, autosave mode, ignore case, the separator & comments sign to configure.
66+
/// </summary>
67+
/// <param name="file">A valid file path, with read and write priviliges</param>
68+
/// <param name="autosave">True, to save each time a Property added or setted. False, to save manualy by calling the Save() method</param>
69+
/// <param name="ignoreCase">True to ignore case, False to make properties keys case sensitive</param>
70+
/// <param name="separator">Separator character for keys and values</param>
71+
/// <param name="comments">Comments definition character</param>
72+
public Ini(string file, bool autosave, bool ignoreCase, char separator, char comments){
73+
this.file = file ;
74+
this.autosave = autosave ;
75+
this.ignoreCase = ignoreCase ;
76+
this.separator[0] = separator ;
77+
this.separatorStr = separator.ToString() ;
78+
this.comments[0] = comments ;
79+
this.commentsStr = comments.ToString() ;
80+
Init() ;
81+
}
82+
83+
/// <summary>
84+
/// Initialize the object by loading sections & properties and their values & comments from specified file
85+
/// </summary>
86+
private void Init(){
87+
//initialize dictionary to store the INI file structure, with sections as keys
88+
//and other lines (properties & line comments) as values in nested dictionaries
89+
sections = new Dictionary<string, Dictionary<string, string>>(ignoreCase ? StringComparer.OrdinalIgnoreCase : StringComparer.Ordinal) ;
90+
if(File.Exists(file)){ //if file not exist, don't do anything else
91+
string[] lines = null ; //init a new string array to store the file lines
92+
try{
93+
lines = File.ReadAllLines(file) ; //load lines from file, on error throws an exception
94+
}catch(Exception){ }
95+
string sectionName = "" ; //default section name is an empty string
96+
int sectionStart ; //section name start position
97+
int sectionEnd ; //section name end position
98+
string[] keyval ; //2-cell array to store key and value of each line
99+
//initilize dictionary to store the 1st founded section properties, setting the ignore case as the selected
100+
properties = new Dictionary<string, string>(ignoreCase ? StringComparer.OrdinalIgnoreCase : StringComparer.Ordinal) ;
101+
int i = 0 ; //line number counter
102+
foreach(string line in lines){ //analyze line by line
103+
if(line.Contains("[") && line.Contains("]")){ //if the chars '[' & ']' a section founded, so extract its name included in these chars
104+
105+
106+
if(properties.Count > 0){ //if initialized properties dictionary has values, means that a previous existed so,
107+
sections[sectionName] = properties ; //add the founded properties to the sections dictionary, with se previous section name
108+
}
109+
sectionStart = line.IndexOf("[") + 1 ; //find the start index of the section name
110+
sectionEnd = line.IndexOf("]") - 1 ; //find the last index of the section name
111+
if(sectionStart > sectionEnd){ //if ending bracket founded before starting, eg(']abc[')
112+
continue ; //ignore & go to next line
113+
}
114+
115+
sectionName = line.Substring(sectionStart, sectionEnd) ; //get the secton name, who is inside the brackets. Any other characters just ignored.
116+
//initialize a new properties dictionary, to store the properties of the founded section
117+
properties = new Dictionary<string, string>(ignoreCase ? StringComparer.OrdinalIgnoreCase : StringComparer.Ordinal) ;
118+
}else{ //this line is property or standalone comment. Analyze and extract it.
119+
if(line.Contains(separatorStr)){ //if no separator exist, this is not a property line
120+
keyval = line.Split(separator, 2) ; //split line at the 1st separator appearacne
121+
keyval[0] = keyval[0].Trim() ; //trim property's name from spaces
122+
if(properties.ContainsKey(keyval[0])){ //if key name already exist, continue to the next line
123+
continue ; //no duplicate key names allowed, in this case kept the 1st that appeared
124+
}
125+
keyval[1] = keyval[1].Trim() ; //trim property's value line from spaces
126+
properties[keyval[0]] = keyval[1] ; //put this part of the line, as value to properties dictionary of the current section
127+
}else if(line.Contains(commentsStr)){ //if there's no separator char, but only a comments sign
128+
//this is a standalone comment line. Keep the comment, wich begins at the index of the comment sign
129+
//until the end of the line. Any preceding characters are trimmed off. The comment will saved to the
130+
//current section properties dictionary, with the comment as value, and the comment sign combined with
131+
//the current line number as key (eg. #15=xxx). This, keep the key name unique.
132+
properties[commentsStr + i.ToString()] = line.Substring(line.IndexOf(comments[0])) ;
133+
}
134+
}
135+
i++ ; //increase the line counter
136+
}
137+
//store the latest founded set of properties to the last founded section
138+
if(properties.Count > 0){
139+
sections[sectionName] = properties ;
140+
}
141+
}
142+
}
143+
144+
/// <summary>
145+
/// Store properties to file
146+
/// </summary>
147+
public void Save(){
148+
string output = "" ; //initilize output string
149+
//add the default section (empty name) properties line by line
150+
if(sections.ContainsKey("")){
151+
foreach(KeyValuePair<string, string> mainKeyVal in sections[""]){
152+
if(mainKeyVal.Key.StartsWith(commentsStr)){
153+
//if theres is a standalone comment line add comment sign and the stored value
154+
output += commentsStr + mainKeyVal.Value ;
155+
}else{
156+
output += mainKeyVal.Key + separatorStr + mainKeyVal.Value ;
157+
}
158+
output += "\r\n" ;
159+
}
160+
output += "\r\n" ;
161+
}
162+
//foreach named sections, add the section name and the properties to the output line by line
163+
foreach(KeyValuePair<string, Dictionary<string,string>> sectsKeyval in sections){
164+
if(sectsKeyval.Key != ""){
165+
//add section name, encloded in brackets
166+
output += "[" + sectsKeyval.Key + "]\r\n" ;
167+
//add the properties of the current section
168+
foreach(KeyValuePair<string, string> propsKeyval in sectsKeyval.Value){
169+
if(propsKeyval.Key.StartsWith(commentsStr)){
170+
//if theres is a standalone comment line add comment sign and the stored value
171+
output += propsKeyval.Value ;
172+
}else{
173+
output += propsKeyval.Key + separatorStr + propsKeyval.Value ;
174+
175+
}
176+
output += "\r\n" ;
177+
}
178+
output += "\r\n" ;
179+
}
180+
}
181+
File.WriteAllText(file, output) ;
182+
}
183+
184+
/// <summary>
185+
/// Strip value part from comments
186+
/// </summary>
187+
/// <param name="val">Value text</param>
188+
/// <returns>The value striped from comments and trimmed from spaces between value and comments</returns>
189+
private string StripComments(string val){
190+
if(val.IndexOf(comments[0]) < 0){
191+
return val ;
192+
}else{
193+
return val.Substring(0, val.IndexOf(comments[0])).Trim() ;
194+
}
195+
}
196+
197+
/// <summary>
198+
/// Store a new value to the value part of the line, keeping the existed comments
199+
/// </summary>
200+
/// <param name="currentVal">Current value part of the line (with value and comments)</param>
201+
/// <param name="newVal">The new value</param>
202+
/// <returns>The new value part of the line</returns>
203+
private string StoreKeepingComments(string currentVal, string newVal){
204+
return newVal + currentVal.Substring(StripComments(currentVal).Length) ;
205+
}
206+
207+
/// <summary>
208+
/// Access properties like Dictionary, negotiating with the default (noname section) with the Property key name only eg: iniObj["keyName"]<br>
209+
/// When getting value of the specified property, or empty string if property not found<br>
210+
/// When setting a value for a non-existed property, the property will be automatically added.<br>
211+
/// If the setting value is <em>null</em> the property will be deleted.
212+
/// </summary>
213+
public string this[string key]{
214+
get{
215+
return this["", key] ;
216+
}
217+
set{
218+
this["", key] = value ;
219+
}
220+
}
221+
222+
/// <summary>
223+
/// Access properties like Dictionary, negotiating with the Section & the Property key name eg: iniObj["sectionName", "keyName"]<br>
224+
/// When getting value of the specified section-property pair, or empty string if property not found<br>
225+
/// When setting a value for a non-existed section-property pair, the section-property pair will be automatically added.<br>
226+
/// If the setting value is <em>null</em> the property will be deleted.
227+
/// </summary>
228+
public string this[string section, string key]{
229+
get{
230+
if(sections.ContainsKey(section) && sections[section].ContainsKey(key)){
231+
return StripComments(sections[section][key]) ;
232+
}else{
233+
return "" ;
234+
}
235+
}
236+
set{
237+
if(value != null){
238+
if(!sections.ContainsKey(section)){
239+
sections[section] = new Dictionary<string, string>() ;
240+
}
241+
if(sections[section].ContainsKey(key)){
242+
sections[section][key] = StoreKeepingComments(sections[section][key], value) ;
243+
}else{
244+
sections[section][key] = value ;
245+
}
246+
}else{
247+
//if setting value is null and key exist, remove this key
248+
if(sections.ContainsKey(section) && sections[section].ContainsKey(key)){
249+
sections[section].Remove(key) ;
250+
}
251+
}
252+
if(autosave){
253+
Save() ;
254+
}
255+
}
256+
}
257+
}
258+
}

0 commit comments

Comments
 (0)