Removed INI parser

This commit is contained in:
Boris Bilc 2024-06-07 00:13:45 +02:00
parent 358294e85b
commit 9352d85147
86 changed files with 0 additions and 18582 deletions

View File

@ -1,14 +0,0 @@
# Linguist overrides
*.h linguist-language=cpp
*.cs linguist-language=C#
# Auto detect text files and perform LF normalization
* text=auto
# Custom for Visual Studio
*.cs diff=csharp
*.sln merge=union
*.csproj merge=union
*.vbproj merge=union
*.vcxproj merge=union
*.vcxproj.filters merge=union

View File

@ -1,25 +0,0 @@
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Rr]elease/
[Bb]in/
[Oo]bj/
# MSTest test Results
[Tt]est[Rr]esult/
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
*.cachefile

View File

@ -1,202 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -1,40 +0,0 @@
#include "stdafx.h"
using namespace System;
using namespace System::Reflection;
using namespace System::Runtime::CompilerServices;
using namespace System::Runtime::InteropServices;
using namespace System::Security::Permissions;
//
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
//
[assembly:AssemblyTitleAttribute("MadMilkmanIniSamplesCPP")];
[assembly:AssemblyDescriptionAttribute("")];
[assembly:AssemblyConfigurationAttribute("")];
[assembly:AssemblyCompanyAttribute("")];
[assembly:AssemblyProductAttribute("MadMilkmanIniSamplesCPP")];
[assembly:AssemblyCopyrightAttribute("Copyright (c) 2015")];
[assembly:AssemblyTrademarkAttribute("")];
[assembly:AssemblyCultureAttribute("")];
//
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the value or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly:AssemblyVersionAttribute("1.0.*")];
[assembly:ComVisible(false)];
[assembly:CLSCompliantAttribute(true)];
[assembly:SecurityPermission(SecurityAction::RequestMinimum, UnmanagedCode = true)];

View File

@ -1,463 +0,0 @@
#include "stdafx.h"
using namespace System;
using namespace System::IO;
using namespace System::Text;
using namespace System::Collections::Generic;
using namespace MadMilkman::Ini;
void HelloWorld()
{
// Create new file.
IniFile^ file = gcnew IniFile();
// Add new section.
IniSection^ section = file->Sections->Add("Section Name");
// Add new key and its value.
IniKey^ key = section->Keys->Add("Key Name", "Hello World");
// Read file's specific value.
Console::WriteLine(file->Sections["Section Name"]->Keys["Key Name"]->Value);
}
void Create()
{
// Create new file with default formatting.
IniFile^ file = gcnew IniFile(gcnew IniOptions());
// Add new content.
IniSection^ section = gcnew IniSection(file, IniSection::GlobalSectionName);
IniKey ^key = gcnew IniKey(file, "Key 1", "Value 1");
file->Sections->Add(section);
section->Keys->Add(key);
// Add new content.
file->Sections->Add("Section 2")->Keys->Add("Key 2", "Value 2");
// Add new content.
file->Sections->Add(
gcnew IniSection(file, "Section 3",
gcnew IniKey(file, "Key 3.1", "Value 3.1"),
gcnew IniKey(file, "Key 3.2", "Value 3.2")));
// Add new content.
Dictionary<String^, String^>^ collection = gcnew Dictionary<String^, String^>();
collection->Add("Key 4.1", "Value 4.1");
collection->Add("Key 4.2", "Value 4.2");
file->Sections->Add(
gcnew IniSection(file, "Section 4", collection));
}
void Load()
{
IniOptions^ options = gcnew IniOptions();
IniFile^ iniFile = gcnew IniFile(options);
// Load file from path.
iniFile->Load("..\\MadMilkman.Ini.Samples.Files\\Load Example.ini");
// Load file from stream.
Stream^ fileStream = File::OpenRead("..\\MadMilkman.Ini.Samples.Files\\Load Example.ini");
try { iniFile->Load(fileStream); }
finally { delete fileStream; }
// Load file's content from string.
String^ iniContent = "[Section 1]" + Environment::NewLine +
"Key 1.1 = Value 1.1" + Environment::NewLine +
"Key 1.2 = Value 1.2" + Environment::NewLine +
"Key 1.3 = Value 1.3" + Environment::NewLine +
"Key 1.4 = Value 1.4";
iniFile->Load(gcnew StringReader(iniContent));
// Read file's content.
for each (IniSection^ section in iniFile->Sections)
{
Console::WriteLine("SECTION: {0}", section->Name);
for each (IniKey^ key in section->Keys)
{
Console::WriteLine("KEY: {0}, VALUE: {1}", key->Name, key->Value);
}
}
}
void Style()
{
IniFile^ file = gcnew IniFile();
file->Sections->Add("Section 1")->Keys->Add("Key 1", "Value 1");
file->Sections->Add("Section 2")->Keys->Add("Key 2", "Value 2");
file->Sections->Add("Section 3")->Keys->Add("Key 3", "Value 3");
// Add leading comments.
file->Sections[0]->LeadingComment->Text = "Section 1 leading comment.";
file->Sections[0]->Keys[0]->LeadingComment->Text = "Key 1 leading comment.";
// Add trailing comments.
file->Sections[1]->TrailingComment->Text = "Section 2 trailing comment->";
file->Sections[1]->Keys[0]->TrailingComment->Text = "Key 2 trailing comment->";
// Add left space, indentation.
file->Sections[1]->LeftIndentation = 4;
file->Sections[1]->TrailingComment->LeftIndentation = 4;
file->Sections[1]->Keys[0]->LeftIndentation = 4;
file->Sections[1]->Keys[0]->TrailingComment->LeftIndentation = 4;
// Add above space, empty lines.
file->Sections[2]->TrailingComment->EmptyLinesBefore = 2;
}
void Save()
{
IniOptions^ options = gcnew IniOptions();
IniFile^ iniFile = gcnew IniFile(options);
iniFile->Sections->Add(
gcnew IniSection(iniFile, "Section 1",
gcnew IniKey(iniFile, "Key 1.1", "Value 1.1"),
gcnew IniKey(iniFile, "Key 1.2", "Value 1.2"),
gcnew IniKey(iniFile, "Key 1.3", "Value 1.3"),
gcnew IniKey(iniFile, "Key 1.4", "Value 1.4")));
// Save file to path.
iniFile->Save("..\\MadMilkman.Ini.Samples.Files\\Save Example.ini");
// Save file to stream.
Stream^ fileStream = File::Create("..\\MadMilkman.Ini.Samples.Files\\Save Example.ini");
try { iniFile->Save(fileStream); }
finally { delete fileStream; }
// Save file's content to string.
StringWriter^ contentWriter = gcnew StringWriter();
iniFile->Save(contentWriter);
String^ iniContent = contentWriter->ToString();
Console::WriteLine(iniContent);
}
void Encrypt()
{
// Enable file's protection by providing an encryption password.
IniOptions^ options = gcnew IniOptions();
options->EncryptionPassword = "M4dM1lkM4n.1n1";
IniFile^ file = gcnew IniFile(options);
IniSection^ section = file->Sections->Add("User's Account");
section->Keys->Add("Username", "John Doe");
section->Keys->Add("Password", "P@55\\/\\/0|2D");
// Save and encrypt the file.
file->Save("..\\MadMilkman.Ini.Samples.Files\\Encrypt Example.ini");
file->Sections->Clear();
// Load and dencrypt the file.
file->Load("..\\MadMilkman.Ini.Samples.Files\\Encrypt Example.ini");
Console::WriteLine("User Name: {0}", file->Sections[0]->Keys["Username"]->Value);
Console::WriteLine("Password: {0}", file->Sections[0]->Keys["Password"]->Value);
}
void Compress()
{
// Enable file's size reduction.
IniOptions^ options = gcnew IniOptions();
options->Compression = true;
IniFile^ file = gcnew IniFile(options);
for (int i = 1; i <= 100; i++)
{
file->Sections->Add("Section " + i)->Keys->Add("Key " + i, "Value " + i);
}
// Save and compress the file.
file->Save("..\\MadMilkman.Ini.Samples.Files\\Compress Example.ini");
file->Sections->Clear();
// Load and decompress the file.
file->Load("..\\MadMilkman.Ini.Samples.Files\\Compress Example.ini");
Console::WriteLine(file->Sections->Count);
}
void Custom()
{
IniOptions^ options = gcnew IniOptions();
options->CommentStarter = IniCommentStarter::Hash;
options->KeyDelimiter = IniKeyDelimiter::Colon;
options->KeySpaceAroundDelimiter = true;
options->SectionWrapper = IniSectionWrapper::CurlyBrackets;
options->Encoding = Encoding::UTF8;
IniFile^ file = gcnew IniFile(options);
// Load file.
file->Load("..\\MadMilkman.Ini.Samples.Files\\Custom Example Input.ini");
// Change first section's fourth key's value.
file->Sections[0]->Keys[3]->Value = "NEW VALUE";
// Save file.
file->Save("..\\MadMilkman.Ini.Samples.Files\\Custom Example Output.ini");
}
void Copy()
{
// Create new file.
IniFile^ file = gcnew IniFile();
// Add new content.
IniSection^ section = file->Sections->Add("Section");
IniKey^ key = section->Keys->Add("Key");
// Add duplicate section.
file->Sections->Add(section->Copy());
// Add duplicate key.
section->Keys->Add(key->Copy());
// Create new file.
IniFile^ newFile = gcnew IniFile(gcnew IniOptions());
// Import first file's section to second file.
newFile->Sections->Add(section->Copy(newFile));
}
void Parse()
{
IniFile^ file = gcnew IniFile();
String^ content = "[Player]" + Environment::NewLine +
"Full Name = John Doe" + Environment::NewLine +
"Birthday = 12/31/1999" + Environment::NewLine +
"Married = Yes" + Environment::NewLine +
"Score = 9999999" + Environment::NewLine +
"Game Time = 00:59:59";
file->Load(gcnew StringReader(content));
// Map 'yes' value as 'true' boolean.
file->ValueMappings->Add("yes", true);
// Map 'no' value as 'false' boolean.
file->ValueMappings->Add("no", false);
IniSection^ playerSection = file->Sections["Player"];
// Retrieve player's name.
String^ playerName = playerSection->Keys["Full Name"]->Value;
// Retrieve player's birthday as DateTime.
DateTime playerBirthday;
playerSection->Keys["Birthday"]->TryParseValue(playerBirthday);
// Retrieve player's marital status as bool.
// TryParseValue succeeds due to the mapping of 'yes' value to 'true' boolean.
bool playerMarried;
playerSection->Keys["Married"]->TryParseValue(playerMarried);
// Retrieve player's score as long.
long playerScore;
playerSection->Keys["Score"]->TryParseValue(playerScore);
// Retrieve player's game time as TimeSpan.
TimeSpan playerGameTime;
playerSection->Keys["Game Time"]->TryParseValue(playerGameTime);
}
void BindInternal()
{
IniFile^ file = gcnew IniFile();
String^ content = "[Machine Settings]" + Environment::NewLine +
"Program Files = C:\\Program Files" + Environment::NewLine +
"[Application Settings]" + Environment::NewLine +
"Name = Example App" + Environment::NewLine +
"Version = 1.0" + Environment::NewLine +
"Full Name = @{Name} v@{Version}" + Environment::NewLine +
"Executable Path = @{Machine Settings|Program Files}\\@{Name}.exe";
file->Load(gcnew StringReader(content));
// Bind placeholders with file's content, internal information.
file->ValueBinding->Bind();
// Retrieve application's full name, value is 'Example App v1.0'.
String^ appFullName = file->Sections["Application Settings"]->Keys["Full Name"]->Value;
// Retrieve application's executable path, value is 'C:\\Program Files\\Example App.exe'.
String^ appExePath = file->Sections["Application Settings"]->Keys["Executable Path"]->Value;
}
void BindExternal()
{
IniFile^ file = gcnew IniFile();
String^ content = "[User's Settings]" + Environment::NewLine +
"Nickname = @{User Alias}" + Environment::NewLine +
"Full Name = @{User Name} @{User Surname}" + Environment::NewLine +
"Profile Page = @{Homepage}/Profiles/@{User Alias}";
file->Load(gcnew StringReader(content));
// Bind placeholders with user's data, external information.
Dictionary<String^, String^>^ userData = gcnew Dictionary<String^, String^>();
userData->Add("User Alias", "Johny");
userData->Add("User Name", "John");
userData->Add("User Surname", "Doe");
file->ValueBinding->Bind(userData);
// Bind 'Homepage' placeholder with 'www.example.com' value.
file->ValueBinding->Bind(
KeyValuePair<String^, String^>("Homepage", "www.example.com"));
// Retrieve user's full name, value is 'John Doe'.
String^ userFullName = file->Sections["User's Settings"]->Keys["Full Name"]->Value;
// Retrieve user's profile page, value is 'www.example.com/Profiles/Johny'.
String^ userProfilePage = file->Sections["User's Settings"]->Keys["Profile Page"]->Value;
}
private ref class BindingCustomizationSample {
public:
void BindCustomize()
{
IniFile^ file = gcnew IniFile();
String^ content = "[Player]" + Environment::NewLine +
"Name = @{Name}" + Environment::NewLine +
"Surname = @{Surname}" + Environment::NewLine +
"Adult = @{Age}" + Environment::NewLine +
"Medal = @{Rank}";
file->Load(gcnew StringReader(content));
// Customize binding operation.
file->ValueBinding->Binding += gcnew EventHandler<IniValueBindingEventArgs^>(this, &BindingCustomizationSample::CustomEventHandler);
// Execute binding operation.
Dictionary<String^, String^>^ dataSource = gcnew Dictionary<String^, String^>();
dataSource->Add("Name", "John");
dataSource->Add("Age", "20");
dataSource->Add("Rank", "1");
file->ValueBinding->Bind(dataSource);
}
void CustomEventHandler(Object^ sender, IniValueBindingEventArgs^ e)
{
if (!e->IsValueFound)
{
e->Value = "UNKNOWN";
return;
}
if (e->PlaceholderKey->Name->Equals("Adult") && e->PlaceholderName->Equals("Age"))
{
int age;
if (int::TryParse(e->Value, age))
{
e->Value = (age >= 18) ? "YES" : "NO";
}
else
{
e->Value = "UNKNOWN";
}
return;
}
if (e->PlaceholderKey->Name->Equals("Medal") && e->PlaceholderName->Equals("Rank"))
{
int rank;
if (int::TryParse(e->Value, rank))
{
switch (rank)
{
case 1:
e->Value = "GOLD";
break;
case 2:
e->Value = "SILVER";
break;
case 3:
e->Value = "BRONCE";
break;
default:
e->Value = "NONE";
break;
}
}
else
{
e->Value = "UNKNOWN";
}
return;
}
}
};
// Custom type used for serialization sample.
private ref class GameCharacter
{
public:
property String^ Name;
// Serialize this property as a key with "Sword" name.
[IniSerialization("Sword")]
property double Attack;
// Serialize this property as a key with "Shield" name.
[IniSerialization("Shield")]
property double Defence;
// Ignore serializing this property.
[IniSerialization(true)]
property double Health;
GameCharacter()
{
this->Health = 100;
}
};
void Serialize()
{
IniFile^ file = gcnew IniFile();
IniSection^ section = file->Sections->Add("User's Character");
GameCharacter^ character = gcnew GameCharacter();
character->Name = "John";
character->Attack = 5.5;
character->Defence = 1;
character->Health = 75;
// Serialize GameCharacter object into section's keys.
section->Serialize(character);
// Deserialize section into GameCharacter object.
GameCharacter^ savedCharacter = section->Deserialize<GameCharacter^>();
Console::WriteLine(section->Keys["Name"]->Value);
Console::WriteLine(savedCharacter->Name);
Console::WriteLine(section->Keys["Sword"]->Value);
Console::WriteLine(savedCharacter->Attack);
Console::WriteLine(section->Keys["Shield"]->Value);
Console::WriteLine(savedCharacter->Defence);
}
void main()
{
HelloWorld();
Create();
Load();
Style();
Save();
Encrypt();
Compress();
Custom();
Copy();
Parse();
BindInternal();
BindExternal();
BindingCustomizationSample^ sample = gcnew BindingCustomizationSample();
sample->BindCustomize();
Serialize();
}

View File

@ -1,94 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{097C11FE-8D4B-48D8-884E-0747454E43DB}</ProjectGuid>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<Keyword>ManagedCProj</Keyword>
<RootNamespace>MadMilkmanIniSamplesCPP</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v110</PlatformToolset>
<CLRSupport>true</CLRSupport>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v110</PlatformToolset>
<CLRSupport>true</CLRSupport>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>Use</PrecompiledHeader>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies />
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>Use</PrecompiledHeader>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies />
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="AssemblyInfo.cpp" />
<ClCompile Include="IniSamples.cpp" />
<ClCompile Include="stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\MadMilkman.Ini\MadMilkman.Ini.csproj">
<Project>{bef9735d-c3cc-41e6-aac6-18c5985d3107}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -1,20 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="AssemblyInfo.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="stdafx.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="IniSamples.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -1,7 +0,0 @@
// stdafx.cpp : source file that includes just the standard includes
// MadMilkman.Ini.Samples.CPP.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information
#include "stdafx.h"

View File

@ -1,8 +0,0 @@
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#pragma once
// TODO: reference additional headers your program requires here

View File

@ -1,456 +0,0 @@
using System;
using System.IO;
using System.Text;
using System.Collections.Generic;
using MadMilkman.Ini;
namespace MadMilkman.Ini.Samples.CS
{
class IniSamples
{
private static void HelloWorld()
{
// Create new file.
IniFile file = new IniFile();
// Add new section.
IniSection section = file.Sections.Add("Section Name");
// Add new key and its value.
IniKey key = section.Keys.Add("Key Name", "Hello World");
// Read file's specific value.
Console.WriteLine(file.Sections["Section Name"].Keys["Key Name"].Value);
}
private static void Create()
{
// Create new file with a default formatting.
IniFile file = new IniFile(new IniOptions());
// Add new content.
IniSection section = new IniSection(file, IniSection.GlobalSectionName);
IniKey key = new IniKey(file, "Key 1", "Value 1");
file.Sections.Add(section);
section.Keys.Add(key);
// Add new content.
file.Sections.Add("Section 2").Keys.Add("Key 2", "Value 2");
// Add new content.
file.Sections.Add(
new IniSection(file, "Section 3",
new IniKey(file, "Key 3.1", "Value 3.1"),
new IniKey(file, "Key 3.2", "Value 3.2")));
// Add new content.
file.Sections.Add(
new IniSection(file, "Section 4",
new Dictionary<string, string>()
{
{"Key 4.1", "Value 4.1"},
{"Key 4.2", "Value 4.2"}
}));
}
private static void Load()
{
IniOptions options = new IniOptions();
IniFile iniFile = new IniFile(options);
// Load file from path.
iniFile.Load(@"..\..\..\MadMilkman.Ini.Samples.Files\Load Example.ini");
// Load file from stream.
using (Stream stream = File.OpenRead(@"..\..\..\MadMilkman.Ini.Samples.Files\Load Example.ini"))
iniFile.Load(stream);
// Load file's content from string.
string iniContent = "[Section 1]" + Environment.NewLine +
"Key 1.1 = Value 1.1" + Environment.NewLine +
"Key 1.2 = Value 1.2" + Environment.NewLine +
"Key 1.3 = Value 1.3" + Environment.NewLine +
"Key 1.4 = Value 1.4";
iniFile.Load(new StringReader(iniContent));
// Read file's content.
foreach (var section in iniFile.Sections)
{
Console.WriteLine("SECTION: {0}", section.Name);
foreach (var key in section.Keys)
Console.WriteLine("KEY: {0}, VALUE: {1}", key.Name, key.Value);
}
}
private static void Style()
{
IniFile file = new IniFile();
file.Sections.Add("Section 1").Keys.Add("Key 1", "Value 1");
file.Sections.Add("Section 2").Keys.Add("Key 2", "Value 2");
file.Sections.Add("Section 3").Keys.Add("Key 3", "Value 3");
// Add leading comments.
file.Sections[0].LeadingComment.Text = "Section 1 leading comment.";
file.Sections[0].Keys[0].LeadingComment.Text = "Key 1 leading comment.";
// Add trailing comments.
file.Sections[1].TrailingComment.Text = "Section 2 trailing comment.";
file.Sections[1].Keys[0].TrailingComment.Text = "Key 2 trailing comment.";
// Add left space, indentation.
file.Sections[1].LeftIndentation = 4;
file.Sections[1].TrailingComment.LeftIndentation = 4;
file.Sections[1].Keys[0].LeftIndentation = 4;
file.Sections[1].Keys[0].TrailingComment.LeftIndentation = 4;
// Add above space, empty lines.
file.Sections[2].TrailingComment.EmptyLinesBefore = 2;
}
private static void Save()
{
IniOptions options = new IniOptions();
IniFile iniFile = new IniFile(options);
iniFile.Sections.Add(
new IniSection(iniFile, "Section 1",
new IniKey(iniFile, "Key 1.1", "Value 1.1"),
new IniKey(iniFile, "Key 1.2", "Value 1.2"),
new IniKey(iniFile, "Key 1.3", "Value 1.3"),
new IniKey(iniFile, "Key 1.4", "Value 1.4")));
// Save file to path.
iniFile.Save(@"..\..\..\MadMilkman.Ini.Samples.Files\Save Example.ini");
// Save file to stream.
using (Stream stream = File.Create(@"..\..\..\MadMilkman.Ini.Samples.Files\Save Example.ini"))
iniFile.Save(stream);
// Save file's content to string.
StringWriter contentWriter = new StringWriter();
iniFile.Save(contentWriter);
string iniContent = contentWriter.ToString();
Console.WriteLine(iniContent);
}
private static void Encrypt()
{
// Enable file's protection by providing an encryption password.
IniOptions options = new IniOptions() { EncryptionPassword = "M4dM1lkM4n.1n1" };
IniFile file = new IniFile(options);
IniSection section = file.Sections.Add("User's Account");
section.Keys.Add("Username", "John Doe");
section.Keys.Add("Password", @"P@55\/\/0|2D");
// Save and encrypt the file.
file.Save(@"..\..\..\MadMilkman.Ini.Samples.Files\Encrypt Example.ini");
file.Sections.Clear();
// Load and dencrypt the file.
file.Load(@"..\..\..\MadMilkman.Ini.Samples.Files\Encrypt Example.ini");
Console.WriteLine("User Name: {0}", file.Sections[0].Keys["Username"].Value);
Console.WriteLine("Password: {0}", file.Sections[0].Keys["Password"].Value);
}
private static void Compress()
{
// Enable file's size reduction.
IniOptions options = new IniOptions() { Compression = true };
IniFile file = new IniFile(options);
for (int i = 1; i <= 100; i++)
file.Sections.Add("Section " + i).Keys.Add("Key " + i, "Value " + i);
// Save and compress the file.
file.Save(@"..\..\..\MadMilkman.Ini.Samples.Files\Compress Example.ini");
file.Sections.Clear();
// Load and decompress the file.
file.Load(@"..\..\..\MadMilkman.Ini.Samples.Files\Compress Example.ini");
Console.WriteLine(file.Sections.Count);
}
private static void Custom()
{
// Create new file with custom formatting.
IniFile file = new IniFile(
new IniOptions()
{
CommentStarter = IniCommentStarter.Hash,
KeyDelimiter = IniKeyDelimiter.Colon,
KeySpaceAroundDelimiter = true,
SectionWrapper = IniSectionWrapper.CurlyBrackets,
Encoding = Encoding.UTF8
});
// Load file.
file.Load(@"..\..\..\MadMilkman.Ini.Samples.Files\Custom Example Input.ini");
// Change first section's fourth key's value.
file.Sections[0].Keys[3].Value = "NEW VALUE";
// Save file.
file.Save(@"..\..\..\MadMilkman.Ini.Samples.Files\Custom Example Output.ini");
}
private static void Copy()
{
// Create new file.
IniFile file = new IniFile();
// Add new content.
IniSection section = file.Sections.Add("Section");
IniKey key = section.Keys.Add("Key");
// Add duplicate section.
file.Sections.Add(section.Copy());
// Add duplicate key.
section.Keys.Add(key.Copy());
// Create new file.
IniFile newFile = new IniFile(new IniOptions());
// Import first file's section to second file.
newFile.Sections.Add(section.Copy(newFile));
}
private static void Parse()
{
IniFile file = new IniFile();
string content = "[Player]" + Environment.NewLine +
"Full Name = John Doe" + Environment.NewLine +
"Birthday = 12/31/1999" + Environment.NewLine +
"Married = Yes" + Environment.NewLine +
"Score = 9999999" + Environment.NewLine +
"Game Time = 00:59:59";
file.Load(new StringReader(content));
// Map 'yes' value as 'true' boolean.
file.ValueMappings.Add("yes", true);
// Map 'no' value as 'false' boolean.
file.ValueMappings.Add("no", false);
IniSection playerSection = file.Sections["Player"];
// Retrieve player's name.
string playerName = playerSection.Keys["Full Name"].Value;
// Retrieve player's birthday as DateTime.
DateTime playerBirthday;
playerSection.Keys["Birthday"].TryParseValue(out playerBirthday);
// Retrieve player's marital status as bool.
// TryParseValue succeeds due to the mapping of 'yes' value to 'true' boolean.
bool playerMarried;
playerSection.Keys["Married"].TryParseValue(out playerMarried);
// Retrieve player's score as long.
long playerScore;
playerSection.Keys["Score"].TryParseValue(out playerScore);
// Retrieve player's game time as TimeSpan.
TimeSpan playerGameTime;
playerSection.Keys["Game Time"].TryParseValue(out playerGameTime);
}
private static void BindInternal()
{
IniFile file = new IniFile();
string content = "[Machine Settings]" + Environment.NewLine +
"Program Files = C:\\Program Files" + Environment.NewLine +
"[Application Settings]" + Environment.NewLine +
"Name = Example App" + Environment.NewLine +
"Version = 1.0" + Environment.NewLine +
"Full Name = @{Name} v@{Version}" + Environment.NewLine +
"Executable Path = @{Machine Settings|Program Files}\\@{Name}.exe";
file.Load(new StringReader(content));
// Bind placeholders with file's content, internal information.
file.ValueBinding.Bind();
// Retrieve application's full name, value is 'Example App v1.0'.
string appFullName = file.Sections["Application Settings"].Keys["Full Name"].Value;
// Retrieve application's executable path, value is 'C:\\Program Files\\Example App.exe'.
string appExePath = file.Sections["Application Settings"].Keys["Executable Path"].Value;
}
private static void BindExternal()
{
IniFile file = new IniFile();
string content = "[User's Settings]" + Environment.NewLine +
"Nickname = @{User Alias}" + Environment.NewLine +
"Full Name = @{User Name} @{User Surname}" + Environment.NewLine +
"Profile Page = @{Homepage}/Profiles/@{User Alias}";
file.Load(new StringReader(content));
// Bind placeholders with user's data, external information.
file.ValueBinding.Bind(
new Dictionary<string, string>
{
{"User Alias", "Johny"},
{"User Name", "John"},
{"User Surname", "Doe"}
});
// Bind 'Homepage' placeholder with 'www.example.com' value.
file.ValueBinding.Bind(
new KeyValuePair<string, string>("Homepage", "www.example.com"));
// Retrieve user's full name, value is 'John Doe'.
string userFullName = file.Sections["User's Settings"].Keys["Full Name"].Value;
// Retrieve user's profile page, value is 'www.example.com/Profiles/Johny'.
string userProfilePage = file.Sections["User's Settings"].Keys["Profile Page"].Value;
}
private static void BindCustomize()
{
IniFile file = new IniFile();
string content = "[Player]" + Environment.NewLine +
"Name = @{Name}" + Environment.NewLine +
"Surname = @{Surname}" + Environment.NewLine +
"Adult = @{Age}" + Environment.NewLine +
"Medal = @{Rank}";
file.Load(new StringReader(content));
// Customize binding operation.
file.ValueBinding.Binding += (sender, e) =>
{
// Set placeholders that do not have a value in data source to 'UNKNOWN'.
if (!e.IsValueFound)
{
e.Value = "UNKNOWN";
return;
}
// Set 'Age' placeholder inside 'Adult' key to an appropriate value.
if (e.PlaceholderKey.Name.Equals("Adult") && e.PlaceholderName.Equals("Age"))
{
int age;
if (int.TryParse(e.Value, out age))
e.Value = (age >= 18) ? "YES" : "NO";
else
e.Value = "UNKNOWN";
return;
}
// Set 'Rank' placeholder inside 'Medal' key to an appropriate value.
if (e.PlaceholderKey.Name.Equals("Medal") && e.PlaceholderName.Equals("Rank"))
{
int rank;
if (int.TryParse(e.Value, out rank))
switch (rank)
{
case 1:
e.Value = "GOLD";
break;
case 2:
e.Value = "SILVER";
break;
case 3:
e.Value = "BRONCE";
break;
default:
e.Value = "NONE";
break;
}
else
e.Value = "UNKNOWN";
return;
}
};
// Execute binding operation.
file.ValueBinding.Bind(
new Dictionary<string, string>
{
{"Name", "John"},
{"Age", "20"},
{"Rank", "1"}
});
}
// Custom type used for serialization sample.
private class GameCharacter
{
public string Name { get; set; }
// Serialize this property as a key with "Sword" name.
[IniSerialization("Sword")]
public double Attack { get; set; }
// Serialize this property as a key with "Shield" name.
[IniSerialization("Shield")]
public double Defence { get; set; }
// Ignore serializing this property.
[IniSerialization(true)]
public double Health { get; set; }
public GameCharacter() { this.Health = 100; }
}
private static void Serialize()
{
IniFile file = new IniFile();
IniSection section = file.Sections.Add("User's Character");
GameCharacter character = new GameCharacter();
character.Name = "John";
character.Attack = 5.5;
character.Defence = 1;
character.Health = 75;
// Serialize GameCharacter object into section's keys.
section.Serialize(character);
// Deserialize section into GameCharacter object.
GameCharacter savedCharacter = section.Deserialize<GameCharacter>();
Console.WriteLine(section.Keys["Name"].Value);
Console.WriteLine(savedCharacter.Name);
Console.WriteLine(section.Keys["Sword"].Value);
Console.WriteLine(savedCharacter.Attack);
Console.WriteLine(section.Keys["Shield"].Value);
Console.WriteLine(savedCharacter.Defence);
}
static void Main()
{
HelloWorld();
Create();
Load();
Style();
Save();
Encrypt();
Compress();
Custom();
Copy();
Parse();
BindInternal();
BindExternal();
BindCustomize();
Serialize();
}
}
}

View File

@ -1,58 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{67F5741B-F6B2-4A4B-8E83-E0FD108086B1}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>MadMilkman.Ini.Samples.CS</RootNamespace>
<AssemblyName>MadMilkman.Ini.Samples.CS</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<Compile Include="IniSamples.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\MadMilkman.Ini\MadMilkman.Ini.csproj">
<Project>{bef9735d-c3cc-41e6-aac6-18c5985d3107}</Project>
<Name>MadMilkman.Ini</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -1,36 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("MadMilkman.Ini.Samples.CS")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("MadMilkman.Ini.Samples.CS")]
[assembly: AssemblyCopyright("Copyright © 2015")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("b1e20845-bdae-4fbe-842c-42d4ee655565")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -1 +0,0 @@
BAwAAB+LCAAAAAAABABV1j2OUDkQReEciT30EtpVrr+AFRAikaAJRqMORkKQQMDuIfAx98Unep/87Pvl09t/P/7//u1l/fP+3ce3Xy/rw+d/v/58e1nv332h2Wl2mknz0/w0l7ZP26dtaXFanBbS8rQ8LaXVaXVaSevT+rSWNqfNaSNtvfLxr3z9q+Zrc3FUZ8Gz8FkKtBBaEC01WiAtlJYyLZwWUEulFlQLq6VYC60F11KvBdhCbCnZwmyBtlTNUDPUTNUMNUPNHmfqHqp7qlTNUDPUTNUMNUPNVM1QM9RM1Qw1Q81UzVAz1EzVDDVDzVTNUDPUTNUcNUfNVc1Rc9Rc1Rw1R80fP+P9G+/vqGqOmqPmquaoOWquao6ao+aq5qg5aq5qjpqj5qrmqDlqrmobtY3aVrWN2kZtq9pGbaO2VW2jtlHbj1vsXmP3HlO1jdpGbavaRm2jtlVto7ZR26q2UduobVXbqG3UtqoFaoFaqFqgFqiFqgVqgVqoWqAWqIWqBWqBWjyu/3v/3wdA1QK1QC1ULVAL1ELVArVALVQtUAvUQtUStUQtVS1RS9RS1RK1RC1VLVFL1FLVErVELVUtUUvU8vFu3ofzvpyqlqglaqlqiVqilqqWqCVqqWqFWqFWqlaoFWqlaoVaoVaqVqgVaqVqhVqhVqpWqBVqpWqFWqFWj8FxF8edHKpWqBVqpWqFWqFWqtaoNWqtao1ao9aq1qg1aq1qjVqj1qrWqDVqrWqNWqPWqtaoNWqtao1ao9aPpXan2t1qqtaoNWqtaoPaoDaqNqgNaqNqg9qgNqo2qA1qo2qD2qA2qjaoDWqjaoPaoDaqNqgNaqNqg9qgNo+JezfuHbnPlft35v7duX/gfgMYovcVBAwAAA==

View File

@ -1,18 +0,0 @@
# Hello World in few languages
{Worlds}
Chinese : 你好世界
Croatian : Zdravo Svijete
Dutch : Hello Wereld
English : Hello World
French : Bonjour Monde
German : Hallo Welt
Greek : γειά σου κόσμος
Italian : Ciao Mondo
Japanese : こんにちは世界
Korean : 여보세요 세계
Portuguese : Olá Mundo
Russian : Здравствулте Мир
Spanish : Hola Mundo

View File

@ -1,18 +0,0 @@

# Hello World in few languages
{Worlds}
Chinese : 你好世界
Croatian : Zdravo Svijete
Dutch : Hello Wereld
English : NEW VALUE
French : Bonjour Monde
German : Hallo Welt
Greek : γειά σου κόσμος
Italian : Ciao Mondo
Japanese : こんにちは世界
Korean : 여보세요 세계
Portuguese : Olá Mundo
Russian : Здравствулте Мир
Spanish : Hola Mundo

View File

@ -1 +0,0 @@
X3zNmiTOWEKAG73S8BzrlddMtsozck0eDN7TYwYQv9kswSItWrB31gjJMHtcuGUxFcimtUxtuZ3y0UzoZ8/TBg==

View File

@ -1,5 +0,0 @@
[Section 1]
Key 1.1=Value 1.1
Key 1.2=Value 1.2
Key 1.3=Value 1.3
Key 1.4=Value 1.4

View File

@ -1,5 +0,0 @@
[Section 1]
Key 1.1=Value 1.1
Key 1.2=Value 1.2
Key 1.3=Value 1.3
Key 1.4=Value 1.4

View File

@ -1,469 +0,0 @@
Imports System
Imports System.IO
Imports System.Text
Imports System.Collections.Generic
Imports MadMilkman.Ini
Module IniSamples
Private Sub HelloWorld()
' Create new file.
Dim file As New IniFile()
' Add new section.
Dim section As IniSection = file.Sections.Add("Section Name")
' Add new key and its value.
Dim key As IniKey = section.Keys.Add("Key Name", "Hello World")
' Read file's specific value.
Console.WriteLine(file.Sections("Section Name").Keys("Key Name").Value)
End Sub
Private Sub Create()
' Create new file with default formatting.
Dim file As New IniFile(New IniOptions())
' Add new content.
Dim section As New IniSection(file, IniSection.GlobalSectionName)
Dim key As New IniKey(file, "Key 1", "Value 1")
file.Sections.Add(section)
section.Keys.Add(key)
' Add new content.
file.Sections.Add("Section 2").Keys.Add("Key 2", "Value 2")
' Add new content.
file.Sections.Add(
New IniSection(file, "Section 3",
New IniKey(file, "Key 3.1", "Value 3.1"),
New IniKey(file, "Key 3.2", "Value 3.2")))
' Add new content.
file.Sections.Add(
New IniSection(file, "Section 4",
New Dictionary(Of String, String)() From {
{"Key 4.1", "Value 4.1"},
{"Key 4.2", "Value 4.2"}
}))
End Sub
Private Sub Load()
Dim options As New IniOptions()
Dim iniFile As New IniFile(options)
' Load file from path.
iniFile.Load("..\..\..\MadMilkman.Ini.Samples.Files\Load Example.ini")
' Load file from stream.
Using stream As Stream = File.OpenRead("..\..\..\MadMilkman.Ini.Samples.Files\Load Example.ini")
iniFile.Load(stream)
End Using
' Load file's content from string.
Dim iniContent As String = "[Section 1]" + Environment.NewLine +
"Key 1.1 = Value 1.1" + Environment.NewLine +
"Key 1.2 = Value 1.2" + Environment.NewLine +
"Key 1.3 = Value 1.3" + Environment.NewLine +
"Key 1.4 = Value 1.4"
iniFile.Load(New StringReader(iniContent))
' Read file's content.
For Each section In iniFile.Sections
Console.WriteLine("SECTION: {0}", section.Name)
For Each key In section.Keys
Console.WriteLine("KEY: {0}, VALUE: {1}", key.Name, key.Value)
Next
Next
End Sub
Private Sub Style()
Dim file As New IniFile()
file.Sections.Add("Section 1").Keys.Add("Key 1", "Value 1")
file.Sections.Add("Section 2").Keys.Add("Key 2", "Value 2")
file.Sections.Add("Section 3").Keys.Add("Key 3", "Value 3")
' Add leading comments.
file.Sections(0).LeadingComment.Text = "Section 1 leading comment."
file.Sections(0).Keys(0).LeadingComment.Text = "Key 1 leading comment."
' Add trailing comments.
file.Sections(1).TrailingComment.Text = "Section 2 trailing comment."
file.Sections(1).Keys(0).TrailingComment.Text = "Key 2 trailing comment."
' Add left space, indentation.
file.Sections(1).LeftIndentation = 4
file.Sections(1).TrailingComment.LeftIndentation = 4
file.Sections(1).Keys(0).LeftIndentation = 4
file.Sections(1).Keys(0).TrailingComment.LeftIndentation = 4
' Add above space, empty lines.
file.Sections(2).TrailingComment.EmptyLinesBefore = 2
End Sub
Private Sub Save()
Dim options As New IniOptions()
Dim iniFile As New IniFile(options)
iniFile.Sections.Add(
New IniSection(iniFile, "Section 1",
New IniKey(iniFile, "Key 1.1", "Value 1.1"),
New IniKey(iniFile, "Key 1.2", "Value 1.2"),
New IniKey(iniFile, "Key 1.3", "Value 1.3"),
New IniKey(iniFile, "Key 1.4", "Value 1.4")))
' Save file to path.
iniFile.Save("..\..\..\MadMilkman.Ini.Samples.Files\Save Example.ini")
' Save file to stream.
Using stream As Stream = File.Create("..\..\..\MadMilkman.Ini.Samples.Files\Save Example.ini")
iniFile.Save(stream)
End Using
' Save file's content to string.
Dim contentWriter As New StringWriter()
iniFile.Save(contentWriter)
Dim iniContent As String = contentWriter.ToString()
Console.WriteLine(iniContent)
End Sub
Private Sub Encrypt()
' Enable file's protection by providing an encryption password.
Dim options As IniOptions = New IniOptions() With {.EncryptionPassword = "M4dM1lkM4n.1n1"}
Dim file As IniFile = New IniFile(options)
Dim section As IniSection = file.Sections.Add("User's Account")
section.Keys.Add("Username", "John Doe")
section.Keys.Add("Password", "P@55\/\/0|2D")
' Save and encrypt the file.
file.Save("..\..\..\MadMilkman.Ini.Samples.Files\Encrypt Example.ini")
file.Sections.Clear()
' Load and dencrypt the file.
file.Load("..\..\..\MadMilkman.Ini.Samples.Files\Encrypt Example.ini")
Console.WriteLine("User Name: {0}", file.Sections(0).Keys("Username").Value)
Console.WriteLine("Password: {0}", file.Sections(0).Keys("Password").Value)
End Sub
Private Sub Compress()
' Enable file's size reduction.
Dim options As IniOptions = New IniOptions() With {.Compression = True}
Dim file = New IniFile(options)
For i As Integer = 1 To 100
file.Sections.Add("Section " + i.ToString()).Keys.Add("Key " + i.ToString(), "Value " + i.ToString())
Next
' Save and compress the file.
file.Save("..\..\..\MadMilkman.Ini.Samples.Files\Compress Example.ini")
file.Sections.Clear()
' Load and decompress the file.
file.Load("..\..\..\MadMilkman.Ini.Samples.Files\Compress Example.ini")
Console.WriteLine(file.Sections.Count)
End Sub
Private Sub Custom()
' Create new file with custom formatting.
Dim file As New IniFile(
New IniOptions() With {
.CommentStarter = IniCommentStarter.Hash,
.KeyDelimiter = IniKeyDelimiter.Colon,
.KeySpaceAroundDelimiter = True,
.SectionWrapper = IniSectionWrapper.CurlyBrackets,
.Encoding = Encoding.UTF8
})
' Load file.
file.Load("..\..\..\MadMilkman.Ini.Samples.Files\Custom Example Input.ini")
' Change first section's fourth key's value.
file.Sections(0).Keys(3).Value = "NEW VALUE"
' Save file.
file.Save("..\..\..\MadMilkman.Ini.Samples.Files\Custom Example Output.ini")
End Sub
Private Sub Copy()
' Create new file.
Dim file As New IniFile()
' Add new content.
Dim section As IniSection = file.Sections.Add("Section")
Dim key As IniKey = section.Keys.Add("Key")
' Add duplicate section.
file.Sections.Add(section.Copy())
' Add duplicate key.
section.Keys.Add(key.Copy())
' Create new file.
Dim newFile As New IniFile(New IniOptions())
' Import first file's section to second file.
newFile.Sections.Add(section.Copy(newFile))
End Sub
Private Sub Parse()
Dim file As New IniFile()
Dim content As String = "[Player]" + Environment.NewLine +
"Full Name = John Doe" + Environment.NewLine +
"Birthday = 12/31/1999" + Environment.NewLine +
"Married = Yes" + Environment.NewLine +
"Score = 9999999" + Environment.NewLine +
"Game Time = 00:59:59"
file.Load(New StringReader(content))
' Map 'yes' value as 'true' boolean.
file.ValueMappings.Add("yes", True)
' Map 'no' value as 'false' boolean.
file.ValueMappings.Add("no", False)
Dim playerSection As IniSection = file.Sections("Player")
' Retrieve player's name.
Dim playerName As String = playerSection.Keys("Full Name").Value
' Retrieve player's birthday as DateTime.
Dim playerBirthday As DateTime
playerSection.Keys("Birthday").TryParseValue(playerBirthday)
' Retrieve player's marital status as bool.
' TryParseValue succeeds due to the mapping of 'yes' value to 'true' boolean.
Dim playerMarried As Boolean
playerSection.Keys("Married").TryParseValue(playerMarried)
' Retrieve player's score as long.
Dim playerScore As Long
playerSection.Keys("Score").TryParseValue(playerScore)
' Retrieve player's game time as TimeSpan.
Dim playerGameTime As TimeSpan
playerSection.Keys("Game Time").TryParseValue(playerGameTime)
End Sub
Private Sub BindInternal()
Dim file As New IniFile()
Dim content As String = "[Machine Settings]" + Environment.NewLine +
"Program Files = C:\Program Files" + Environment.NewLine +
"[Application Settings]" + Environment.NewLine +
"Name = Example App" + Environment.NewLine +
"Version = 1.0" + Environment.NewLine +
"Full Name = @{Name} v@{Version}" + Environment.NewLine +
"Executable Path = @{Machine Settings|Program Files}\@{Name}.exe"
file.Load(New StringReader(content))
' Bind placeholders with file's content, internal information.
file.ValueBinding.Bind()
' Retrieve application's full name, value is 'Example App v1.0'.
Dim appFullName As String = file.Sections("Application Settings").Keys("Full Name").Value
' Retrieve application's executable path, value is 'C:\\Program Files\\Example App.exe'.
Dim appExePath As String = file.Sections("Application Settings").Keys("Executable Path").Value
End Sub
Private Sub BindExternal()
Dim file As New IniFile()
Dim content As String = "[User's Settings]" + Environment.NewLine +
"Nickname = @{User Alias}" + Environment.NewLine +
"Full Name = @{User Name} @{User Surname}" + Environment.NewLine +
"Profile Page = @{Homepage}/Profiles/@{User Alias}"
file.Load(New StringReader(content))
' Bind placeholders with user's data, external information.
file.ValueBinding.Bind(
New Dictionary(Of String, String)() From
{
{"User Alias", "Johny"},
{"User Name", "John"},
{"User Surname", "Doe"}
})
' Bind 'Homepage' placeholder with 'www.example.com' value.
file.ValueBinding.Bind(
New KeyValuePair(Of String, String)("Homepage", "www.example.com"))
' Retrieve user's full name, value is 'John Doe'.
Dim userFullName As String = file.Sections("User's Settings").Keys("Full Name").Value
' Retrieve user's profile page, value is 'www.example.com/Profiles/Johny'.
Dim userProfilePage As String = file.Sections("User's Settings").Keys("Profile Page").Value
End Sub
Private Sub BindCustomize()
Dim file As New IniFile()
Dim content As String = "[Player]" + Environment.NewLine +
"Name = @{Name}" + Environment.NewLine +
"Surname = @{Surname}" + Environment.NewLine +
"Adult = @{Age}" + Environment.NewLine +
"Medal = @{Rank}"
file.Load(New StringReader(content))
' Customize binding operation.
AddHandler file.ValueBinding.Binding,
Sub(sender, e)
' Set placeholders that do not have a value in data source to 'UNKNOWN'.
If Not e.IsValueFound Then
e.Value = "UNKNOWN"
Return
End If
' Set 'Age' placeholder inside 'Adult' key to an appropriate value.
If e.PlaceholderKey.Name.Equals("Adult") AndAlso e.PlaceholderName.Equals("Age") Then
Dim age As Integer
If Integer.TryParse(e.Value, age) Then
e.Value = If((age >= 18), "YES", "NO")
Else
e.Value = "UNKNOWN"
End If
Return
End If
' Set 'Rank' placeholder inside 'Medal' key to an appropriate value.
If e.PlaceholderKey.Name.Equals("Medal") AndAlso e.PlaceholderName.Equals("Rank") Then
Dim rank As Integer
If Integer.TryParse(e.Value, rank) Then
Select Case rank
Case 1
e.Value = "GOLD"
Exit Select
Case 2
e.Value = "SILVER"
Exit Select
Case 3
e.Value = "BRONCE"
Exit Select
Case Else
e.Value = "NONE"
Exit Select
End Select
Else
e.Value = "UNKNOWN"
End If
Return
End If
End Sub
' Execute binding operation.
file.ValueBinding.Bind(New Dictionary(Of String, String)() From {
{"Name", "John"},
{"Age", "20"},
{"Rank", "1"}
})
End Sub
' Custom type used for serialization sample.
Private Class GameCharacter
Public Property Name() As String
Get
Return m_Name
End Get
Set(value As String)
m_Name = Value
End Set
End Property
Private m_Name As String
' Serialize this property as a key with "Sword" name.
<IniSerialization("Sword")>
Public Property Attack() As Double
Get
Return m_Attack
End Get
Set(value As Double)
m_Attack = value
End Set
End Property
Private m_Attack As Double
' Serialize this property as a key with "Shield" name.
<IniSerialization("Shield")>
Public Property Defence() As Double
Get
Return m_Defence
End Get
Set(value As Double)
m_Defence = value
End Set
End Property
Private m_Defence As Double
' Ignore serializing this property.
<IniSerialization(True)>
Public Property Health() As Double
Get
Return m_Health
End Get
Set(value As Double)
m_Health = value
End Set
End Property
Private m_Health As Double
Public Sub New()
Me.Health = 100
End Sub
End Class
Private Sub Serialize()
Dim file As New IniFile()
Dim section As IniSection = file.Sections.Add("User's Character")
Dim character As New GameCharacter()
character.Name = "John"
character.Attack = 5.5
character.Defence = 1
character.Health = 75
' Serialize GameCharacter object into section's keys.
section.Serialize(character)
' Deserialize section into GameCharacter object.
Dim savedCharacter As GameCharacter = section.Deserialize(Of GameCharacter)()
Console.WriteLine(section.Keys("Name").Value)
Console.WriteLine(savedCharacter.Name)
Console.WriteLine(section.Keys("Sword").Value)
Console.WriteLine(savedCharacter.Attack)
Console.WriteLine(section.Keys("Shield").Value)
Console.WriteLine(savedCharacter.Defence)
End Sub
Sub Main()
HelloWorld()
Create()
Load()
Style()
Save()
Encrypt()
Compress()
Custom()
Copy()
Parse()
BindInternal()
BindExternal()
BindCustomize()
Serialize()
End Sub
End Module

View File

@ -1,102 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{4FEA3A29-874B-4E1B-A60C-584E703FEA11}</ProjectGuid>
<OutputType>Exe</OutputType>
<StartupObject>MadMilkman.Ini.Samples.VB.IniSamples</StartupObject>
<RootNamespace>MadMilkman.Ini.Samples.VB</RootNamespace>
<AssemblyName>MadMilkman.Ini.Samples.VB</AssemblyName>
<FileAlignment>512</FileAlignment>
<MyType>Console</MyType>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<DefineDebug>true</DefineDebug>
<DefineTrace>true</DefineTrace>
<OutputPath>bin\Debug\</OutputPath>
<DocumentationFile>MadMilkman.Ini.Samples.VB.xml</DocumentationFile>
<NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<DefineDebug>false</DefineDebug>
<DefineTrace>true</DefineTrace>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DocumentationFile>MadMilkman.Ini.Samples.VB.xml</DocumentationFile>
<NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>
</PropertyGroup>
<PropertyGroup>
<OptionExplicit>On</OptionExplicit>
</PropertyGroup>
<PropertyGroup>
<OptionCompare>Binary</OptionCompare>
</PropertyGroup>
<PropertyGroup>
<OptionStrict>Off</OptionStrict>
</PropertyGroup>
<PropertyGroup>
<OptionInfer>On</OptionInfer>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<Compile Include="IniSamples.vb" />
<Compile Include="My Project\AssemblyInfo.vb" />
<Compile Include="My Project\Application.Designer.vb">
<AutoGen>True</AutoGen>
<DependentUpon>Application.myapp</DependentUpon>
</Compile>
<Compile Include="My Project\Resources.Designer.vb">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="My Project\Settings.Designer.vb">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="My Project\Resources.resx">
<Generator>VbMyResourcesResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.vb</LastGenOutput>
<CustomToolNamespace>My.Resources</CustomToolNamespace>
<SubType>Designer</SubType>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<None Include="My Project\Application.myapp">
<Generator>MyApplicationCodeGenerator</Generator>
<LastGenOutput>Application.Designer.vb</LastGenOutput>
</None>
<None Include="My Project\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<CustomToolNamespace>My</CustomToolNamespace>
<LastGenOutput>Settings.Designer.vb</LastGenOutput>
</None>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\MadMilkman.Ini\MadMilkman.Ini.csproj">
<Project>{bef9735d-c3cc-41e6-aac6-18c5985d3107}</Project>
<Name>MadMilkman.Ini</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -1,13 +0,0 @@
'------------------------------------------------------------------------------
' <auto-generated>
' This code was generated by a tool.
' Runtime Version:4.0.30319.18444
'
' Changes to this file may cause incorrect behavior and will be lost if
' the code is regenerated.
' </auto-generated>
'------------------------------------------------------------------------------
Option Strict On
Option Explicit On

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<MyApplicationData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<MySubMain>false</MySubMain>
<SingleInstance>false</SingleInstance>
<ShutdownMode>0</ShutdownMode>
<EnableVisualStyles>true</EnableVisualStyles>
<AuthenticationMode>0</AuthenticationMode>
<ApplicationType>2</ApplicationType>
<SaveMySettingsOnExit>true</SaveMySettingsOnExit>
</MyApplicationData>

View File

@ -1,35 +0,0 @@
Imports System
Imports System.Reflection
Imports System.Runtime.InteropServices
' General Information about an assembly is controlled through the following
' set of attributes. Change these attribute values to modify the information
' associated with an assembly.
' Review the values of the assembly attributes
<Assembly: AssemblyTitle("MadMilkman.Ini.Samples.VB")>
<Assembly: AssemblyDescription("")>
<Assembly: AssemblyCompany("")>
<Assembly: AssemblyProduct("MadMilkman.Ini.Samples.VB")>
<Assembly: AssemblyCopyright("Copyright © 2015")>
<Assembly: AssemblyTrademark("")>
<Assembly: ComVisible(False)>
'The following GUID is for the ID of the typelib if this project is exposed to COM
<Assembly: Guid("076ab4a2-c8bd-4e3c-bcc2-73829d6c834d")>
' Version information for an assembly consists of the following four values:
'
' Major Version
' Minor Version
' Build Number
' Revision
'
' You can specify all the values or you can default the Build and Revision Numbers
' by using the '*' as shown below:
' <Assembly: AssemblyVersion("1.0.*")>
<Assembly: AssemblyVersion("1.0.0.0")>
<Assembly: AssemblyFileVersion("1.0.0.0")>

View File

@ -1,62 +0,0 @@
'------------------------------------------------------------------------------
' <auto-generated>
' This code was generated by a tool.
' Runtime Version:4.0.30319.18444
'
' Changes to this file may cause incorrect behavior and will be lost if
' the code is regenerated.
' </auto-generated>
'------------------------------------------------------------------------------
Option Strict On
Option Explicit On
Namespace My.Resources
'This class was auto-generated by the StronglyTypedResourceBuilder
'class via a tool like ResGen or Visual Studio.
'To add or remove a member, edit your .ResX file then rerun ResGen
'with the /str option, or rebuild your VS project.
'''<summary>
''' A strongly-typed resource class, for looking up localized strings, etc.
'''</summary>
<Global.System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0"), _
Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
Global.Microsoft.VisualBasic.HideModuleNameAttribute()> _
Friend Module Resources
Private resourceMan As Global.System.Resources.ResourceManager
Private resourceCulture As Global.System.Globalization.CultureInfo
'''<summary>
''' Returns the cached ResourceManager instance used by this class.
'''</summary>
<Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
Friend ReadOnly Property ResourceManager() As Global.System.Resources.ResourceManager
Get
If Object.ReferenceEquals(resourceMan, Nothing) Then
Dim temp As Global.System.Resources.ResourceManager = New Global.System.Resources.ResourceManager("MadMilkman.Ini.Samples.VB.Resources", GetType(Resources).Assembly)
resourceMan = temp
End If
Return resourceMan
End Get
End Property
'''<summary>
''' Overrides the current thread's CurrentUICulture property for all
''' resource lookups using this strongly typed resource class.
'''</summary>
<Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
Friend Property Culture() As Global.System.Globalization.CultureInfo
Get
Return resourceCulture
End Get
Set(ByVal value As Global.System.Globalization.CultureInfo)
resourceCulture = value
End Set
End Property
End Module
End Namespace

View File

@ -1,117 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -1,73 +0,0 @@
'------------------------------------------------------------------------------
' <auto-generated>
' This code was generated by a tool.
' Runtime Version:4.0.30319.18444
'
' Changes to this file may cause incorrect behavior and will be lost if
' the code is regenerated.
' </auto-generated>
'------------------------------------------------------------------------------
Option Strict On
Option Explicit On
Namespace My
<Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
Global.System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0"), _
Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
Partial Friend NotInheritable Class MySettings
Inherits Global.System.Configuration.ApplicationSettingsBase
Private Shared defaultInstance As MySettings = CType(Global.System.Configuration.ApplicationSettingsBase.Synchronized(New MySettings), MySettings)
#Region "My.Settings Auto-Save Functionality"
#If _MyType = "WindowsForms" Then
Private Shared addedHandler As Boolean
Private Shared addedHandlerLockObject As New Object
<Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
Private Shared Sub AutoSaveSettings(ByVal sender As Global.System.Object, ByVal e As Global.System.EventArgs)
If My.Application.SaveMySettingsOnExit Then
My.Settings.Save()
End If
End Sub
#End If
#End Region
Public Shared ReadOnly Property [Default]() As MySettings
Get
#If _MyType = "WindowsForms" Then
If Not addedHandler Then
SyncLock addedHandlerLockObject
If Not addedHandler Then
AddHandler My.Application.Shutdown, AddressOf AutoSaveSettings
addedHandler = True
End If
End SyncLock
End If
#End If
Return defaultInstance
End Get
End Property
End Class
End Namespace
Namespace My
<Global.Microsoft.VisualBasic.HideModuleNameAttribute(), _
Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute()> _
Friend Module MySettingsProperty
<Global.System.ComponentModel.Design.HelpKeywordAttribute("My.Settings")> _
Friend ReadOnly Property Settings() As Global.MadMilkman.Ini.Samples.VB.My.MySettings
Get
Return Global.MadMilkman.Ini.Samples.VB.My.MySettings.Default
End Get
End Property
End Module
End Namespace

View File

@ -1,7 +0,0 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" UseMySettingsClassName="true">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

View File

@ -1,118 +0,0 @@
using System;
using System.Collections.Generic;
using NUnit.Framework;
namespace MadMilkman.Ini.Tests
{
[TestFixture]
public class BugFixes
{
[Test]
public void Bug1()
{
string iniFileContent = "[Segment [A]]" + Environment.NewLine +
"[Segment [A]];[Comment];" + Environment.NewLine +
"[Segment [A][1]]" + Environment.NewLine +
"[Segment [A][1]] ;[Comment][1];" + Environment.NewLine +
"[Segment;A]" + Environment.NewLine +
"[Segment[A;B]]" + Environment.NewLine +
"[Segment[A;B]];" + Environment.NewLine +
"[Segment[A;B]] ;[Comment];" + Environment.NewLine +
"[Segment[A;B]]AB;Invalid comment" + Environment.NewLine +
"[Segment[A;B]][[;Invalid comment" + Environment.NewLine +
"[Segment[A;B;]";
IniOptions options = new IniOptions();
IniFile file = IniUtilities.LoadIniFileContent(iniFileContent, options);
Assert.AreEqual("Segment [A]", file.Sections[0].Name);
Assert.AreEqual("Segment [A]", file.Sections[1].Name);
Assert.AreEqual("[Comment];", file.Sections[1].LeadingComment.Text);
Assert.AreEqual("Segment [A][1]", file.Sections[2].Name);
Assert.AreEqual("Segment [A][1]", file.Sections[3].Name);
Assert.AreEqual("[Comment][1];", file.Sections[3].LeadingComment.Text);
Assert.AreEqual(2, file.Sections[3].LeadingComment.LeftIndentation);
Assert.AreEqual("Segment;A", file.Sections[4].Name);
Assert.AreEqual(null, file.Sections[4].LeadingComment.Text);
Assert.AreEqual("Segment[A;B]", file.Sections[5].Name);
Assert.AreEqual(null, file.Sections[5].LeadingComment.Text);
Assert.AreEqual("Segment[A;B]", file.Sections[6].Name);
Assert.AreEqual(string.Empty, file.Sections[6].LeadingComment.Text);
Assert.AreEqual("Segment[A;B]", file.Sections[7].Name);
Assert.AreEqual("[Comment];", file.Sections[7].LeadingComment.Text);
Assert.AreEqual(4, file.Sections[7].LeadingComment.LeftIndentation);
Assert.AreEqual("Segment[A;B]", file.Sections[8].Name);
Assert.AreEqual(null, file.Sections[8].LeadingComment.Text);
Assert.AreEqual("Segment[A;B]", file.Sections[9].Name);
Assert.AreEqual(null, file.Sections[9].LeadingComment.Text);
Assert.AreEqual("Segment[A;B;", file.Sections[10].Name);
string[] lines = IniUtilities.SaveIniFileContent(file, options);
Assert.AreEqual("[Segment [A]]", lines[0]);
Assert.AreEqual("[Segment [A]];[Comment];", lines[1]);
Assert.AreEqual("[Segment [A][1]]", lines[2]);
Assert.AreEqual("[Segment [A][1]] ;[Comment][1];", lines[3]);
Assert.AreEqual("[Segment;A]", lines[4]);
Assert.AreEqual("[Segment[A;B]]", lines[5]);
Assert.AreEqual("[Segment[A;B]];", lines[6]);
Assert.AreEqual("[Segment[A;B]] ;[Comment];", lines[7]);
Assert.AreEqual("[Segment[A;B]]", lines[8]);
Assert.AreEqual("[Segment[A;B]]", lines[9]);
Assert.AreEqual("[Segment[A;B;]", lines[10]);
}
public class Bug2Class
{
public string[] NullArray { get; set; }
public List<string> NullList { get; set; }
public string[] EmptyArray { get; set; }
public List<string> EmptyList { get; set; }
}
[Test]
public void Bug2()
{
var ini = new IniFile();
var sec = ini.Sections.Add("Sample");
sec.Serialize(
new Bug2Class()
{
EmptyArray = new string[3],
EmptyList = new List<string>()
});
var deserializeObj = sec.Deserialize<Bug2Class>();
Assert.IsNull(sec.Keys["NullArray"].Value);
Assert.IsNull(sec.Keys["NullList"].Value);
Assert.AreEqual("{,,}", sec.Keys["EmptyArray"].Value);
Assert.AreEqual("{}", sec.Keys["EmptyList"].Value);
Assert.IsNull(deserializeObj.NullArray);
Assert.IsNull(deserializeObj.NullList);
CollectionAssert.AreEqual(new string[] { "", "", "" }, deserializeObj.EmptyArray);
CollectionAssert.IsEmpty(deserializeObj.EmptyList);
}
[Test]
public void Bug3()
{
string iniFileContent = "[sektion]" + Environment.NewLine +
"key=\"Data Source=server;Initial Catalog=catalog;Integrated Security=SSPI\"";
IniFile file = IniUtilities.LoadIniFileContent(iniFileContent, new IniOptions());
IniKey key = file.Sections["sektion"].Keys["key"];
Assert.AreEqual("\"Data Source=server;Initial Catalog=catalog;Integrated Security=SSPI\"", key.Value);
Assert.IsNull(key.LeadingComment.Text);
}
}
}

View File

@ -1,400 +0,0 @@
using System;
using System.Linq;
using System.Collections.Generic;
using NUnit.Framework;
namespace MadMilkman.Ini.Tests
{
[TestFixture]
public class IniFileCreateUpdateTests
{
[Test]
public void CreateIniFileBasicTest()
{
var file = new IniFile();
var section1 = file.Sections.Add("Section 1.");
var section2 = file.Sections.Add("Section 2.");
var section3 = file.Sections.Add("Section 3.");
var key1 = section1.Keys.Add("Key 1.", "Value 1.");
var key2 = section2.Keys.Add("Key 2.", "Value 2.");
var key3 = section3.Keys.Add("Key 3.", "Value 3.");
Assert.AreEqual(3, file.Sections.Count);
Assert.AreEqual("Section 1.", section1.Name);
Assert.AreEqual("Section 2.", section2.Name);
Assert.AreEqual("Section 3.", section3.Name);
Assert.AreEqual(1, section1.Keys.Count);
Assert.AreEqual(1, section2.Keys.Count);
Assert.AreEqual(1, section3.Keys.Count);
Assert.AreEqual("Key 1.", key1.Name);
Assert.AreEqual("Value 1.", key1.Value);
Assert.AreEqual("Key 2.", key2.Name);
Assert.AreEqual("Value 2.", key2.Value);
Assert.AreEqual("Key 3.", key3.Name);
Assert.AreEqual("Value 3.", key3.Value);
}
[Test]
public void CreateIniFileAdvanceTest()
{
var file = new IniFile();
file.Sections.Add(
new IniSection(file, "Section 1.",
new IniKey(file, "Key 1.1.") { Value = "Value 1.1." },
new IniKey(file, "Key 1.2.") { Value = "Value 1.2." }));
file.Sections.Add(
new IniSection(file, "Section 2.",
new IniKey(file, "Key 2.1.") { Value = "Value 2.1." },
new IniKey(file, "Key 2.2.") { Value = "Value 2.2." }));
file.Sections.Add(
new IniSection(file, "Section 3.",
new IniKey(file, "Key 3.1.") { Value = "Value 3.1." },
new IniKey(file, "Key 3.2.") { Value = "Value 3.2." }));
Assert.AreEqual(3, file.Sections.Count);
Assert.AreEqual("Section 1.", file.Sections[0].Name);
Assert.AreEqual("Section 2.", file.Sections[1].Name);
Assert.AreEqual("Section 3.", file.Sections[2].Name);
Assert.AreEqual(2, file.Sections[0].Keys.Count);
Assert.AreEqual(2, file.Sections[1].Keys.Count);
Assert.AreEqual(2, file.Sections[2].Keys.Count);
Assert.AreEqual("Key 1.1.", file.Sections[0].Keys[0].Name);
Assert.AreEqual("Value 1.1.", file.Sections[0].Keys[0].Value);
Assert.AreEqual("Key 1.2.", file.Sections[0].Keys[1].Name);
Assert.AreEqual("Value 1.2.", file.Sections[0].Keys[1].Value);
Assert.AreEqual("Key 2.1.", file.Sections[1].Keys[0].Name);
Assert.AreEqual("Value 2.1.", file.Sections[1].Keys[0].Value);
Assert.AreEqual("Key 2.2.", file.Sections[1].Keys[1].Name);
Assert.AreEqual("Value 2.2.", file.Sections[1].Keys[1].Value);
Assert.AreEqual("Key 3.1.", file.Sections[2].Keys[0].Name);
Assert.AreEqual("Value 3.1.", file.Sections[2].Keys[0].Value);
Assert.AreEqual("Key 3.2.", file.Sections[2].Keys[1].Name);
Assert.AreEqual("Value 3.2.", file.Sections[2].Keys[1].Value);
}
[Test]
public void CreateIniFileExpertTest()
{
var dictionary = new Dictionary<string, string>()
{
{ "Key 2.1.", "Value 2.1." },
{ "Key 2.2.", "Value 2.2." },
{ "Key 2.3.", "Value 2.3." },
{ "Key 2.4.", "Value 2.4." }
};
var file = new IniFile();
file.Sections.Add("Section 1.").Keys.Add(new KeyValuePair<string, string>("Key 1.1.", "Value 1.1."));
file.Sections.Add("Section 2.", dictionary);
Assert.AreEqual(2, file.Sections.Count);
Assert.AreEqual("Section 1.", file.Sections[0].Name);
Assert.AreEqual("Section 2.", file.Sections[1].Name);
Assert.AreEqual(1, file.Sections[0].Keys.Count);
Assert.AreEqual(4, file.Sections[1].Keys.Count);
Assert.AreEqual("Key 1.1.", file.Sections[0].Keys[0].Name);
Assert.AreEqual("Value 1.1.", file.Sections[0].Keys[0].Value);
Assert.AreEqual("Key 2.1.", file.Sections[1].Keys[0].Name);
Assert.AreEqual("Value 2.1.", file.Sections[1].Keys[0].Value);
Assert.AreEqual("Key 2.2.", file.Sections[1].Keys[1].Name);
Assert.AreEqual("Value 2.2.", file.Sections[1].Keys[1].Value);
Assert.AreEqual("Key 2.3.", file.Sections[1].Keys[2].Name);
Assert.AreEqual("Value 2.3.", file.Sections[1].Keys[2].Value);
Assert.AreEqual("Key 2.4.", file.Sections[1].Keys[3].Name);
Assert.AreEqual("Value 2.4.", file.Sections[1].Keys[3].Value);
}
[Test]
public void UpdateIniFileLinqTest()
{
var file = new IniFile();
var section1 = file.Sections.Add("Section 1.");
var key1 = section1.Keys.Add("Key 1.1.", "Value 1.1.");
var key2 = section1.Keys.Add("Key 1.2.", "Value 1.2.");
foreach (var key in section1.Keys.Where(k => k.Name.Contains("1")))
key.Name = key.Name.Replace("Key 1.", "First Section Key ");
Assert.AreEqual("First Section Key 1.", section1.Keys[0].Name);
Assert.AreEqual("First Section Key 2.", section1.Keys[1].Name);
var values = from key in section1.Keys select key.Value;
Assert.AreEqual(2, values.Count());
Assert.AreEqual("Value 1.1.", values.First());
Assert.AreEqual("Value 1.2.", values.Last());
}
[Test]
public void UpdateIniFileCorrectTest()
{
var file = new IniFile();
var section = new IniSection(file, "Section",
new IniKey(file, "Key"));
file.Sections.Add(section);
Assert.AreEqual(1, file.Sections.Count);
file.Sections.Clear();
Assert.AreEqual(0, file.Sections.Count);
file.Sections.Add(section);
Assert.AreEqual(1, file.Sections.Count);
var key = section.Keys[0];
section.Keys.RemoveAt(0);
Assert.AreEqual(0, section.Keys.Count);
section.Keys.Add(key);
Assert.AreEqual(1, section.Keys.Count);
}
[Test, ExpectedException(typeof(InvalidOperationException))]
public void UpdateIniFileIncorrectBasicTest()
{
var file = new IniFile();
var section = file.Sections.Add("Section");
file.Sections.Add(section);
}
[Test, ExpectedException(typeof(InvalidOperationException))]
public void UpdateIniFileIncorrectAdvanceTest()
{
var file = new IniFile(new IniOptions());
var section = file.Sections.Add("Section");
var newFile = new IniFile(new IniOptions());
newFile.Sections.Add(section);
}
[Test]
public void UpdateIniFileCopyTest()
{
var file = new IniFile();
file.Sections.Add(
new IniSection(file, "Section",
new IniKey(file, "Key", "Value")));
var section = file.Sections[0];
file.Sections.Add(section.Copy());
Assert.AreEqual(2, file.Sections.Count);
section.Name = "S";
section.Keys[0].Name = "K";
section.Keys[0].Value = "V";
section = file.Sections[1];
Assert.AreEqual("Section", section.Name);
Assert.AreEqual("Key", section.Keys[0].Name);
Assert.AreEqual("Value", section.Keys[0].Value);
var newFile = new IniFile();
newFile.Sections.Add(section.Copy(newFile));
Assert.AreEqual(1, newFile.Sections.Count);
section.Name = "S";
section.Keys[0].Name = "K";
section.Keys[0].Value = "V";
section = newFile.Sections[0];
Assert.AreEqual("Section", section.Name);
Assert.AreEqual("Key", section.Keys[0].Name);
Assert.AreEqual("Value", section.Keys[0].Value);
section.Keys.Add(section.Keys[0].Copy());
Assert.AreEqual(2, section.Keys.Count);
}
[Test]
public void UpdateIgnoreDuplicatesTest()
{
var options = new IniOptions()
{
KeyDuplicate = IniDuplication.Ignored,
KeyNameCaseSensitive = true,
SectionDuplicate = IniDuplication.Ignored,
SectionNameCaseSensitive = false
};
var file = new IniFile(options);
file.Sections.Add(
new IniSection(file, "SECTION",
new IniKey(file, "KEY"),
new IniKey(file, "key")));
file.Sections.Add(
new IniSection(file, "section"));
Assert.AreEqual(1, file.Sections.Count);
Assert.AreEqual(2, file.Sections[0].Keys.Count);
Assert.IsTrue(file.Sections[0].Keys.Contains("KEY"));
Assert.IsTrue(file.Sections[0].Keys.Contains("key"));
Assert.AreEqual("key", file.Sections[0].Keys[1].Name);
file.Sections[0].Keys[1].Name = "KEY";
Assert.AreNotEqual("KEY", file.Sections[0].Keys[1].Name);
file.Sections[0].Keys.Insert(0, "key");
Assert.AreEqual(2, file.Sections[0].Keys.Count);
Assert.AreNotEqual("key", file.Sections[0].Keys[0].Name);
file.Sections[0].Keys.Remove("KEY");
Assert.IsFalse(file.Sections.Contains("KEY"));
Assert.AreEqual("key", file.Sections[0].Keys[0].Name);
file.Sections[0].Keys[0].Name = "KEY";
Assert.AreEqual("KEY", file.Sections[0].Keys[0].Name);
}
[Test, ExpectedException(typeof(InvalidOperationException))]
public void UpdateDisallowDuplicatesSectionsTest()
{
var options = new IniOptions()
{
SectionDuplicate = IniDuplication.Disallowed
};
var file = new IniFile(options);
file.Sections.Add("SECTION1").Keys.Add("KEY1");
var section = new IniSection(file, "SECTION1");
file.Sections.Add(section);
}
[Test, ExpectedException(typeof(InvalidOperationException))]
public void UpdateDisallowDuplicatesKeysTest()
{
var options = new IniOptions()
{
KeyDuplicate = IniDuplication.Disallowed,
};
var file = new IniFile(options);
file.Sections.Add("SECTION1").Keys.Add("KEY1");
file.Sections.Add("SECTION1").Keys.Add("KEY1");
Assert.AreEqual(2, file.Sections.Count);
Assert.AreEqual(1, file.Sections[0].Keys.Count);
Assert.AreEqual(1, file.Sections[1].Keys.Count);
var key = new IniKey(file, "KEY1");
file.Sections[0].Keys.Add(key);
}
[Test]
public void UpdateArrayIndexerTest()
{
var file = new IniFile();
file.Sections.Add(
new IniSection(file, "SECTION 0",
new IniKey(file, "UNKNOWN"),
new IniKey(file, "KEY 1"),
new IniKey(file, "KEY 2"),
new IniKey(file, "UNKNOWN")));
file.Sections.Add(new IniSection(file, "UNKNOWN"));
file.Sections.Add(new IniSection(file, "SEC 2"));
file.Sections.Add(new IniSection(file, "UNKNOWN"));
bool isOneKeyNull = false;
foreach (var key in file.Sections[0].Keys["UNKNOWN", "UNKNOWN", "UNKNOWN", "KEY 2", "KEY 1"])
{
if (key == null)
{
if (isOneKeyNull) Assert.Fail();
isOneKeyNull = true;
}
else
key.Value = "VALUE " + key.ParentCollection.IndexOf(key);
}
if (!isOneKeyNull) Assert.Fail();
for (int i = 0; i < file.Sections[0].Keys.Count; i++)
Assert.AreEqual("VALUE " + i, file.Sections[0].Keys[i].Value);
bool isOneSectionRenamed = false;
foreach (var section in file.Sections["UNKNOWN", "UNKNOWN", "SEC 2", "SECTION 2"])
{
string newSectionName = "SECTION " + section.ParentCollection.IndexOf(section);
if (section.Name == newSectionName)
{
if (isOneSectionRenamed) Assert.Fail();
isOneSectionRenamed = true;
}
else
section.Name = "SECTION " + section.ParentCollection.IndexOf(section);
}
if (!isOneSectionRenamed) Assert.Fail();
for (int i = 0; i < file.Sections.Count; i++)
Assert.AreEqual("SECTION " + i, file.Sections[i].Name);
var order = new IniSection(file, "ORDER",
new IniKey(file, "A"),
new IniKey(file, "B"),
new IniKey(file, "C"),
new IniKey(file, "A"),
new IniKey(file, "B"),
new IniKey(file, "C"));
file.Sections.Add(order);
int returnedIndex = 0;
foreach (var key in order.Keys["A", "A", "B", "B", "C", "C"])
key.Value = (returnedIndex++).ToString();
Assert.AreEqual("0", order.Keys[0].Value);
Assert.AreEqual("1", order.Keys[3].Value);
Assert.AreEqual("2", order.Keys[1].Value);
Assert.AreEqual("3", order.Keys[4].Value);
Assert.AreEqual("4", order.Keys[2].Value);
Assert.AreEqual("5", order.Keys[5].Value);
}
[Test]
public void IniItemParentsTest()
{
var file = new IniFile();
var section = new IniSection(file, "Section");
var key = new IniKey(file, "Key");
Assert.AreSame(file, section.ParentFile);
Assert.AreSame(file, key.ParentFile);
Assert.IsNull(section.ParentCollection);
Assert.IsNull(key.ParentCollection);
Assert.IsNull(key.ParentSection);
section.Keys.Add(key);
Assert.AreSame(section.Keys, key.ParentCollection);
Assert.AreSame(section, key.ParentSection);
file.Sections.Add(section);
Assert.AreSame(file.Sections, section.ParentCollection);
file.Sections.Remove(section);
Assert.IsNull(section.ParentCollection);
section.Keys.Remove(key);
Assert.IsNull(key.ParentCollection);
Assert.IsNull(key.ParentSection);
}
}
}

View File

@ -1,71 +0,0 @@
using System;
using System.IO;
using NUnit.Framework;
namespace MadMilkman.Ini.Tests
{
[TestFixture]
public class IniFileEncryptionCompressionTests
{
[Test]
public void CompressAndDecompressTest()
{
var file = new IniFile();
var section = file.Sections.Add("Compression Test");
for (int i = 0; i < 1000; i++)
section.Keys.Add(
new IniKey(file, "Key " + i, Guid.NewGuid().ToString()));
var compressedFile = new IniFile(new IniOptions() { Compression = true });
compressedFile.Sections.Add(section.Copy(compressedFile));
var fileStream = new MemoryStream();
file.Save(fileStream);
var compressedFileStream = new MemoryStream();
compressedFile.Save(compressedFileStream);
Assert.That(compressedFileStream.Length, Is.LessThan(fileStream.Length));
compressedFile.Sections.Clear();
compressedFile.Load(compressedFileStream);
Assert.AreEqual(file.Sections[0].Name, compressedFile.Sections[0].Name);
for (int i = 0; i < file.Sections[0].Keys.Count; i++)
{
Assert.AreEqual(file.Sections[0].Keys[i].Name, compressedFile.Sections[0].Keys[i].Name);
Assert.AreEqual(file.Sections[0].Keys[i].Value, compressedFile.Sections[0].Keys[i].Value);
}
}
[Test]
public void EncryptAndDecryptTest()
{
var file = new IniFile();
var section = file.Sections.Add("Encrypt Test");
section.Keys.Add("Key 1", "Value 1");
section.Keys.Add("Key 2", "Value 2");
var encryptedFile = new IniFile(new IniOptions() { EncryptionPassword = @"abcdef" });
encryptedFile.Sections.Add(section.Copy(encryptedFile));
var encryptedFileWriter = new StringWriter();
encryptedFile.Save(encryptedFileWriter);
var encryptedFileContent = encryptedFileWriter.ToString();
Assert.IsFalse(encryptedFileContent.Contains("Encrypt Test"));
Assert.IsFalse(encryptedFileContent.Contains("Key 1"));
Assert.IsFalse(encryptedFileContent.Contains("Value 1"));
Assert.IsFalse(encryptedFileContent.Contains("Key 2"));
Assert.IsFalse(encryptedFileContent.Contains("Value 2"));
encryptedFile.Sections.Clear();
encryptedFile.Load(new StringReader(encryptedFileContent));
Assert.AreEqual("Encrypt Test", encryptedFile.Sections[0].Name);
Assert.AreEqual("Key 1", encryptedFile.Sections[0].Keys[0].Name);
Assert.AreEqual("Value 1", encryptedFile.Sections[0].Keys[0].Value);
Assert.AreEqual("Key 2", encryptedFile.Sections[0].Keys[1].Name);
Assert.AreEqual("Value 2", encryptedFile.Sections[0].Keys[1].Value);
}
}
}

View File

@ -1,307 +0,0 @@
using System;
using System.IO;
using System.Text;
using NUnit.Framework;
namespace MadMilkman.Ini.Tests
{
[TestFixture]
public class IniFileReadTests
{
[Test]
public void ReadDefaultTest()
{
string iniFileContent = ";Section's trailing comment." + Environment.NewLine +
"[Section's name];Section's leading comment." + Environment.NewLine +
";Key's trailing comment." + Environment.NewLine +
"Key's name = Key's value;Key's leading comment.";
IniFile file = IniUtilities.LoadIniFileContent(iniFileContent, new IniOptions());
Assert.AreEqual(1, file.Sections.Count);
Assert.AreEqual("Section's trailing comment.", file.Sections[0].TrailingComment.Text);
Assert.AreEqual("Section's name", file.Sections[0].Name);
Assert.AreEqual("Section's leading comment.", file.Sections[0].LeadingComment.Text);
Assert.AreEqual(1, file.Sections[0].Keys.Count);
Assert.AreEqual("Key's trailing comment.", file.Sections[0].Keys[0].TrailingComment.Text);
Assert.AreEqual("Key's name", file.Sections[0].Keys[0].Name);
Assert.AreEqual("Key's value", file.Sections[0].Keys[0].Value);
Assert.AreEqual("Key's leading comment.", file.Sections[0].Keys[0].LeadingComment.Text);
}
[Test]
public void ReadCustomTest()
{
string iniFileContent = "#Section's trailing comment." + Environment.NewLine +
"{Section's name}#Section's leading comment." + Environment.NewLine +
"#Key's trailing comment." + Environment.NewLine +
"Key's name : Key's value#Key's leading comment.";
IniOptions options = new IniOptions()
{
CommentStarter = IniCommentStarter.Hash,
SectionWrapper = IniSectionWrapper.CurlyBrackets,
KeyDelimiter = IniKeyDelimiter.Colon
};
IniFile file = IniUtilities.LoadIniFileContent(iniFileContent, options);
Assert.AreEqual(1, file.Sections.Count);
Assert.AreEqual("Section's trailing comment.", file.Sections[0].TrailingComment.Text);
Assert.AreEqual("Section's name", file.Sections[0].Name);
Assert.AreEqual("Section's leading comment.", file.Sections[0].LeadingComment.Text);
Assert.AreEqual(1, file.Sections[0].Keys.Count);
Assert.AreEqual("Key's trailing comment.", file.Sections[0].Keys[0].TrailingComment.Text);
Assert.AreEqual("Key's name", file.Sections[0].Keys[0].Name);
Assert.AreEqual("Key's value", file.Sections[0].Keys[0].Value);
Assert.AreEqual("Key's leading comment.", file.Sections[0].Keys[0].LeadingComment.Text);
}
[Test]
public void ReadGlobalSectionTest()
{
string iniFileContent = ";Trailing comment1" + Environment.NewLine +
"Key1 = Value1" + Environment.NewLine +
";Trailing comment2" + Environment.NewLine +
"Key2 = Value2";
IniFile file = IniUtilities.LoadIniFileContent(iniFileContent, new IniOptions());
Assert.AreEqual(1, file.Sections.Count);
Assert.AreEqual(IniSection.GlobalSectionName, file.Sections[0].Name);
Assert.AreEqual(2, file.Sections[0].Keys.Count);
Assert.AreEqual("Trailing comment1", file.Sections[0].Keys[0].TrailingComment.Text);
Assert.AreEqual("Key1", file.Sections[0].Keys[0].Name);
Assert.AreEqual("Value1", file.Sections[0].Keys[0].Value);
Assert.AreEqual("Trailing comment2", file.Sections[0].Keys[1].TrailingComment.Text);
Assert.AreEqual("Key2", file.Sections[0].Keys[1].Name);
Assert.AreEqual("Value2", file.Sections[0].Keys[1].Value);
}
[Test]
public void ReadMultipleGlobalSectionsTest()
{
string inputContent = "Key = Value" + Environment.NewLine +
"[Section]" + Environment.NewLine +
"Key = Value";
IniFile file = new IniFile();
using (var stream = new MemoryStream(Encoding.ASCII.GetBytes(inputContent)))
{
file.Load(stream);
file.Load(stream);
file.Load(stream);
}
Assert.AreEqual(6, file.Sections.Count);
Assert.AreEqual(IniSection.GlobalSectionName, file.Sections[0].Name);
Assert.AreEqual(IniSection.GlobalSectionName, file.Sections[2].Name);
Assert.AreEqual(IniSection.GlobalSectionName, file.Sections[4].Name);
Assert.AreEqual("Section", file.Sections[1].Name);
Assert.AreEqual("Section", file.Sections[3].Name);
Assert.AreEqual("Section", file.Sections[5].Name);
foreach (var section in file.Sections)
Assert.AreEqual(1, section.Keys.Count);
string outputContent;
using (var stream = new MemoryStream())
{
file.Save(stream);
outputContent = new StreamReader(stream, Encoding.ASCII).ReadToEnd();
}
file.Sections.Clear();
using (var stream = new MemoryStream(Encoding.ASCII.GetBytes(outputContent)))
file.Load(stream);
Assert.AreEqual(6, file.Sections.Count);
Assert.AreEqual(IniSection.GlobalSectionName, file.Sections[0].Name);
Assert.AreEqual(IniSection.GlobalSectionName, file.Sections[2].Name);
Assert.AreEqual(IniSection.GlobalSectionName, file.Sections[4].Name);
Assert.AreEqual("Section", file.Sections[1].Name);
Assert.AreEqual("Section", file.Sections[3].Name);
Assert.AreEqual("Section", file.Sections[5].Name);
foreach (var section in file.Sections)
Assert.AreEqual(1, section.Keys.Count);
}
[Test]
public void ReadUTF8EncodingTest()
{
string iniFileContent = "[Καλημέρα κόσμε]" + Environment.NewLine +
"こんにちは 世界 = ¥ £ € $ ¢ ₡ ₢ ₣ ₤ ₥ ₦ ₧ ₨ ₩ ₪ ₫ ₭ ₮ ₯ ₹";
IniFile file = IniUtilities.LoadIniFileContent(iniFileContent, new IniOptions() { Encoding = Encoding.UTF8 });
Assert.AreEqual("Καλημέρα κόσμε", file.Sections[0].Name);
Assert.AreEqual("こんにちは 世界", file.Sections[0].Keys[0].Name);
Assert.AreEqual("¥ £ € $ ¢ ₡ ₢ ₣ ₤ ₥ ₦ ₧ ₨ ₩ ₪ ₫ ₭ ₮ ₯ ₹", file.Sections[0].Keys[0].Value);
}
[Test]
public void ReadEmptyLinesTest()
{
string iniFileContent = Environment.NewLine +
" \t " + Environment.NewLine +
"[Section]" + Environment.NewLine +
Environment.NewLine +
Environment.NewLine +
" \t " + Environment.NewLine +
"Key = Value" + Environment.NewLine +
Environment.NewLine +
" \t " + Environment.NewLine +
";" + Environment.NewLine +
"[Section]" + Environment.NewLine +
Environment.NewLine +
" \t " + Environment.NewLine +
Environment.NewLine +
";" + Environment.NewLine +
"Key = Value";
IniFile file = IniUtilities.LoadIniFileContent(iniFileContent, new IniOptions());
Assert.AreEqual(2, file.Sections[0].LeadingComment.EmptyLinesBefore);
Assert.AreEqual(3, file.Sections[0].Keys[0].LeadingComment.EmptyLinesBefore);
Assert.AreEqual(2, file.Sections[1].TrailingComment.EmptyLinesBefore);
Assert.AreEqual(3, file.Sections[1].Keys[0].TrailingComment.EmptyLinesBefore);
}
[Test]
public void ReadCommentEdgeCasesTest()
{
string iniFileContent = ";" + Environment.NewLine +
";Section's trailing comment;" + Environment.NewLine +
"[Section]" + Environment.NewLine +
"[Section];" + Environment.NewLine +
"[Section] ;" + Environment.NewLine +
";" + Environment.NewLine +
";Key's trailing comment;" + Environment.NewLine +
"Key = Value " + Environment.NewLine +
"Key = Value;" + Environment.NewLine +
"Key = Value ;";
IniFile file = IniUtilities.LoadIniFileContent(iniFileContent, new IniOptions());
Assert.AreEqual(Environment.NewLine + "Section's trailing comment;", file.Sections[0].TrailingComment.Text);
Assert.AreEqual("Section", file.Sections[0].Name);
Assert.IsNull(file.Sections[0].LeadingComment.Text);
Assert.AreEqual(0, file.Sections[0].LeadingComment.LeftIndentation);
Assert.AreEqual("Section", file.Sections[1].Name);
Assert.IsEmpty(file.Sections[1].LeadingComment.Text);
Assert.AreEqual(0, file.Sections[1].LeadingComment.LeftIndentation);
Assert.AreEqual("Section", file.Sections[2].Name);
Assert.IsEmpty(file.Sections[2].LeadingComment.Text);
Assert.AreEqual(2, file.Sections[2].LeadingComment.LeftIndentation);
Assert.AreEqual(Environment.NewLine + "Key's trailing comment;", file.Sections[2].Keys[0].TrailingComment.Text);
Assert.AreEqual("Key", file.Sections[2].Keys[0].Name);
Assert.AreEqual("Value", file.Sections[2].Keys[0].Value);
Assert.IsNull(file.Sections[2].Keys[0].LeadingComment.Text);
Assert.AreEqual(0, file.Sections[2].Keys[0].LeadingComment.LeftIndentation);
Assert.AreEqual("Key", file.Sections[2].Keys[1].Name);
Assert.AreEqual("Value", file.Sections[2].Keys[1].Value);
Assert.IsEmpty(file.Sections[2].Keys[1].LeadingComment.Text);
Assert.AreEqual(0, file.Sections[2].Keys[1].LeadingComment.LeftIndentation);
Assert.AreEqual("Key", file.Sections[2].Keys[2].Name);
Assert.AreEqual("Value", file.Sections[2].Keys[2].Value);
Assert.IsEmpty(file.Sections[2].Keys[2].LeadingComment.Text);
Assert.AreEqual(2, file.Sections[2].Keys[2].LeadingComment.LeftIndentation);
}
[Test]
public void ReadValueEdgeCasesTest()
{
string iniFileContent = "[Section]" + Environment.NewLine +
"Key=" + Environment.NewLine +
"Key=;" + Environment.NewLine +
"Key= " + Environment.NewLine +
"Key= ;" + Environment.NewLine +
"Key =" + Environment.NewLine +
"Key =;" + Environment.NewLine +
"Key = " + Environment.NewLine +
"Key = ;";
IniFile file = IniUtilities.LoadIniFileContent(iniFileContent, new IniOptions());
Assert.IsEmpty(file.Sections[0].Keys[0].Value);
Assert.IsNull(file.Sections[0].Keys[0].LeadingComment.Text);
Assert.AreEqual(0, file.Sections[0].Keys[0].LeadingComment.LeftIndentation);
Assert.IsEmpty(file.Sections[0].Keys[1].Value);
Assert.IsEmpty(file.Sections[0].Keys[1].LeadingComment.Text);
Assert.AreEqual(0, file.Sections[0].Keys[1].LeadingComment.LeftIndentation);
Assert.IsEmpty(file.Sections[0].Keys[2].Value);
Assert.IsNull(file.Sections[0].Keys[2].LeadingComment.Text);
Assert.AreEqual(0, file.Sections[0].Keys[2].LeadingComment.LeftIndentation);
Assert.IsEmpty(file.Sections[0].Keys[3].Value);
Assert.IsEmpty(file.Sections[0].Keys[3].LeadingComment.Text);
Assert.AreEqual(0, file.Sections[0].Keys[3].LeadingComment.LeftIndentation);
Assert.IsEmpty(file.Sections[0].Keys[4].Value);
Assert.IsNull(file.Sections[0].Keys[4].LeadingComment.Text);
Assert.AreEqual(0, file.Sections[0].Keys[4].LeadingComment.LeftIndentation);
Assert.IsEmpty(file.Sections[0].Keys[5].Value);
Assert.IsEmpty(file.Sections[0].Keys[5].LeadingComment.Text);
Assert.AreEqual(0, file.Sections[0].Keys[5].LeadingComment.LeftIndentation);
Assert.IsEmpty(file.Sections[0].Keys[6].Value);
Assert.IsNull(file.Sections[0].Keys[6].LeadingComment.Text);
Assert.AreEqual(0, file.Sections[0].Keys[6].LeadingComment.LeftIndentation);
Assert.IsEmpty(file.Sections[0].Keys[7].Value);
Assert.IsEmpty(file.Sections[0].Keys[7].LeadingComment.Text);
Assert.AreEqual(0, file.Sections[0].Keys[7].LeadingComment.LeftIndentation);
}
[Test]
public void ReadSectionEdgeCasesTest()
{
string iniFileContent = "[" + Environment.NewLine +
"]" + Environment.NewLine +
"[]" + Environment.NewLine +
"[;]" + Environment.NewLine +
"[;;]" + Environment.NewLine +
"[[]]" + Environment.NewLine +
"[[]];" + Environment.NewLine +
"[[;]]" + Environment.NewLine +
"[[;]];";
IniFile file = IniUtilities.LoadIniFileContent(iniFileContent, new IniOptions());
Assert.AreEqual(7, file.Sections.Count);
Assert.AreEqual(string.Empty, file.Sections[0].Name);
Assert.AreEqual(";", file.Sections[1].Name);
Assert.AreEqual(";;", file.Sections[2].Name);
Assert.AreEqual("[]", file.Sections[3].Name);
Assert.AreEqual("[]", file.Sections[4].Name);
Assert.AreEqual(string.Empty, file.Sections[4].LeadingComment.Text);
Assert.AreEqual("[;]", file.Sections[5].Name);
Assert.AreEqual("[;]", file.Sections[6].Name);
Assert.AreEqual(string.Empty, file.Sections[6].LeadingComment.Text);
}
[Test]
public void ReadQuotedValue()
{
string iniFileContent = "key1 = \"Test;Test\"" + Environment.NewLine +
"key2 = \"Test;Test\";" + Environment.NewLine +
"key3 = \"Test;Test" + Environment.NewLine +
"key4 = \"Test;Test;Test\"Test;Test;Test";
IniFile file = IniUtilities.LoadIniFileContent(iniFileContent, new IniOptions());
IniSection section = file.Sections[0];
Assert.AreEqual("\"Test;Test\"", file.Sections[0].Keys[0].Value);
Assert.IsNull(file.Sections[0].Keys[0].LeadingComment.Text);
Assert.AreEqual("\"Test;Test\"", file.Sections[0].Keys[1].Value);
Assert.AreEqual(string.Empty, file.Sections[0].Keys[1].LeadingComment.Text);
Assert.AreEqual("\"Test", file.Sections[0].Keys[2].Value);
Assert.AreEqual("Test", file.Sections[0].Keys[2].LeadingComment.Text);
Assert.AreEqual("\"Test;Test;Test\"Test", file.Sections[0].Keys[3].Value);
Assert.AreEqual("Test;Test", file.Sections[0].Keys[3].LeadingComment.Text);
}
}
}

View File

@ -1,144 +0,0 @@
using System;
using System.IO;
using System.Text;
using NUnit.Framework;
namespace MadMilkman.Ini.Tests
{
[TestFixture]
public class IniFileWriteTests
{
[Test]
public void WriteDefaultTest()
{
IniOptions options = new IniOptions();
IniFile file = new IniFile(options);
file.Sections.Add(
new IniSection(file, "Section",
new IniKey(file, "Key", "Value")
{
TrailingComment = { Text = "Trailing comment" },
LeadingComment = { Text = "Leading comment" }
})
{
TrailingComment = { Text = "Trailing comment" },
LeadingComment = { Text = "Leading comment" }
});
string[] lines = IniUtilities.SaveIniFileContent(file, options);
Assert.AreEqual(";Trailing comment", lines[0]);
Assert.AreEqual("[Section];Leading comment", lines[1]);
Assert.AreEqual(";Trailing comment", lines[2]);
Assert.AreEqual("Key=Value;Leading comment", lines[3]);
}
[Test]
public void WriteCustomTest()
{
IniOptions options = new IniOptions()
{
KeyDelimiter = IniKeyDelimiter.Colon,
KeySpaceAroundDelimiter = true,
SectionWrapper = IniSectionWrapper.Parentheses
};
IniFile file = new IniFile(options);
file.Sections.Add(
new IniSection(file, "Section",
new IniKey(file, "Key", "Value")));
string[] lines = IniUtilities.SaveIniFileContent(file, options);
Assert.AreEqual("(Section)", lines[0]);
Assert.AreEqual("Key : Value", lines[1]);
}
[Test]
public void WriteGlobalSectionTest()
{
IniOptions options = new IniOptions();
IniFile file = new IniFile(options);
file.Sections.Add(
new IniSection(file, IniSection.GlobalSectionName,
new IniKey(file, "Key1", "Value1"),
new IniKey(file, "Key2", "Value2")));
string[] lines = IniUtilities.SaveIniFileContent(file, options);
Assert.AreEqual("Key1=Value1", lines[0]);
Assert.AreEqual("Key2=Value2", lines[1]);
}
[Test]
public void WriteUTF8EncodingTest()
{
IniOptions options = new IniOptions() { Encoding = Encoding.UTF8 };
IniFile file = new IniFile(options);
file.Sections.Add(new IniSection(file, "Καλημέρα κόσμε"));
file.Sections.Add(new IniSection(file, "こんにちは 世界"));
string[] lines = IniUtilities.SaveIniFileContent(file, options);
Assert.AreEqual("[Καλημέρα κόσμε]", lines[0]);
Assert.AreEqual("[こんにちは 世界]", lines[1]);
}
[Test]
public void WriteEmptyLinesTest()
{
IniOptions options = new IniOptions() { Encoding = Encoding.UTF8 };
IniFile file = new IniFile(options);
file.Sections.Add(
new IniSection(file, "Section",
new IniKey(file, "Key")
{
TrailingComment = { Text = string.Empty, EmptyLinesBefore = 2 },
LeadingComment = { Text = string.Empty, EmptyLinesBefore = 1 }
})
{
TrailingComment = { Text = string.Empty, EmptyLinesBefore = 2 },
LeadingComment = { Text = string.Empty, EmptyLinesBefore = 1 }
});
string[] lines = IniUtilities.SaveIniFileContent(file, options);
Assert.IsEmpty(lines[0]);
Assert.IsEmpty(lines[1]);
Assert.AreEqual(";", lines[2]);
Assert.IsEmpty(lines[3]);
Assert.AreEqual("[Section];", lines[4]);
Assert.IsEmpty(lines[5]);
Assert.IsEmpty(lines[6]);
Assert.AreEqual(";", lines[7]);
Assert.IsEmpty(lines[8]);
Assert.AreEqual("Key=;", lines[9]);
}
[Test]
public void WriteLeftIndentionTest()
{
IniOptions options = new IniOptions() { Encoding = Encoding.UTF8 };
IniFile file = new IniFile(options);
file.Sections.Add(
new IniSection(file, "Section",
new IniKey(file, "Key")
{
LeftIndentation = 2,
TrailingComment = { Text = string.Empty, LeftIndentation = 4 },
LeadingComment = { Text = string.Empty, LeftIndentation = 2 }
})
{
LeftIndentation = 2,
TrailingComment = { Text = string.Empty, LeftIndentation = 4 },
LeadingComment = { Text = string.Empty, LeftIndentation = 2 }
});
string[] lines = IniUtilities.SaveIniFileContent(file, options);
Assert.AreEqual(" ;", lines[0]);
Assert.AreEqual(" [Section] ;", lines[1]);
Assert.AreEqual(" ;", lines[2]);
Assert.AreEqual(" Key= ;", lines[3]);
}
}
}

View File

@ -1,126 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
namespace MadMilkman.Ini.Tests
{
[TestFixture]
public class IniSerializationDeserializationTests
{
[Test]
public void SerializeDeserializeTest()
{
var file = new IniFile();
var section = file.Sections.Add("Sample Class");
var serializedClass = new SampleClass();
serializedClass.Initialize();
section.Serialize(serializedClass);
var deserializedClass = section.Deserialize<SampleClass>();
Assert.IsTrue(serializedClass.Equals(deserializedClass));
}
[Test]
public void SerializeDeserializeAttributeTest()
{
var file = new IniFile();
var section = file.Sections.Add("Sample Attributed Class");
var serializedClass = new SampleAttributedClass();
serializedClass.Initialize();
section.Serialize(serializedClass);
Assert.IsNull(section.Keys["FirstSampleProperty"]);
Assert.IsNotNull(section.Keys["SecondSampleProperty"]);
Assert.IsNotNull(section.Keys["3. Sample Property"]);
Assert.IsNotNull(section.Keys["FourthSampleProperty"]);
var deserializedClass = section.Deserialize<SampleAttributedClass>();
Assert.AreNotEqual(serializedClass.FirstSampleProperty, deserializedClass.FirstSampleProperty);
Assert.IsNull(deserializedClass.FirstSampleProperty);
Assert.AreEqual(serializedClass.SecondSampleProperty, deserializedClass.SecondSampleProperty);
Assert.AreEqual(serializedClass.ThirdSampleProperty, deserializedClass.ThirdSampleProperty);
Assert.IsTrue(
// null
string.IsNullOrEmpty(serializedClass.FourthSampleProperty) &&
// string.Empty
string.IsNullOrEmpty(deserializedClass.FourthSampleProperty));
}
private class SampleClass
{
public char SampleChar { get; set; }
public string SampleString { get; set; }
public DateTime SampleDate { get; set; }
public TimeSpan SampleTime { get; set; }
public DayOfWeek SampleDay { get; set; }
public byte SampleByte { get; set; }
public double SampleDouble { get; set; }
public int[] SampleValueArray { get; set; }
public string[] SampleReferenceArray { get; set; }
public List<int> SampleValueList { get; set; }
public List<string> SampleReferenceList { get; set; }
public void Initialize()
{
this.SampleChar = 'S';
this.SampleString = "Sample";
this.SampleDate = new DateTime(2000, 1, 10);
this.SampleTime = new TimeSpan(20, 1, 10);
this.SampleDay = DayOfWeek.Sunday;
this.SampleByte = 200;
this.SampleDouble = 2000.2;
this.SampleValueArray = new int[] { 2, 20, 200 };
this.SampleReferenceArray = new string[] { "Sample 1", "Sample 2", "Sample 3" };
this.SampleValueList = new List<int>() { 2000, 20000, 200000 };
this.SampleReferenceList = new List<string>() { "Sample 4", "Sample 5", "Sample 6" };
}
public override int GetHashCode()
{
return base.GetHashCode();
}
public override bool Equals(object obj)
{
SampleClass sampleObj;
if (obj == null || (sampleObj = obj as SampleClass) == null)
return false;
return this.SampleChar == sampleObj.SampleChar &&
this.SampleString == sampleObj.SampleString &&
this.SampleDate == sampleObj.SampleDate &&
this.SampleTime == sampleObj.SampleTime &&
this.SampleDay == sampleObj.SampleDay &&
this.SampleByte == sampleObj.SampleByte &&
this.SampleDouble == sampleObj.SampleDouble &&
this.SampleValueArray.SequenceEqual(sampleObj.SampleValueArray) &&
this.SampleReferenceArray.SequenceEqual(sampleObj.SampleReferenceArray) &&
this.SampleValueList.SequenceEqual(sampleObj.SampleValueList) &&
this.SampleReferenceList.SequenceEqual(sampleObj.SampleReferenceList);
}
}
private class SampleAttributedClass
{
[IniSerialization(true)]
public string FirstSampleProperty { get; set; }
[IniSerialization(false)]
public string SecondSampleProperty { get; set; }
[IniSerialization("3. Sample Property")]
public string ThirdSampleProperty { get; set; }
public string FourthSampleProperty { get; set; }
public void Initialize()
{
this.FirstSampleProperty = "1. Sample Content";
this.SecondSampleProperty = "2. Sample Content";
this.ThirdSampleProperty = "3. Sample Content";
}
}
}
}

View File

@ -1,30 +0,0 @@
using System;
using System.IO;
namespace MadMilkman.Ini.Tests
{
public static class IniUtilities
{
public static IniFile LoadIniFileContent(string iniFileContent, IniOptions options)
{
IniFile file = new IniFile(options);
using (var stream = new MemoryStream(options.Encoding.GetBytes(iniFileContent)))
file.Load(stream);
return file;
}
public static string[] SaveIniFileContent(IniFile file, IniOptions options)
{
string iniFileContent;
using (var stream = new MemoryStream())
{
file.Save(stream);
iniFileContent = new StreamReader(stream, options.Encoding).ReadToEnd();
}
return iniFileContent.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
}
}
}

View File

@ -1,308 +0,0 @@
using System;
using System.Collections.Generic;
using NUnit.Framework;
namespace MadMilkman.Ini.Tests
{
[TestFixture]
public class IniValueManipulationTests
{
[Test]
public void ParseValueTest()
{
var dateTime = new DateTime(9999, 12, 31, 23, 59, 59);
var timeSpan = new TimeSpan(10, 23, 59, 59, 999);
var file = new IniFile();
file.Sections.Add(
new IniSection(file, "Section",
new IniKey(file, "bool", bool.TrueString),
new IniKey(file, "number", 10.ToString()),
new IniKey(file, "date", dateTime.ToString()),
new IniKey(file, "time", timeSpan.ToString()),
new IniKey(file, "day", DayOfWeek.Sunday.ToString())));
bool resultingBoolean;
Assert.IsTrue(file.Sections["Section"].Keys["bool"].TryParseValue(out resultingBoolean));
Assert.AreEqual(true, resultingBoolean);
var numberKey = file.Sections["Section"].Keys["number"];
byte resultingByte;
Assert.IsTrue(numberKey.TryParseValue(out resultingByte));
Assert.AreEqual((byte)10, resultingByte);
sbyte resultingSignedByte;
Assert.IsTrue(numberKey.TryParseValue(out resultingSignedByte));
Assert.AreEqual((sbyte)10, resultingSignedByte);
short resultingShort;
Assert.IsTrue(numberKey.TryParseValue(out resultingShort));
Assert.AreEqual((short)10, resultingShort);
ushort resultingUnsignedShort;
Assert.IsTrue(numberKey.TryParseValue(out resultingUnsignedShort));
Assert.AreEqual((ushort)10, resultingUnsignedShort);
int resultingInteger;
Assert.IsTrue(numberKey.TryParseValue(out resultingInteger));
Assert.AreEqual(10, resultingInteger);
uint resultingUnsignedInteger;
Assert.IsTrue(numberKey.TryParseValue(out resultingUnsignedInteger));
Assert.AreEqual(10U, resultingUnsignedInteger);
long resultingLong;
Assert.IsTrue(numberKey.TryParseValue(out resultingLong));
Assert.AreEqual(10L, resultingLong);
ulong resultingUnsignedLong;
Assert.IsTrue(numberKey.TryParseValue(out resultingUnsignedLong));
Assert.AreEqual(10UL, resultingUnsignedLong);
float resultingSingle;
Assert.IsTrue(numberKey.TryParseValue(out resultingSingle));
Assert.AreEqual(10F, resultingSingle);
double resultingDouble;
Assert.IsTrue(numberKey.TryParseValue(out resultingDouble));
Assert.AreEqual(10D, resultingDouble);
decimal resultingDecimal;
Assert.IsTrue(numberKey.TryParseValue(out resultingDecimal));
Assert.AreEqual(10M, resultingDecimal);
DateTime resultingDateTime;
Assert.IsTrue(file.Sections["Section"].Keys["date"].TryParseValue(out resultingDateTime));
Assert.AreEqual(dateTime, resultingDateTime);
TimeSpan resultingTimeSpan;
Assert.IsTrue(file.Sections["Section"].Keys["time"].TryParseValue(out resultingTimeSpan));
Assert.AreEqual(timeSpan, resultingTimeSpan);
DayOfWeek resultingEnum;
Assert.IsTrue(file.Sections["Section"].Keys["day"].TryParseValue(out resultingEnum));
Assert.AreEqual(DayOfWeek.Sunday, resultingEnum);
}
[Test]
public void ParseValueArrayTest()
{
var file = new IniFile();
file.Sections.Add(
new IniSection(file, "Section",
new IniKey(file, "integers", "{ 1 , 2 , 3 , 4 , 5 , 6 }"),
new IniKey(file, "invalid integers", "{ 1 , 2 , 3 , A , B , C }"),
new IniKey(file, "dates", "{1/1/2010, 1/1/2011, 1/1/2012, 1/1/2013}")));
var section = file.Sections[0];
int[] numberArray;
Assert.IsTrue(section.Keys[0].TryParseValue(out numberArray));
Assert.AreEqual(6, numberArray.Length);
List<int> numberList;
Assert.IsTrue(section.Keys[0].TryParseValue(out numberList));
Assert.AreEqual(6, numberList.Count);
for (int i = 0; i < 6; i++)
Assert.IsTrue(numberArray[i] == i + 1 && numberList[i] == i + 1);
Assert.IsFalse(section.Keys[1].TryParseValue(out numberArray));
Assert.IsNull(numberArray);
Assert.IsFalse(section.Keys[1].TryParseValue(out numberList));
Assert.IsNull(numberList);
DateTime[] dateArray;
Assert.IsTrue(section.Keys[2].TryParseValue(out dateArray));
for (int i = 0; i < 4; i++)
{
Assert.AreEqual(1, dateArray[i].Day);
Assert.AreEqual(1, dateArray[i].Month);
Assert.AreEqual(2010 + i, dateArray[i].Year);
}
}
[Test]
public void ParseValueMappingsTest()
{
var file = new IniFile();
file.Sections.Add(
new IniSection(file, "TRUE BOOLEANS",
new IniKey(file, "bool value", "YES"),
new IniKey(file, "bool value", "ON"),
new IniKey(file, "bool value", "1"),
new IniKey(file, "bool value", "TRUE")));
file.Sections.Add(
new IniSection(file, "FALSE BOOLEANS",
new IniKey(file, "bool value", "NO"),
new IniKey(file, "bool value", "OFF"),
new IniKey(file, "bool value", "0"),
new IniKey(file, "bool value", "FALSE")));
file.Sections.Add(
new IniSection(file, "DOUBLES",
new IniKey(file, "double value", "+∞"),
new IniKey(file, "double value", "-∞"),
new IniKey(file, "double value", "NaN")));
file.Sections.Add(
new IniSection(file, "ARRAYS",
new IniKey(file, "bool values", "{YES, ON, 1, TRUE}"),
new IniKey(file, "bool values", "{NO, OFF, 0, FALSE}"),
new IniKey(file, "double values", "{1.1, 10.1, 100.1, 1000.1, +∞}")));
file.ValueMappings.Add("yes", true);
file.ValueMappings.Add("on", true);
file.ValueMappings.Add("1", true);
file.ValueMappings.Add("no", false);
file.ValueMappings.Add("off", false);
file.ValueMappings.Add("0", false);
file.ValueMappings.Add("+∞", double.PositiveInfinity);
file.ValueMappings.Add("-∞", double.NegativeInfinity);
file.ValueMappings.Add("NaN", double.NaN);
foreach (var key in file.Sections["TRUE BOOLEANS"].Keys)
{
bool booleanResult;
Assert.IsTrue(key.TryParseValue(out booleanResult));
Assert.IsTrue(booleanResult);
}
foreach (var key in file.Sections["FALSE BOOLEANS"].Keys)
{
bool booleanResult;
Assert.IsTrue(key.TryParseValue(out booleanResult));
Assert.IsFalse(booleanResult);
}
double doubleResult;
Assert.IsTrue(file.Sections["DOUBLES"].Keys[0].TryParseValue(out doubleResult));
Assert.AreEqual(double.PositiveInfinity, doubleResult);
Assert.IsTrue(file.Sections["DOUBLES"].Keys[1].TryParseValue(out doubleResult));
Assert.AreEqual(double.NegativeInfinity, doubleResult);
Assert.IsTrue(file.Sections["DOUBLES"].Keys[2].TryParseValue(out doubleResult));
Assert.IsNaN(doubleResult);
bool[] booleansResult;
Assert.IsTrue(file.Sections["ARRAYS"].Keys[0].TryParseValue(out booleansResult));
foreach (var boolean in booleansResult)
Assert.IsTrue(boolean);
Assert.IsTrue(file.Sections["ARRAYS"].Keys[1].TryParseValue(out booleansResult));
foreach (var boolean in booleansResult)
Assert.IsFalse(boolean);
List<double> doublesResult;
Assert.IsTrue(file.Sections["ARRAYS"].Keys[2].TryParseValue(out doublesResult));
Assert.AreEqual(1.1, doublesResult[0]);
Assert.AreEqual(10.1, doublesResult[1]);
Assert.AreEqual(100.1, doublesResult[2]);
Assert.AreEqual(1000.1, doublesResult[3]);
Assert.AreEqual(double.PositiveInfinity, doublesResult[4]);
}
[Test]
public void BindValueWithInternalDataTest()
{
string iniFileContent = "[Source Section]\n" +
"Source Key 1 = Source Value 1\n" +
"Source Key 2 = Source Value 2\n" +
"Source Key 3 = Source Value 3\n" +
"[Binding Section]\n" +
"Source Key 4 = Source Value 4\n" +
"Test Key 1 = @{Source Section|Source Key 1}\n" +
"Test Key 2-3 = @{Source Section|Source Key 2} and @{Source Section|Source Key 3}\n" +
"Test Key 1-4 = @{Source Section|Source Key 1} and @{Source Key 4}\n" +
"Test Key X = @{Unknown}";
IniFile file = IniUtilities.LoadIniFileContent(iniFileContent, new IniOptions());
file.ValueBinding.Bind();
var bindedSection = file.Sections["Binding Section"];
Assert.AreEqual("Source Value 1", bindedSection.Keys["Test Key 1"].Value);
Assert.AreEqual("Source Value 2 and Source Value 3", bindedSection.Keys["Test Key 2-3"].Value);
Assert.AreEqual("Source Value 1 and Source Value 4", bindedSection.Keys["Test Key 1-4"].Value);
Assert.AreEqual("@{Unknown}", bindedSection.Keys["Test Key X"].Value);
}
[Test]
public void BindValueWithExternalDataTest()
{
string iniFileContent = "[Binding Section]\n" +
"Test Key 1 = @{First Tester}\n" +
"Test Key 2-3 = @{Second Tester} and @{Third Tester}\n" +
"Test Key 3-3-4 = {@{Third Tester}, @{Third Tester}, @{Fourth Tester}}\n" +
"Test Key X = @{Unknown}\n" +
"Test Key Nested = @{Nested @{Test}}";
IniFile file = IniUtilities.LoadIniFileContent(iniFileContent, new IniOptions());
file.ValueBinding.Bind(
new Dictionary<string, string>()
{
{"First Tester", "Source Value 1"},
{"Second Tester", "Source Value 2"},
{"Third Tester", "Source Value 3"},
{"Fourth Tester", "Source Value 4"},
{"Test", "Tester"}
});
var bindedSection = file.Sections["Binding Section"];
Assert.AreEqual("Source Value 1", bindedSection.Keys["Test Key 1"].Value);
Assert.AreEqual("Source Value 2 and Source Value 3", bindedSection.Keys["Test Key 2-3"].Value);
Assert.AreEqual("{Source Value 3, Source Value 3, Source Value 4}", bindedSection.Keys["Test Key 3-3-4"].Value);
Assert.AreEqual("@{Unknown}", bindedSection.Keys["Test Key X"].Value);
Assert.AreEqual("@{Nested Tester}", bindedSection.Keys["Test Key Nested"].Value);
file.ValueBinding.Bind(new KeyValuePair<string, string>("Nested Tester", "Nested Source Value"));
Assert.AreEqual("Nested Source Value", bindedSection.Keys["Test Key Nested"].Value);
}
[Test]
public void BindValueCustomization()
{
string iniFileContent = "[Binding Customization Section]\n" +
"Test Key 1 = @{First Tester}\n" +
"Test Key 2-3 = @{Second Tester} and @{Third Tester}\n" +
"Test Key 2-4 = @{Second Tester} and @{Fourth Tester}\n" +
"Test Key X = @{Unknown}";
IniFile file = IniUtilities.LoadIniFileContent(iniFileContent, new IniOptions());
file.ValueBinding.Binding += (sender, e) =>
{
if (!e.IsValueFound)
e.Value = "Missing";
else
switch (e.PlaceholderName)
{
case "First Tester":
e.Value = "Custom " + e.Value;
break;
case "Third Tester":
e.Value = null;
break;
case "Fourth Tester":
e.Value = string.Empty;
break;
}
};
file.ValueBinding.Bind(
new Dictionary<string, string>()
{
{"First Tester", "Source Value 1"},
{"Second Tester", "Source Value 2"},
{"Third Tester", "Source Value 3"},
{"Fourth Tester", "Source Value 4"}
});
var bindedSection = file.Sections["Binding Customization Section"];
Assert.AreEqual("Custom Source Value 1", bindedSection.Keys["Test Key 1"].Value);
Assert.AreEqual("Source Value 2 and @{Third Tester}", bindedSection.Keys["Test Key 2-3"].Value);
Assert.AreEqual("Source Value 2 and ", bindedSection.Keys["Test Key 2-4"].Value);
Assert.AreEqual("Missing", bindedSection.Keys["Test Key X"].Value);
}
}
}

View File

@ -1,76 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{BDD080C9-016F-4869-95DE-61171E2AB746}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>MadMilkman.Ini.Tests</RootNamespace>
<AssemblyName>MadMilkman.Ini.Tests</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="nunit.core">
<HintPath>Resources\NUnitTestAdapter.1.2\lib\nunit.core.dll</HintPath>
</Reference>
<Reference Include="nunit.core.interfaces">
<HintPath>Resources\NUnitTestAdapter.1.2\lib\nunit.core.interfaces.dll</HintPath>
</Reference>
<Reference Include="nunit.framework">
<HintPath>Resources\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
</Reference>
<Reference Include="nunit.util">
<HintPath>Resources\NUnitTestAdapter.1.2\lib\nunit.util.dll</HintPath>
</Reference>
<Reference Include="NUnit.VisualStudio.TestAdapter">
<HintPath>Resources\NUnitTestAdapter.1.2\lib\NUnit.VisualStudio.TestAdapter.dll</HintPath>
</Reference>
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<Compile Include="BugFixes.cs" />
<Compile Include="IniFileCreateUpdateTests.cs" />
<Compile Include="IniFileEncryptionCompressionTests.cs" />
<Compile Include="IniSerializationDeserializationTests.cs" />
<Compile Include="IniValueManipulationTests.cs" />
<Compile Include="IniFileWriteTests.cs" />
<Compile Include="IniUtilities.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="IniFileReadTests.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MadMilkman.Ini\MadMilkman.Ini.csproj">
<Project>{bef9735d-c3cc-41e6-aac6-18c5985d3107}</Project>
<Name>MadMilkman.Ini</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -1,36 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("MadMilkman.Ini.Tests")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("MadMilkman.Ini.Tests")]
[assembly: AssemblyCopyright("Copyright © 2015")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("ad6f8d98-8028-453b-be32-406fe9a3b9cd")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -1,24 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<!--
The .NET 2.0 build of the console runner only
runs under .NET 2.0 or higher. The setting
useLegacyV2RuntimeActivationPolicy only applies
under .NET 4.0 and permits use of mixed mode
assemblies, which would otherwise not load
correctly.
-->
<startup useLegacyV2RuntimeActivationPolicy="true">
<!-- Comment out the next line to force use of .NET 4.0 -->
</startup>
<runtime>
<!-- Ensure that test exceptions don't crash NUnit -->
<legacyUnhandledExceptionPolicy enabled="1"/>
<!-- Run partial trust V2 assemblies in full trust under .NET 4.0 -->
<loadFromRemoteSources enabled="true"/>
<!-- Look for addins in the addins directory for now -->
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="lib;addins"/>
</assemblyBinding>
</runtime>
</configuration>

View File

@ -1,15 +0,0 @@
Copyright © 2002-2014 Charlie Poole
Copyright © 2002-2004 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov
Copyright © 2000-2002 Philip A. Craig
This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment (see the following) in the product documentation is required.
Portions Copyright © 2002-2014 Charlie Poole or Copyright © 2002-2004 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov or Copyright © 2000-2002 Philip A. Craig
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.

View File

@ -1,110 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MadMilkman.Ini", "MadMilkman.Ini\MadMilkman.Ini.csproj", "{BEF9735D-C3CC-41E6-AAC6-18C5985D3107}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MadMilkman.Ini.Tests", "MadMilkman.Ini.Tests\MadMilkman.Ini.Tests.csproj", "{BDD080C9-016F-4869-95DE-61171E2AB746}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MadMilkman.Ini.Samples.CS", "MadMilkman.Ini.Samples\MadMilkman.Ini.Samples.CS\MadMilkman.Ini.Samples.CS.csproj", "{67F5741B-F6B2-4A4B-8E83-E0FD108086B1}"
EndProject
Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "MadMilkman.Ini.Samples.VB", "MadMilkman.Ini.Samples\MadMilkman.Ini.Samples.VB\MadMilkman.Ini.Samples.VB.vbproj", "{4FEA3A29-874B-4E1B-A60C-584E703FEA11}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MadMilkman.Ini.Samples.Files", "MadMilkman.Ini.Samples.Files", "{AEF2490D-0F64-453B-9DCA-C1286517E311}"
ProjectSection(SolutionItems) = preProject
MadMilkman.Ini.Samples\MadMilkman.Ini.Samples.Files\Compress Example.ini = MadMilkman.Ini.Samples\MadMilkman.Ini.Samples.Files\Compress Example.ini
MadMilkman.Ini.Samples\MadMilkman.Ini.Samples.Files\Custom Example Input.ini = MadMilkman.Ini.Samples\MadMilkman.Ini.Samples.Files\Custom Example Input.ini
MadMilkman.Ini.Samples\MadMilkman.Ini.Samples.Files\Custom Example Output.ini = MadMilkman.Ini.Samples\MadMilkman.Ini.Samples.Files\Custom Example Output.ini
MadMilkman.Ini.Samples\MadMilkman.Ini.Samples.Files\Encrypt Example.ini = MadMilkman.Ini.Samples\MadMilkman.Ini.Samples.Files\Encrypt Example.ini
MadMilkman.Ini.Samples\MadMilkman.Ini.Samples.Files\Load Example.ini = MadMilkman.Ini.Samples\MadMilkman.Ini.Samples.Files\Load Example.ini
MadMilkman.Ini.Samples\MadMilkman.Ini.Samples.Files\Save Example.ini = MadMilkman.Ini.Samples\MadMilkman.Ini.Samples.Files\Save Example.ini
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MadMilkman.Ini.Samples.CPP", "MadMilkman.Ini.Samples\MadMilkman.Ini.Samples.CPP\MadMilkman.Ini.Samples.CPP.vcxproj", "{097C11FE-8D4B-48D8-884E-0747454E43DB}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MadMilkman.Ini.Samples", "MadMilkman.Ini.Samples", "{861D28E8-3AF2-48AF-B212-9C998BB8B200}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|Mixed Platforms = Debug|Mixed Platforms
Debug|Win32 = Debug|Win32
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|Mixed Platforms = Release|Mixed Platforms
Release|Win32 = Release|Win32
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{BEF9735D-C3CC-41E6-AAC6-18C5985D3107}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BEF9735D-C3CC-41E6-AAC6-18C5985D3107}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BEF9735D-C3CC-41E6-AAC6-18C5985D3107}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{BEF9735D-C3CC-41E6-AAC6-18C5985D3107}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{BEF9735D-C3CC-41E6-AAC6-18C5985D3107}.Debug|Win32.ActiveCfg = Debug|Any CPU
{BEF9735D-C3CC-41E6-AAC6-18C5985D3107}.Debug|x86.ActiveCfg = Debug|Any CPU
{BEF9735D-C3CC-41E6-AAC6-18C5985D3107}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BEF9735D-C3CC-41E6-AAC6-18C5985D3107}.Release|Any CPU.Build.0 = Release|Any CPU
{BEF9735D-C3CC-41E6-AAC6-18C5985D3107}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{BEF9735D-C3CC-41E6-AAC6-18C5985D3107}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{BEF9735D-C3CC-41E6-AAC6-18C5985D3107}.Release|Win32.ActiveCfg = Release|Any CPU
{BEF9735D-C3CC-41E6-AAC6-18C5985D3107}.Release|x86.ActiveCfg = Release|Any CPU
{BDD080C9-016F-4869-95DE-61171E2AB746}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BDD080C9-016F-4869-95DE-61171E2AB746}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BDD080C9-016F-4869-95DE-61171E2AB746}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{BDD080C9-016F-4869-95DE-61171E2AB746}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{BDD080C9-016F-4869-95DE-61171E2AB746}.Debug|Win32.ActiveCfg = Debug|Any CPU
{BDD080C9-016F-4869-95DE-61171E2AB746}.Debug|x86.ActiveCfg = Debug|Any CPU
{BDD080C9-016F-4869-95DE-61171E2AB746}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BDD080C9-016F-4869-95DE-61171E2AB746}.Release|Any CPU.Build.0 = Release|Any CPU
{BDD080C9-016F-4869-95DE-61171E2AB746}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{BDD080C9-016F-4869-95DE-61171E2AB746}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{BDD080C9-016F-4869-95DE-61171E2AB746}.Release|Win32.ActiveCfg = Release|Any CPU
{BDD080C9-016F-4869-95DE-61171E2AB746}.Release|x86.ActiveCfg = Release|Any CPU
{67F5741B-F6B2-4A4B-8E83-E0FD108086B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{67F5741B-F6B2-4A4B-8E83-E0FD108086B1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{67F5741B-F6B2-4A4B-8E83-E0FD108086B1}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{67F5741B-F6B2-4A4B-8E83-E0FD108086B1}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{67F5741B-F6B2-4A4B-8E83-E0FD108086B1}.Debug|Win32.ActiveCfg = Debug|Any CPU
{67F5741B-F6B2-4A4B-8E83-E0FD108086B1}.Debug|x86.ActiveCfg = Debug|Any CPU
{67F5741B-F6B2-4A4B-8E83-E0FD108086B1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{67F5741B-F6B2-4A4B-8E83-E0FD108086B1}.Release|Any CPU.Build.0 = Release|Any CPU
{67F5741B-F6B2-4A4B-8E83-E0FD108086B1}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{67F5741B-F6B2-4A4B-8E83-E0FD108086B1}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{67F5741B-F6B2-4A4B-8E83-E0FD108086B1}.Release|Win32.ActiveCfg = Release|Any CPU
{67F5741B-F6B2-4A4B-8E83-E0FD108086B1}.Release|x86.ActiveCfg = Release|Any CPU
{4FEA3A29-874B-4E1B-A60C-584E703FEA11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4FEA3A29-874B-4E1B-A60C-584E703FEA11}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4FEA3A29-874B-4E1B-A60C-584E703FEA11}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{4FEA3A29-874B-4E1B-A60C-584E703FEA11}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{4FEA3A29-874B-4E1B-A60C-584E703FEA11}.Debug|Win32.ActiveCfg = Debug|Any CPU
{4FEA3A29-874B-4E1B-A60C-584E703FEA11}.Debug|x86.ActiveCfg = Debug|Any CPU
{4FEA3A29-874B-4E1B-A60C-584E703FEA11}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4FEA3A29-874B-4E1B-A60C-584E703FEA11}.Release|Any CPU.Build.0 = Release|Any CPU
{4FEA3A29-874B-4E1B-A60C-584E703FEA11}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{4FEA3A29-874B-4E1B-A60C-584E703FEA11}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{4FEA3A29-874B-4E1B-A60C-584E703FEA11}.Release|Win32.ActiveCfg = Release|Any CPU
{4FEA3A29-874B-4E1B-A60C-584E703FEA11}.Release|x86.ActiveCfg = Release|Any CPU
{097C11FE-8D4B-48D8-884E-0747454E43DB}.Debug|Any CPU.ActiveCfg = Debug|Win32
{097C11FE-8D4B-48D8-884E-0747454E43DB}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
{097C11FE-8D4B-48D8-884E-0747454E43DB}.Debug|Mixed Platforms.Build.0 = Debug|Win32
{097C11FE-8D4B-48D8-884E-0747454E43DB}.Debug|Win32.ActiveCfg = Debug|Win32
{097C11FE-8D4B-48D8-884E-0747454E43DB}.Debug|Win32.Build.0 = Debug|Win32
{097C11FE-8D4B-48D8-884E-0747454E43DB}.Debug|x86.ActiveCfg = Debug|Win32
{097C11FE-8D4B-48D8-884E-0747454E43DB}.Debug|x86.Build.0 = Debug|Win32
{097C11FE-8D4B-48D8-884E-0747454E43DB}.Release|Any CPU.ActiveCfg = Release|Win32
{097C11FE-8D4B-48D8-884E-0747454E43DB}.Release|Mixed Platforms.ActiveCfg = Release|Win32
{097C11FE-8D4B-48D8-884E-0747454E43DB}.Release|Mixed Platforms.Build.0 = Release|Win32
{097C11FE-8D4B-48D8-884E-0747454E43DB}.Release|Win32.ActiveCfg = Release|Win32
{097C11FE-8D4B-48D8-884E-0747454E43DB}.Release|Win32.Build.0 = Release|Win32
{097C11FE-8D4B-48D8-884E-0747454E43DB}.Release|x86.ActiveCfg = Release|Win32
{097C11FE-8D4B-48D8-884E-0747454E43DB}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{4FEA3A29-874B-4E1B-A60C-584E703FEA11} = {861D28E8-3AF2-48AF-B212-9C998BB8B200}
{AEF2490D-0F64-453B-9DCA-C1286517E311} = {861D28E8-3AF2-48AF-B212-9C998BB8B200}
{097C11FE-8D4B-48D8-884E-0747454E43DB} = {861D28E8-3AF2-48AF-B212-9C998BB8B200}
{67F5741B-F6B2-4A4B-8E83-E0FD108086B1} = {861D28E8-3AF2-48AF-B212-9C998BB8B200}
EndGlobalSection
EndGlobal

View File

@ -1,755 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<doc>
<assembly>
<name>MadMilkman.Ini</name>
</assembly>
<members>
<member name="T:MadMilkman.Ini.IniComment">
<summary>
Represents a comment object used by <see cref="T:MadMilkman.Ini.IniItem" /> objects, <see cref="T:MadMilkman.Ini.IniSection" /> and <see cref="T:MadMilkman.Ini.IniKey" />.
</summary>
</member>
<member name="P:MadMilkman.Ini.IniComment.EmptyLinesBefore">
<summary>
Gets or sets the amount of empty lines before this <see cref="P:MadMilkman.Ini.IniComment.Text">comment's text</see>.
</summary>
</member>
<member name="P:MadMilkman.Ini.IniComment.LeftIndentation">
<summary>
Gets or sets the amount of whitespace characters before this <see cref="P:MadMilkman.Ini.IniComment.Text">comment's text</see>.
</summary>
</member>
<member name="P:MadMilkman.Ini.IniComment.Text">
<summary>
Gets or sets a text of this <see cref="T:MadMilkman.Ini.IniComment" /> instance.
</summary>
</member>
<member name="T:MadMilkman.Ini.IniCommentStarter">
<summary>
Defines <see cref="T:MadMilkman.Ini.IniComment">comment's</see> starting character.
</summary>
</member>
<member name="F:MadMilkman.Ini.IniCommentStarter.Semicolon">
<summary>
Use ';' as <see cref="T:MadMilkman.Ini.IniComment">comment's</see> starting character.
</summary>
</member>
<member name="F:MadMilkman.Ini.IniCommentStarter.Hash">
<summary>
Use '#' as <see cref="T:MadMilkman.Ini.IniComment">comment's</see> starting character.
</summary>
</member>
<member name="T:MadMilkman.Ini.IniDuplication">
<summary>
Defines a behaviour for duplicate <see cref="P:MadMilkman.Ini.IniItem.Name" /> occurences.
</summary>
</member>
<member name="F:MadMilkman.Ini.IniDuplication.Allowed">
<summary>
Allow duplicate names in <see cref="T:MadMilkman.Ini.IniItemCollection`1" />.
</summary>
</member>
<member name="F:MadMilkman.Ini.IniDuplication.Disallowed">
<summary>
Disallow duplicate names in <see cref="T:MadMilkman.Ini.IniItemCollection`1" />.
</summary>
</member>
<member name="F:MadMilkman.Ini.IniDuplication.Ignored">
<summary>
Ignore duplicate names.
</summary>
</member>
<member name="T:MadMilkman.Ini.IniFile">
<summary>
In-memory representation of an INI file.
</summary>
</member>
<member name="M:MadMilkman.Ini.IniFile.#ctor">
<summary>
Initializes a new instance of <see cref="T:MadMilkman.Ini.IniFile" /> class.
</summary>
</member>
<member name="M:MadMilkman.Ini.IniFile.#ctor(MadMilkman.Ini.IniOptions)">
<summary>
Initializes a new instance of <see cref="T:MadMilkman.Ini.IniFile" /> class.
</summary>
<param name="options">
<see cref="T:MadMilkman.Ini.IniOptions" /> object that defines INI file's format, settings for both <see cref="O:MadMilkman.Ini.IniFile.Load">Load</see> and <see cref="O:MadMilkman.Ini.IniFile.Save">Save</see> methods.</param>
</member>
<member name="M:MadMilkman.Ini.IniFile.Load(System.IO.Stream)">
<summary>
Loads a file from a stream.
</summary>
<param name="fileStream">Stream from which to load a file.</param>
</member>
<member name="M:MadMilkman.Ini.IniFile.Load(System.IO.TextReader)">
<summary>
Loads a file from a reader.
</summary>
<param name="fileReader">Reader from which to load a file.</param>
</member>
<member name="M:MadMilkman.Ini.IniFile.Load(System.String)">
<summary>
Loads a file from a path.
</summary>
<param name="filePath">Path from which to load a file.</param>
</member>
<member name="M:MadMilkman.Ini.IniFile.Save(System.IO.Stream)">
<summary>
Saves a file to a stream.
</summary>
<param name="fileStream">Stream to which to save a file.</param>
</member>
<member name="M:MadMilkman.Ini.IniFile.Save(System.IO.TextWriter)">
<summary>
Saves a file to a writer.
</summary>
<param name="fileWriter">Writer to which to save a file.</param>
</member>
<member name="M:MadMilkman.Ini.IniFile.Save(System.String)">
<summary>
Saves a file to a path.
</summary>
<param name="filePath">Path to which to save a file.</param>
</member>
<member name="P:MadMilkman.Ini.IniFile.Sections">
<summary>
Gets file's sections.
</summary>
</member>
<member name="P:MadMilkman.Ini.IniFile.ValueBinding">
<summary>
Gets the object that exposes binding operations, which are executed with <see cref="O:MadMilkman.Ini.IniValueBinding.Bind" /> methods.
</summary>
</member>
<member name="P:MadMilkman.Ini.IniFile.ValueMappings">
<summary>
Gets the mappings of <see cref="P:MadMilkman.Ini.IniKey.Value" />s and their results, used in <see cref="O:MadMilkman.Ini.IniKey.TryParseValue" /> methods.
</summary>
</member>
<member name="T:MadMilkman.Ini.IniItem">
<summary>
Represents a base class for INI content items, <see cref="T:MadMilkman.Ini.IniSection" /> and <see cref="T:MadMilkman.Ini.IniKey" />.
</summary>
</member>
<member name="P:MadMilkman.Ini.IniItem.LeadingComment">
<summary>
Gets the <see cref="T:MadMilkman.Ini.IniComment" /> object that represents a comment that follows this <see cref="T:MadMilkman.Ini.IniItem" /> on the same line.
</summary>
</member>
<member name="P:MadMilkman.Ini.IniItem.LeftIndentation">
<summary>
Gets or sets the amount of whitespace characters before this <see cref="P:MadMilkman.Ini.IniItem.Name">item's name</see>.
</summary>
</member>
<member name="P:MadMilkman.Ini.IniItem.Name">
<summary>
Gets and sets the name of the current <see cref="T:MadMilkman.Ini.IniItem" />.
</summary>
</member>
<member name="P:MadMilkman.Ini.IniItem.ParentFile">
<summary>
Gets the <see cref="T:MadMilkman.Ini.IniFile" /> to which this <see cref="T:MadMilkman.Ini.IniItem" /> belongs to.
</summary>
</member>
<member name="P:MadMilkman.Ini.IniItem.TrailingComment">
<summary>
Gets the <see cref="T:MadMilkman.Ini.IniComment" /> object that represents a comments that occur before this <see cref="T:MadMilkman.Ini.IniItem" />.
</summary>
</member>
<member name="T:MadMilkman.Ini.IniItemCollection`1">
<summary>
Represents a base generic class for INI content item collections, <see cref="T:MadMilkman.Ini.IniSectionCollection" /> and <see cref="T:MadMilkman.Ini.IniKeyCollection" />.
</summary>
<typeparam name="T">
<see cref="T:MadMilkman.Ini.IniItem" /> derived type.</typeparam>
</member>
<member name="M:MadMilkman.Ini.IniItemCollection`1.Add(`0)">
<summary>
Adds an item to the end of this collection.
</summary>
<param name="item">Item to add to this collection.</param>
</member>
<member name="M:MadMilkman.Ini.IniItemCollection`1.Clear">
<summary>
Removes all items from this collection.
</summary>
</member>
<member name="M:MadMilkman.Ini.IniItemCollection`1.Contains(System.String)">
<summary>
Determines whether an item is in this collection.
</summary>
<param name="name">Name of the item to locate in this collection.</param>
<returns>
<see langword="true" /> if the item with specified name is in the collection.</returns>
</member>
<member name="M:MadMilkman.Ini.IniItemCollection`1.Contains(`0)">
<summary>
Determines whether an item is in this collection.
</summary>
<param name="item">Item to locate in this collection.</param>
<returns>
<see langword="true" /> if the specified item is in the collection.</returns>
</member>
<member name="M:MadMilkman.Ini.IniItemCollection`1.CopyTo(`0[],System.Int32)">
<summary>
Shallow copies the items of this collection to an array.
</summary>
<param name="array">One-dimensional array that is the destination of the items copied from this collection.</param>
<param name="arrayIndex">Zero-based index in array at which copying begins.</param>
</member>
<member name="P:MadMilkman.Ini.IniItemCollection`1.Count">
<summary>
Gets the number of items in this collection.
</summary>
</member>
<member name="M:MadMilkman.Ini.IniItemCollection`1.GetEnumerator">
<summary>
Returns an enumerator that iterates through the collection.
</summary>
<returns>
<see cref="T:System.Collections.Generic.IEnumerator`1" /> object that can be used to iterate through the collection.</returns>
</member>
<member name="M:MadMilkman.Ini.IniItemCollection`1.IndexOf(System.String)">
<summary>
Searches for the specified item and returns the zero-based index of the first occurrence within this collection.
</summary>
<param name="name">Name of the item to locate in this collection.</param>
<returns>Index of the first occurrence of the item with specified name in the collection.</returns>
</member>
<member name="M:MadMilkman.Ini.IniItemCollection`1.IndexOf(`0)">
<summary>
Searches for the specified item and returns the zero-based index of the first occurrence within this collection.
</summary>
<param name="item">Item to locate in this collection.</param>
<returns>Index of the first occurrence of specified item in the collection.</returns>
</member>
<member name="M:MadMilkman.Ini.IniItemCollection`1.Insert(System.Int32,`0)">
<summary>
Inserts an item to this collection at the specified index.
</summary>
<param name="index">Zero-based index at which item should be inserted.</param>
<param name="item">Item to insert to this collection.</param>
</member>
<member name="P:MadMilkman.Ini.IniItemCollection`1.Item(System.Int32)">
<summary>
Gets or sets the item at the specified index.
</summary>
<param name="index">Zero-based index of the item to get or set.</param>
</member>
<member name="P:MadMilkman.Ini.IniItemCollection`1.Item(System.String)">
<summary>
Gets the first item of the specified name.
</summary>
<param name="name">Name of the item to get.</param>
</member>
<member name="P:MadMilkman.Ini.IniItemCollection`1.Item(System.String[])">
<summary>
Gets the first items of the specified names.
</summary>
<param name="names">Names of the items to get.</param>
</member>
<member name="M:MadMilkman.Ini.IniItemCollection`1.Remove(System.String)">
<summary>
Removes the first occurrence of specific item from this collection.
</summary>
<param name="name">Name of the item to remove from this collection.</param>
<returns>
<see langword="true" /> if the item with specified name is removed from the collection.</returns>
</member>
<member name="M:MadMilkman.Ini.IniItemCollection`1.Remove(`0)">
<summary>
Removes the first occurrence of specific item from this collection.
</summary>
<param name="item">Item to remove from this collection.</param>
<returns>
<see langword="true" /> if the specified item is removed from the collection.</returns>
</member>
<member name="M:MadMilkman.Ini.IniItemCollection`1.RemoveAt(System.Int32)">
<summary>
Removes an item at the specified index from this collection.
</summary>
<param name="index">Zero-based index at which item should be inserted.</param>
</member>
<member name="T:MadMilkman.Ini.IniKey">
<summary>
Represents a key item of the INI file with name and value content.
</summary>
</member>
<member name="M:MadMilkman.Ini.IniKey.#ctor(MadMilkman.Ini.IniFile,System.Collections.Generic.KeyValuePair{System.String,System.String})">
<summary>
Initializes a new instance of the <see cref="T:MadMilkman.Ini.IniKey" /> class.
</summary>
<param name="parentFile">The owner file.</param>
<param name="nameValuePair">The key's data, pair of key's name and key's value.</param>
</member>
<member name="M:MadMilkman.Ini.IniKey.#ctor(MadMilkman.Ini.IniFile,System.String)">
<summary>
Initializes a new instance of the <see cref="T:MadMilkman.Ini.IniKey" /> class.
</summary>
<param name="parentFile">The owner file.</param>
<param name="name">The key's name.</param>
</member>
<member name="M:MadMilkman.Ini.IniKey.#ctor(MadMilkman.Ini.IniFile,System.String,System.String)">
<summary>
Initializes a new instance of the <see cref="T:MadMilkman.Ini.IniKey" /> class.
</summary>
<param name="parentFile">The owner file.</param>
<param name="name">The key's name.</param>
<param name="value">The key's value.</param>
</member>
<member name="M:MadMilkman.Ini.IniKey.Copy">
<summary>
Copies this <see cref="T:MadMilkman.Ini.IniKey" /> instance.
</summary>
<returns>Copied <see cref="T:MadMilkman.Ini.IniKey" />.</returns>
</member>
<member name="M:MadMilkman.Ini.IniKey.Copy(MadMilkman.Ini.IniFile)">
<summary>
Copies this <see cref="T:MadMilkman.Ini.IniKey" /> instance and sets copied instance's <see cref="P:MadMilkman.Ini.IniItem.ParentFile">ParentFile</see>.
</summary>
<param name="destinationFile">Copied key's parent file.</param>
<returns>Copied <see cref="T:MadMilkman.Ini.IniKey" /> that belongs to a specified <see cref="T:MadMilkman.Ini.IniFile" />.</returns>
</member>
<member name="M:MadMilkman.Ini.IniKey.IsSupportedValueType(System.Type)">
<summary>
Indicates whether the <see cref="P:MadMilkman.Ini.IniKey.Value" /> can be converted to specified type.
</summary>
<param name="type">Type of the object to convert the <see cref="P:MadMilkman.Ini.IniKey.Value" /> to.</param>
<returns>
<see langword="true" /> if the specified type is supported.</returns>
</member>
<member name="P:MadMilkman.Ini.IniKey.ParentCollection">
<summary>
Gets the <see cref="T:MadMilkman.Ini.IniKeyCollection" /> to which this <see cref="T:MadMilkman.Ini.IniKey" /> belongs to.
</summary>
</member>
<member name="P:MadMilkman.Ini.IniKey.ParentSection">
<summary>
Gets the <see cref="T:MadMilkman.Ini.IniSection" /> to which this <see cref="T:MadMilkman.Ini.IniKey" /> belongs to.
</summary>
</member>
<member name="M:MadMilkman.Ini.IniKey.TryParseValue``1(System.Collections.Generic.List{``0}@)">
<summary>
Converts the <see cref="P:MadMilkman.Ini.IniKey.Value" /> to a list of the specified type.
</summary>
<param name="results">Uninitialized list of a specific type which will hold the converted values if the conversion succeeds.</param>
<typeparam name="T">Type of the objects in list to convert the <see cref="P:MadMilkman.Ini.IniKey.Value" /> to.</typeparam>
<returns>Value that indicates whether the conversion succeeded.</returns>
</member>
<member name="M:MadMilkman.Ini.IniKey.TryParseValue``1(``0@)">
<summary>
Converts the <see cref="P:MadMilkman.Ini.IniKey.Value" /> to an instance of the specified type.
</summary>
<param name="result">Uninitialized instance of a specific type which will hold the converted value if the conversion succeeds.</param>
<typeparam name="T">Type of the object to convert the <see cref="P:MadMilkman.Ini.IniKey.Value" /> to.</typeparam>
<returns>Value that indicates whether the conversion succeeded.</returns>
</member>
<member name="M:MadMilkman.Ini.IniKey.TryParseValue``1(``0[]@)">
<summary>
Converts the <see cref="P:MadMilkman.Ini.IniKey.Value" /> to an array of the specified type.
</summary>
<param name="results">Uninitialized array of a specific type which will hold the converted values if the conversion succeeds.</param>
<typeparam name="T">Type of the objects in array to convert the <see cref="P:MadMilkman.Ini.IniKey.Value" /> to.</typeparam>
<returns>Value that indicates whether the conversion succeeded.</returns>
</member>
<member name="P:MadMilkman.Ini.IniKey.Value">
<summary>
Gets and sets <see cref="T:MadMilkman.Ini.IniKey" /> value.
</summary>
</member>
<member name="T:MadMilkman.Ini.IniKeyCollection">
<summary>
Represents a collection of <see cref="T:MadMilkman.Ini.IniKey" /> items.
</summary>
</member>
<member name="M:MadMilkman.Ini.IniKeyCollection.Add(System.Collections.Generic.KeyValuePair{System.String,System.String})">
<summary>
Adds an item to the end of this collection.
</summary>
<param name="nameValuePair">The key's data, pair of key's name and key's value, to add to this collection.</param>
<returns>
<see cref="T:MadMilkman.Ini.IniKey" /> that was added to this collection.</returns>
</member>
<member name="M:MadMilkman.Ini.IniKeyCollection.Add(System.String)">
<summary>
Adds an item to the end of this collection.
</summary>
<param name="name">Name of the <see cref="T:MadMilkman.Ini.IniKey" /> to add to this collection.</param>
<returns>
<see cref="T:MadMilkman.Ini.IniKey" /> that was added to this collection.</returns>
</member>
<member name="M:MadMilkman.Ini.IniKeyCollection.Add(System.String,System.String)">
<summary>
Adds an item to the end of this collection.
</summary>
<param name="name">Name of the <see cref="T:MadMilkman.Ini.IniKey" /> to add to this collection.</param>
<param name="value">Value of the <see cref="T:MadMilkman.Ini.IniKey" /> to add to this collection.</param>
<returns>
<see cref="T:MadMilkman.Ini.IniKey" /> that was added to this collection.</returns>
</member>
<member name="M:MadMilkman.Ini.IniKeyCollection.Insert(System.Int32,System.Collections.Generic.KeyValuePair{System.String,System.String})">
<summary>
Inserts an item to this collection at the specified index.
</summary>
<param name="index">Zero-based index at which item should be inserted.</param>
<param name="nameValuePair">The key's data, pair of key's name and key's value, to insert to this collection.</param>
<returns>
<see cref="T:MadMilkman.Ini.IniKey" /> that was inserted to this collection.</returns>
</member>
<member name="M:MadMilkman.Ini.IniKeyCollection.Insert(System.Int32,System.String)">
<summary>
Inserts an item to this collection at the specified index.
</summary>
<param name="index">Zero-based index at which item should be inserted.</param>
<param name="name">Name of the <see cref="T:MadMilkman.Ini.IniKey" /> to insert to this collection.</param>
<returns>
<see cref="T:MadMilkman.Ini.IniKey" /> that was inserted to this collection.</returns>
</member>
<member name="M:MadMilkman.Ini.IniKeyCollection.Insert(System.Int32,System.String,System.String)">
<summary>
Inserts an item to this collection at the specified index.
</summary>
<param name="index">Zero-based index at which item should be inserted.</param>
<param name="name">Name of the <see cref="T:MadMilkman.Ini.IniKey" /> to insert to this collection.</param>
<param name="value">Value of the <see cref="T:MadMilkman.Ini.IniKey" /> to insert to this collection.</param>
<returns>
<see cref="T:MadMilkman.Ini.IniKey" /> that was inserted to this collection.</returns>
</member>
<member name="T:MadMilkman.Ini.IniKeyDelimiter">
<summary>
Defines <see cref="T:MadMilkman.Ini.IniKey">key's</see> name and value delimiter character.
</summary>
</member>
<member name="F:MadMilkman.Ini.IniKeyDelimiter.Equal">
<summary>
Use '=' as <see cref="T:MadMilkman.Ini.IniKey">key's</see> name and value delimiter character.
</summary>
</member>
<member name="F:MadMilkman.Ini.IniKeyDelimiter.Colon">
<summary>
Use ':' as <see cref="T:MadMilkman.Ini.IniKey">key's</see> name and value delimiter character.
</summary>
</member>
<member name="T:MadMilkman.Ini.IniOptions">
<summary>
Represents a class that defines INI file's format, stores properties used for both reading and writing a file.
</summary>
</member>
<member name="M:MadMilkman.Ini.IniOptions.#ctor">
<summary>
Initializes a new instance of the <see cref="T:MadMilkman.Ini.IniOptions" /> class.
</summary>
</member>
<member name="P:MadMilkman.Ini.IniOptions.CommentStarter">
<summary>
Gets or sets comments starting character.
</summary>
</member>
<member name="P:MadMilkman.Ini.IniOptions.Compression">
<summary>
<para>Gets or sets a value indicating if file's size is reduced.</para>
<para>If <see langword="true" /> file is decompressed on Load and compressed on Save.</para>
</summary>
</member>
<member name="P:MadMilkman.Ini.IniOptions.Encoding">
<summary>
Gets or sets encoding for reading and writing an INI file.
</summary>
</member>
<member name="P:MadMilkman.Ini.IniOptions.EncryptionPassword">
<summary>
<para>Gets or sets an INI file's protection password.</para>
<para>File is decrypted on Load and encrypted on Save if a password is not <see langword="null" /> or <see cref="F:System.String.Empty" />.</para>
</summary>
</member>
<member name="P:MadMilkman.Ini.IniOptions.KeyDelimiter">
<summary>
Gets or sets keys name and value delimiter character.
</summary>
</member>
<member name="P:MadMilkman.Ini.IniOptions.KeyDuplicate">
<summary>
Gets or sets a value indicating whether keys with same name are allowed, disallowed or ignored.
</summary>
</member>
<member name="P:MadMilkman.Ini.IniOptions.KeyNameCaseSensitive">
<summary>
Gets or sets a value indicating whether keys name are case sensitive.
</summary>
</member>
<member name="P:MadMilkman.Ini.IniOptions.KeySpaceAroundDelimiter">
<summary>
Gets or sets a value indicating whether space is written around the keys delimiter.
</summary>
</member>
<member name="P:MadMilkman.Ini.IniOptions.SectionDuplicate">
<summary>
Gets or sets a value indicating whether sections with same name are allowed, disallowed or ignored.
</summary>
</member>
<member name="P:MadMilkman.Ini.IniOptions.SectionNameCaseSensitive">
<summary>
Gets or sets a value indicating whether sections name are case sensitive.
</summary>
</member>
<member name="P:MadMilkman.Ini.IniOptions.SectionWrapper">
<summary>
Gets or sets wrapper characters of sections name.
</summary>
</member>
<member name="T:MadMilkman.Ini.IniSection">
<summary>
Represents a section item of the INI file with name and keys content.
</summary>
</member>
<member name="M:MadMilkman.Ini.IniSection.#ctor(MadMilkman.Ini.IniFile,System.String)">
<summary>
Initializes a new instance of the <see cref="T:MadMilkman.Ini.IniSection" /> class.
</summary>
<param name="parentFile">The owner file.</param>
<param name="name">The section's name.</param>
</member>
<member name="M:MadMilkman.Ini.IniSection.#ctor(MadMilkman.Ini.IniFile,System.String,MadMilkman.Ini.IniKey[])">
<summary>
Initializes a new instance of the <see cref="T:MadMilkman.Ini.IniSection" /> class.
</summary>
<param name="parentFile">The owner file.</param>
<param name="name">The section's name.</param>
<param name="keys">The section's keys.</param>
</member>
<member name="M:MadMilkman.Ini.IniSection.#ctor(MadMilkman.Ini.IniFile,System.String,System.Collections.Generic.IEnumerable{MadMilkman.Ini.IniKey})">
<summary>
Initializes a new instance of the <see cref="T:MadMilkman.Ini.IniSection" /> class.
</summary>
<param name="parentFile">The owner file.</param>
<param name="name">The section's name.</param>
<param name="keys">The section's keys.</param>
</member>
<member name="M:MadMilkman.Ini.IniSection.#ctor(MadMilkman.Ini.IniFile,System.String,System.Collections.Generic.IEnumerable{System.Collections.Generic.KeyValuePair{System.String,System.String}})">
<summary>
Initializes a new instance of the <see cref="T:MadMilkman.Ini.IniSection" /> class.
</summary>
<param name="parentFile">The owner file.</param>
<param name="name">The section's name.</param>
<param name="nameValuePairs">The section's keys data, pairs of key's name and key's value.</param>
</member>
<member name="M:MadMilkman.Ini.IniSection.Copy">
<summary>
Copies this <see cref="T:MadMilkman.Ini.IniSection" /> instance.
</summary>
<returns>Copied <see cref="T:MadMilkman.Ini.IniSection" />.</returns>
</member>
<member name="M:MadMilkman.Ini.IniSection.Copy(MadMilkman.Ini.IniFile)">
<summary>
Copies this <see cref="T:MadMilkman.Ini.IniSection" /> instance and sets copied instance's <see cref="P:MadMilkman.Ini.IniItem.ParentFile">ParentFile</see>.
</summary>
<param name="destinationFile">Copied section's parent file.</param>
<returns>Copied <see cref="T:MadMilkman.Ini.IniSection" /> that belongs to a specified <see cref="T:MadMilkman.Ini.IniFile" />.</returns>
</member>
<member name="M:MadMilkman.Ini.IniSection.Deserialize``1">
<summary>
Deserializes this <see cref="T:MadMilkman.Ini.IniSection" /> into an object of specified type.
</summary>
<typeparam name="T">The type of deserialized object.</typeparam>
<returns>The object being deserialized.</returns>
</member>
<member name="F:MadMilkman.Ini.IniSection.GlobalSectionName">
<summary>
Represents a section name which is used to define a global section, used for storing first keys series that don't belong to any section.
</summary>
</member>
<member name="P:MadMilkman.Ini.IniSection.Keys">
<summary>
Gets the <see cref="T:MadMilkman.Ini.IniSection">section's</see> key collection.
</summary>
</member>
<member name="P:MadMilkman.Ini.IniSection.ParentCollection">
<summary>
Gets the <see cref="T:MadMilkman.Ini.IniSectionCollection" /> to which this <see cref="T:MadMilkman.Ini.IniSection" /> belongs to.
</summary>
</member>
<member name="M:MadMilkman.Ini.IniSection.Serialize``1(``0)">
<summary>
Serializes the specified object into this <see cref="T:MadMilkman.Ini.IniSection" />.
</summary>
<param name="source">The object to serialize.</param>
<typeparam name="T">The type of serialized object.</typeparam>
</member>
<member name="T:MadMilkman.Ini.IniSectionCollection">
<summary>
Represents a collection of <see cref="T:MadMilkman.Ini.IniSection" /> items.
</summary>
</member>
<member name="M:MadMilkman.Ini.IniSectionCollection.Add(System.String)">
<summary>
Adds an item to the end of this collection.
</summary>
<param name="name">Name of the <see cref="T:MadMilkman.Ini.IniSection" /> to add to this collection.</param>
<returns>
<see cref="T:MadMilkman.Ini.IniSection" /> that was added to this collection.</returns>
</member>
<member name="M:MadMilkman.Ini.IniSectionCollection.Add(System.String,System.Collections.Generic.IEnumerable{System.Collections.Generic.KeyValuePair{System.String,System.String}})">
<summary>
Adds an item to the end of this collection.
</summary>
<param name="name">Name of the <see cref="T:MadMilkman.Ini.IniSection" /> to add to this collection.</param>
<param name="nameValuePairs">The section's keys data, pairs of key's name and key's value, to add to this collection.</param>
<returns>
<see cref="T:MadMilkman.Ini.IniSection" /> that was added to this collection.</returns>
</member>
<member name="M:MadMilkman.Ini.IniSectionCollection.Insert(System.Int32,System.String)">
<summary>
Inserts an item to this collection at the specified index.
</summary>
<param name="index">Zero-based index at which item should be inserted.</param>
<param name="name">Name of the <see cref="T:MadMilkman.Ini.IniSection" /> to insert to this collection.</param>
<returns>
<see cref="T:MadMilkman.Ini.IniSection" /> that was inserted to this collection.</returns>
</member>
<member name="M:MadMilkman.Ini.IniSectionCollection.Insert(System.Int32,System.String,System.Collections.Generic.IEnumerable{System.Collections.Generic.KeyValuePair{System.String,System.String}})">
<summary>
Inserts an item to this collection at the specified index.
</summary>
<param name="index">Zero-based index at which item should be inserted.</param>
<param name="name">Name of the <see cref="T:MadMilkman.Ini.IniSection" /> to insert to this collection.</param>
<param name="nameValuePairs">The section's keys data, pairs of key's name and key's value, to insert to this collection.</param>
<returns>
<see cref="T:MadMilkman.Ini.IniSection" /> that was inserted to this collection.</returns>
</member>
<member name="T:MadMilkman.Ini.IniSectionWrapper">
<summary>
Defines <see cref="T:MadMilkman.Ini.IniSection">section's</see> wrapper characters around its name.
</summary>
</member>
<member name="F:MadMilkman.Ini.IniSectionWrapper.SquareBrackets">
<summary>
Use '[' and ']' as <see cref="T:MadMilkman.Ini.IniSection">section's</see> wrapper characters.
</summary>
</member>
<member name="F:MadMilkman.Ini.IniSectionWrapper.AngleBrackets">
<summary>
Use '&lt;' and '&gt;' as <see cref="T:MadMilkman.Ini.IniSection">section's</see> wrapper characters.
</summary>
</member>
<member name="F:MadMilkman.Ini.IniSectionWrapper.CurlyBrackets">
<summary>
Use '{' and '}' as <see cref="T:MadMilkman.Ini.IniSection">section's</see> wrapper characters.
</summary>
</member>
<member name="F:MadMilkman.Ini.IniSectionWrapper.Parentheses">
<summary>
Use '(' and ')' as <see cref="T:MadMilkman.Ini.IniSection">section's</see> wrapper characters.
</summary>
</member>
<member name="T:MadMilkman.Ini.IniSerializationAttribute">
<summary>
Indicates the behavior of public property when serializing or deserializing the object that contains it.
</summary>
</member>
<member name="M:MadMilkman.Ini.IniSerializationAttribute.#ctor(System.Boolean)">
<summary>
Initializes a new instance of the IniSerializationAttribute class and specifies if serialization is ignored.
</summary>
<param name="ignore">The value indicating whether serialization is ignored.</param>
</member>
<member name="M:MadMilkman.Ini.IniSerializationAttribute.#ctor(System.String)">
<summary>
Initializes a new instance of the IniSerializationAttribute class and specifies the <see cref="T:MadMilkman.Ini.IniKey" />'s name.
</summary>
<param name="alias">The name of the generated <see cref="T:MadMilkman.Ini.IniKey" />.</param>
</member>
<member name="P:MadMilkman.Ini.IniSerializationAttribute.Alias">
<summary>
Gets the <see cref="T:MadMilkman.Ini.IniKey" /> name of serialized the property.
</summary>
</member>
<member name="P:MadMilkman.Ini.IniSerializationAttribute.Ignore">
<summary>
Gets the value indicating whether serialization is ignored.
</summary>
</member>
<member name="T:MadMilkman.Ini.IniValueBinding">
<summary>
Represents a class that is used for binding operations, an operation in which the <see cref="T:MadMilkman.Ini.IniKey">placeholder keys</see> values are replaced with an internal or external data.
</summary>
</member>
<member name="M:MadMilkman.Ini.IniValueBinding.Bind">
<summary>
Executes a binding operation with internal data source.
</summary>
</member>
<member name="M:MadMilkman.Ini.IniValueBinding.Bind(System.Object)">
<summary>
Executes a binding operation with external data source.
</summary>
<param name="dataSource">The binding data source.</param>
</member>
<member name="M:MadMilkman.Ini.IniValueBinding.Bind(System.Object,System.String)">
<summary>
Executes a binding operation with external data source, only on specified section.
</summary>
<param name="dataSource">The binding data source.</param>
<param name="sectionName">The <see cref="T:MadMilkman.Ini.IniSection" />'s name.</param>
</member>
<member name="E:MadMilkman.Ini.IniValueBinding.Binding">
<summary>
Occurs when a placeholder is binding with data source value and can be used to customize the binding operation.
</summary>
</member>
<member name="T:MadMilkman.Ini.IniValueBindingEventArgs">
<summary>
Provides data for <see cref="E:MadMilkman.Ini.IniValueBinding.Binding" /> event.
</summary>
</member>
<member name="P:MadMilkman.Ini.IniValueBindingEventArgs.IsValueFound">
<summary>
Gets a value indicating whether value was found in the data source.
</summary>
</member>
<member name="P:MadMilkman.Ini.IniValueBindingEventArgs.PlaceholderKey">
<summary>
Gets the placeholder's <see cref="T:MadMilkman.Ini.IniKey" />.
</summary>
</member>
<member name="P:MadMilkman.Ini.IniValueBindingEventArgs.PlaceholderName">
<summary>
Gets the placeholder's name.
</summary>
</member>
<member name="P:MadMilkman.Ini.IniValueBindingEventArgs.Value">
<summary>
Gets or sets the data source value that will replace the placeholder.
</summary>
</member>
<member name="T:MadMilkman.Ini.IniValueMappings">
<summary>
Represents a class of mapped <see cref="P:MadMilkman.Ini.IniKey.Value" />s and their results, used in <see cref="O:MadMilkman.Ini.IniKey.TryParseValue" /> methods.
</summary>
</member>
<member name="M:MadMilkman.Ini.IniValueMappings.Add``1(System.String,``0)">
<summary>
Adds a new mapping of <see cref="P:MadMilkman.Ini.IniKey.Value" /> to resulting object of parse methods.
</summary>
<param name="value">The key's value.</param>
<param name="mappedResult">The object that represents parsed <see cref="P:MadMilkman.Ini.IniKey.Value" />.</param>
<typeparam name="T">Type of the object that represents parsed <see cref="P:MadMilkman.Ini.IniKey.Value" />.</typeparam>
</member>
<member name="M:MadMilkman.Ini.IniValueMappings.Contains(System.String)">
<summary>
Determines whether the collection contains a mapping for a specified key's value.
</summary>
<param name="value">The key's value to locate in the collection.</param>
<returns>
<see langword="true" /> if the collection contains a mapping for a specified key's value.</returns>
</member>
<member name="M:MadMilkman.Ini.IniValueMappings.Remove(System.String)">
<summary>
Removes a mapping for a specified key's value in the collection.
</summary>
<param name="value">The key's value to remove in the collection.</param>
<returns>
<see langword="true" /> if a mapping for a specified key's value is successfully found and removed.</returns>
</member>
</members>
</doc>

View File

@ -1,19 +0,0 @@
namespace MadMilkman.Ini
{
/// <summary>
/// Defines <see cref="IniComment">comment's</see> starting character.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1008:EnumsShouldHaveZeroValue",
Justification = "I'm defining and using enum values with specific characters and null character, aka '\0', has no purpose here.")]
public enum IniCommentStarter
{
/// <summary>
/// Use ';' as <see cref="IniComment">comment's</see> starting character.
/// </summary>
Semicolon = ';',
/// <summary>
/// Use '#' as <see cref="IniComment">comment's</see> starting character.
/// </summary>
Hash = '#'
}
}

View File

@ -1,8 +0,0 @@
namespace MadMilkman.Ini
{
internal enum IniCommentType
{
Leading = 0,
Trailing
}
}

View File

@ -1,27 +0,0 @@
namespace MadMilkman.Ini
{
/// <summary>
/// Defines a behaviour for duplicate <see cref="IniItem.Name"/> occurences.
/// </summary>
public enum IniDuplication
{
/// <summary>
/// Allow duplicate names in <see cref="IniItemCollection{T}"/>.
/// </summary>
Allowed = 0,
/// <summary>
/// Disallow duplicate names in <see cref="IniItemCollection{T}"/>.
/// </summary>
/// <remarks>
/// <see cref="System.InvalidOperationException"/> is thrown on duplicate name occurence.
/// </remarks>
Disallowed,
/// <summary>
/// Ignore duplicate names.
/// </summary>
/// <remarks>
/// Prevents adding or inserting an <see cref="IniItem"/> if its name already exists in <see cref="IniItemCollection{T}"/>.
/// </remarks>
Ignored
}
}

View File

@ -1,19 +0,0 @@
namespace MadMilkman.Ini
{
/// <summary>
/// Defines <see cref="IniKey">key's</see> name and value delimiter character.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1008:EnumsShouldHaveZeroValue",
Justification = "I'm defining and using enum values with specific characters and null character, aka '\0', has no purpose here.")]
public enum IniKeyDelimiter
{
/// <summary>
/// Use '=' as <see cref="IniKey">key's</see> name and value delimiter character.
/// </summary>
Equal = '=',
/// <summary>
/// Use ':' as <see cref="IniKey">key's</see> name and value delimiter character.
/// </summary>
Colon = ':'
}
}

View File

@ -1,26 +0,0 @@
namespace MadMilkman.Ini
{
/// <summary>
/// Defines <see cref="IniSection">section's</see> wrapper characters around its name.
/// </summary>
public enum IniSectionWrapper
{
/// <summary>
/// Use '[' and ']' as <see cref="IniSection">section's</see> wrapper characters.
/// </summary>
SquareBrackets = 0,
/// <summary>
/// Use '&lt;' and '&gt;' as <see cref="IniSection">section's</see> wrapper characters.
/// </summary>
AngleBrackets,
/// <summary>
/// Use '{' and '}' as <see cref="IniSection">section's</see> wrapper characters.
/// </summary>
CurlyBrackets,
/// <summary>
/// Use '(' and ')' as <see cref="IniSection">section's</see> wrapper characters.
/// </summary>
Parentheses
}
}

View File

@ -1,161 +0,0 @@
using System;
using System.IO;
using System.Diagnostics;
namespace MadMilkman.Ini
{
/// <summary>
/// In-memory representation of an INI file.
/// </summary>
/// <remarks>
/// <para><see cref="IniFile"/> is a central class of MadMilkman.Ini component.</para>
/// <para>To define an INI file's format use <see cref="IniOptions"/> object.</para>
/// <para>To load (read) an INI file from a file's path or a stream use <see cref="O:MadMilkman.Ini.IniFile.Load">IniFile.Load</see> methods.</para>
/// <para>To save (write) an INI file to a file's path or a stream use <see cref="O:MadMilkman.Ini.IniFile.Save">IniFile.Save</see> methods.</para>
/// <para>To view INI file's structure representation see <see href="c49dc3a5-866f-4d2d-8f89-db303aceb5fe.htm#diagram" target="_self">IniFile's Content Hierarchy Diagram</see>.</para>
/// </remarks>
/// <seealso href="c49dc3a5-866f-4d2d-8f89-db303aceb5fe.htm" target="_self">Overview</seealso>
/// <seealso href="http://en.wikipedia.org/wiki/INI_file">INI file format on Wikipedia.</seealso>
public sealed class IniFile
{
internal readonly IniOptions options;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly IniSectionCollection sections;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private IniValueMappings valueMappings;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private IniValueBinding valueBinding;
/// <summary>
/// Initializes a new instance of <see cref="IniFile"/> class.
/// </summary>
public IniFile() : this(new IniOptions()) { }
/// <summary>
/// Initializes a new instance of <see cref="IniFile"/> class.
/// </summary>
/// <param name="options"><see cref="IniOptions"/> object that defines INI file's format, settings for both <see cref="O:MadMilkman.Ini.IniFile.Load">Load</see> and <see cref="O:MadMilkman.Ini.IniFile.Save">Save</see> methods.</param>
public IniFile(IniOptions options)
{
if (options == null)
throw new ArgumentNullException("options");
this.options = new IniOptions(options);
this.sections = new IniSectionCollection(this, options.SectionDuplicate, options.SectionNameCaseSensitive);
}
/// <summary>
/// Gets file's sections.
/// </summary>
public IniSectionCollection Sections { get { return this.sections; } }
/// <summary>
/// Gets the mappings of <see cref="IniKey.Value"/>s and their results, used in <see cref="O:MadMilkman.Ini.IniKey.TryParseValue"/> methods.
/// </summary>
public IniValueMappings ValueMappings
{
get
{
if (this.valueMappings == null)
this.valueMappings = new IniValueMappings();
return this.valueMappings;
}
}
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
internal bool HasValueMappings { get { return this.valueMappings != null; } }
/// <summary>
/// Gets the object that exposes binding operations, which are executed with <see cref="O:MadMilkman.Ini.IniValueBinding.Bind"/> methods.
/// </summary>
public IniValueBinding ValueBinding
{
get
{
if (this.valueBinding == null)
this.valueBinding = new IniValueBinding(this);
return this.valueBinding;
}
}
/// <summary>
/// Loads a file from a path.
/// </summary>
/// <param name="filePath">Path from which to load a file.</param>
public void Load(string filePath)
{
if (filePath == null)
throw new ArgumentNullException("filePath");
using (Stream fileStream = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
this.Load(fileStream);
}
/// <summary>
/// Loads a file from a stream.
/// </summary>
/// <param name="fileStream">Stream from which to load a file.</param>
public void Load(Stream fileStream)
{
if (fileStream == null)
throw new ArgumentNullException("fileStream");
this.Load(new StreamReader(fileStream, this.options.Encoding));
if (fileStream.CanSeek)
fileStream.Seek(0, SeekOrigin.Begin);
}
/// <summary>
/// Loads a file from a reader.
/// </summary>
/// <param name="fileReader">Reader from which to load a file.</param>
public void Load(TextReader fileReader)
{
if (fileReader == null)
throw new ArgumentNullException("fileReader");
new IniReader(this.options).Read(this, fileReader);
}
/// <summary>
/// Saves a file to a path.
/// </summary>
/// <param name="filePath">Path to which to save a file.</param>
public void Save(string filePath)
{
if (filePath == null)
throw new ArgumentNullException("filePath");
using (Stream fileStream = File.Create(filePath))
this.Save(fileStream);
}
/// <summary>
/// Saves a file to a stream.
/// </summary>
/// <param name="fileStream">Stream to which to save a file.</param>
public void Save(Stream fileStream)
{
if (fileStream == null)
throw new ArgumentNullException("fileStream");
this.Save(new StreamWriter(fileStream, this.options.Encoding));
if (fileStream.CanSeek)
fileStream.Seek(0, SeekOrigin.Begin);
}
/// <summary>
/// Saves a file to a writer.
/// </summary>
/// <param name="fileWriter">Writer to which to save a file.</param>
public void Save(TextWriter fileWriter)
{
if (fileWriter == null)
throw new ArgumentNullException("fileWriter");
new IniWriter(this.options).Write(this, fileWriter);
}
}
}

View File

@ -1,29 +0,0 @@
using System.Diagnostics;
using System.Collections.Generic;
namespace MadMilkman.Ini
{
internal sealed class DebugCollectionViewer<T>
{
private readonly IEnumerable<T> sequence;
public DebugCollectionViewer(IEnumerable<T> sequence)
{
if (sequence == null)
throw new System.ArgumentNullException("sequence");
this.sequence = sequence;
}
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
public T[] Items
{
get
{
var collection = this.sequence as ICollection<T> ?? new List<T>(this.sequence);
var array = new T[collection.Count];
collection.CopyTo(array, 0);
return array;
}
}
}
}

View File

@ -1,4 +0,0 @@
namespace MadMilkman.Ini
{
internal interface IItemNameVerifier { bool VerifyItemName(string name); }
}

View File

@ -1,20 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<Comments>
<Comment name="AddIgnored">
<remarks>
<para>If item duplicates are <see cref="IniDuplication.Ignored">ignored</see> and this item is a duplicate, has an existing name in this collection, then it is <b>not added</b>.</para>
</remarks>
</Comment>
<Comment name="InsertIgnored">
<remarks>
<para>If item duplicates are <see cref="IniDuplication.Ignored">ignored</see> and this item is a duplicate, has an existing name in this collection, then it is <b>not inserted</b>.</para>
</remarks>
</Comment>
<Comment name="TryParseValueSupport">
<remarks>
<para>For supported types see the remarks of <see cref="IsSupportedValueType(Type)"/> method.</para>
<para>Mapped value results in <see cref="IniFile.ValueMappings"/> have priority over parsing the value.</para>
</remarks>
<seealso href="c49dc3a5-866f-4d2d-8f89-db303aceb5fe.htm#parsing" target="_self">IniKey's Value Parsing</seealso>
</Comment>
</Comments>

View File

@ -1,58 +0,0 @@
using System.Diagnostics;
namespace MadMilkman.Ini
{
/// <summary>
/// Represents a comment object used by <see cref="IniItem"/> objects, <see cref="IniSection"/> and <see cref="IniKey"/>.
/// </summary>
[DebuggerDisplay("Text = {Text}")]
public sealed class IniComment
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string text;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly IniCommentType type;
/// <summary>
/// Gets or sets the amount of empty lines before this <see cref="IniComment.Text">comment's text</see>.
/// </summary>
public int EmptyLinesBefore { get; set; }
/// <summary>
/// Gets or sets the amount of whitespace characters before this <see cref="IniComment.Text">comment's text</see>.
/// </summary>
public int LeftIndentation { get; set; }
/// <summary>
/// Gets or sets a text of this <see cref="IniComment"/> instance.
/// </summary>
/// <remarks>
/// <para>For <see cref="IniItem.LeadingComment">LeadingComment</see> text should not contain new line characters.
/// If it does, they will be replaced with a space characters.</para>
/// </remarks>
public string Text
{
get { return this.text; }
set
{
if (value != null && this.type == IniCommentType.Leading)
this.text = value.Replace("\r\n", " ")
.Replace("\n", " ")
.Replace("\r", " ");
else
this.text = value;
}
}
internal IniComment(IniCommentType type) { this.type = type; }
// Deep copy constructor.
internal IniComment(IniComment source)
{
this.text = source.text;
this.type = source.type;
this.EmptyLinesBefore = source.EmptyLinesBefore;
this.LeftIndentation = source.LeftIndentation;
}
}
}

View File

@ -1,112 +0,0 @@
using System;
using System.Diagnostics;
namespace MadMilkman.Ini
{
/// <summary>
/// Represents a base class for INI content items, <see cref="IniSection"/> and <see cref="IniKey"/>.
/// </summary>
/// <remarks>
/// <para>All INI items share the same content like <see cref="Name"/>, <see cref="LeadingComment"/> and <see cref="TrailingComment"/>.
/// These properties are defined on an <see cref="IniItem"/> class, a base class for INI content items.</para>
/// </remarks>
[DebuggerDisplay("Name = {Name}")]
public abstract class IniItem
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string name;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly IniFile parentFile;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private IniComment leadingComment;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private IniComment trailingComment;
/// <summary>
/// Gets and sets the name of the current <see cref="IniItem"/>.
/// </summary>
/// <remarks>
/// When setting <see cref="IniItem.Name"/> the value is verified by the item's <see cref="IniDuplication"/> rule.
/// </remarks>
public string Name
{
get { return this.name; }
set
{
if (this.ParentCollectionCore == null || ((IItemNameVerifier)this.ParentCollectionCore).VerifyItemName(value))
this.name = value;
}
}
/// <summary>
/// Gets or sets the amount of whitespace characters before this <see cref="IniItem.Name">item's name</see>.
/// </summary>
public int LeftIndentation { get; set; }
/// <summary>
/// Gets the <see cref="IniComment"/> object that represents a comment that follows this <see cref="IniItem"/> on the same line.
/// </summary>
public IniComment LeadingComment
{
get
{
if (this.leadingComment == null)
this.leadingComment = new IniComment(IniCommentType.Leading);
return this.leadingComment;
}
}
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
internal bool HasLeadingComment { get { return this.leadingComment != null; } }
/// <summary>
/// Gets the <see cref="IniComment"/> object that represents a comments that occur before this <see cref="IniItem"/>.
/// </summary>
public IniComment TrailingComment
{
get
{
if (this.trailingComment == null)
this.trailingComment = new IniComment(IniCommentType.Trailing);
return this.trailingComment;
}
}
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
internal bool HasTrailingComment { get { return this.trailingComment != null; } }
/// <summary>
/// Gets the <see cref="IniFile"/> to which this <see cref="IniItem"/> belongs to.
/// </summary>
public IniFile ParentFile { get { return this.parentFile; } }
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
internal object ParentCollectionCore { get; set; }
internal IniItem(IniFile parentFile, string name, IniComment trailingComment = null)
{
if (name == null)
throw new ArgumentNullException("name");
if (parentFile == null)
throw new ArgumentNullException("parentFile");
this.name = name;
this.parentFile = parentFile;
this.trailingComment = trailingComment;
}
// Deep copy constructor.
internal IniItem(IniFile parentFile, IniItem sourceItem)
{
if (parentFile == null)
throw new ArgumentNullException("parentFile");
this.name = sourceItem.name;
this.parentFile = parentFile;
if (sourceItem.HasLeadingComment)
this.leadingComment = new IniComment(sourceItem.leadingComment);
if (sourceItem.HasTrailingComment)
this.trailingComment = new IniComment(sourceItem.trailingComment);
}
}
}

View File

@ -1,211 +0,0 @@
using System;
using System.Diagnostics;
using System.Collections.Generic;
namespace MadMilkman.Ini
{
/// <summary>
/// Represents a key item of the INI file with name and value content.
/// </summary>
public sealed class IniKey : IniItem
{
/// <summary>
/// Gets and sets <see cref="IniKey"/> value.
/// </summary>
/// <seealso href="c49dc3a5-866f-4d2d-8f89-db303aceb5fe.htm#parsing" target="_self">IniKey's Value Parsing</seealso>
/// <seealso href="c49dc3a5-866f-4d2d-8f89-db303aceb5fe.htm#binding" target="_self">IniKey's Value Binding</seealso>
public string Value { get; set; }
/// <summary>
/// Gets the <see cref="IniKeyCollection"/> to which this <see cref="IniKey"/> belongs to.
/// </summary>
public IniKeyCollection ParentCollection { get { return (IniKeyCollection)this.ParentCollectionCore; } }
/// <summary>
/// Gets the <see cref="IniSection"/> to which this <see cref="IniKey"/> belongs to.
/// </summary>
public IniSection ParentSection { get { return (IniSection)((this.ParentCollectionCore != null) ? this.ParentCollection.Owner : null); } }
internal bool IsValueArray
{
get
{
return !string.IsNullOrEmpty(this.Value) &&
this.Value[0] == '{' &&
this.Value[this.Value.Length - 1] == '}';
}
}
internal string[] Values
{
get
{
var values = this.Value.Substring(1, this.Value.Length - 2).Split(',');
for (int i = 0; i < values.Length; i++)
values[i] = values[i].Trim();
return values;
}
set
{
this.Value = "{" + string.Join(",", value) + "}";
}
}
/// <summary>
/// Initializes a new instance of the <see cref="IniKey"/> class.
/// </summary>
/// <param name="parentFile">The owner file.</param>
/// <param name="name">The key's name.</param>
public IniKey(IniFile parentFile, string name) : this(parentFile, name, (string)null) { }
/// <summary>
/// Initializes a new instance of the <see cref="IniKey"/> class.
/// </summary>
/// <param name="parentFile">The owner file.</param>
/// <param name="name">The key's name.</param>
/// <param name="value">The key's value.</param>
public IniKey(IniFile parentFile, string name, string value) : base(parentFile, name) { this.Value = value; }
/// <summary>
/// Initializes a new instance of the <see cref="IniKey"/> class.
/// </summary>
/// <param name="parentFile">The owner file.</param>
/// <param name="nameValuePair">The key's data, pair of key's name and key's value.</param>
public IniKey(IniFile parentFile, KeyValuePair<string, string> nameValuePair) : base(parentFile, nameValuePair.Key) { this.Value = nameValuePair.Value; }
// Constructor used by IniReader.
internal IniKey(IniFile parentFile, string name, IniComment trailingComment)
: base(parentFile, name, trailingComment) { }
// Deep copy constructor.
internal IniKey(IniFile destinationFile, IniKey sourceKey)
: base(destinationFile, sourceKey) { this.Value = sourceKey.Value; }
/// <summary>
/// Copies this <see cref="IniKey"/> instance.
/// </summary>
/// <returns>Copied <see cref="IniKey"/>.</returns>
/// <seealso href="c49dc3a5-866f-4d2d-8f89-db303aceb5fe.htm#copying" target="_self">IniItem's Copying</seealso>
public IniKey Copy() { return this.Copy(this.ParentFile); }
/// <summary>
/// Copies this <see cref="IniKey"/> instance and sets copied instance's <see cref="IniItem.ParentFile">ParentFile</see>.
/// </summary>
/// <param name="destinationFile">Copied key's parent file.</param>
/// <returns>Copied <see cref="IniKey"/> that belongs to a specified <see cref="IniFile"/>.</returns>
/// <seealso href="c49dc3a5-866f-4d2d-8f89-db303aceb5fe.htm#copying" target="_self">IniItem's Copying</seealso>
public IniKey Copy(IniFile destinationFile) { return new IniKey(destinationFile, this); }
/// <summary>
/// Indicates whether the <see cref="IniKey.Value"/> can be converted to specified type.
/// </summary>
/// <param name="type">Type of the object to convert the <see cref="IniKey.Value"/> to.</param>
/// <returns><see langword="true"/> if the specified type is supported.</returns>
/// <remarks>
/// Currently supported types are:
/// <list type="bullet">
/// <item><description>System.Boolean</description></item>
/// <item><description>System.Byte</description></item>
/// <item><description>System.SByte</description></item>
/// <item><description>System.Int16</description></item>
/// <item><description>System.UInt16</description></item>
/// <item><description>System.Int32</description></item>
/// <item><description>System.UInt32</description></item>
/// <item><description>System.Int64</description></item>
/// <item><description>System.UInt64</description></item>
/// <item><description>System.Char</description></item>
/// <item><description>System.Single</description></item>
/// <item><description>System.Double</description></item>
/// <item><description>System.Decimal</description></item>
/// <item><description>System.DateTime</description></item>
/// <item><description>System.TimeSpan</description></item>
/// <item><description>System.Enum</description></item>
/// <item><description>System.String</description></item>
/// </list>
/// Additionally both Array and List of the above types are supported.
/// </remarks>
public static bool IsSupportedValueType(Type type)
{
if (type == null)
throw new ArgumentNullException("type");
return type.IsPrimitive ||
type.IsEnum ||
type == typeof(String) ||
type == typeof(Decimal) ||
type == typeof(DateTime) ||
type == typeof(TimeSpan) ||
(type.IsArray && IsSupportedValueType(type.GetElementType())) ||
(type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>) && IsSupportedValueType(type.GetGenericArguments()[0]));
}
/// <summary>
/// Converts the <see cref="IniKey.Value"/> to an instance of the specified type.
/// </summary>
/// <param name="result">Uninitialized instance of a specific type which will hold the converted value if the conversion succeeds.</param>
/// <typeparam name="T">Type of the object to convert the <see cref="IniKey.Value"/> to.</typeparam>
/// <returns>Value that indicates whether the conversion succeeded.</returns>
/// <include file='IniInternal\SharedDocumentationComments.xml' path='Comments/Comment[@name="TryParseValueSupport"]/*'/>
public bool TryParseValue<T>(out T result)
{
if (this.ParentFile.HasValueMappings && this.ParentFile.ValueMappings.TryGetResult<T>(this.Value, out result))
return true;
else
return IniValueParser<T>.TryParse(this.Value, out result);
}
/// <summary>
/// Converts the <see cref="IniKey.Value"/> to an array of the specified type.
/// </summary>
/// <param name="results">Uninitialized array of a specific type which will hold the converted values if the conversion succeeds.</param>
/// <typeparam name="T">Type of the objects in array to convert the <see cref="IniKey.Value"/> to.</typeparam>
/// <returns>Value that indicates whether the conversion succeeded.</returns>
/// <include file='IniInternal\SharedDocumentationComments.xml' path='Comments/Comment[@name="TryParseValueSupport"]/*'/>
public bool TryParseValue<T>(out T[] results)
{
List<T> listResults;
if (this.TryParseValue<T>(out listResults))
{
results = listResults.ToArray();
return true;
}
results = null;
return false;
}
/// <summary>
/// Converts the <see cref="IniKey.Value"/> to a list of the specified type.
/// </summary>
/// <param name="results">Uninitialized list of a specific type which will hold the converted values if the conversion succeeds.</param>
/// <typeparam name="T">Type of the objects in list to convert the <see cref="IniKey.Value"/> to.</typeparam>
/// <returns>Value that indicates whether the conversion succeeded.</returns>
/// <include file='IniInternal\SharedDocumentationComments.xml' path='Comments/Comment[@name="TryParseValueSupport"]/*'/>
public bool TryParseValue<T>(out List<T> results)
{
if (this.IsValueArray)
{
var listResults = new List<T>();
foreach (var value in this.Values)
{
T result;
if (this.ParentFile.HasValueMappings && this.ParentFile.ValueMappings.TryGetResult<T>(value, out result))
listResults.Add(result);
else if (IniValueParser<T>.TryParse(value, out result))
listResults.Add(result);
else
{
results = null;
return false;
}
}
results = listResults;
return true;
}
results = null;
return false;
}
}
}

View File

@ -1,132 +0,0 @@
using System.Diagnostics;
using System.Collections.Generic;
namespace MadMilkman.Ini
{
/// <summary>
/// Represents a section item of the INI file with name and keys content.
/// </summary>
public sealed class IniSection : IniItem
{
/// <summary>
/// Represents a section name which is used to define a global section, used for storing first keys series that don't belong to any section.
/// </summary>
/// <remarks>
/// <para>
/// If a section with this name is located as a first file's section then its name and comments are ignored.
/// If a section with this name isn't located as first file's section then it will be written with <c>MADMILKMAN_INI_FILE_GLOBAL_SECTION</c> name.
/// </para>
/// </remarks>
public const string GlobalSectionName = "MADMILKMAN_INI_FILE_GLOBAL_SECTION";
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly IniKeyCollection keys;
/// <summary>
/// Gets the <see cref="IniSection">section's</see> key collection.
/// </summary>
public IniKeyCollection Keys { get { return this.keys; } }
/// <summary>
/// Gets the <see cref="IniSectionCollection"/> to which this <see cref="IniSection"/> belongs to.
/// </summary>
public IniSectionCollection ParentCollection { get { return (IniSectionCollection)this.ParentCollectionCore; } }
/// <summary>
/// Initializes a new instance of the <see cref="IniSection"/> class.
/// </summary>
/// <param name="parentFile">The owner file.</param>
/// <param name="name">The section's name.</param>
public IniSection(IniFile parentFile, string name) : this(parentFile, name, (IEnumerable<IniKey>)null) { }
/// <summary>
/// Initializes a new instance of the <see cref="IniSection"/> class.
/// </summary>
/// <param name="parentFile">The owner file.</param>
/// <param name="name">The section's name.</param>
/// <param name="keys">The section's keys.</param>
public IniSection(IniFile parentFile, string name, params IniKey[] keys) : this(parentFile, name, (IEnumerable<IniKey>)keys) { }
/// <summary>
/// Initializes a new instance of the <see cref="IniSection"/> class.
/// </summary>
/// <param name="parentFile">The owner file.</param>
/// <param name="name">The section's name.</param>
/// <param name="nameValuePairs">The section's keys data, pairs of key's name and key's value.</param>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures",
Justification = "I don't want to use IDictionary<string, string>, there is no need for such a contract because IEnumerable<KeyValuePair<string, string>> is enough.")]
public IniSection(IniFile parentFile, string name, IEnumerable<KeyValuePair<string, string>> nameValuePairs)
: this(parentFile, name, GetIniKeysFromKeyValuePairs(parentFile, nameValuePairs)) { }
/// <summary>
/// Initializes a new instance of the <see cref="IniSection"/> class.
/// </summary>
/// <param name="parentFile">The owner file.</param>
/// <param name="name">The section's name.</param>
/// <param name="keys">The section's keys.</param>
public IniSection(IniFile parentFile, string name, IEnumerable<IniKey> keys)
: base(parentFile, name)
{
this.keys = new IniKeyCollection(parentFile, this, parentFile.options.KeyDuplicate, parentFile.options.KeyNameCaseSensitive);
if (keys != null)
foreach (IniKey key in keys)
this.keys.Add(key);
}
// Constructor used by IniReader.
internal IniSection(IniFile parentFile, string name, IniComment trailingComment)
: base(parentFile, name, trailingComment)
{
this.keys = new IniKeyCollection(parentFile, this, parentFile.options.KeyDuplicate, parentFile.options.KeyNameCaseSensitive);
}
// Deep copy constructor.
internal IniSection(IniFile destinationFile, IniSection sourceSection)
: base(destinationFile, sourceSection)
{
this.keys = new IniKeyCollection(destinationFile, this, destinationFile.options.KeyDuplicate, destinationFile.options.KeyNameCaseSensitive);
foreach (var key in sourceSection.keys)
this.keys.Add(key.Copy(destinationFile));
}
/// <summary>
/// Copies this <see cref="IniSection"/> instance.
/// </summary>
/// <returns>Copied <see cref="IniSection"/>.</returns>
/// <seealso href="c49dc3a5-866f-4d2d-8f89-db303aceb5fe.htm#copying" target="_self">IniItem's Copying</seealso>
public IniSection Copy() { return this.Copy(this.ParentFile); }
/// <summary>
/// Copies this <see cref="IniSection"/> instance and sets copied instance's <see cref="IniItem.ParentFile">ParentFile</see>.
/// </summary>
/// <param name="destinationFile">Copied section's parent file.</param>
/// <returns>Copied <see cref="IniSection"/> that belongs to a specified <see cref="IniFile"/>.</returns>
/// <seealso href="c49dc3a5-866f-4d2d-8f89-db303aceb5fe.htm#copying" target="_self">IniItem's Copying</seealso>
public IniSection Copy(IniFile destinationFile) { return new IniSection(destinationFile, this); }
/// <summary>
/// Serializes the specified object into this <see cref="IniSection"/>.
/// </summary>
/// <typeparam name="T">The type of serialized object.</typeparam>
/// <param name="source">The object to serialize.</param>
/// <seealso href="c49dc3a5-866f-4d2d-8f89-db303aceb5fe.htm#serializing" target="_self">IniSection's Object Serialization</seealso>
public void Serialize<T>(T source) where T : class, new() { IniSerializer.Serialize(source, this); }
/// <summary>
/// Deserializes this <see cref="IniSection"/> into an object of specified type.
/// </summary>
/// <typeparam name="T">The type of deserialized object.</typeparam>
/// <returns>The object being deserialized.</returns>
/// <seealso href="c49dc3a5-866f-4d2d-8f89-db303aceb5fe.htm#serializing" target="_self">IniSection's Object Serialization</seealso>
public T Deserialize<T>() where T : class, new() { return IniSerializer.Deserialize<T>(this); }
private static IEnumerable<IniKey> GetIniKeysFromKeyValuePairs(IniFile parentFile, IEnumerable<KeyValuePair<string, string>> nameValuePairs)
{
if (nameValuePairs != null)
foreach (var pair in nameValuePairs)
yield return new IniKey(parentFile, pair);
}
}
}

View File

@ -1,291 +0,0 @@
using System;
using System.Diagnostics;
using System.Collections;
using System.Collections.Generic;
namespace MadMilkman.Ini
{
/// <summary>
/// Represents a base generic class for INI content item collections, <see cref="IniSectionCollection"/> and <see cref="IniKeyCollection"/>.
/// </summary>
/// <typeparam name="T"><see cref="IniItem"/> derived type.</typeparam>
/// <seealso cref="IniItem"/>
[DebuggerDisplay("Count = {Count}"), DebuggerTypeProxy(typeof(DebugCollectionViewer<>))]
public abstract class IniItemCollection<T> : IItemNameVerifier, IList<T> where T : IniItem
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly bool caseSensitive;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly IniDuplication duplication;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly IList<T> items;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly IniFile parentFile;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly IniItem owner;
/// <exclude/>
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
protected IniFile ParentFile { get { return this.parentFile; } }
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
internal IniItem Owner { get { return this.owner; } }
///
/// <summary>
/// Gets the number of items in this collection.
/// </summary>
public int Count { get { return this.items.Count; } }
internal IniItemCollection(IniFile parentFile, IniItem owner, IniDuplication duplication, bool caseSensitive)
{
this.caseSensitive = caseSensitive;
this.duplication = duplication;
this.parentFile = parentFile;
this.owner = owner;
this.items = new List<T>();
}
/// <summary>
/// Adds an item to the end of this collection.
/// </summary>
/// <param name="item">Item to add to this collection.</param>
/// <include file='IniInternal\SharedDocumentationComments.xml' path='Comments/Comment[@name="AddIgnored"]/*'/>
public void Add(T item)
{
if (this.VerifyItem(item))
this.items.Add(item);
}
/// <summary>
/// Removes all items from this collection.
/// </summary>
public void Clear()
{
foreach (var item in this.items)
item.ParentCollectionCore = null;
this.items.Clear();
}
/// <summary>
/// Determines whether an item is in this collection.
/// </summary>
/// <param name="item">Item to locate in this collection.</param>
/// <returns><see langword="true"/> if the specified item is in the collection.</returns>
public bool Contains(T item) { return this.items.Contains(item); }
/// <summary>
/// Determines whether an item is in this collection.
/// </summary>
/// <param name="name">Name of the item to locate in this collection.</param>
/// <returns><see langword="true"/> if the item with specified name is in the collection.</returns>
public bool Contains(string name) { return this.GetItemIndexByName(name) != -1; }
/// <summary>
/// Shallow copies the items of this collection to an array.
/// </summary>
/// <param name="array">One-dimensional array that is the destination of the items copied from this collection.</param>
/// <param name="arrayIndex">Zero-based index in array at which copying begins.</param>
public void CopyTo(T[] array, int arrayIndex) { this.items.CopyTo(array, arrayIndex); }
/// <summary>
/// Searches for the specified item and returns the zero-based index of the first occurrence within this collection.
/// </summary>
/// <param name="item">Item to locate in this collection.</param>
/// <returns>Index of the first occurrence of specified item in the collection.</returns>
public int IndexOf(T item) { return this.items.IndexOf(item); }
/// <summary>
/// Searches for the specified item and returns the zero-based index of the first occurrence within this collection.
/// </summary>
/// <param name="name">Name of the item to locate in this collection.</param>
/// <returns>Index of the first occurrence of the item with specified name in the collection.</returns>
public int IndexOf(string name) { return this.GetItemIndexByName(name); }
/// <summary>
/// Inserts an item to this collection at the specified index.
/// </summary>
/// <param name="index">Zero-based index at which item should be inserted.</param>
/// <param name="item">Item to insert to this collection.</param>
/// <include file='IniInternal\SharedDocumentationComments.xml' path='Comments/Comment[@name="InsertIgnored"]/*'/>
public void Insert(int index, T item)
{
if (this.VerifyItem(item))
this.items.Insert(index, item);
}
/// <summary>
/// Removes the first occurrence of specific item from this collection.
/// </summary>
/// <param name="item">Item to remove from this collection.</param>
/// <returns><see langword="true"/> if the specified item is removed from the collection.</returns>
public bool Remove(T item)
{
if (!this.items.Remove(item))
return false;
item.ParentCollectionCore = null;
return true;
}
/// <summary>
/// Removes the first occurrence of specific item from this collection.
/// </summary>
/// <param name="name">Name of the item to remove from this collection.</param>
/// <returns><see langword="true"/> if the item with specified name is removed from the collection.</returns>
public bool Remove(string name)
{
int index = this.GetItemIndexByName(name);
if (index == -1)
return false;
this.items.RemoveAt(index);
return true;
}
/// <summary>
/// Removes an item at the specified index from this collection.
/// </summary>
/// <param name="index">Zero-based index at which item should be inserted.</param>
public void RemoveAt(int index)
{
this.items[index].ParentCollectionCore = null;
this.items.RemoveAt(index);
}
/// <summary>
/// Gets or sets the item at the specified index.
/// </summary>
/// <param name="index">Zero-based index of the item to get or set.</param>
/// <remarks>
/// If item duplicates are <see cref="IniDuplication.Ignored">ignored</see> and value is a duplicate item, has an existing name in this collection, then this value <b>is ignored</b>.
/// </remarks>
public T this[int index]
{
get { return this.items[index]; }
set
{
if (this.VerifyItem(value))
{
this.items[index].ParentCollectionCore = null;
this.items[index] = value;
}
}
}
/// <summary>
/// Gets the first item of the specified name.
/// </summary>
/// <param name="name">Name of the item to get.</param>
/// <remarks>If item with the specified name doesn't exist a <see langword="null"/> value is returned.</remarks>
public T this[string name]
{
get
{
int index = this.GetItemIndexByName(name);
return (index != -1) ? this.items[index] : null;
}
}
/// <summary>
/// Gets the first items of the specified names.
/// </summary>
/// <param name="names">Names of the items to get.</param>
/// <remarks>If item with any specified name doesn't exist a <see langword="null"/> value is returned in its place.</remarks>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1043:UseIntegralOrStringArgumentForIndexers",
Justification = "I believe that this non-standard indexer can provide some useful data store access.")]
public IEnumerable<T> this[params string[] names]
{
get
{
var returnedNames = new Dictionary<string, int>();
int index;
for (int i = 0; i < names.Length; i++)
{
string name = names[i];
if (returnedNames.TryGetValue(name, out index))
{
if (index != -1)
{
index = GetItemIndexByName(name, index + 1);
returnedNames[name] = index;
}
}
else
{
index = GetItemIndexByName(name);
returnedNames.Add(name, index);
}
yield return (index != -1) ? this.items[index] : null;
}
}
}
/// <summary>
/// Returns an enumerator that iterates through the collection.
/// </summary>
/// <returns><see cref="IEnumerator{T}"/> object that can be used to iterate through the collection.</returns>
public IEnumerator<T> GetEnumerator() { return this.items.GetEnumerator(); }
private int GetItemIndexByName(string name, int startIndex = 0)
{
var iniItems = (IEnumerable<IniItem>)this.items;
int index = 0;
foreach (var item in iniItems)
{
if (index >= startIndex &&
item.Name.Equals(name, (this.caseSensitive) ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase))
return index;
else
index++;
}
return -1;
}
private bool VerifyItem(IniItem item)
{
if (item == null)
throw new ArgumentNullException("item");
if (item.ParentFile != this.parentFile)
throw new InvalidOperationException();
if (item.ParentCollectionCore != null)
throw new InvalidOperationException();
if (!this.VerifyItemName(item.Name))
return false;
item.ParentCollectionCore = this;
return true;
}
private bool VerifyItemName(string name) { return ((IItemNameVerifier)this).VerifyItemName(name); }
bool IItemNameVerifier.VerifyItemName(string name)
{
if (this.duplication != IniDuplication.Allowed && this.Contains(name))
{
if (this.duplication == IniDuplication.Disallowed)
throw new InvalidOperationException();
return false;
}
return true;
}
/// <exclude/>
IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); }
/// <exclude/>
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
bool ICollection<T>.IsReadOnly { get { return false; } }
}
}

View File

@ -1,77 +0,0 @@
using System.Collections.Generic;
namespace MadMilkman.Ini
{
/// <summary>
/// Represents a collection of <see cref="IniKey"/> items.
/// </summary>
/// <seealso cref="IniKey"/>
public sealed class IniKeyCollection : IniItemCollection<IniKey>
{
internal IniKeyCollection(IniFile parentFile, IniSection parentSection, IniDuplication duplication, bool caseSensitive)
: base(parentFile, parentSection, duplication, caseSensitive) { }
/// <summary>
/// Adds an item to the end of this collection.
/// </summary>
/// <param name="name">Name of the <see cref="IniKey"/> to add to this collection.</param>
/// <returns><see cref="IniKey"/> that was added to this collection.</returns>
/// <include file='IniInternal\SharedDocumentationComments.xml' path='Comments/Comment[@name="AddIgnored"]/*'/>
public IniKey Add(string name) { return this.Add(name, null); }
/// <summary>
/// Adds an item to the end of this collection.
/// </summary>
/// <param name="nameValuePair">The key's data, pair of key's name and key's value, to add to this collection.</param>
/// <returns><see cref="IniKey"/> that was added to this collection.</returns>
/// <include file='IniInternal\SharedDocumentationComments.xml' path='Comments/Comment[@name="AddIgnored"]/*'/>
public IniKey Add(KeyValuePair<string, string> nameValuePair) { return this.Add(nameValuePair.Key, nameValuePair.Value); }
/// <summary>
/// Adds an item to the end of this collection.
/// </summary>
/// <param name="name">Name of the <see cref="IniKey"/> to add to this collection.</param>
/// <param name="value">Value of the <see cref="IniKey"/> to add to this collection.</param>
/// <returns><see cref="IniKey"/> that was added to this collection.</returns>
/// <include file='IniInternal\SharedDocumentationComments.xml' path='Comments/Comment[@name="AddIgnored"]/*'/>
public IniKey Add(string name, string value)
{
var key = new IniKey(this.ParentFile, name, value);
this.Add(key);
return key;
}
/// <summary>
/// Inserts an item to this collection at the specified index.
/// </summary>
/// <param name="index">Zero-based index at which item should be inserted.</param>
/// <param name="name">Name of the <see cref="IniKey"/> to insert to this collection.</param>
/// <returns><see cref="IniKey"/> that was inserted to this collection.</returns>
/// <include file='IniInternal\SharedDocumentationComments.xml' path='Comments/Comment[@name="InsertIgnored"]/*'/>
public IniKey Insert(int index, string name) { return this.Insert(index, name, null); }
/// <summary>
/// Inserts an item to this collection at the specified index.
/// </summary>
/// <param name="index">Zero-based index at which item should be inserted.</param>
/// <param name="nameValuePair">The key's data, pair of key's name and key's value, to insert to this collection.</param>
/// <returns><see cref="IniKey"/> that was inserted to this collection.</returns>
/// <include file='IniInternal\SharedDocumentationComments.xml' path='Comments/Comment[@name="InsertIgnored"]/*'/>
public IniKey Insert(int index, KeyValuePair<string, string> nameValuePair){ return this.Insert(index, nameValuePair.Key, nameValuePair.Value); }
/// <summary>
/// Inserts an item to this collection at the specified index.
/// </summary>
/// <param name="index">Zero-based index at which item should be inserted.</param>
/// <param name="name">Name of the <see cref="IniKey"/> to insert to this collection.</param>
/// <param name="value">Value of the <see cref="IniKey"/> to insert to this collection.</param>
/// <returns><see cref="IniKey"/> that was inserted to this collection.</returns>
/// <include file='IniInternal\SharedDocumentationComments.xml' path='Comments/Comment[@name="InsertIgnored"]/*'/>
public IniKey Insert(int index, string name, string value)
{
var key = new IniKey(this.ParentFile, name, value);
this.Insert(index, key);
return key;
}
}
}

View File

@ -1,64 +0,0 @@
using System.Collections.Generic;
namespace MadMilkman.Ini
{
/// <summary>
/// Represents a collection of <see cref="IniSection"/> items.
/// </summary>
/// <seealso cref="IniSection"/>
public sealed class IniSectionCollection : IniItemCollection<IniSection>
{
internal IniSectionCollection(IniFile parentFile, IniDuplication duplication, bool caseSensitive)
: base(parentFile, null, duplication, caseSensitive) { }
/// <summary>
/// Adds an item to the end of this collection.
/// </summary>
/// <param name="name">Name of the <see cref="IniSection"/> to add to this collection.</param>
/// <returns><see cref="IniSection"/> that was added to this collection.</returns>
/// <include file='IniInternal\SharedDocumentationComments.xml' path='Comments/Comment[@name="AddIgnored"]/*'/>
public IniSection Add(string name) { return this.Add(name, null); }
/// <summary>
/// Adds an item to the end of this collection.
/// </summary>
/// <param name="name">Name of the <see cref="IniSection"/> to add to this collection.</param>
/// <param name="nameValuePairs">The section's keys data, pairs of key's name and key's value, to add to this collection.</param>
/// <returns><see cref="IniSection"/> that was added to this collection.</returns>
/// <include file='IniInternal\SharedDocumentationComments.xml' path='Comments/Comment[@name="AddIgnored"]/*'/>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures",
Justification = "I don't want to use IDictionary<string, string>, there is no need for such a contract because IEnumerable<KeyValuePair<string, string>> is enough.")]
public IniSection Add(string name, IEnumerable<KeyValuePair<string, string>> nameValuePairs)
{
var section = new IniSection(this.ParentFile, name, nameValuePairs);
this.Add(section);
return section;
}
/// <summary>
/// Inserts an item to this collection at the specified index.
/// </summary>
/// <param name="index">Zero-based index at which item should be inserted.</param>
/// <param name="name">Name of the <see cref="IniSection"/> to insert to this collection.</param>
/// <returns><see cref="IniSection"/> that was inserted to this collection.</returns>
/// <include file='IniInternal\SharedDocumentationComments.xml' path='Comments/Comment[@name="InsertIgnored"]/*'/>
public IniSection Insert(int index, string name) { return this.Insert(index, name, null); }
/// <summary>
/// Inserts an item to this collection at the specified index.
/// </summary>
/// <param name="index">Zero-based index at which item should be inserted.</param>
/// <param name="name">Name of the <see cref="IniSection"/> to insert to this collection.</param>
/// <param name="nameValuePairs">The section's keys data, pairs of key's name and key's value, to insert to this collection.</param>
/// <returns><see cref="IniSection"/> that was inserted to this collection.</returns>
/// <include file='IniInternal\SharedDocumentationComments.xml' path='Comments/Comment[@name="InsertIgnored"]/*'/>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures",
Justification = "I don't want to use IDictionary<string, string>, there is no need for such a contract because IEnumerable<KeyValuePair<string, string>> is enough.")]
public IniSection Insert(int index, string name, IEnumerable<KeyValuePair<string, string>> nameValuePairs)
{
var section = new IniSection(this.ParentFile, name, nameValuePairs);
this.Insert(index, section);
return section;
}
}
}

View File

@ -1,213 +0,0 @@
using System.Text;
using System.Diagnostics;
namespace MadMilkman.Ini
{
/// <summary>
/// Represents a class that defines INI file's format, stores properties used for both reading and writing a file.
/// </summary>
/// <remarks>
/// <para>After an instance of this class is passed to an <see cref="IniFile"/> constructor, further changes on that instance's properties will have no effect.</para>
/// <list type="table">
/// <listheader>
/// <term>Property</term>
/// <description>Default Value</description>
/// </listheader>
/// <item>
/// <term><see cref="IniOptions.CommentStarter">CommentStarter</see></term>
/// <description><see cref="IniCommentStarter.Semicolon"/></description>
/// </item>
/// <item>
/// <term><see cref="IniOptions.CommentStarter">Compression</see></term>
/// <description><see langword="false"/></description>
/// </item>
/// <item>
/// <term><see cref="IniOptions.CommentStarter">EncryptionPassword</see></term>
/// <description><see langword="null"/></description>
/// </item>
/// <item>
/// <term><see cref="IniOptions.Encoding">Encoding</see></term>
/// <description><see cref="System.Text.Encoding.ASCII">Encoding.ASCII</see></description>
/// </item>
/// <item>
/// <term><see cref="IniOptions.KeyDelimiter">KeyDelimiter</see></term>
/// <description><see cref="IniKeyDelimiter.Equal"/></description>
/// </item>
/// <item>
/// <term><see cref="IniOptions.KeyDuplicate">KeyDuplicate</see></term>
/// <description><see cref="IniDuplication.Allowed"/></description>
/// </item>
/// <item>
/// <term><see cref="IniOptions.KeyNameCaseSensitive">KeyNameCaseSensitive</see></term>
/// <description><see langword="false"/></description>
/// </item>
/// <item>
/// <term><see cref="IniOptions.KeySpaceAroundDelimiter">KeySpaceAroundDelimiter</see></term>
/// <description><see langword="false"/></description>
/// </item>
/// <item>
/// <term><see cref="IniOptions.SectionDuplicate">SectionDuplicate</see></term>
/// <description><see cref="IniDuplication.Allowed"/></description>
/// </item>
/// <item>
/// <term><see cref="IniOptions.SectionNameCaseSensitive">SectionNameCaseSensitive</see></term>
/// <description><see langword="false"/></description>
/// </item>
/// <item>
/// <term><see cref="IniOptions.SectionWrapper">SectionWrapper</see></term>
/// <description><see cref="IniSectionWrapper.SquareBrackets"/></description>
/// </item>
/// </list>
/// </remarks>
public sealed class IniOptions
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private Encoding encoding;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private IniSectionWrapper sectionWrapper;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
internal char sectionWrapperStart;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
internal char sectionWrapperEnd;
/// <summary>
/// Gets or sets encoding for reading and writing an INI file.
/// </summary>
/// <remarks>
/// Value should not be <see langword="null"/>, if it is then a default <see cref="System.Text.Encoding.ASCII">Encoding.ASCII</see> value will be used.
/// </remarks>
public Encoding Encoding
{
get { return this.encoding; }
set
{
if (value == null)
this.encoding = Encoding.ASCII;
this.encoding = value;
}
}
/// <summary>
/// Gets or sets comments starting character.
/// </summary>
public IniCommentStarter CommentStarter { get; set; }
/// <summary>
/// <para>Gets or sets a value indicating if file's size is reduced.</para>
/// <para>If <see langword="true"/> file is decompressed on Load and compressed on Save.</para>
/// </summary>
public bool Compression { get; set; }
/// <summary>
/// <para>Gets or sets an INI file's protection password.</para>
/// <para>File is decrypted on Load and encrypted on Save if a password is not <see langword="null"/> or <see cref="System.String.Empty"/>.</para>
/// </summary>
public string EncryptionPassword { get; set; }
/// <summary>
/// Gets or sets keys name and value delimiter character.
/// </summary>
public IniKeyDelimiter KeyDelimiter { get; set; }
/// <summary>
/// Gets or sets a value indicating whether keys with same name are allowed, disallowed or ignored.
/// </summary>
public IniDuplication KeyDuplicate { get; set; }
/// <summary>
/// Gets or sets a value indicating whether keys name are case sensitive.
/// </summary>
public bool KeyNameCaseSensitive { get; set; }
/// <summary>
/// Gets or sets a value indicating whether space is written around the keys delimiter.
/// </summary>
public bool KeySpaceAroundDelimiter { get; set; }
/// <summary>
/// Gets or sets a value indicating whether sections with same name are allowed, disallowed or ignored.
/// </summary>
public IniDuplication SectionDuplicate { get; set; }
/// <summary>
/// Gets or sets a value indicating whether sections name are case sensitive.
/// </summary>
public bool SectionNameCaseSensitive { get; set; }
/// <summary>
/// Gets or sets wrapper characters of sections name.
/// </summary>
public IniSectionWrapper SectionWrapper
{
get { return this.sectionWrapper; }
set
{
this.sectionWrapper = value;
this.SectionWrapperToCharacters(out this.sectionWrapperStart, out this.sectionWrapperEnd);
}
}
/// <summary>
/// Initializes a new instance of the <see cref="IniOptions"/> class.
/// </summary>
public IniOptions()
{
this.encoding = Encoding.ASCII;
this.CommentStarter = IniCommentStarter.Semicolon;
this.Compression = false;
this.EncryptionPassword = null;
this.KeyDelimiter = IniKeyDelimiter.Equal;
this.KeyDuplicate = IniDuplication.Allowed;
this.KeyNameCaseSensitive = false;
this.KeySpaceAroundDelimiter = false;
this.SectionDuplicate = IniDuplication.Allowed;
this.SectionNameCaseSensitive = false;
this.SectionWrapper = IniSectionWrapper.SquareBrackets;
}
// Deep copy constructor.
internal IniOptions(IniOptions options)
{
this.encoding = options.encoding;
this.CommentStarter = options.CommentStarter;
this.Compression = options.Compression;
this.EncryptionPassword = options.EncryptionPassword;
this.KeyDelimiter = options.KeyDelimiter;
this.KeyDuplicate = options.KeyDuplicate;
this.KeyNameCaseSensitive = options.KeyNameCaseSensitive;
this.KeySpaceAroundDelimiter = options.KeySpaceAroundDelimiter;
this.SectionDuplicate = options.SectionDuplicate;
this.SectionNameCaseSensitive = options.SectionNameCaseSensitive;
this.SectionWrapper = options.SectionWrapper;
}
/* REMARKS: ToChar(bool) extension method on IniSectionWrapper would be nice, but in order to define
* an extension method in .NET 2.0 we need to declare ExtensionAttribute our self.
*
* Changing SectionWrapperToCharacters method's return type to Tuple<char, char> would be nice,
* but writing our own Tuple implementation for .NET 2.0 is an unnecessary overhead. */
private void SectionWrapperToCharacters(out char startCharacter, out char endCharacte)
{
switch (this.sectionWrapper)
{
case IniSectionWrapper.AngleBrackets:
startCharacter = '<';
endCharacte = '>';
break;
case IniSectionWrapper.CurlyBrackets:
startCharacter = '{';
endCharacte = '}';
break;
case IniSectionWrapper.Parentheses:
startCharacter = '(';
endCharacte = ')';
break;
default:
startCharacter = '[';
endCharacte = ']';
break;
}
}
}
}

View File

@ -1,43 +0,0 @@
using System;
using System.Text;
using System.IO;
using System.IO.Compression;
namespace MadMilkman.Ini
{
internal static class IniCompressor
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope",
Justification = "MemoryStream doesn't have unmanaged resources.")]
public static string Compress(string text, Encoding encoding)
{
byte[] content = encoding.GetBytes(text);
var stream = new MemoryStream();
using (var compressor = new GZipStream(stream, CompressionMode.Compress, true))
compressor.Write(content, 0, content.Length);
byte[] compressedContent = new byte[stream.Length + 4];
stream.Position = 0;
stream.Read(compressedContent, 4, compressedContent.Length - 4);
Buffer.BlockCopy(BitConverter.GetBytes(content.Length), 0, compressedContent, 0, 4);
return Convert.ToBase64String(compressedContent);
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope",
Justification = "MemoryStream doesn't have unmanaged resources.")]
public static string Decompress(string text, Encoding encoding)
{
byte[] compressedContent = Convert.FromBase64String(text);
var stream = new MemoryStream(compressedContent, 4, compressedContent.Length - 4);
byte[] content = new byte[BitConverter.ToInt32(compressedContent, 0)];
stream.Position = 0;
using (var decompressor = new GZipStream(stream, CompressionMode.Decompress, false))
decompressor.Read(content, 0, content.Length);
return encoding.GetString(content);
}
}
}

View File

@ -1,58 +0,0 @@
using System;
using System.Text;
using System.IO;
using System.Security.Cryptography;
namespace MadMilkman.Ini
{
internal static class IniEncryptor
{
/* REMARKS: RijndaelManaged
* - KeySize - BlockSize
* DEFAULT = 256 DEFAULT = 128
* MIN = 128 MIN = 128
* MAX = 256 MAX = 256
*
* - InitializationVector.Length
* MUST = RijndaelManaged.BlockSize / 8
*
* - key.Length
* MUST = RijndaelManaged.KeySize / 8 */
private static readonly byte[] InitializationVector = { 77, 52, 225, 184, 143, 77, 49, 225, 184, 187, 107, 77, 52, 225, 185, 137 };
private static readonly byte[] Salt = { 49, 110, 49, 102, 49, 108, 51, 39, 53, 95, 53, 52, 108, 55, 95, 118, 52, 108, 117, 51 };
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope",
Justification = "MemoryStream doesn't have unmanaged resources.")]
public static string Encrypt(string text, string passwordPhrase, Encoding encoding)
{
byte[] content = encoding.GetBytes(text);
byte[] key = new Rfc2898DeriveBytes(passwordPhrase, IniEncryptor.Salt, 1000).GetBytes(32);
var stream = new MemoryStream();
using (var rijndaelAlgorithm = new RijndaelManaged())
using (var encryptor = rijndaelAlgorithm.CreateEncryptor(key, IniEncryptor.InitializationVector))
using (var cryptoStream = new CryptoStream(stream, encryptor, CryptoStreamMode.Write))
cryptoStream.Write(content, 0, content.Length);
return Convert.ToBase64String(stream.ToArray());
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope",
Justification = "MemoryStream doesn't have unmanaged resources.")]
public static string Decrypt(string text, string passwordPhrase, Encoding encoding)
{
byte[] encryptedContent = Convert.FromBase64String(text);
byte[] key = new Rfc2898DeriveBytes(passwordPhrase, IniEncryptor.Salt, 1000).GetBytes(32);
byte[] content = new byte[encryptedContent.Length];
int contentCount;
using (var rijndaelAlgorithm = new RijndaelManaged())
using (var decryptor = rijndaelAlgorithm.CreateDecryptor(key, IniEncryptor.InitializationVector))
using (var cryptoStream = new CryptoStream(new MemoryStream(encryptedContent), decryptor, CryptoStreamMode.Read))
contentCount = cryptoStream.Read(content, 0, content.Length);
return encoding.GetString(content, 0, contentCount);
}
}
}

View File

@ -1,197 +0,0 @@
using System;
using System.IO;
namespace MadMilkman.Ini
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1001:TypesThatOwnDisposableFieldsShouldBeDisposable",
Justification = "StringReader doesn't have unmanaged resources.")]
internal sealed class IniReader
{
private readonly IniOptions options;
private TextReader reader;
private int currentEmptyLinesBefore;
private IniComment currentTrailingComment;
private IniSection currentSection;
public IniReader(IniOptions options)
{
this.options = options;
this.currentEmptyLinesBefore = 0;
this.currentTrailingComment = null;
this.currentSection = null;
}
public void Read(IniFile iniFile, TextReader textReader)
{
this.reader = new StringReader(this.DecompressAndDecryptText(textReader.ReadToEnd()));
string line;
while ((line = this.reader.ReadLine()) != null)
{
if (line.Trim().Length == 0)
this.currentEmptyLinesBefore++;
else
this.ReadLine(line, iniFile);
}
}
private string DecompressAndDecryptText(string fileContent)
{
if (this.options.Compression)
fileContent = IniCompressor.Decompress(fileContent, this.options.Encoding);
if (!string.IsNullOrEmpty(this.options.EncryptionPassword))
fileContent = IniEncryptor.Decrypt(fileContent, this.options.EncryptionPassword, this.options.Encoding);
return fileContent;
}
private void ReadLine(string line, IniFile file)
{
/* REMARKS: All 'whitespace' and 'tab' characters increase the LeftIndention by 1.
*
* CONSIDER: Implement different processing of 'tab' characters. They are often represented as 4 spaces,
* or they can stretch to a next 'tab stop' position which occurs each 8 characters:
* 0 8 16
* |.......|.......|... */
// Index of first non 'whitespace' character.
int startIndex = Array.FindIndex(line.ToCharArray(), c => !(char.IsWhiteSpace(c) || c == '\t'));
char startCharacter = line[startIndex];
if (startCharacter == (char)this.options.CommentStarter)
this.ReadTrailingComment(startIndex, line.Substring(++startIndex));
else if (startCharacter == this.options.sectionWrapperStart)
this.ReadSection(startIndex, line, file);
else
this.ReadKey(startIndex, line, file);
this.currentEmptyLinesBefore = 0;
}
private void ReadTrailingComment(int leftIndention, string text)
{
if (this.currentTrailingComment == null)
this.currentTrailingComment = new IniComment(IniCommentType.Trailing)
{
EmptyLinesBefore = this.currentEmptyLinesBefore,
LeftIndentation = leftIndention,
Text = text
};
else
this.currentTrailingComment.Text += Environment.NewLine + text;
}
/* MZ(2015-08-29): Added support for section names that may contain end wrapper or comment starter characters. */
private void ReadSection(int leftIndention, string line, IniFile file)
{
int sectionEndIndex = -1, potentialCommentIndex, tempIndex = leftIndention;
while (tempIndex != -1 && ++tempIndex <= line.Length)
{
potentialCommentIndex = line.IndexOf((char)this.options.CommentStarter, tempIndex);
if (potentialCommentIndex != -1)
sectionEndIndex = line.LastIndexOf(this.options.sectionWrapperEnd, potentialCommentIndex - 1, potentialCommentIndex - tempIndex);
else
sectionEndIndex = line.LastIndexOf(this.options.sectionWrapperEnd, line.Length - 1, line.Length - tempIndex);
if (sectionEndIndex != -1)
break;
else
tempIndex = potentialCommentIndex;
}
if (sectionEndIndex != -1)
{
this.currentSection = new IniSection(file,
line.Substring(leftIndention + 1, sectionEndIndex - leftIndention - 1),
this.currentTrailingComment)
{
LeftIndentation = leftIndention,
LeadingComment = { EmptyLinesBefore = this.currentEmptyLinesBefore }
};
file.Sections.Add(this.currentSection);
if (++sectionEndIndex < line.Length)
this.ReadSectionLeadingComment(line.Substring(sectionEndIndex));
}
this.currentTrailingComment = null;
}
private void ReadSectionLeadingComment(string lineLeftover)
{
// Index of first non 'whitespace' character.
int leftIndention = Array.FindIndex(lineLeftover.ToCharArray(), c => !(char.IsWhiteSpace(c) || c == '\t'));
if (leftIndention != -1 && lineLeftover[leftIndention] == (char)this.options.CommentStarter)
{
var leadingComment = this.currentSection.LeadingComment;
leadingComment.Text = lineLeftover.Substring(leftIndention + 1);
leadingComment.LeftIndentation = leftIndention;
}
}
private void ReadKey(int leftIndention, string line, IniFile file)
{
int keyDelimiterIndex = line.IndexOf((char)this.options.KeyDelimiter, leftIndention);
if (keyDelimiterIndex != -1)
{
if (this.currentSection == null)
this.currentSection = file.Sections.Add(IniSection.GlobalSectionName);
var currentKey = new IniKey(file,
line.Substring(leftIndention, keyDelimiterIndex - leftIndention).TrimEnd(),
this.currentTrailingComment)
{
LeftIndentation = leftIndention,
LeadingComment = { EmptyLinesBefore = this.currentEmptyLinesBefore }
};
this.currentSection.Keys.Add(currentKey);
this.ReadValue(line.Substring(++keyDelimiterIndex).TrimStart(), currentKey);
}
this.currentTrailingComment = null;
}
private void ReadValue(string lineLeftover, IniKey key)
{
int valueEndIndex = lineLeftover.IndexOf((char)this.options.CommentStarter);
if (valueEndIndex == -1)
key.Value = lineLeftover.TrimEnd();
else if (valueEndIndex == 0)
key.Value = key.LeadingComment.Text = string.Empty;
else
this.ReadValueLeadingComment(lineLeftover, valueEndIndex, key);
}
/* MZ(2016-02-23): Added support for quoted values which can contain comment's starting characters. */
private void ReadValueLeadingComment(string lineLeftover, int potentialCommentIndex, IniKey key)
{
int quoteEndIndex = lineLeftover.IndexOf('"', 1);
if (lineLeftover[0] == '"' && quoteEndIndex != -1)
while (quoteEndIndex > potentialCommentIndex && potentialCommentIndex != -1)
potentialCommentIndex = lineLeftover.IndexOf((char)this.options.CommentStarter, ++potentialCommentIndex);
if (potentialCommentIndex == -1)
key.Value = lineLeftover.TrimEnd();
else
{
key.LeadingComment.Text = lineLeftover.Substring(potentialCommentIndex + 1);
// The amount of 'whitespace' characters between key's value and comment's starting character.
int leftIndention = 0;
while (lineLeftover[--potentialCommentIndex] == ' ' || lineLeftover[potentialCommentIndex] == '\t')
leftIndention++;
key.LeadingComment.LeftIndentation = leftIndention;
key.Value = lineLeftover.Substring(0, ++potentialCommentIndex);
}
}
}
}

View File

@ -1,128 +0,0 @@
using System;
using System.IO;
namespace MadMilkman.Ini
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1001:TypesThatOwnDisposableFieldsShouldBeDisposable",
Justification = "StringWriter doesn't have unmanaged resources.")]
internal sealed class IniWriter
{
private static readonly string[] NewLines = { "\r\n", "\n", "\r" };
private readonly IniOptions options;
private TextWriter writer;
public IniWriter(IniOptions options) { this.options = options; }
public void Write(IniFile iniFile, TextWriter textWriter)
{
this.writer = new StringWriter(System.Globalization.CultureInfo.InvariantCulture);
this.WriteSections(iniFile.Sections);
textWriter.Write(this.EncryptAndCompressText(this.writer.ToString()));
textWriter.Flush();
}
private string EncryptAndCompressText(string fileContent)
{
if (!string.IsNullOrEmpty(this.options.EncryptionPassword))
fileContent = IniEncryptor.Encrypt(fileContent, this.options.EncryptionPassword, this.options.Encoding);
if (this.options.Compression)
fileContent = IniCompressor.Compress(fileContent, this.options.Encoding);
return fileContent;
}
private void WriteSections(IniSectionCollection sections)
{
if (sections.Count == 0)
return;
this.WriteFirstSection(sections[0]);
for (int i = 1; i < sections.Count; i++)
this.WriteSection(sections[i]);
}
private void WriteFirstSection(IniSection section)
{
if (section.Name.Equals(IniSection.GlobalSectionName))
this.WriteKeys(section.Keys);
else
this.WriteSection(section);
}
private void WriteSection(IniSection section)
{
this.WriteItem(section,
// E.g. " [SectionName]"
new String(' ', section.LeftIndentation) +
this.options.sectionWrapperStart +
section.Name +
this.options.sectionWrapperEnd);
this.WriteKeys(section.Keys);
}
private void WriteKeys(IniKeyCollection keys)
{
foreach (IniKey key in keys)
this.WriteItem(key,
// E.g. " KeyName = KeyValue"
new String(' ', key.LeftIndentation) +
key.Name +
((this.options.KeySpaceAroundDelimiter) ? " " : string.Empty) +
(char)this.options.KeyDelimiter +
((this.options.KeySpaceAroundDelimiter) ? " " : string.Empty) +
key.Value);
}
private void WriteItem(IniItem item, string itemContent)
{
if (item.HasTrailingComment)
this.WriteTrailingComment(item.TrailingComment);
if (item.HasLeadingComment)
this.WriteEmptyLines(item.LeadingComment.EmptyLinesBefore);
this.writer.Write(itemContent);
if (item.HasLeadingComment)
this.WriteLeadingComment(item.LeadingComment);
else
this.writer.WriteLine();
}
private void WriteTrailingComment(IniComment trailingComment)
{
this.WriteEmptyLines(trailingComment.EmptyLinesBefore);
// E.g. " ;CommentText
// ;CommentText"
if (trailingComment.Text != null)
foreach (string commentLine in trailingComment.Text.Split(IniWriter.NewLines, StringSplitOptions.None))
this.writer.WriteLine(
new String(' ', trailingComment.LeftIndentation) +
(char)this.options.CommentStarter +
commentLine);
}
private void WriteLeadingComment(IniComment leadingComment)
{
// E.g. " ;CommentText"
if (leadingComment.Text != null)
this.writer.WriteLine(
new String(' ', leadingComment.LeftIndentation) +
(char)this.options.CommentStarter +
leadingComment.Text);
else
this.writer.WriteLine();
}
private void WriteEmptyLines(int count)
{
for (int i = 0; i < count; i++)
this.writer.WriteLine();
}
}
}

View File

@ -1,34 +0,0 @@
using System;
namespace MadMilkman.Ini
{
/// <summary>
/// Indicates the behavior of public property when serializing or deserializing the object that contains it.
/// </summary>
[AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
public sealed class IniSerializationAttribute : Attribute
{
/// <summary>
/// Gets the <see cref="IniKey"/> name of serialized the property.
/// </summary>
public string Alias { get; private set; }
/// <summary>
/// Gets the value indicating whether serialization is ignored.
/// </summary>
public bool Ignore { get; private set; }
/// <summary>
/// Initializes a new instance of the IniSerializationAttribute class and specifies the <see cref="IniKey"/>'s name.
/// </summary>
/// <param name="alias">The name of the generated <see cref="IniKey"/>.</param>
public IniSerializationAttribute(string alias) { this.Alias = alias; }
/// <summary>
/// Initializes a new instance of the IniSerializationAttribute class and specifies if serialization is ignored.
/// </summary>
/// <param name="ignore">The value indicating whether serialization is ignored.</param>
public IniSerializationAttribute(bool ignore) { this.Ignore = ignore; }
}
}

View File

@ -1,128 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
namespace MadMilkman.Ini
{
internal static class IniSerializer
{
private static readonly Predicate<Type> PropertyTypeVerifier = IniKey.IsSupportedValueType;
public static void Serialize<T>(T source, IniSection section) where T : class, new()
{
foreach (var propertyPair in GetPropertyPairs(typeof(T)))
{
var key = section.Keys.Add(propertyPair.Key);
if (key.ParentCollectionCore != null)
SetKeyValue(propertyPair.Value, source, key);
}
}
public static T Deserialize<T>(IniSection section) where T : class, new()
{
T destination = new T();
foreach (var propertyPair in GetPropertyPairs(typeof(T)))
{
var key = section.Keys[propertyPair.Key];
if (key != null)
SetPropertyValue(propertyPair.Value, destination, key);
}
return destination;
}
private static IEnumerable<KeyValuePair<string, PropertyInfo>> GetPropertyPairs(Type type)
{
foreach (var property in type.GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
if (!IniSerializer.PropertyTypeVerifier(property.PropertyType))
continue;
string propertyName = null;
var attributes = property.GetCustomAttributes(typeof(IniSerializationAttribute), false);
if (attributes.Length > 0)
{
var attribute = (IniSerializationAttribute)attributes[0];
if (attribute.Ignore)
continue;
propertyName = attribute.Alias;
}
yield return new KeyValuePair<string, PropertyInfo>((propertyName) ?? property.Name, property);
}
}
private static void SetKeyValue(PropertyInfo property, object source, IniKey key)
{
object propertyValue = property.GetValue(source, null);
if (propertyValue == null)
return;
if (property.PropertyType.IsArray || property.PropertyType.GetInterface(typeof(IList).Name) != null)
{
var values = new List<string>();
/* MZ(2016-01-02): Fixed issue with null items in array and list. */
foreach (var item in (IEnumerable)propertyValue)
values.Add(item != null ? item.ToString() : null);
key.Values = values.ToArray();
}
else
key.Value = propertyValue.ToString();
}
private static void SetPropertyValue(PropertyInfo property, object destination, IniKey key)
{
var propertyType = property.PropertyType;
if (propertyType.IsArray)
{
/* MZ(2016-01-02): Fixed issue with null array and list. */
if (!key.IsValueArray)
return;
var values = key.Values;
var itemType = propertyType.GetElementType();
var array = Array.CreateInstance(itemType, values.Length);
for (int i = 0; i < values.Length; i++)
array.SetValue(
TypeDescriptor.GetConverter(itemType).ConvertFromInvariantString(values[i]),
i);
property.SetValue(destination, array, null);
}
else if (propertyType.GetInterface(typeof(IList).Name) != null)
{
/* MZ(2016-01-02): Fixed issue with null array and list. */
if (!key.IsValueArray)
return;
var itemType = propertyType.GetGenericArguments()[0];
var list = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(itemType));
var values = key.Values;
if (!(values.Length == 1 && string.IsNullOrEmpty(values[0])))
foreach (var value in values)
list.Add(
TypeDescriptor.GetConverter(itemType).ConvertFromInvariantString(value));
property.SetValue(destination, list, null);
}
else
property.SetValue(
destination,
TypeDescriptor.GetConverter(propertyType).ConvertFromInvariantString(key.Value),
null);
}
}
}

View File

@ -1,194 +0,0 @@
using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Text.RegularExpressions;
namespace MadMilkman.Ini
{
/// <summary>
/// Represents a class that is used for binding operations, an operation in which the <see cref="IniKey">placeholder keys</see> values are replaced with an internal or external data.
/// </summary>
/// <remarks>
/// <para><see cref="IniValueBinding"/> can be accessed through <see cref="IniFile.ValueBinding"/> property.</para>
/// <para>Binding can be executed with internal data source or with a provided external data source.</para>
/// <para>For more information see <see href="c49dc3a5-866f-4d2d-8f89-db303aceb5fe.htm#binding" target="_self">IniKey's Value Binding</see>.</para>
/// </remarks>
/// <seealso href="c49dc3a5-866f-4d2d-8f89-db303aceb5fe.htm#binding" target="_self">IniKey's Value Binding</seealso>
public sealed class IniValueBinding
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly IniValueBindingEventArgs args;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly IniFile iniFile;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private static readonly Regex placeholderPattern = new Regex(@"@\{[\w\s|]+\}", RegexOptions.Compiled | RegexOptions.CultureInvariant);
/// <summary>
/// Occurs when a placeholder is binding with data source value and can be used to customize the binding operation.
/// </summary>
public event EventHandler<IniValueBindingEventArgs> Binding;
internal IniValueBinding(IniFile iniFile)
{
if (iniFile == null)
throw new ArgumentNullException("iniFile");
this.iniFile = iniFile;
this.args = new IniValueBindingEventArgs();
}
/// <summary>
/// Executes a binding operation with internal data source.
/// </summary>
/// <seealso href="c49dc3a5-866f-4d2d-8f89-db303aceb5fe.htm#binding" target="_self">IniKey's Value Binding</seealso>
public void Bind()
{
foreach (var placeholderPair in this.GetPlaceholderPairs(null))
{
IniKey placeholderKey = placeholderPair.Key;
string placeholder = placeholderPair.Value;
string placeholderName = placeholder.Substring(2, placeholder.Length - 3);
string targetedValue;
int separator = placeholder.IndexOf('|');
if (separator != -1)
{
var targetedSection = this.iniFile.Sections[placeholder.Substring(2, separator - 2)];
if (targetedSection == null)
continue;
targetedValue = GetTargetedValue(
targetedSection,
placeholder.Substring(separator + 1, placeholder.Length - separator - 2));
}
else
targetedValue = GetTargetedValue(
placeholderKey.ParentSection,
placeholderName);
this.ExecuteBinding(placeholder, placeholderName, placeholderKey, targetedValue);
}
}
/// <summary>
/// Executes a binding operation with external data source.
/// </summary>
/// <param name="dataSource">The binding data source.</param>
/// <seealso href="c49dc3a5-866f-4d2d-8f89-db303aceb5fe.htm#binding" target="_self">IniKey's Value Binding</seealso>
public void Bind(object dataSource) { this.Bind(dataSource, null); }
/// <summary>
/// Executes a binding operation with external data source, only on specified section.
/// </summary>
/// <param name="dataSource">The binding data source.</param>
/// <param name="sectionName">The <see cref="IniSection"/>'s name.</param>
/// <seealso href="c49dc3a5-866f-4d2d-8f89-db303aceb5fe.htm#binding" target="_self">IniKey's Value Binding</seealso>
public void Bind(object dataSource, string sectionName)
{
if (dataSource == null)
throw new ArgumentNullException("dataSource");
var dataSourceDictionary = CreateDataSourceDictionary(dataSource);
if (dataSourceDictionary == null)
return;
foreach (var placeholderPair in this.GetPlaceholderPairs(this.iniFile.Sections[sectionName]))
{
IniKey placeholderKey = placeholderPair.Key;
string placeholder = placeholderPair.Value;
string placeholderName = placeholder.Substring(2, placeholder.Length - 3);
string targetedValue;
dataSourceDictionary.TryGetValue(placeholderName, out targetedValue);
this.ExecuteBinding(placeholder, placeholderName, placeholderKey, targetedValue);
}
}
private void ExecuteBinding(string placeholder, string placeholderName, IniKey placeholderKey, string targetedValue)
{
this.args.Initialize(placeholderName, placeholderKey, targetedValue, targetedValue != null);
if (this.Binding != null)
this.Binding(this, this.args);
if (this.args.Value != null)
placeholderKey.Value = placeholderKey.Value.Replace(placeholder, this.args.Value);
this.args.Reset();
}
// Returns placeholder pairs as KeyValuePair<IniKey, string>:
// Key = IniKey in which value's the placeholder resides
// Value = Placeholder, e.g. @{Placeholder}
private IEnumerable<KeyValuePair<IniKey, string>> GetPlaceholderPairs(IniSection section)
{
if (section != null)
{
foreach (IniKey key in section.Keys)
if (key.Value != null)
{
int matchStartat = key.Value.IndexOf("@{");
if (matchStartat != -1)
foreach (Match match in placeholderPattern.Matches(key.Value, matchStartat))
yield return new KeyValuePair<IniKey, string>(key, match.Value);
}
}
else
{
foreach (IniSection iniSection in this.iniFile.Sections)
foreach (var placeholderPair in this.GetPlaceholderPairs(iniSection))
yield return placeholderPair;
}
}
private static string GetTargetedValue(IniSection targetedSection, string targetedKeyName)
{
IniKey targetedKey = targetedSection.Keys[targetedKeyName];
return targetedKey != null ? targetedKey.Value : null;
}
/* REMARKS: TODO re-factor this, use providers ...
*
* CONSIDER: Implement support for any custom (including anonymous) types, use reflation ... */
private static IDictionary<string, string> CreateDataSourceDictionary(object dataSource)
{
var dictionary = dataSource as IDictionary<string, string>;
if (dictionary != null)
return dictionary;
var collection = dataSource as ICollection<KeyValuePair<string, string>>;
if (collection != null)
{
dictionary = new Dictionary<string, string>(collection.Count);
foreach (var dataSourceItem in collection)
if (!dictionary.ContainsKey(dataSourceItem.Key))
dictionary.Add(dataSourceItem);
return dictionary;
}
var enumerator = dataSource as IEnumerable<KeyValuePair<string, string>>;
if (enumerator != null)
{
dictionary = new Dictionary<string, string>();
foreach (var dataSourceItem in enumerator)
if (!dictionary.ContainsKey(dataSourceItem.Key))
dictionary.Add(dataSourceItem);
return dictionary;
}
if (dataSource is KeyValuePair<string, string>)
{
dictionary = new Dictionary<string, string>(1);
dictionary.Add((KeyValuePair<string, string>)dataSource);
return dictionary;
}
return null;
}
}
}

View File

@ -1,56 +0,0 @@
using System;
using System.Diagnostics;
namespace MadMilkman.Ini
{
/// <summary>
/// Provides data for <see cref="IniValueBinding.Binding"/> event.
/// </summary>
public sealed class IniValueBindingEventArgs : EventArgs
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string placeholderName;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private IniKey placeholderKey;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private bool isValueFound;
/// <summary>
/// Gets the placeholder's name.
/// </summary>
public string PlaceholderName { get { return this.placeholderName; } }
/// <summary>
/// Gets the placeholder's <see cref="IniKey"/>.
/// </summary>
public IniKey PlaceholderKey { get { return this.placeholderKey; } }
/// <summary>
/// Gets or sets the data source value that will replace the placeholder.
/// </summary>
/// <value>
/// The data source value that will replace the placeholder, if it's not <see langword="null"/>.
/// </value>
public string Value { get; set; }
/// <summary>
/// Gets a value indicating whether value was found in the data source.
/// </summary>
/// <value>
/// <see langword="true"/> if value was found in the data source.
/// </value>
public bool IsValueFound { get { return this.isValueFound; } }
internal IniValueBindingEventArgs() { }
internal void Initialize(string placeholderName, IniKey placeholderKey, string value, bool isValueFound)
{
this.placeholderName = placeholderName;
this.placeholderKey = placeholderKey;
this.Value = value;
this.isValueFound = isValueFound;
}
internal void Reset() { this.Initialize(null, null, null, false); }
}
}

View File

@ -1,77 +0,0 @@
using System;
using System.Diagnostics;
using System.Collections.Generic;
namespace MadMilkman.Ini
{
/// <summary>
/// Represents a class of mapped <see cref="IniKey.Value"/>s and their results, used in <see cref="O:MadMilkman.Ini.IniKey.TryParseValue"/> methods.
/// </summary>
/// <remarks>
/// <para><see cref="IniValueMappings"/> can be accessed through <see cref="IniFile.ValueMappings"/> property.</para>
/// <para>Mapped value results have priority over parsing the value.</para>
/// <para>For more information see <see href="c49dc3a5-866f-4d2d-8f89-db303aceb5fe.htm#parsing" target="_self">IniKey's Value Parsing</see>.</para>
/// </remarks>
/// <seealso href="c49dc3a5-866f-4d2d-8f89-db303aceb5fe.htm#parsing" target="_self">IniKey's Value Parsing</seealso>
public sealed class IniValueMappings
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private static readonly Predicate<Type> MappedTypeVerifier = IniKey.IsSupportedValueType;
private readonly IDictionary<string, object> mappings;
internal IniValueMappings() { this.mappings = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase); }
/// <summary>
/// Adds a new mapping of <see cref="IniKey.Value"/> to resulting object of parse methods.
/// </summary>
/// <param name="value">The key's value.</param>
/// <param name="mappedResult">The object that represents parsed <see cref="IniKey.Value"/>.</param>
/// <typeparam name="T">Type of the object that represents parsed <see cref="IniKey.Value"/>.</typeparam>
/// <remarks>
/// <para>The key's value cannot be <see langword="null"/>.</para>
/// <para>The mapped result's type must be one of the supported types for parsing, see the remarks of <see cref="IniKey.IsSupportedValueType(Type)"/> method.</para>
/// <para>Collection cannot contain multiple entries of same key's value, value comparison is case-insensitive.</para>
/// </remarks>
public void Add<T>(string value, T mappedResult)
{
if (value == null)
throw new ArgumentNullException("value");
if (this.Contains(value) || !IniValueMappings.MappedTypeVerifier(typeof(T)))
throw new InvalidOperationException();
this.mappings.Add(value, mappedResult);
}
/// <summary>
/// Determines whether the collection contains a mapping for a specified key's value.
/// </summary>
/// <param name="value">The key's value to locate in the collection.</param>
/// <returns><see langword="true"/> if the collection contains a mapping for a specified key's value.</returns>
public bool Contains(string value) { return this.mappings.ContainsKey(value); }
/// <summary>
/// Removes a mapping for a specified key's value in the collection.
/// </summary>
/// <param name="value">The key's value to remove in the collection.</param>
/// <returns><see langword="true"/> if a mapping for a specified key's value is successfully found and removed.</returns>
public bool Remove(string value) { return this.mappings.Remove(value); }
internal bool TryGetResult<T>(string value, out T result)
{
if (!string.IsNullOrEmpty(value))
{
object mappedResult;
if (this.mappings.TryGetValue(value, out mappedResult) &&
mappedResult.GetType() == typeof(T))
{
result = (T)mappedResult;
return true;
}
}
result = default(T);
return false;
}
}
}

View File

@ -1,67 +0,0 @@
using System;
namespace MadMilkman.Ini
{
delegate bool TryParseDelegate<TDelegate>(string value, out TDelegate result);
internal static class IniValueParser<T>
{
private static TryParseDelegate<T> parser;
static IniValueParser() { InitializeParser(typeof(T)); }
private static void InitializeParser(Type type)
{
if (type.IsEnum) SetParser<T>(EnumTryParse);
else if (type == typeof(TimeSpan)) SetParser<TimeSpan>(TimeSpan.TryParse);
else
switch (Type.GetTypeCode(type))
{
case TypeCode.Boolean: SetParser<bool>(bool.TryParse); break;
case TypeCode.Byte: SetParser<byte>(byte.TryParse); break;
case TypeCode.SByte: SetParser<sbyte>(sbyte.TryParse); break;
case TypeCode.Int16: SetParser<short>(short.TryParse); break;
case TypeCode.UInt16: SetParser<ushort>(ushort.TryParse); break;
case TypeCode.Int32: SetParser<int>(int.TryParse); break;
case TypeCode.UInt32: SetParser<uint>(uint.TryParse); break;
case TypeCode.Int64: SetParser<long>(long.TryParse); break;
case TypeCode.UInt64: SetParser<ulong>(ulong.TryParse); break;
case TypeCode.Single: SetParser<float>(float.TryParse); break;
case TypeCode.Double: SetParser<double>(double.TryParse); break;
case TypeCode.Decimal: SetParser<decimal>(decimal.TryParse); break;
case TypeCode.Char: SetParser<char>(char.TryParse); break;
case TypeCode.DateTime: SetParser<DateTime>(DateTime.TryParse); break;
case TypeCode.String: SetParser<string>((string value, out string result) => { result = value; return true; }); break;
}
}
private static void SetParser<TParser>(TryParseDelegate<TParser> parser)
{
IniValueParser<TParser>.parser = parser;
}
private static bool EnumTryParse<TEnum>(string value, out TEnum result)
{
/* REMARKS: To support case insensitivity instead of Enum.IsDefined use Enum.GetNames
* to achieve case insensitive string comparison between enum's names and value. */
Type type = typeof(TEnum);
if (Enum.IsDefined((type), value))
{
result = (TEnum)Enum.Parse(type, value);
return true;
}
result = default(TEnum);
return false;
}
public static bool TryParse(string value, out T result)
{
if (parser == null)
throw new NotSupportedException();
return parser(value, out result);
}
}
}

View File

@ -1,91 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{BEF9735D-C3CC-41E6-AAC6-18C5985D3107}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>MadMilkman.Ini</RootNamespace>
<AssemblyName>MadMilkman.Ini</AssemblyName>
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<DocumentationFile>bin\Debug\MadMilkman.Ini.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Release\MadMilkman.Ini.xml</DocumentationFile>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup>
<SignAssembly>true</SignAssembly>
</PropertyGroup>
<PropertyGroup>
<AssemblyOriginatorKeyFile>Properties\MadMilkman.Ini.StrongNameKey.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<Compile Include="IniInternal\DebugCollectionViewer.cs" />
<Compile Include="IniInternal\GlobalSuppressions.cs" />
<Compile Include="IniEnums\IniCommentStarter.cs" />
<Compile Include="IniEnums\IniCommentType.cs" />
<Compile Include="IniEnums\IniDuplication.cs" />
<Compile Include="IniEnums\IniKeyDelimiter.cs" />
<Compile Include="IniEnums\IniSectionWrapper.cs" />
<Compile Include="IniFile.cs" />
<Compile Include="IniItemsCollection\IniItemCollection.cs" />
<Compile Include="IniItemsCollection\IniKeyCollection.cs" />
<Compile Include="IniItems\IniComment.cs" />
<Compile Include="IniInternal\IItemNameVerifier.cs" />
<Compile Include="IniItems\IniItem.cs" />
<Compile Include="IniItems\IniKey.cs" />
<Compile Include="IniItems\IniSection.cs" />
<Compile Include="IniOptions.cs" />
<Compile Include="IniItemsCollection\IniSectionCollection.cs" />
<Compile Include="IniReaderWriter\IniCompressor.cs" />
<Compile Include="IniReaderWriter\IniEncryptor.cs" />
<Compile Include="IniReaderWriter\IniReader.cs" />
<Compile Include="IniReaderWriter\IniWriter.cs" />
<Compile Include="IniUtilities\IniSerializationAttribute.cs" />
<Compile Include="IniUtilities\IniSerializer.cs" />
<Compile Include="IniUtilities\IniValueBinding.cs" />
<Compile Include="IniUtilities\IniValueBindingEventArgs.cs" />
<Compile Include="IniUtilities\IniValueMappings.cs" />
<Compile Include="IniUtilities\IniValueParser.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="Properties\MadMilkman.Ini.StrongNameKey.snk" />
</ItemGroup>
<ItemGroup>
<Content Include="Properties\MadMilkman.Ini.png" />
<Content Include="IniInternal\SharedDocumentationComments.xml" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -1,22 +0,0 @@
using System;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security;
using System.Resources;
[assembly: AssemblyTitle("MadMilkman.Ini")]
[assembly: AssemblyDescription("INI file's reader and writer for .NET framework.")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("MadMilkman")]
[assembly: AssemblyProduct("MadMilkman.Ini")]
[assembly: AssemblyCopyright("Copyright © MadMilkman")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("aa0460b5-031d-49f3-a71b-2eb353055941")]
[assembly: AllowPartiallyTrustedCallers]
[assembly: CLSCompliant(true)]
[assembly: AssemblyVersion("1.0.6.0")]
[assembly: NeutralResourcesLanguageAttribute("en-US")]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -1,115 +0,0 @@
# ![MadMilkman.Ini component's icon](../master/MadMilkman.Ini/Properties/MadMilkman.Ini.png) MadMilkman.Ini
**MadMilkman.Ini** is a .NET component which simplifies processing of INI files and requires only a minimum **.NET Framework version 2.0**.
It is 100% managed code (C#), **compatible with Mono framework**, which provides an easy to use programming interface.
## Advantages:
* Enables reading and writing of various INI file formats.
* Enables easy manipulation of INI file's content.
* Enables copying and merging multiple INI file's contents.
* Enables encrypting and decrypting INI files.
* Enables compressing and decompressing INI files.
* Enables serializing and deserializing custom types into an INI content.
## Installation:
You can use this component in any way that suits you:
* As _private assembly_ by adding [MadMilkman.Ini.dll](https://github.com/MarioZ/MadMilkman.Ini/raw/master/MadMilkman.Ini.zip) inside your project.
* As _shared assembly_ by installing [MadMilkman.Ini.Setup.msi](https://github.com/MarioZ/MadMilkman.Ini/raw/master/MadMilkman.Ini.Setup.msi).
* As _package_ via [NuGet](http://www.nuget.org/packages/MadMilkman.Ini):
```powershell
PM> Install-Package MadMilkman.Ini
```
## First steps:
1. Create new .NET project.
2. Add new reference to MadMilkman.Ini.dll.
3. Add MadMilkman.Ini namespace.
* C# - `using MadMilkman.Ini;`
* VB.NET - `Import MadMilkman.Ini`
* C++/CLI - `using namespace MadMilkman::Ini;`
4. Write some INI files processing code.
* Use code samples located in MadMilkman.Ini.Samples, written in C#, VB.NET and C++/CLI as starting point.
* Read [MadMilkman.Ini.Documentation.chm](https://github.com/MarioZ/MadMilkman.Ini/raw/master/MadMilkman.Ini.Documentation.chm) to learn more about the component and its API references.
> If you are experiencing difficulties with viewing the CHM file's content after downloading it, right-click on CHM file, select "Properties" and under the "General" tab click "Unblock".
## Feedback & Support:
Please feel free to contact me with any questions, suggestions or issues regarding the MadMilkman.Ini component, I will be more than happy to provide a help.
Also if you found the component useful or useless I would be interested in hearing about it.
## Overview
MadMilkman.Ini provides a simple and intuitive programming interface which makes it very easy to create new or process existing INI files. Because INI file format is loosely defined and has no real standard, different files can have different format. By default MadMilkman.Ini processes the following format (however it is possible to define a custom formatting via IniOptions class):
```cfg
;Section trailing comment
[Section name]
Key name = Key value ;Key leading comment
```
### C# #
```csharp
// Create new file with a default formatting.
IniFile file = new IniFile();
// Add new section.
IniSection section = file.Sections.Add("Section name");
// Add trailing comment.
section.TrailingComment.Text = "Section trailing comment";
// Add new key and its value.
IniKey key = section.Keys.Add("Key name", "Key value ");
// Add leading comment.
key.LeadingComment.Text = "Key leading comment";
// Save file.
file.Save("Sample.ini");
```
### VB.NET
```vb.net
' Create new file with a default formatting.
Dim file As New IniFile()
' Add new section.
Dim section As IniSection = file.Sections.Add("Section name")
' Add trailing comment.
section.TrailingComment.Text = "Section trailing comment"
' Add new key and its value.
Dim key As IniKey = section.Keys.Add("Key name", "Key value ")
' Add leading comment.
key.LeadingComment.Text = "Key leading comment"
' Save file.
file.Save("Sample.ini")
```
### C++/CLI
```cpp
// Create new file with a default formatting.
IniFile^ file = gcnew IniFile();
// Add new section.
IniSection^ section = file->Sections->Add("Section name");
// Add trailing comment.
section->TrailingComment->Text = "Section trailing comment";
// Add new key and its value.
IniKey^ key = section->Keys->Add("Key name", "Key value ");
// Add leading comment.
key->LeadingComment->Text = "Key leading comment";
// Save file.
file->Save("Sample.ini");
```
**Compression** feature enables you to reduce INI file's size.
**Encryption** feature enables you to protect INI file by providing an encryption password.
**Parsing** feature enables you to retrieve the key's value as an instance of a specific type via key's TryParseValue method, all currently supported types are listed in key's IsSupportedValueType method remarks.
**Binding** feature enables you to define placeholders inside a key's value which can be binded (replaced) with an internal or external data source via Bind() method.
**Serialization** feature enables you to serialize an object into section's keys.
More details can be found in [MadMilkman.Ini.Documentation.chm](https://github.com/MarioZ/MadMilkman.Ini/raw/master/MadMilkman.Ini.Documentation.chm).

View File

@ -1,38 +0,0 @@
[1.0.6.0] NEW RELEASE
[1.0.5.2] Added support for quoted values which can contain comment's starting characters.
[1.0.5.1] Fixed issue with NULL array and list when deserializing object.
[1.0.5.0] NEW RELEASE
[1.0.4.3] Added support for section names that may contain end wrapper or comment starter characters.
[1.0.4.1] Fixed issue with SerializeDeserializeAttributeTest.
Improved string array indexer in IniItemCollection.
[1.0.4.0] NEW RELEASE
[1.0.3.3] Added support for serializing and deserializing objects into an INI content.
Added support for string array indexer in IniItemCollection.
[1.0.3.2] Added support for customizing binding operations via Binding event.
[1.0.3.1] Added support for reducing INI file via compression and decompression.
Added support for protecting INI file via encryption and decryption.
[1.0.3.0] NEW RELEASE
[1.0.2.3] Added support for defining placeholders in IniKey.Value and binding them with internal or external data source.
[1.0.2.2] Added support for IniKey.ParentSection property.
[1.0.2.1] Switched from MS tests to NUnit tests.
[1.0.2.0] NEW RELEASE
[1.0.1.4] Reduced memory footprint.
[1.0.1.3] Fixed issue with using IniItemCollection.Clear and then adding any of previous IniItems to IniItemCollection.
[1.0.1.2] Added support for mapping specific IniKey.Value to specific result object with IniFile.ValueMappings.
Mapped results have priority over parsing the value when using IniKey.TryParseValue methods.
Fixed issue with parsing key's value to enum.
[1.0.1.1] Added support for enums, decimals, arrays and lists in TryParseValue.
Performance improvements on TryParseValue methods.
[1.0.1.0] NEW RELEASE
[1.0.0.4] Added support for converting IniKey.Value via IniKey.TryParseValue(out T).
Type's support can be checked by IniKey.IsSupportedValueType(Type) or read its remarks in documentation.
[1.0.0.3] Small performance improvement on reading and writing an INI file.
[1.0.0.2] Added support for creating IniSection's Keys from Dictionary and creating IniKey from KeyValuePair.
[1.0.0.1] Added support for loading file via TextReader and saving file via TextWriter.
[1.0.0.0] INITIAL RELEASE