├── .gitattributes ├── .github ├── FUNDING.yml ├── assets │ └── star_us.gif └── workflows │ └── dotnet.yml ├── .gitignore ├── .vscode ├── launch.json └── tasks.json ├── CodeAnalyzers.targets ├── ConfigParser.sln ├── Directory.Build.props ├── Directory.Build.targets ├── LICENSE ├── README.md ├── appveyor.yml ├── global.json ├── src ├── ConfigParser.NullSection.cs ├── ConfigParser.cs ├── ConfigParser.csproj ├── ConfigParser.csproj.DotSettings ├── ConfigParserException.cs ├── ConfigParserSettings.cs ├── Entries │ ├── ConfigComment.cs │ ├── ConfigKeyValue.cs │ ├── ConfigLine.cs │ ├── ConfigSection.cs │ ├── ConfigSectionBase.cs │ ├── IConfigKeyValue.cs │ └── IConfigLine.cs └── Helpers │ ├── FileInfoExtensions.cs │ ├── Logging.cs │ └── YesNoConverter.cs └── tests ├── ConfigParser.Tests.csproj ├── ConfigParser.Tests.csproj.DotSettings ├── ConfigParserTests.cs ├── IntegrationTests.cs ├── JsonHelpers ├── ConfigParserSettingsResolver.cs ├── CultureConverter.cs ├── EncodingConverter.cs └── EnumConverter.cs └── Resources ├── Encoding ├── ANSI Cyrillic.txt ├── ANSI Latin1.txt ├── UTF16-BE.txt ├── UTF16-BE.txt.json ├── UTF16-LE.txt ├── UTF16-LE.txt.json ├── UTF32-BE.txt ├── UTF32-BE.txt.json ├── UTF7.txt ├── UTF7.txt.json ├── UTF8-Without-BOM.txt ├── UTF8-Without-BOM.txt.json ├── UTF8.txt └── UTF8.txt.json ├── RealWorld ├── CONFIG.SYS ├── CONFIG.SYS.json ├── FALLOUT.INI ├── FALLOUT.INI.json ├── Gothic.INI ├── ROTK.ini ├── main.cf.default ├── main.cf.default.json ├── mysqld.cnf ├── mysqld.cnf.json ├── openssl.cnf ├── openssl.cnf.json ├── redis.conf ├── redis.conf.json ├── skinr.help.ini ├── wakatime.cfg └── wakatime.cfg.json ├── Structure ├── from-scratch.conf ├── indented.ini ├── interpolation.conf ├── multi-line-delimited.ini ├── multi-line.ini ├── only-comments.ini └── simple-keys.ini └── Values ├── array.cnf ├── boolean.ini └── double.conf /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: salaros # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: salaros # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: https://www.paypal.me/salarosUSA # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /.github/assets/star_us.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salaros/config-parser/3ed0da9ae156228154d816f12c85c8f7684c7c65/.github/assets/star_us.gif -------------------------------------------------------------------------------- /.github/workflows/dotnet.yml: -------------------------------------------------------------------------------- 1 | name: Build Config Parser 2 | 3 | on: 4 | push: 5 | branches: [ "master" ] 6 | 7 | pull_request: 8 | branches: [ "master" ] 9 | 10 | jobs: 11 | build: 12 | runs-on: windows-latest 13 | 14 | steps: 15 | - name: Checkout 16 | uses: actions/checkout@v3 17 | with: 18 | fetch-depth: 0 19 | 20 | # Install the .NET Core workload 21 | - name: Install .NET Core 22 | uses: actions/setup-dotnet@v2 23 | with: 24 | dotnet-version: 6.0.x 25 | 26 | - name: Setup NuGet.exe 27 | uses: NuGet/setup-nuget@v1 28 | with: 29 | nuget-api-key: ${{secrets.NUGET_API_KEY}} 30 | 31 | # Execute all unit tests in the solution 32 | - name: Execute unit tests 33 | run: | 34 | dotnet restore 35 | dotnet build --no-restore 36 | 37 | # Execute all unit tests in the solution 38 | - name: Execute unit tests 39 | run: dotnet test tests --no-build --no-restore 40 | 41 | 42 | - name: Use GitVersion to generate SemVer version 43 | if: startsWith(github.ref, 'refs/tags') 44 | run: | 45 | dotnet tool update gitversion.tool --tool-path .github/tools 46 | echo ::set-env name=TAG_VERSION::$(.github/tools/dotnet-gitversion /output json /showvariable SemVer) 47 | 48 | - name: Set package version 49 | if: startsWith(github.ref, 'refs/tags') 50 | uses: KageKirin/set-csproj-version@v1 51 | with: 52 | version: ${{ env.TAG_NAME }} 53 | 54 | - name: NuGet push 55 | if: startsWith(github.ref, 'refs/tags') 56 | run: nuget push **\*.nupkg 57 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # Exclude NuGet packages 5 | packages 6 | 7 | # User-specific files 8 | *.suo 9 | *.user 10 | *.sln.docstates 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | x64/ 18 | build/ 19 | bld/ 20 | [Bb]in/ 21 | [Oo]bj/ 22 | 23 | # Roslyn cache directories 24 | *.ide/ 25 | 26 | # MSTest test Results 27 | [Tt]est[Rr]esult*/ 28 | [Bb]uild[Ll]og.* 29 | 30 | #NUNIT 31 | *.VisualState.xml 32 | TestResult.xml 33 | 34 | # Build Results of an ATL Project 35 | [Dd]ebugPS/ 36 | [Rr]eleasePS/ 37 | dlldata.c 38 | 39 | *_i.c 40 | *_p.c 41 | *_i.h 42 | *.ilk 43 | *.meta 44 | *.obj 45 | *.pch 46 | *.pdb 47 | *.pgc 48 | *.pgd 49 | *.rsp 50 | *.sbr 51 | *.tlb 52 | *.tli 53 | *.tlh 54 | *.tmp 55 | *.tmp_proj 56 | *.log 57 | *.vspscc 58 | *.vssscc 59 | .builds 60 | *.pidb 61 | *.svclog 62 | *.scc 63 | 64 | # Chutzpah Test files 65 | _Chutzpah* 66 | 67 | # Visual C++ cache files 68 | ipch/ 69 | *.aps 70 | *.ncb 71 | *.opensdf 72 | *.sdf 73 | *.cachefile 74 | 75 | # Visual Studio profiler 76 | *.psess 77 | *.vsp 78 | *.vspx 79 | 80 | # TFS 2012 Local Workspace 81 | $tf/ 82 | 83 | # Guidance Automation Toolkit 84 | *.gpState 85 | 86 | # ReSharper is a .NET coding add-in 87 | _ReSharper*/ 88 | *.[Rr]e[Ss]harper 89 | *.DotSettings.user 90 | 91 | # JustCode is a .NET coding addin-in 92 | .JustCode 93 | 94 | # TeamCity is a build add-in 95 | _TeamCity* 96 | 97 | # DotCover is a Code Coverage Tool 98 | *.dotCover 99 | 100 | # NCrunch 101 | _NCrunch_* 102 | .*crunch*.local.xml 103 | 104 | # MightyMoose 105 | *.mm.* 106 | AutoTest.Net/ 107 | 108 | # Web workbench (sass) 109 | .sass-cache/ 110 | 111 | # Installshield output folder 112 | [Ee]xpress/ 113 | 114 | # DocProject is a documentation generator add-in 115 | DocProject/buildhelp/ 116 | DocProject/Help/*.HxT 117 | DocProject/Help/*.HxC 118 | DocProject/Help/*.hhc 119 | DocProject/Help/*.hhk 120 | DocProject/Help/*.hhp 121 | DocProject/Help/Html2 122 | DocProject/Help/html 123 | 124 | # Click-Once directory 125 | publish/ 126 | 127 | # Publish Web Output 128 | *.[Pp]ublish.xml 129 | *.azurePubxml 130 | ## TODO: Comment the next line if you want to checkin your 131 | ## web deploy settings but do note that will include unencrypted 132 | ## passwords 133 | #*.pubxml 134 | 135 | # NuGet Packages Directory 136 | packages/* 137 | ## TODO: If the tool you use requires repositories.config 138 | ## uncomment the next line 139 | #!packages/repositories.config 140 | 141 | # Enable "build/" folder in the NuGet Packages folder since 142 | # NuGet packages use it for MSBuild targets. 143 | # This line needs to be after the ignore of the build folder 144 | # (and the packages folder if the line above has been uncommented) 145 | !packages/build/ 146 | 147 | # Windows Azure Build Output 148 | csx/ 149 | *.build.csdef 150 | 151 | # Windows Store app package directory 152 | AppPackages/ 153 | 154 | # Others 155 | sql/ 156 | *.Cache 157 | ClientBin/ 158 | [Ss]tyle[Cc]op.* 159 | ~$* 160 | *~ 161 | *.dbmdl 162 | *.dbproj.schemaview 163 | *.pfx 164 | *.publishsettings 165 | node_modules/ 166 | 167 | # RIA/Silverlight projects 168 | Generated_Code/ 169 | 170 | # Backup & report files from converting an old project file 171 | # to a newer Visual Studio version. Backup files are not needed, 172 | # because we have git ;-) 173 | _UpgradeReport_Files/ 174 | Backup*/ 175 | UpgradeLog*.XML 176 | UpgradeLog*.htm 177 | 178 | # SQL Server files 179 | *.mdf 180 | *.ldf 181 | 182 | # Business Intelligence projects 183 | *.rdl.data 184 | *.bim.layout 185 | *.bim_*.settings 186 | 187 | # Microsoft Fakes 188 | FakesAssemblies/ 189 | 190 | # LightSwitch generated files 191 | GeneratedArtifacts/ 192 | _Pvt_Extensions/ 193 | ModelManifest.xml 194 | 195 | # Visual Studio settings folder 196 | .vs 197 | 198 | # Exclude dotnet/NuGet tools 199 | tools/ 200 | 201 | # Exclude coverage results 202 | tests/coverage\.xml 203 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to find out which attributes exist for C# debugging 3 | // Use hover for the description of the existing attributes 4 | // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": ".NET Core Launch (console)", 9 | "type": "coreclr", 10 | "request": "launch", 11 | "preLaunchTask": "build", 12 | // If you have changed target frameworks, make sure to update the program path. 13 | "program": "${workspaceFolder}/tests/bin/Debug/netcoreapp2.1/ConfigParser.Tests.dll", 14 | "args": [], 15 | "cwd": "${workspaceFolder}/tests", 16 | // For more information about the 'console' field, see https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md#console-terminal-window 17 | "console": "internalConsole", 18 | "stopAtEntry": false, 19 | "internalConsoleOptions": "openOnSessionStart" 20 | }, 21 | { 22 | "name": ".NET Core Attach", 23 | "type": "coreclr", 24 | "request": "attach", 25 | "processId": "${command:pickProcess}" 26 | } 27 | , 28 | { 29 | "name": ".NET Core Launch (console)", 30 | "type": "coreclr", 31 | "request": "launch", 32 | "preLaunchTask": "build", 33 | "program": "${workspaceFolder}/tests/bin/Debug/netcoreapp2.1/ConfigParser.Tests.dll", 34 | "args": [], 35 | "cwd": "${workspaceFolder}/tests", 36 | "console": "internalConsole", 37 | "stopAtEntry": false, 38 | "internalConsoleOptions": "openOnSessionStart" 39 | }, 40 | { 41 | "name": ".NET Core Attach", 42 | "type": "coreclr", 43 | "request": "attach", 44 | "processId": "${command:pickProcess}" 45 | } 46 | ] 47 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "label": "build", 6 | "command": "dotnet", 7 | "type": "process", 8 | "args": [ 9 | "build", 10 | "${workspaceFolder}/tests/ConfigParser.Tests.csproj" 11 | ], 12 | "problemMatcher": "$msCompile" 13 | }, 14 | { 15 | "label": "build", 16 | "command": "dotnet", 17 | "type": "process", 18 | "args": [ 19 | "build", 20 | "${workspaceFolder}/tests/ConfigParser.Tests.csproj" 21 | ], 22 | "problemMatcher": "$msCompile" 23 | } 24 | ] 25 | } -------------------------------------------------------------------------------- /CodeAnalyzers.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | 11 | 12 | $(MSBuildThisFileDirectory) 13 | 14 | 15 | 16 | 17 | 24 | $(NoWarn),1573,1591,1712 25 | 26 | 27 | 28 | 29 | false 30 | true 31 | true 32 | $(SolutionDir)\stylecop.ruleset 33 | 34 | 35 | 36 | 37 | 38 | 39 | all 40 | runtime; build; native; contentfiles; analyzers; buildtransitive 41 | 42 | 43 | 44 | 45 | 46 | all 47 | runtime; build; native; contentfiles; analyzers; buildtransitive 48 | 49 | 50 | 51 | 52 | all 53 | runtime; build; native; contentfiles; analyzers; buildtransitive 54 | 55 | 56 | 57 | 58 | all 59 | runtime; build; native; contentfiles; analyzers 60 | 61 | 62 | 63 | 67 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /ConfigParser.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30611.23 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConfigParser", "src\ConfigParser.csproj", "{B835EC8E-1BD4-4B41-A01B-E5C80B4F51C0}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{610826DA-5E33-40B5-AF2C-27DA4A73FDA1}" 9 | ProjectSection(SolutionItems) = preProject 10 | .gitattributes = .gitattributes 11 | .gitignore = .gitignore 12 | appveyor.yml = appveyor.yml 13 | CodeAnalyzers.targets = CodeAnalyzers.targets 14 | Directory.Build.props = Directory.Build.props 15 | Directory.Build.targets = Directory.Build.targets 16 | global.json = global.json 17 | LICENSE = LICENSE 18 | README.md = README.md 19 | EndProjectSection 20 | EndProject 21 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConfigParser.Tests", "tests\ConfigParser.Tests.csproj", "{1949CF4D-6ACB-49D1-BBEC-D5E4CCE96946}" 22 | EndProject 23 | Global 24 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 25 | Debug|Any CPU = Debug|Any CPU 26 | Debug|x86 = Debug|x86 27 | Release|Any CPU = Release|Any CPU 28 | Release|x86 = Release|x86 29 | EndGlobalSection 30 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 31 | {B835EC8E-1BD4-4B41-A01B-E5C80B4F51C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 32 | {B835EC8E-1BD4-4B41-A01B-E5C80B4F51C0}.Debug|Any CPU.Build.0 = Debug|Any CPU 33 | {B835EC8E-1BD4-4B41-A01B-E5C80B4F51C0}.Debug|x86.ActiveCfg = Debug|Any CPU 34 | {B835EC8E-1BD4-4B41-A01B-E5C80B4F51C0}.Debug|x86.Build.0 = Debug|Any CPU 35 | {B835EC8E-1BD4-4B41-A01B-E5C80B4F51C0}.Release|Any CPU.ActiveCfg = Release|Any CPU 36 | {B835EC8E-1BD4-4B41-A01B-E5C80B4F51C0}.Release|Any CPU.Build.0 = Release|Any CPU 37 | {B835EC8E-1BD4-4B41-A01B-E5C80B4F51C0}.Release|x86.ActiveCfg = Release|Any CPU 38 | {B835EC8E-1BD4-4B41-A01B-E5C80B4F51C0}.Release|x86.Build.0 = Release|Any CPU 39 | {1949CF4D-6ACB-49D1-BBEC-D5E4CCE96946}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 40 | {1949CF4D-6ACB-49D1-BBEC-D5E4CCE96946}.Debug|Any CPU.Build.0 = Debug|Any CPU 41 | {1949CF4D-6ACB-49D1-BBEC-D5E4CCE96946}.Debug|x86.ActiveCfg = Debug|Any CPU 42 | {1949CF4D-6ACB-49D1-BBEC-D5E4CCE96946}.Debug|x86.Build.0 = Debug|Any CPU 43 | {1949CF4D-6ACB-49D1-BBEC-D5E4CCE96946}.Release|Any CPU.ActiveCfg = Release|Any CPU 44 | {1949CF4D-6ACB-49D1-BBEC-D5E4CCE96946}.Release|Any CPU.Build.0 = Release|Any CPU 45 | {1949CF4D-6ACB-49D1-BBEC-D5E4CCE96946}.Release|x86.ActiveCfg = Release|Any CPU 46 | {1949CF4D-6ACB-49D1-BBEC-D5E4CCE96946}.Release|x86.Build.0 = Release|Any CPU 47 | EndGlobalSection 48 | GlobalSection(SolutionProperties) = preSolution 49 | HideSolutionNode = FALSE 50 | EndGlobalSection 51 | GlobalSection(ExtensibilityGlobals) = postSolution 52 | SolutionGuid = {C925688F-B1AA-4F13-A48C-D5538AA5B08E} 53 | EndGlobalSection 54 | EndGlobal 55 | -------------------------------------------------------------------------------- /Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8.0 5 | true 6 | 7 | 8 | 9 | 10 | Debug;Release 11 | true 12 | true 13 | $(MSBuildThisFileDirectory) 14 | $(SolutionDir)\bin\$(Configuration)\ 15 | 16 | 17 | 18 | 19 | $(MSBuildProjectName.Contains('.Test')) 20 | 21 | 22 | 23 | bin\$(Configuration)\ 24 | 25 | true 26 | 27 | 28 | 29 | 30 | true 31 | opencover 32 | $(SolutionDir)/tests/coverage/ 33 | 34 | 35 | 36 | 37 | Debug 38 | AnyCPU 39 | 40 | 41 | $(DefineConstants);DEBUG 42 | true 43 | portable 44 | 45 | 46 | full 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /Directory.Build.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | 11 | 12 | $(MSBuildThisFileDirectory) 13 | 14 | 15 | 16 | 17 | 24 | $(NoWarn),1573,1591,1712 25 | 26 | 27 | 28 | 29 | false 30 | true 31 | true 32 | $(SolutionDir)\stylecop.ruleset 33 | 34 | 35 | 36 | 37 | 38 | 39 | all 40 | runtime; build; native; contentfiles; analyzers; buildtransitive 41 | 42 | 43 | 44 | 45 | 46 | all 47 | runtime; build; native; contentfiles; analyzers; buildtransitive 48 | 49 | 50 | 51 | 52 | all 53 | runtime; build; native; contentfiles; analyzers; buildtransitive 54 | 55 | 56 | 57 | 58 | all 59 | runtime; build; native; contentfiles; analyzers 60 | 61 | 62 | 63 | 67 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2015 Zhmayev Yaroslav aka Salaros 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ConfigParser 2 | [![Build status](https://ci.appveyor.com/api/projects/status/08aiy2tgs7n3y2fg?svg=true)](https://ci.appveyor.com/project/salaros/configparser) 3 | [![AppVeyor tests branch](https://img.shields.io/appveyor/tests/salaros/configparser/master.svg)](https://ci.appveyor.com/project/salaros/configparser/build/tests) 4 | [![Coverage Status](https://coveralls.io/repos/github/salaros/config-parser/badge.svg?branch=master)](https://coveralls.io/github/salaros/config-parser?branch=master) 5 | ============= 6 | 7 | ![GitHub top language](https://img.shields.io/github/languages/top/salaros/config-parser.svg?colorB=333333) 8 | [![.NET Standard](https://img.shields.io/badge/cross%20platform-yes-45a234.svg)](https://en.wikipedia.org/wiki/Cross-platform) 9 | [![.NET Standard](https://img.shields.io/badge/.NET%20Standard-2.0+-484877.svg)](https://social.msdn.microsoft.com/Forums/vstudio/en-US/7035edc6-97fc-49ee-8eee-2fa4d040a63b/) 10 | [![.NET Framework](https://img.shields.io/badge/.NET%20Framework-4.0+-748478.svg)](https://social.msdn.microsoft.com/Forums/vstudio/en-US/7035edc6-97fc-49ee-8eee-2fa4d040a63b/) 11 | 12 | [![License](https://img.shields.io/github/license/salaros/config-parser.svg)](https://github.com/salaros/configparser/blob/master/LICENSE) 13 | [![NuGet](https://img.shields.io/nuget/v/Salaros.ConfigParser.svg?label=NuGet&colorA=004880&colorB=CFC76B)](https://www.nuget.org/packages/Salaros.ConfigParser) 14 | [![NuGet Pre Release](https://img.shields.io/nuget/vpre/Salaros.ConfigParser.svg?label=NuGet%20pre-release&colorA=504880&colorB=CFC76B)](https://www.nuget.org/packages/Salaros.ConfigParser) 15 | [![NuGet](https://img.shields.io/nuget/dt/Salaros.ConfigParser.svg?colorA=004880&colorB=CFC76B)](https://www.nuget.org/packages/Salaros.ConfigParser) 16 | 17 | [![Donate Patreon](https://img.shields.io/badge/donate-Patreon-f96854.svg)](https://www.patreon.com/salaros/) 18 | [![Donate Paypal](https://img.shields.io/badge/donate-PayPal-009cde.svg)](https://paypal.me/salarosIT) 19 | [![Donate Liberapay](https://img.shields.io/badge/donate-Liberapay-ffc600.svg)](https://liberapay.com/salaros/) 20 | 21 | **ConfigParser** - is a slim, cross-platform, fully managed C# library for reading and writing .ini, .conf, .cfg etc configuration files. 22 | 23 | You could use it in your [Unity 3D](https://unity3d.com/), [Xamarin](http://xamarin.com) (iOS & Android), .NET Framework applications (even with old 4.0/4.5), .NET Core CLI and ASP.NET Core applications, [Mono](https://www.mono-project.com/) etc 24 | 25 | Features 26 | ======== 27 | 28 | ## Customization 29 | 30 | - [x] customizable encoding (most encodings can be auto-detected) 31 | - [x] customizable culture 32 | - [x] customizable number styles (e.g. currencies, exponential notation etc) 33 | - [x] customizable line endings (usually auto-detected) 34 | - [x] customizable true and false (e.g. "verum" / "falsum" ) 35 | - [x] customizable comment characters 36 | - [x] customizable key/value separator (defaults to '=') 37 | 38 | ## Read and preserved 39 | 40 | - [x] file header comments 41 | - [x] config files with no sections (like in this [SectionName]) or even mixed: first section has no header, just keys 42 | - [x] comments in general 43 | - [x] section comments 44 | - [x] empty lines 45 | - [x] indented sections 46 | - [x] indented keys 47 | - [x] indented values 48 | 49 | ## Values 50 | 51 | - [x] default values 52 | - [x] multi-line values (both quoted and not) 53 | - [x] quoted values 54 | - [x] null values (value-less keys) 55 | - [x] array values 56 | - [x] fancy float / double 57 | - [x] byte-encoded values 58 | - [x] smart boolean values (0/1, on/off, enabled/disabled work of the box) 59 | 60 | and more... 61 | 62 | ## 🟊🟊🟊 Support this project 🟊🟊🟊 63 | 64 | You can support us in a small way, please consider starring and sharing this repo! It helps us getting known and grow the community. 65 | 66 | ![star us](.github/assets/star_us.gif) 67 | 68 | Installation 69 | ============ 70 | 71 | **Config Parser** can be installed via [NuGet](https://www.nuget.org/packages/Salaros.ConfigParser) 72 | by using Package Manager in your IDE, `dotnet` binary or Package Console 73 | 74 | ```bash 75 | # Add the Salaros.ConfigParser package to a project named [] 76 | dotnet add [] package Salaros.ConfigParser 77 | ``` 78 | 79 | or Visual Studio's Package Console 80 | 81 | ```powershell 82 | # Add the Salaros.ConfigParser package to the default project 83 | Install-Package Salaros.ConfigParser 84 | 85 | # Add the Salaros.ConfigParser package to a project named [] 86 | Install-Package Salaros.ConfigParser -ProjectName [] 87 | ``` 88 | 89 | Usage 90 | ===== 91 | 92 | ```csharp 93 | // Initialize config file instance from file 94 | var configFileFromPath = new ConfigParser(@"path\to\configfile.cnf"); 95 | 96 | // Parse text 97 | var configFileFromString = new ConfigParser(@" 98 | [Strings] 99 | canBeIndented = value 100 | andQuoted = ""quotes will be stripped"" 101 | 102 | [Numbers] 103 | withD = 0.6D 104 | dollars = $2,999 105 | 106 | [boolean] 107 | numericTrue = 1 108 | textFalse = true 109 | yesWorks = yes 110 | upperCaseWorks = on 111 | worksAsWell = Enabled 112 | 113 | [Advanced] 114 | arrayWorkToo = 115 | arrayElement1 116 | arrayElement2 117 | valueLessKey", 118 | new ConfigParserSettings 119 | { 120 | MultiLineValues = MultiLineValues.Simple | MultiLineValues.AllowValuelessKeys | MultiLineValues.QuoteDelimitedValues, 121 | Culture = new CultureInfo("en-US") 122 | } 123 | ); 124 | 125 | configFileFromString.GetValue("Strings", "canBeIndented"); // value 126 | configFileFromString["Strings"]["canBeIndented"]; // returns 'value' too 127 | configFileFromString.GetValue("Strings", "andQuoted"); // quotes will be stripped 128 | 129 | configFileFromString.GetValue("Numbers", "withD", 0D); // 0,6 130 | configFileFromString.GetValue("Numbers", "dollars", 0D, // 2999 131 | NumberStyles.AllowCurrencySymbol); 132 | configFileFromString.GetValue("Numbers", "dollars"); // $2,999 133 | 134 | configFileFromString.GetValue("boolean", "numericTrue", false); // True 135 | configFileFromString.GetValue("boolean", "textFalse", false); // True 136 | configFileFromString.GetValue("boolean", "yesWorks", false); // True 137 | configFileFromString.GetValue("boolean", "upperCaseWorks", false); // True 138 | configFileFromString.GetValue("boolean", "worksAsWell", false); // True 139 | 140 | configFileFromString.GetArrayValue("Advanced", "arraysWorkToo"); // ["arrayElement1","arrayElement2"] 141 | configFileFromString.GetValue("Advanced", "valueLessKey"); // 142 | ``` 143 | 144 | How to build 145 | ============ 146 | 147 | You need Git and [.NET Core SDK](https://www.microsoft.com/net/download/) 148 | 149 | ```bash 150 | git clone https://github.com/salaros/ConfigParser 151 | cd ConfigParser 152 | dotnet build 153 | ``` 154 | 155 | How to test 156 | =========== 157 | 158 | **ConfigParser** uses [xUnit.net](https://xunit.github.io/), so you can run unit tests by simply using the following command: 159 | 160 | ```bash 161 | dotnet test tests 162 | ``` 163 | 164 | License 165 | ======= 166 | 167 | **ConfigParser** is distributed under the [MIT license](LICENSE), which grants you 168 | 169 | - [x] Private use 170 | - [x] Commercial use 171 | - [x] Modification 172 | - [x] Distribution 173 | 174 | However you have to include the content of [license](LICENSE) file in your source code (if you distribute your Software in text form), otherwise include it in your own LICENSE file or to some sort of **About -> Open-source libraries** section if you distribute your Software as a compiled library / binary. 175 | Here is why (part of [MIT license](LICENSE)): 176 | 177 | ``` 178 | The above copyright notice and this permission notice 179 | shall be included in all copies or substantial portions of the Software. 180 | ``` 181 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | # Operating system (build VM template) 2 | os: Windows Server 2019 3 | 4 | # If the build configuration does not specify build worker image 5 | # then Visual Studio 2015 image is used. 6 | image: Visual Studio 2019 7 | 8 | # Restrict to Git branches below 9 | branches: 10 | only: 11 | - master 12 | 13 | # Build Configuration, i.e. Debug, Release, etc. 14 | configuration: Debug 15 | 16 | # Scripts that run after cloning repository 17 | install: 18 | - cmd: dotnet restore 19 | 20 | environment: 21 | VERSION_SIMPLE: '{version}' 22 | VERSION_INFORMATIONAL: '{version}' 23 | VERSION_UNSTABLE_SUFFIX: 'preview' 24 | COVERALLS_REPO_TOKEN: 25 | secure: SwUOMUwmhBrcTwFa+ySSMLZ9c6G9nD/J2TJzYt/ZPiR9v2zGgKrN9UCswn1IIYKx 26 | APPVEYOR_TOKEN: 27 | secure: LtoVAPATN9iTCl1zkCvEktqP92QSEEngyS3vqG3GphE= 28 | 29 | init: 30 | - ps: | 31 | $env:VERSION_SIMPLE = $env:APPVEYOR_BUILD_VERSION.TrimStart("v") 32 | $env:VERSION_INFORMATIONAL = "$env:VERSION_SIMPLE" 33 | $env:GITHUB_REPO_API = "https://api.github.com/repos/$env:APPVEYOR_REPO_NAME/tags" 34 | 35 | if ($env:APPVEYOR_REPO_TAG -eq "true" -and $env:APPVEYOR_REPO_TAG_NAME) { 36 | ### CHECK IF A IT'S A TAGGED BUILD 37 | $env:APPVEYOR_REPO_TAG_NAME = $env:APPVEYOR_REPO_TAG_NAME.TrimStart("v") 38 | Write-Host "Building a tagged Git commit: $git_current_tag"; 39 | if ($env:APPVEYOR_REPO_TAG_NAME -match '^([0-9]+\.[0-9]+\.[0-9]+(\.[0-9]+)?)$') { 40 | $tag_ver = [version]$env:APPVEYOR_REPO_TAG_NAME 41 | $env:VERSION_INFORMATIONAL = "{0}.{1}.{2}" -f $tag_ver.Major, $tag_ver.Minor, $tag_ver.Build 42 | $env:VERSION_SIMPLE = "$env:VERSION_INFORMATIONAL.$env:APPVEYOR_BUILD_NUMBER" 43 | } 44 | } elseif ($env:VERSION_INFORMATIONAL -match '^([0-9]+\.[0-9]+\.[0-9]+(\.[0-9]+)?)$') { 45 | $current_ver = [version]$env:VERSION_INFORMATIONAL 46 | $env:VERSION_INFORMATIONAL = "{0}.{1}.{2}" -f $current_ver.Major, $current_ver.Minor, $current_ver.Build 47 | $env:VERSION_INFORMATIONAL = "{0}-{1}{2}" -f $env:VERSION_INFORMATIONAL, $env:VERSION_UNSTABLE_SUFFIX, $env:APPVEYOR_BUILD_NUMBER 48 | } 49 | 50 | ### MAKE CALCULATED INFORMATIONAL VERSION THE ACTUAL BUILD VERSION 51 | Update-AppveyorBuild -Version $env:VERSION_INFORMATIONAL 52 | Write-Host "Using build version: $env:VERSION_SIMPLE" 53 | Write-Host "Using (informational) build version: $env:VERSION_INFORMATIONAL" 54 | 55 | dotnet_csproj: 56 | patch: true 57 | file: '**\*.csproj' 58 | assembly_version: $(VERSION_SIMPLE) 59 | file_version: $(VERSION_SIMPLE) 60 | version: $(VERSION_INFORMATIONAL) 61 | package_version: $(VERSION_INFORMATIONAL) 62 | informational_version: $(VERSION_INFORMATIONAL) 63 | 64 | # Run scripts below before 65 | before_build: 66 | - cmd: where dotnet 67 | - cmd: dotnet clean 68 | 69 | # Run scripts below before 70 | build_script: 71 | - cmd: dotnet build 72 | 73 | # NuGet files qualified as artifacts 74 | artifacts: 75 | - path: 'bin\**\*.nupkg' # find the NuGet files 76 | name: NuGet_Files 77 | 78 | # Deploy to GitHub releases 79 | deploy: 80 | - 81 | provider: GitHub 82 | auth_token: 83 | secure: 2+d0KgCbWQpUR8TZfzvUEzbi4NQP6F/Tt0PUwLn6jXZCyO8FnrFVFJPsFa0QBQFl 84 | artifact: NuGet_Files 85 | draft: false 86 | force_update: true 87 | prerelease: false 88 | release: "$(APPVEYOR_PROJECT_NAME) v$(APPVEYOR_REPO_TAG_NAME)" 89 | tag: $(APPVEYOR_REPO_TAG_NAME) 90 | on: 91 | appveyor_repo_tag: true 92 | 93 | - 94 | provider: NuGet 95 | api_key: 96 | secure: fLRrY6iKFQhPFD5fHraib6Ot+0x3eKiVWoBCiKT5zPRCqxWxLAycIO8lJWg3o43r 97 | artifact: NuGet_Files 98 | server: # remove to push to NuGet.org 99 | skip_symbols: false 100 | symbol_server: # remove to push symbols to SymbolSource.org 101 | 102 | - 103 | provider: NuGet 104 | server: https://ci.appveyor.com/nuget/salaros/api/v2/package 105 | symbol_server: https://ci.appveyor.com/nuget/salaros/api/v2/package 106 | api_key: 107 | secure: 3zmnmVBweTgdk4SBM/rWHdC9JOM9s0pxm1bw1d+WHDo= 108 | artifact: NuGet_Files 109 | 110 | after_deploy: 111 | - ps: | 112 | if ($env:APPVEYOR_REPO_TAG -eq "true" -and $env:APPVEYOR_REPO_TAG_NAME) { 113 | $apiUrl = 'https://ci.appveyor.com/api' 114 | $headers = @{ 115 | "Authorization" = "Bearer $env:APPVEYOR_TOKEN" 116 | "Content-type" = "application/json" 117 | } 118 | Invoke-RestMethod -Method Put "$apiUrl/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/settings/build-number" -Body '{"nextBuildNumber": 1 }' -Headers $headers 119 | $env:APPVEYOR_REPO_TAG_NAME = $env:APPVEYOR_REPO_TAG_NAME.TrimStart("v") 120 | if ($env:APPVEYOR_REPO_TAG_NAME -match '^([0-9]+\.[0-9]+\.[0-9]+(\.[0-9]+)?)$') { 121 | $tag_ver = [version]$env:APPVEYOR_REPO_TAG_NAME 122 | $ver_format = "version: {0}.{1}.{2}.{3}" -f $tag_ver.Major, $tag_ver.Minor, ($tag_ver.Build + 1), '{build}' 123 | $headers."Content-type" = "text/plain"; 124 | Invoke-RestMethod -Method Put "$apiUrl/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/settings/yaml" -Body $ver_format -Headers $headers 125 | } 126 | } 127 | 128 | # Start builds on tags only (GitHub and BitBucket) 129 | skip_non_tags: false 130 | 131 | # Tests shall stay off for now 132 | test_script: 133 | - cmd: dotnet test .\tests 134 | 135 | # Test coverage: OpenCover + Coveralls 136 | after_test: 137 | - ps: | 138 | # Install NuGet packages and tools 139 | nuget install OpenCover -Version 4.6.519 -OutputDirectory packages 140 | dotnet tool install coveralls.net --tool-path tools 141 | 142 | # Set variables 143 | .\packages\OpenCover.4.6.519\tools\OpenCover.Console.exe -target:dotnet.exe -targetargs:"test tests" -register:user -filter:"+[*]* -[xunit*]* -[*Tests]* -[*]*.Logging.*" -excludedirs:"src\obj;src\Helpers;Helpers" -output:"tests\coverage.xml" -oldStyle 144 | .\tools\csmacnz.Coveralls.exe --opencover -i .\tests\coverage.xml --repoToken $env:COVERALLS_REPO_TOKEN --commitId $env:APPVEYOR_REPO_COMMIT --commitBranch $env:APPVEYOR_REPO_BRANCH --commitAuthor $env:APPVEYOR_REPO_COMMIT_AUTHOR --commitEmail $env:APPVEYOR_REPO_COMMIT_AUTHOR_EMAIL --commitMessage "$env:APPVEYOR_REPO_COMMIT_MESSAGE" --jobId $env:APPVEYOR_JOB_ID 145 | -------------------------------------------------------------------------------- /global.json: -------------------------------------------------------------------------------- 1 | { 2 | "projects": [ 3 | "src", 4 | "tests" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /src/ConfigParser.NullSection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | 4 | namespace Salaros.Configuration 5 | { 6 | public partial class ConfigParser 7 | { 8 | public class NullConfigSection 9 | { 10 | private ConfigParser parent; 11 | 12 | public NullConfigSection(ConfigParser parent) 13 | { 14 | this.parent = parent; 15 | } 16 | 17 | public T GetValue(string keyName, T defaultValue = default(T)) 18 | { 19 | if (string.IsNullOrWhiteSpace(keyName)) 20 | throw new ArgumentException("Key name must be a non-empty string.", nameof(keyName)); 21 | 22 | var iniKey = new ConfigKeyValue(keyName, parent.Settings.KeyValueSeparator, defaultValue, -1); 23 | var key = parent.fileHeader.Section.Keys.FirstOrDefault(k => Equals(keyName, k.Name)); 24 | if (key != null) 25 | return (T)key.ValueRaw; 26 | 27 | parent.fileHeader.Section.AddLine(iniKey); 28 | return defaultValue; 29 | } 30 | 31 | public string GetValue(string keyName, string defaultValue = null) => GetValue(keyName, defaultValue); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/ConfigParser.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.0;net40;net45 5 | ..\bin\$(Configuration)\ 6 | latest 7 | Salaros.Configuration 8 | ConfigParser 9 | 10 | 11 | 12 | true 13 | true 14 | Salaros.ConfigParser 15 | ConfigParser 16 | Salaros 17 | Zhmayev Yaroslav aka Salaros 18 | Copyright 2015 (c) Salaros 19 | ConfigParser 20 | A slim, cross-platform, fully managed C# library for reading/writing .ini, .conf, .cfg etc configuration files. 21 | 0.3.7 22 | 0.3.7 23 | 0.3.7 24 | true 25 | https://raw.githubusercontent.com/salaros/config-parser/master/LICENSE 26 | https://github.com/salaros/config-parser 27 | https://github.com/salaros/config-parser 28 | Git 29 | configuration,configuration-files,file,configuration-file,config,ini,cfg,configs,conf,mono,dotnet,managed,csharp,cross-platform 30 | English 31 | 32 | 33 | 34 | 35 | 36 | 37 | /usr/lib/mono 38 | /Library/Frameworks/Mono.framework/Versions/Current/lib/mono 39 | 40 | $(MonoPath)/4.0-api 41 | $(MonoPath)/4.5-api 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | TRACE;LIBLOG_PUBLIC 55 | 56 | 57 | 58 | TRACE;DEBUG;LIBLOG_PUBLIC 59 | full 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /src/ConfigParser.csproj.DotSettings: -------------------------------------------------------------------------------- 1 |  2 | True 3 | True 4 | 5 | -------------------------------------------------------------------------------- /src/ConfigParserException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Salaros.Configuration 4 | { 5 | public class ConfigParserException : Exception 6 | { 7 | /// 8 | /// 9 | /// Initializes a new instance of the class. 10 | /// 11 | /// Message. 12 | /// Line number. 13 | /// Inner exception. 14 | public ConfigParserException(string message, int lineNumber = -1, Exception innterException = null) 15 | : base(message, innterException) 16 | { 17 | LineNumber = lineNumber; 18 | Message = (lineNumber < 0) 19 | ? message 20 | : $"{message}. On the line no. #{lineNumber}."; 21 | } 22 | 23 | /// 24 | /// Gets the line number. 25 | /// 26 | /// The line number. 27 | public int LineNumber { get; } 28 | 29 | /// 30 | /// 31 | /// Gets a message that describes the current exception. 32 | /// 33 | public override string Message { get; } 34 | } 35 | } 36 | 37 | -------------------------------------------------------------------------------- /src/ConfigParserSettings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Text.RegularExpressions; 7 | using System.Threading; 8 | 9 | namespace Salaros.Configuration 10 | { 11 | public class ConfigParserSettings 12 | { 13 | protected Regex keyMatcher, commentMatcher, valueMatcher, arrayStartMatcher; 14 | 15 | /// 16 | /// Initializes the class. 17 | /// 18 | static ConfigParserSettings() 19 | { 20 | SectionMatcher = new Regex(@"^(?(\s+)?)\[(?.*?)\](?.*)$", RegexOptions.Compiled); 21 | } 22 | 23 | /// 24 | /// Gets the culture used for reading boolean, decimal values etc. 25 | /// 26 | /// 27 | /// The culture used for reading boolean, decimal values etc. 28 | /// 29 | public CultureInfo Culture { get; set; } = Thread.CurrentThread.CurrentCulture; 30 | 31 | /// 32 | /// Gets the multi-line value-related settings. 33 | /// 34 | /// 35 | /// The multi-line value-related settings. 36 | /// 37 | public MultiLineValues MultiLineValues { get; set; } = MultiLineValues.NotAllowed; 38 | 39 | /// 40 | /// Gets the encoding. 41 | /// 42 | /// 43 | /// The encoding. 44 | /// 45 | public Encoding Encoding { get; set; } = null; 46 | 47 | /// 48 | /// Gets or sets the boolean converter. 49 | /// 50 | /// 51 | /// The boolean converter. 52 | /// 53 | public BooleanConverter BooleanConverter { get; set; } = null; 54 | 55 | /// 56 | /// Gets the new line string. 57 | /// 58 | /// 59 | /// The new line string. 60 | /// 61 | public string NewLine { get; set; } = Environment.NewLine; 62 | 63 | /// 64 | /// Gets the key value separator. 65 | /// 66 | /// 67 | /// The key value separator. 68 | /// 69 | public string KeyValueSeparator { get; set; } = "="; 70 | 71 | /// 72 | /// Gets the comment characters. 73 | /// 74 | /// 75 | /// The comment characters. 76 | /// 77 | public string[] CommentCharacters { get; set; } = { "#", ";" }; 78 | 79 | /// 80 | /// Gets the section matcher. 81 | /// 82 | /// 83 | /// The section matcher. 84 | /// 85 | internal static Regex SectionMatcher { get; set; } 86 | 87 | /// Gets the array value line matcher (matches the whitespaces at the beggining of each array value). 88 | /// The array start matcher. 89 | internal Regex ArrayStartMatcher => arrayStartMatcher ?? (arrayStartMatcher = 90 | new Regex(@"^(\s{1,})", RegexOptions.Compiled)); 91 | 92 | /// 93 | /// Gets the comment matcher. 94 | /// 95 | /// 96 | /// The comment matcher. 97 | /// 98 | internal Regex CommentMatcher => commentMatcher ?? (commentMatcher = 99 | new Regex( 100 | $@"^(?(\s+)?({string.Join("|", CommentCharacters.Select(c => c.ToString()))})+(\s+)?)(?(\s+)?.*?)$", 101 | RegexOptions.Compiled)); 102 | 103 | /// 104 | /// Gets the key matcher. 105 | /// 106 | /// 107 | /// The key matcher. 108 | /// 109 | internal Regex KeyMatcher => keyMatcher ?? (keyMatcher = 110 | new Regex($@"^(?.*?)(?(\s+)?{Regex.Escape(KeyValueSeparator)}(\s+)?)", 111 | RegexOptions.Compiled)); 112 | 113 | /// 114 | /// Gets the value matcher. 115 | /// 116 | /// 117 | /// The value matcher. 118 | /// 119 | internal Regex ValueMatcher => valueMatcher ?? (valueMatcher = MultiLineValues.HasFlag(MultiLineValues.QuoteDelimitedValues) 120 | ? new Regex(@"^(?\"")?(?[^\""]+)(?\"")?(\s+)?$", RegexOptions.Compiled) 121 | : new Regex(@"^(?.*?)?$", RegexOptions.Compiled)); 122 | } 123 | 124 | /// 125 | /// Flags / settings for handling multi-line values 126 | /// 127 | [Flags] 128 | public enum MultiLineValues 129 | { 130 | Simple = 0, 131 | NotAllowed = 1, 132 | QuoteDelimitedValues = 2, 133 | AllowValuelessKeys = 4, 134 | AllowEmptyTopSection = 8 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /src/Entries/ConfigComment.cs: -------------------------------------------------------------------------------- 1 | namespace Salaros.Configuration 2 | { 3 | public class ConfigComment : ConfigLine 4 | { 5 | protected string delimiter; 6 | 7 | /// 8 | /// 9 | /// Initializes a new instance of the class. 10 | /// 11 | /// Delimiter. 12 | /// 13 | /// Line number. 14 | public ConfigComment(string delimiter = ";", string comment = "", int lineNumber = -1) 15 | : base(lineNumber) 16 | { 17 | Delimiter = delimiter; 18 | Comment = comment; 19 | } 20 | 21 | /// 22 | /// Gets the delimiter. 23 | /// 24 | /// The delimiter. 25 | public string Delimiter 26 | { 27 | get; 28 | } 29 | 30 | /// 31 | /// Gets the delimiter. 32 | /// 33 | /// The delimiter. 34 | public string Comment 35 | { 36 | get; 37 | internal set; 38 | } 39 | 40 | /// 41 | /// 42 | /// Returns a that represents the current . 43 | /// 44 | /// A that represents the current . 45 | public override string ToString() 46 | { 47 | return (string.IsNullOrWhiteSpace(Comment)) 48 | ? Delimiter 49 | : $"{Delimiter}{Comment}"; 50 | } 51 | } 52 | } 53 | 54 | -------------------------------------------------------------------------------- /src/Entries/ConfigKeyValue.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Salaros.Configuration 4 | { 5 | public class ConfigKeyValue : ConfigLine, IConfigKeyValue 6 | { 7 | protected string keyName; 8 | 9 | #region Constructors 10 | 11 | /// 12 | /// Initializes a new instance of the class. 13 | /// 14 | /// Name of the key. 15 | /// The separator. 16 | /// Value. 17 | /// Line number. 18 | /// key 19 | /// 20 | public ConfigKeyValue(string keyName, string separator, T value, int lineNumber) 21 | : base(lineNumber) 22 | { 23 | if (string.IsNullOrWhiteSpace(keyName)) 24 | throw new ArgumentNullException(nameof(keyName)); 25 | 26 | if (separator is null) 27 | throw new ArgumentNullException(nameof(separator)); 28 | 29 | this.keyName = keyName; 30 | Separator = separator; 31 | Value = value; 32 | } 33 | 34 | #endregion 35 | 36 | #region Properties 37 | 38 | /// 39 | /// 40 | /// Gets the name of the key. 41 | /// 42 | /// 43 | /// The name of the key. 44 | /// 45 | public string Name => keyName.Trim(); 46 | 47 | /// 48 | /// Gets or sets the separator. 49 | /// 50 | /// 51 | /// The separator. 52 | /// 53 | public string Separator { get; } 54 | 55 | /// 56 | /// Gets the value. 57 | /// 58 | /// The value. 59 | public T Value 60 | { 61 | get => (T)ValueRaw; 62 | internal set => ValueRaw = value; 63 | } 64 | 65 | /// 66 | /// 67 | /// Gets the value raw. 68 | /// 69 | /// 70 | /// The value raw. 71 | /// 72 | public object ValueRaw 73 | { 74 | get; set; 75 | } 76 | 77 | /// 78 | /// 79 | /// Gets the name of the section. 80 | /// 81 | /// 82 | /// The name of the section. 83 | /// 84 | public string SectionName => Section?.SectionName; 85 | 86 | /// 87 | /// Gets the raw content of the line. 88 | /// 89 | /// 90 | /// The raw content of the line. 91 | /// 92 | /// ReSharper disable once InheritdocConsiderUsage 93 | public override string Content 94 | { 95 | get => ValueRaw?.ToString(); 96 | set => ValueRaw = value; 97 | } 98 | 99 | #endregion 100 | 101 | #region Methods 102 | 103 | /// 104 | /// 105 | /// Returns a that represents the current . 106 | /// 107 | /// A that represents the current . 108 | public override string ToString() 109 | { 110 | return ToString(MultiLineValues.NotAllowed); 111 | } 112 | 113 | /// ReSharper disable once InheritdocInvalidUsage 114 | /// 115 | /// 116 | /// Returns a that represents this instance. 117 | /// 118 | /// The multi line settings. 119 | /// 120 | /// A that represents this instance. 121 | /// 122 | public override string ToString(MultiLineValues multiLineSettings) 123 | { 124 | switch (multiLineSettings) 125 | { 126 | case MultiLineValues.AllowValuelessKeys when string.IsNullOrWhiteSpace(Content): 127 | return keyName; 128 | 129 | case MultiLineValues.QuoteDelimitedValues: 130 | return $"{keyName}{Separator}\"{Content}\""; 131 | 132 | default: 133 | return $"{keyName}{Separator}{Content}"; 134 | } 135 | } 136 | 137 | #endregion 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /src/Entries/ConfigLine.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | 3 | namespace Salaros.Configuration 4 | { 5 | public class ConfigLine : IConfigLine 6 | { 7 | protected int lineNumber; 8 | private string lineContent; 9 | internal static readonly Regex IndentationMatcher; 10 | 11 | #region Constructor 12 | 13 | static ConfigLine() 14 | { 15 | IndentationMatcher = new Regex(@"^(\s+)", RegexOptions.Compiled | RegexOptions.Singleline); 16 | } 17 | 18 | /// 19 | /// Initializes a new instance of the class. 20 | /// 21 | /// Line number. 22 | /// Raw line content. 23 | public ConfigLine(int lineNumber = -1, string lineContent = "") 24 | { 25 | this.lineContent = lineContent; 26 | this.lineNumber = lineNumber; 27 | } 28 | 29 | #endregion 30 | 31 | #region Properties 32 | 33 | #region IConfigLine implementation 34 | 35 | /// 36 | /// 37 | /// Gets the line number. 38 | /// 39 | /// The line number. 40 | public virtual int LineNumber 41 | { 42 | get 43 | { 44 | if (lineNumber < 0 && Section != null) 45 | lineNumber = Section.GetLineNumber(this); 46 | 47 | return lineNumber; 48 | } 49 | } 50 | 51 | /// 52 | /// 53 | /// Gets the raw content of the line. 54 | /// 55 | /// The raw content of the line. 56 | public virtual string Content 57 | { 58 | get => lineContent; 59 | set => lineContent = value; 60 | } 61 | 62 | #endregion 63 | 64 | /// 65 | /// 66 | /// Gets the section. 67 | /// 68 | /// 69 | /// The section. 70 | /// 71 | public ConfigSection Section 72 | { 73 | get; internal set; 74 | } 75 | 76 | /// 77 | /// 78 | /// Gets the indentation. 79 | /// 80 | /// 81 | /// The indentation. 82 | /// 83 | public string Indentation => IndentationMatcher?.Match(ToString()).Value; 84 | 85 | #endregion 86 | 87 | #region Methods 88 | 89 | /// 90 | /// Returns a that represents the current . 91 | /// 92 | /// A that represents the current . 93 | public override string ToString() 94 | { 95 | return Content; 96 | } 97 | 98 | /// 99 | /// 100 | /// Returns a that represents this instance. 101 | /// 102 | /// The multi line settings. 103 | /// 104 | /// A that represents this instance. 105 | /// 106 | public virtual string ToString(MultiLineValues multiLineSettings) 107 | { 108 | return ToString(); 109 | } 110 | 111 | #endregion 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/Entries/ConfigSection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.ObjectModel; 4 | using System.Linq; 5 | 6 | namespace Salaros.Configuration 7 | { 8 | public class ConfigSection : ConfigSectionBase, IConfigLine 9 | { 10 | protected int lineNumber; 11 | protected string sectionName, comment; 12 | 13 | #region Constructors 14 | 15 | /// 16 | /// Initializes a new instance of the class. 17 | /// 18 | /// Section name. 19 | /// Line number. 20 | /// The indentation. 21 | /// The comment. 22 | /// sectionName 23 | /// 24 | public ConfigSection(string sectionName, int lineNumber = -1, string indentation = "", string comment = "") 25 | : this() 26 | { 27 | this.sectionName = sectionName ?? throw new ArgumentNullException(nameof(sectionName)); 28 | this.lineNumber = lineNumber; 29 | this.comment = comment; 30 | 31 | Indentation = indentation; 32 | } 33 | 34 | /// 35 | /// Initializes a new instance of the class. 36 | /// 37 | internal ConfigSection() 38 | : base() 39 | { 40 | sectionName = string.Empty; 41 | lineNumber = 0; 42 | } 43 | 44 | #endregion 45 | 46 | #region Methods 47 | 48 | /// 49 | /// Returns a that represents the current . 50 | /// 51 | /// A that represents the current . 52 | public override string ToString() => Content; 53 | 54 | /// 55 | /// Adds a configuration file line. 56 | /// 57 | /// The configuration file line to add. 58 | internal override void AddLine(ConfigLine configLine) 59 | { 60 | base.AddLine(configLine); 61 | configLine.Section = this; 62 | } 63 | 64 | /// 65 | /// 66 | /// Returns a that represents this instance. 67 | /// 68 | /// The multi line settings. 69 | /// 70 | /// A that represents this instance. 71 | /// 72 | public string ToString(MultiLineValues multiLineSettings) => ToString(); 73 | 74 | #endregion 75 | 76 | #region Properties 77 | 78 | #region IConfigLine implementation 79 | 80 | /// 81 | /// 82 | /// Gets the section. 83 | /// 84 | /// 85 | /// The section. 86 | /// 87 | public ConfigSection Section => this; 88 | 89 | 90 | /// 91 | /// 92 | /// Gets the line number. 93 | /// 94 | /// The line number. 95 | public virtual int LineNumber => lineNumber; 96 | 97 | #endregion 98 | 99 | /// 100 | /// Gets the name of the section. 101 | /// 102 | /// The name of the section. 103 | public string SectionName => sectionName; 104 | 105 | /// 106 | /// Gets the keys. 107 | /// 108 | /// The keys. 109 | public 110 | #if NET40 111 | ReadOnlyCollection Keys 112 | #else 113 | IReadOnlyCollection Keys 114 | #endif 115 | => new ReadOnlyCollection(lines.OfType().OrderBy(k => k.LineNumber).ToList()); 116 | 117 | /// 118 | /// Gets all the lines of the given section. 119 | /// 120 | /// The lines. 121 | public override 122 | #if NET40 123 | ReadOnlyCollection Lines 124 | #else 125 | IReadOnlyCollection Lines 126 | #endif 127 | { 128 | get 129 | { 130 | var allLines = (string.IsNullOrWhiteSpace(sectionName)) 131 | ? new List() 132 | : new List { this }; 133 | allLines.AddRange(lines.Cast().OrderBy(k => k.LineNumber)); 134 | return new ReadOnlyCollection(allLines); 135 | } 136 | } 137 | 138 | /// 139 | /// Gets the raw content of the line. 140 | /// 141 | /// 142 | /// The raw content of the line. 143 | /// 144 | /// ReSharper disable once InheritdocConsiderUsage 145 | public string Content => string.IsNullOrWhiteSpace(sectionName) 146 | ? string.Empty 147 | : $"{Indentation}[{sectionName}]{comment}"; 148 | 149 | /// 150 | /// 151 | /// Gets the indentation. 152 | /// 153 | /// 154 | /// The indentation. 155 | /// 156 | /// 157 | public string Indentation 158 | { 159 | get; 160 | } 161 | 162 | #endregion 163 | 164 | #region Indexing 165 | 166 | /// 167 | /// Gets the with the specified key name. 168 | /// 169 | /// 170 | /// The . 171 | /// 172 | /// Name of the key. 173 | /// Key value. 174 | public override string this[string keyName] 175 | { 176 | get 177 | { 178 | return (keyName is null) 179 | ? null 180 | : Keys 181 | ?.FirstOrDefault(s => keyName.Equals(s.Name, StringComparison.InvariantCultureIgnoreCase)) 182 | ?.ValueRaw as string; 183 | } 184 | } 185 | 186 | #endregion 187 | } 188 | } 189 | -------------------------------------------------------------------------------- /src/Entries/ConfigSectionBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.ObjectModel; 4 | using System.Linq; 5 | using System.Text; 6 | 7 | namespace Salaros.Configuration 8 | { 9 | public abstract class ConfigSectionBase 10 | { 11 | protected List lines; 12 | 13 | protected ConfigSectionBase() 14 | { 15 | lines = new List(); 16 | } 17 | 18 | #region Properties 19 | 20 | /// 21 | /// Gets all the lines of the given section. 22 | /// 23 | /// The lines. 24 | public abstract 25 | #if NET40 26 | ReadOnlyCollection Lines 27 | #else 28 | IReadOnlyCollection Lines 29 | #endif 30 | { get; } 31 | 32 | public abstract string this[string value] { get; } 33 | 34 | #endregion Properties 35 | 36 | #region Methods 37 | 38 | /// 39 | /// Gets the line number of the given line. 40 | /// 41 | /// The line number. 42 | /// Line. 43 | internal int GetLineNumber(ConfigLine line) 44 | { 45 | if (line == null) 46 | throw new ArgumentNullException(nameof(line)); 47 | 48 | return (lines == null || !lines.Any()) 49 | ? -1 50 | : lines.IndexOf(line); 51 | } 52 | 53 | /// 54 | /// Adds a configuration file line. 55 | /// 56 | /// The configuration file line to add. 57 | internal virtual void AddLine(ConfigLine configLine) 58 | { 59 | lines.Add(configLine); 60 | } 61 | 62 | #endregion Methods 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/Entries/IConfigKeyValue.cs: -------------------------------------------------------------------------------- 1 | namespace Salaros.Configuration 2 | { 3 | public interface IConfigKeyValue : IConfigLine 4 | { 5 | /// 6 | /// Gets the name of the key. 7 | /// 8 | /// 9 | /// The name of the key. 10 | /// 11 | string Name { get; } 12 | 13 | /// 14 | /// Gets the value raw. 15 | /// 16 | /// 17 | /// The value raw. 18 | /// 19 | object ValueRaw { get; set; } 20 | 21 | /// 22 | /// Gets the name of the section. 23 | /// 24 | /// 25 | /// The name of the section. 26 | /// 27 | string SectionName { get; } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Entries/IConfigLine.cs: -------------------------------------------------------------------------------- 1 | namespace Salaros.Configuration 2 | { 3 | public interface IConfigLine 4 | { 5 | /// 6 | /// Gets the line number. 7 | /// 8 | /// The line number. 9 | int LineNumber { get; } 10 | 11 | /// 12 | /// Gets the raw content of the line. 13 | /// 14 | /// The raw content of the line. 15 | string Content { get; } 16 | 17 | /// 18 | /// Gets the section. 19 | /// 20 | /// 21 | /// The section. 22 | /// 23 | ConfigSection Section { get; } 24 | 25 | /// 26 | /// Gets the indentation. 27 | /// 28 | /// 29 | /// The indentation. 30 | /// 31 | string Indentation { get; } 32 | 33 | /// 34 | /// Returns a that represents this instance. 35 | /// 36 | /// The multi line settings. 37 | /// 38 | /// A that represents this instance. 39 | /// 40 | string ToString(MultiLineValues multiLineSettings); 41 | } 42 | } 43 | 44 | -------------------------------------------------------------------------------- /src/Helpers/FileInfoExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Text; 3 | using System.Text.RegularExpressions; 4 | 5 | // ReSharper disable once CheckNamespace 6 | 7 | namespace System.IO 8 | { 9 | /// 10 | /// Extensions for class 11 | /// 12 | public static class FileInfoExtensions 13 | { 14 | public static readonly Regex UnicodeLetters; 15 | public static readonly Regex AnsiLatin1Mangled; 16 | 17 | /// 18 | /// Initializes the class. 19 | /// 20 | static FileInfoExtensions() 21 | { 22 | AnsiLatin1Mangled = new Regex(@"[ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿŸ]", RegexOptions.Compiled | RegexOptions.Multiline); 23 | UnicodeLetters = new Regex(@"\p{L}", RegexOptions.Compiled | RegexOptions.Multiline); 24 | } 25 | 26 | /// 27 | /// Tries the get file encoding. 28 | /// 29 | /// The file. 30 | /// The encoding. 31 | /// 32 | /// file 33 | public static bool TryGetEncoding(this FileInfo file, out Encoding encoding) 34 | { 35 | if (null == file || !file.Exists) 36 | throw new ArgumentException($"{nameof(file)} must be a valid path to a file!"); 37 | 38 | var bytes = new byte[10]; 39 | using (var fs = new FileStream(file.FullName, FileMode.Open, FileAccess.Read)) 40 | { 41 | fs.Read(bytes, 0, 10); 42 | #if !NETSTANDARD1_6 43 | fs.Close(); 44 | #endif 45 | } 46 | 47 | switch (bytes) 48 | { 49 | case var utf7 when 0x2B == utf7[0] && 0x2F == utf7[1] && 0x76 == utf7[2]: 50 | encoding = Encoding.UTF7; 51 | break; 52 | 53 | case var utf32 when 0x00 == utf32[0] && 0x00 == utf32[1] && 0xFE == utf32[2] && 0xFF == utf32[3]: 54 | encoding = Encoding.GetEncoding(12001); // UTF-32, big endian byte order; available only to managed applications 55 | break; 56 | 57 | case var utf32 when 0xFF == utf32[0] && 0xFE == utf32[1] && 0x00 == utf32[2] && 0x00 == utf32[3]: 58 | encoding = Encoding.GetEncoding(12000); // UTF-32, little endian byte order; available only to managed applications 59 | break; 60 | 61 | case var unicode when 0xFE == unicode[0] && 0xFF == unicode[1]: 62 | encoding = Encoding.GetEncoding(1201); // 1201 unicodeFFFE Unicode (UTF-16BE aka Unicode big endian) 63 | break; 64 | 65 | case var unicode when 0xFF == unicode[0] && 0xFE == unicode[1]: 66 | encoding = Encoding.GetEncoding(1200); // 1200 UTF-16 Unicode (UTF-16LE aka Unicode little endian) 67 | break; 68 | 69 | case var utf8 when HasBomMarker(utf8): 70 | encoding = new UTF8Encoding(true); // UTF-8 with BOM 71 | break; 72 | 73 | case var _ when file.IsInUtf8(): 74 | encoding = new UTF8Encoding(false); // UTF-8 without BOM 75 | break; 76 | 77 | case var _ when file.IsInAnsiLatin1(): 78 | encoding = Encoding.GetEncoding(1252); // ANSI Latin 79 | break; 80 | 81 | default: 82 | encoding = null; 83 | return false; 84 | } 85 | 86 | return true; 87 | } 88 | 89 | /// 90 | /// Gets the encoding. 91 | /// 92 | /// The file. 93 | /// if set to true [throws an exception if encoding is not detected]. 94 | /// 95 | /// Detected file encoding or null detection failed 96 | /// 97 | /// file 98 | /// 99 | public static Encoding GetEncoding(this FileInfo file, bool throwIfNotDetected = false) 100 | { 101 | if (null == file || !file.Exists) 102 | throw new ArgumentException($"{nameof(file)} must be a valid path to a file!"); 103 | 104 | var encoding = (file.TryGetEncoding(out var fileEncoding)) 105 | ? fileEncoding 106 | : null; 107 | 108 | if (null == encoding && throwIfNotDetected) 109 | { 110 | throw new InvalidDataException( 111 | $"Unable to detect encoding automatically of the following shared parameter file: {file.FullName}. " + 112 | "Most likely it's a non-Latin ANSI, e.g. ANSI Cyrillic, Hebrew, Arabic, Greek, Turkish, Vietnamese etc" 113 | ); 114 | } 115 | 116 | return encoding; 117 | } 118 | 119 | /// 120 | /// Determines whether [is in ANSI latin1] [the specified thresh hold]. 121 | /// 122 | /// The file. 123 | /// The threshold of mangled characters. 124 | /// 125 | /// true if [file is ANSI Latin1-encoded] and [the number of mangled characters is lower than specified threshold]; otherwise, false. 126 | /// 127 | /// file 128 | public static bool IsInAnsiLatin1(this FileInfo file, double mangledCharThreshold = 60.0) 129 | { 130 | if (null == file || !file.Exists) 131 | throw new ArgumentException($"{nameof(file)} must be a valid path to a file!"); 132 | 133 | var ansiLatin1Encoding = Encoding.GetEncoding(1252); 134 | var ansiText = File.ReadAllText(file.FullName, ansiLatin1Encoding); 135 | 136 | var unicodeLettersFound = UnicodeLetters.Matches(ansiText); 137 | var ansiMangledFound = AnsiLatin1Mangled.Matches(ansiText); 138 | var matchRate = ansiMangledFound.Count * 100 / unicodeLettersFound.Count; 139 | return (matchRate <= mangledCharThreshold); 140 | } 141 | 142 | /// 143 | /// Determines whether [has UTF-8 BOM marker]. 144 | /// 145 | /// The file. 146 | /// 147 | /// true if [the specified file] [has UTF-8 BOM marker]; otherwise, false. 148 | /// 149 | /// file 150 | public static bool HasBomMarker(this FileInfo file) 151 | { 152 | if (null == file || !file.Exists) 153 | throw new ArgumentException($"{nameof(file)} must be a valid path to a file!"); 154 | 155 | var buffer = new byte[10]; 156 | using (var fs = new FileStream(file.FullName, FileMode.Open, FileAccess.Read)) 157 | { 158 | fs.Read(buffer, 0, 10); 159 | #if !NETSTANDARD1_6 160 | fs.Close(); 161 | #endif 162 | } 163 | 164 | return 0xEF == buffer[0] && 0xBB == buffer[1] && 0xBF == buffer[2]; 165 | } 166 | 167 | /// 168 | /// Determines whether [has UTF-8 BOM marker] [the specified bytes]. 169 | /// 170 | /// The bytes. 171 | /// 172 | /// true if [the specified bytes] [has UTF-8 BOM marker]; otherwise, false. 173 | /// 174 | /// bytes 175 | public static bool HasBomMarker(byte[] bytes) 176 | { 177 | if (bytes == null || !bytes.Any()) 178 | throw new ArgumentException($"{nameof(bytes)} must be a non-empty array of bytes!"); 179 | 180 | return 0xEF == bytes[0] && 0xBB == bytes[1] && 0xBF == bytes[2]; 181 | } 182 | 183 | /// 184 | /// Determines whether [is in UTF-8]. 185 | /// 186 | /// The file. 187 | /// 188 | /// true if[the specified file] [is in UTF-8]; otherwise, false. 189 | /// 190 | /// file 191 | public static bool IsInUtf8(this FileInfo file) 192 | { 193 | if (null == file || !file.Exists) 194 | throw new ArgumentException($"{nameof(file)} must be a valid path to a file!"); 195 | 196 | try 197 | { 198 | using (var fileStream = new FileStream(file.FullName, FileMode.Open, FileAccess.Read)) 199 | { 200 | using var streamReader = new StreamReader(fileStream, new UTF8Encoding(file.HasBomMarker(), true), true); 201 | streamReader.ReadToEnd(); 202 | } 203 | return true; 204 | } 205 | catch (DecoderFallbackException) 206 | { 207 | return false; 208 | } 209 | } 210 | 211 | /// 212 | /// Detects the most used new line string / character in a file. 213 | /// 214 | /// The file information. 215 | /// The configuration file. 216 | /// 217 | /// configFile 218 | public static string DetectNewLine(this FileInfo fileInfo, string configFile) 219 | { 220 | if (string.IsNullOrWhiteSpace(configFile) || !File.Exists(configFile)) 221 | throw new ArgumentNullException(nameof(configFile)); 222 | 223 | configFile = File.ReadAllText(configFile); 224 | 225 | var windowsEndings = Regex.Matches(configFile, "\r\n").Count; 226 | var unixEndings = Regex.Matches(configFile, "\n").Count; 227 | var oldMacEndings = Regex.Matches(configFile, "\r").Count; 228 | 229 | return windowsEndings >= unixEndings && windowsEndings >= oldMacEndings 230 | ? "\r\n" 231 | : unixEndings > windowsEndings && unixEndings > oldMacEndings 232 | ? "\n" 233 | : oldMacEndings > windowsEndings && oldMacEndings > unixEndings 234 | ? "\r" 235 | : Environment.NewLine; 236 | } 237 | } 238 | } 239 | -------------------------------------------------------------------------------- /src/Helpers/YesNoConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Globalization; 4 | 5 | namespace Salaros.Configuration 6 | { 7 | public class YesNoConverter : BooleanConverter 8 | { 9 | protected readonly string yes, no; 10 | 11 | /// 12 | /// Initializes a new instance of the class. 13 | /// 14 | /// The yes. 15 | /// The no. 16 | /// 17 | /// yes 18 | /// or 19 | /// no 20 | /// or 21 | /// 22 | /// 23 | public YesNoConverter(string yes = "yes", string no = "no") 24 | { 25 | if (string.IsNullOrWhiteSpace(yes)) throw new ArgumentException(nameof(yes)); 26 | if (string.IsNullOrWhiteSpace(no)) throw new ArgumentException(nameof(no)); 27 | if (Equals(yes, no)) 28 | throw new ArgumentException($"Yes ({yes}) and No ({no}) values must be two different values!"); 29 | 30 | this.yes = yes; 31 | this.no = no; 32 | } 33 | 34 | /// 35 | /// 36 | /// Converts the given value object to the specified type, using the specified context and culture information. 37 | /// 38 | /// An that provides a format context. 39 | /// A . If is passed, the current culture is assumed. 40 | /// The to convert. 41 | /// The to convert the parameter to. 42 | /// 43 | /// An that represents the converted value. 44 | /// 45 | public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) 46 | { 47 | return value is bool boolean && destinationType == typeof(string) 48 | ? boolean ? yes : no 49 | : base.ConvertTo(context, culture, value, destinationType); 50 | } 51 | 52 | /// 53 | /// 54 | /// Converts the given value object to a Boolean object. 55 | /// 56 | /// An that provides a format context. 57 | /// A that specifies the culture to which to convert. 58 | /// The to convert. 59 | /// 60 | /// An that represents the converted . 61 | /// 62 | public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) 63 | { 64 | var booleanText = value as string; 65 | if (no.Equals(booleanText, StringComparison.OrdinalIgnoreCase)) 66 | return false; 67 | 68 | if (yes.Equals(booleanText, StringComparison.OrdinalIgnoreCase)) 69 | return true; 70 | 71 | return null; 72 | } 73 | 74 | /// 75 | /// Gets the value of Yes / True. 76 | /// 77 | /// 78 | /// The yes. 79 | /// 80 | public string Yes => yes; 81 | 82 | /// 83 | /// Gets the value of No / False. 84 | /// 85 | /// 86 | /// The no. 87 | /// 88 | public string No => no; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /tests/ConfigParser.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net6.0;net452 5 | false 6 | Salaros.Configuration.Tests 7 | portable 8 | 9 | 10 | 11 | ..\bin\$(Configuration)\ 12 | Salaros 13 | ConfigParser 14 | Zhmayev Yaroslav aka Salaros 15 | 16 | 17 | 18 | 2.3.* 19 | 2.4.* 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | all 30 | runtime; build; native; contentfiles; analyzers; buildtransitive 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | PreserveNewest 50 | 51 | 52 | 53 | 54 | 55 | PreserveNewest 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /tests/ConfigParser.Tests.csproj.DotSettings: -------------------------------------------------------------------------------- 1 |  2 | True -------------------------------------------------------------------------------- /tests/ConfigParserTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Threading; 4 | using Xunit; 5 | 6 | namespace Salaros.Configuration.Tests 7 | { 8 | public class ConfigParserTests 9 | { 10 | [Fact] 11 | public void ExistingFileIsUpdatedCorrectly() 12 | { 13 | var configFilePathTmp = Path.GetTempFileName(); 14 | File.WriteAllLines(configFilePathTmp, new[] 15 | { 16 | "[Settings]", 17 | "Recno = chocolate" 18 | }); 19 | 20 | var configFile = new ConfigParser(configFilePathTmp); 21 | configFile.SetValue("Settings", "Recno", "123"); 22 | configFile.Save(configFilePathTmp); 23 | 24 | Assert.Equal("[Settings]\r\nRecno = 123", configFile.ToString()); 25 | } 26 | 27 | [Fact] 28 | public void FileCanBeSavedToTheSamePath() 29 | { 30 | var configFilePathTmp = Path.GetTempFileName(); 31 | File.WriteAllLines(configFilePathTmp, new[] 32 | { 33 | "[Baz]", 34 | "Foo = bar" 35 | }); 36 | var dateModifiedOld = File.GetLastWriteTime(configFilePathTmp); 37 | 38 | var configFile = new ConfigParser(configFilePathTmp); 39 | configFile.Save(); 40 | 41 | Assert.True(File.GetLastWriteTime(configFilePathTmp).Ticks >= dateModifiedOld.Ticks); 42 | } 43 | 44 | [Fact] 45 | public void FileCanBeSavedToNewPath() 46 | { 47 | var configFilePathTmp = Path.GetTempFileName(); 48 | File.WriteAllLines(configFilePathTmp, new[] 49 | { 50 | "[Baz]", 51 | "Foo = bar" 52 | }); 53 | 54 | var configFile = new ConfigParser(configFilePathTmp); 55 | var configFilePathTmpNew = Path.GetTempFileName(); 56 | configFile.Save(configFilePathTmpNew); 57 | 58 | Assert.True(File.Exists(configFilePathTmpNew)); 59 | } 60 | 61 | [Fact] 62 | public void ArrayIsReadCorrectly() 63 | { 64 | // Set up 65 | var settings = new ConfigParserSettings { MultiLineValues = MultiLineValues.Simple | MultiLineValues.QuoteDelimitedValues }; 66 | var configFile = new ConfigParser( 67 | @"[Advanced] 68 | Select = 69 | select * from 70 | from table 71 | where ID = '5' 72 | ", 73 | settings); 74 | 75 | // Act 76 | var arrayValues = configFile.GetArrayValue("Advanced", "Select"); 77 | 78 | // Assert 79 | Assert.Equal(3, arrayValues?.Length ?? 0); 80 | Assert.Equal("select * from", arrayValues[0]); 81 | Assert.Equal("from table", arrayValues[1]); 82 | Assert.Equal("where ID = '5'", arrayValues[2]); 83 | } 84 | 85 | [Fact] 86 | public void JoinMultilineValueWorks() 87 | { 88 | // Set up 89 | var settings = new ConfigParserSettings { MultiLineValues = MultiLineValues.Simple }; 90 | var configFile = new ConfigParser( 91 | @"[Advanced] 92 | ExampleValue = Lorem ipsum dolor sit amet 93 | consectetur adipiscing elit 94 | sed do eiusmod tempor incididunt 95 | ", 96 | settings); 97 | 98 | // Act 99 | var multiLineJoint = configFile.JoinMultilineValue("Advanced", "ExampleValue", " "); 100 | 101 | // Assert 102 | Assert.Equal("Lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor incididunt", multiLineJoint); 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /tests/JsonHelpers/ConfigParserSettingsResolver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Text; 4 | using Koopman.CheckPoint.Json; 5 | using Newtonsoft.Json.Serialization; 6 | 7 | namespace Salaros.Configuration.Tests 8 | { 9 | internal class ConfigParserSettingsResolver : DefaultContractResolver 10 | { 11 | /// 12 | /// 13 | /// Creates a for the given type. 14 | /// 15 | /// Type of the object. 16 | /// 17 | /// A for the given type. 18 | /// 19 | protected override JsonPrimitiveContract CreatePrimitiveContract(Type objectType) 20 | { 21 | var contract = base.CreatePrimitiveContract(objectType); 22 | if (objectType == typeof(MultiLineValues)) 23 | { 24 | contract.Converter = new EnumConverter(); 25 | } 26 | return contract; 27 | } 28 | 29 | /// 30 | /// 31 | /// Creates a for the given type. 32 | /// 33 | /// Type of the object. 34 | /// 35 | /// A for the given type. 36 | /// 37 | protected override JsonObjectContract CreateObjectContract(Type objectType) 38 | { 39 | if (objectType == null) throw new ArgumentNullException(nameof(objectType)); 40 | 41 | var contract = base.CreateObjectContract(objectType); 42 | switch (objectType) 43 | { 44 | case var _ when objectType == typeof(Encoding) || objectType.IsSubclassOf(typeof(Encoding)): 45 | contract.Converter = new EncodingConverter(); 46 | break; 47 | 48 | case var _ when objectType == typeof(CultureInfo): 49 | contract.Converter = new CultureConverter(); 50 | break; 51 | } 52 | 53 | return contract; 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /tests/JsonHelpers/CultureConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using Newtonsoft.Json; 4 | 5 | namespace Salaros.Configuration.Tests 6 | { 7 | public class CultureConverter : JsonConverter 8 | { 9 | /// 10 | /// 11 | /// Determines whether this instance can convert the specified object type. 12 | /// 13 | /// Type of the object. 14 | /// 15 | /// true if this instance can convert the specified object type; otherwise, false. 16 | /// 17 | public override bool CanConvert(Type objectType) 18 | { 19 | return typeof(CultureInfo).IsAssignableFrom(objectType); 20 | } 21 | 22 | /// 23 | /// 24 | /// Writes the JSON representation of the object. 25 | /// 26 | /// The to write to. 27 | /// The value. 28 | /// The calling serializer. 29 | public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 30 | { 31 | writer.WriteValue(((CultureInfo)value).Name); 32 | } 33 | 34 | /// 35 | /// 36 | /// Reads the JSON representation of the object. 37 | /// 38 | /// The to read from. 39 | /// Type of the object. 40 | /// The existing value of object being read. 41 | /// The calling serializer. 42 | /// 43 | /// The object value. 44 | /// 45 | public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 46 | { 47 | return string.IsNullOrWhiteSpace(reader?.Value?.ToString()) 48 | ? CultureInfo.InvariantCulture 49 | : new CultureInfo((string)reader.Value); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /tests/JsonHelpers/EncodingConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Text; 4 | using Newtonsoft.Json; 5 | 6 | namespace Salaros.Configuration.Tests 7 | { 8 | public class EncodingConverter : JsonConverter 9 | { 10 | /// 11 | /// 12 | /// Determines whether this instance can convert the specified object type. 13 | /// 14 | /// Type of the object. 15 | /// 16 | /// true if this instance can convert the specified object type; otherwise, false. 17 | /// 18 | public override bool CanConvert(Type objectType) 19 | { 20 | return typeof(Encoding).IsAssignableFrom(objectType); 21 | } 22 | 23 | /// 24 | /// 25 | /// Writes the JSON representation of the object. 26 | /// 27 | /// The to write to. 28 | /// The value. 29 | /// The calling serializer. 30 | public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 31 | { 32 | var json = JsonConvert.SerializeObject((EncodingPortable)(Encoding)value); 33 | writer.WriteRawValue(json); 34 | } 35 | 36 | /// 37 | /// 38 | /// Reads the JSON representation of the object. 39 | /// 40 | /// The to read from. 41 | /// Type of the object. 42 | /// The existing value of object being read. 43 | /// The calling serializer. 44 | /// 45 | /// The object value. 46 | /// 47 | public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 48 | { 49 | if (!(reader is JsonTextReader)) 50 | return null; 51 | 52 | var encodingPortable = new EncodingPortable(); 53 | while (reader.Read()) 54 | { 55 | switch (reader.Value) 56 | { 57 | case nameof(EncodingPortable.CodePage) when reader.Read(): 58 | encodingPortable.CodePage = int.Parse(reader.Value?.ToString()); 59 | break; 60 | 61 | case nameof(EncodingPortable.WithPreamble) when reader.Read(): 62 | encodingPortable.WithPreamble = bool.Parse(reader.Value?.ToString()); 63 | break; 64 | 65 | case null: 66 | return (Encoding)encodingPortable; 67 | } 68 | } 69 | 70 | return null; 71 | } 72 | 73 | internal class EncodingPortable 74 | { 75 | public int CodePage { get; internal set; } = -1; 76 | 77 | public bool WithPreamble { get; internal set; } = true; 78 | 79 | // User-defined conversion from Digit to double 80 | public static implicit operator EncodingPortable(Encoding encoding) 81 | { 82 | if (encoding == null) throw new ArgumentNullException(nameof(encoding)); 83 | 84 | return new EncodingPortable 85 | { 86 | CodePage = encoding.CodePage, 87 | WithPreamble = encoding.GetPreamble()?.Any() ?? false 88 | }; 89 | } 90 | // User-defined conversion from double to Digit 91 | public static implicit operator Encoding(EncodingPortable encodingPortable) 92 | { 93 | if (encodingPortable == null) throw new ArgumentNullException(nameof(encodingPortable)); 94 | 95 | switch (encodingPortable.CodePage) 96 | { 97 | case 65001: 98 | return new UTF8Encoding(encodingPortable.WithPreamble); 99 | 100 | default: 101 | return Encoding.GetEncoding(encodingPortable.CodePage); 102 | } 103 | } 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /tests/JsonHelpers/EnumConverter.cs: -------------------------------------------------------------------------------- 1 | // MIT License 2 | // 3 | // Copyright (c) 2018 Tim Koopman 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 6 | // associated documentation files (the "Software"), to deal in the Software without restriction, 7 | // including without limitation the rights to use, copy, modify, merge, publish, distribute, 8 | // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in all copies or 12 | // substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 15 | // NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 18 | // OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | 20 | // Copyright (c) 2007 James Newton-King 21 | // 22 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 23 | // associated documentation files (the "Software"), to deal in the Software without restriction, 24 | // including without limitation the rights to use, copy, modify, merge, publish, distribute, 25 | // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 26 | // furnished to do so, subject to the following conditions: 27 | // 28 | // The above copyright notice and this permission notice shall be included in all copies or 29 | // substantial portions of the Software. 30 | // 31 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 32 | // NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 33 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 34 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 35 | // OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 36 | 37 | using Newtonsoft.Json; 38 | using System; 39 | using System.Collections.Generic; 40 | using System.Linq; 41 | using System.Reflection; 42 | using System.Runtime.Serialization; 43 | using System.Text.RegularExpressions; 44 | 45 | // ReSharper disable once CheckNamespace 46 | 47 | namespace Koopman.CheckPoint.Json 48 | { 49 | /// 50 | /// 51 | /// Converts an to and from its name string value. 52 | /// 53 | internal class EnumConverter : JsonConverter 54 | { 55 | #region Constructors 56 | 57 | /// 58 | /// Initializes a new instance of the class. 59 | /// 60 | public EnumConverter( 61 | StringCases outputCase, 62 | string outputSplitWords, 63 | OutputArrayOptions outputArray, 64 | bool nullAsZero) 65 | { 66 | OutputArray = outputArray; 67 | OutputCase = outputCase; 68 | OutputSplitWords = outputSplitWords; 69 | NullAsZero = nullAsZero; 70 | } 71 | 72 | public EnumConverter() : this(StringCases.NoChange, null, OutputArrayOptions.Auto, false) 73 | { 74 | } 75 | 76 | public EnumConverter(StringCases outputCase) : this(outputCase, null, OutputArrayOptions.Auto, false) 77 | { 78 | } 79 | 80 | public EnumConverter(StringCases outputCase, string outputSplitWords) : this(outputCase, outputSplitWords, OutputArrayOptions.Auto, false) 81 | { 82 | } 83 | 84 | #endregion Constructors 85 | 86 | #region Enums 87 | 88 | public enum OutputArrayOptions 89 | { 90 | Auto, 91 | Yes, 92 | No 93 | } 94 | 95 | // String case to write values in. 96 | public enum StringCases 97 | { 98 | NoChange, 99 | Uppercase, 100 | Lowercase 101 | } 102 | 103 | #endregion Enums 104 | 105 | #region Properties 106 | 107 | public bool NullAsZero { get; } 108 | public OutputArrayOptions OutputArray { get; } 109 | public StringCases OutputCase { get; } 110 | public string OutputSplitWords { get; } 111 | 112 | #endregion Properties 113 | 114 | #region Methods 115 | 116 | /// 117 | /// 118 | /// Determines whether this instance can convert the specified object type. 119 | /// 120 | /// Type of the object. 121 | /// 122 | /// true if this instance can convert the specified object type; otherwise, false. 123 | /// 124 | public override bool CanConvert(Type objectType) 125 | { 126 | var t = (GetIsNullable(objectType)) 127 | ? Nullable.GetUnderlyingType(objectType) 128 | : objectType; 129 | 130 | return t.GetTypeInfo().IsEnum; 131 | } 132 | 133 | /// 134 | /// Reads the JSON representation of the object. 135 | /// 136 | /// The to read from. 137 | /// Type of the object. 138 | /// The existing value of object being read. 139 | /// The calling serializer. 140 | /// The object value. 141 | public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 142 | { 143 | bool isNullable = GetIsNullable(objectType); 144 | var t = isNullable ? Nullable.GetUnderlyingType(objectType) : objectType; 145 | 146 | if (reader.TokenType == JsonToken.Null) 147 | { 148 | if (NullAsZero) 149 | return 0; 150 | 151 | if (!isNullable) 152 | throw new JsonSerializationException($"Cannot convert null value to {objectType}."); 153 | 154 | return null; 155 | } 156 | 157 | try 158 | { 159 | if (reader.TokenType == JsonToken.String) 160 | { 161 | string enumText = reader.Value.ToString(); 162 | 163 | if (enumText == string.Empty) 164 | { 165 | if (NullAsZero) 166 | return 0; 167 | 168 | if (isNullable) 169 | return null; 170 | } 171 | 172 | return DeserializeValue(enumText, t); 173 | } 174 | 175 | if (reader.TokenType == JsonToken.StartArray) 176 | { 177 | int result = 0; 178 | reader.Read(); 179 | while (reader.TokenType == JsonToken.String) 180 | { 181 | string enumText = reader.Value.ToString(); 182 | if (enumText != string.Empty) 183 | { 184 | result |= (int)DeserializeValue(enumText, t); 185 | } 186 | reader.Read(); 187 | } 188 | return result; 189 | } 190 | } 191 | catch (Exception) 192 | { 193 | throw new JsonSerializationException($"Error converting value {reader.Value} to type '{objectType}'."); 194 | } 195 | 196 | throw new JsonSerializationException($"Error converting value {reader.Value} to type '{objectType}'."); 197 | } 198 | 199 | /// 200 | /// Writes the JSON representation of the object. 201 | /// 202 | /// The to write to. 203 | /// The value. 204 | /// The calling serializer. 205 | public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 206 | { 207 | bool isNullable = GetIsNullable(value.GetType()); 208 | var t = isNullable ? Nullable.GetUnderlyingType(value.GetType()) : value.GetType(); 209 | 210 | bool asArray = (OutputArray == OutputArrayOptions.Auto) ? 211 | t.GetTypeInfo().GetCustomAttribute(typeof(FlagsAttribute)) != null : 212 | OutputArray == OutputArrayOptions.Yes; 213 | 214 | var e = (Enum)value; 215 | if (asArray) 216 | { 217 | writer.WriteStartArray(); 218 | 219 | if (value != null) 220 | { 221 | var values = new List(); string[] flags = t.GetTypeInfo().GetEnumNames(); 222 | foreach (string flag in flags) 223 | { 224 | var flagEnum = (Enum)Enum.Parse(t, flag); 225 | var flagInfo = t.GetTypeInfo().GetMember(flag); 226 | var ignore = flagInfo[0].GetCustomAttribute(typeof(JsonIgnoreAttribute)) != null; 227 | if (!ignore && e.HasFlag(flagEnum)) 228 | writer.WriteValue(SerializeValue(flag, t)); 229 | } 230 | } 231 | 232 | writer.WriteEndArray(); 233 | } 234 | else if (value == null) 235 | writer.WriteNull(); 236 | else 237 | { 238 | var flagInfo = t.GetTypeInfo().GetMember(e.ToString()); 239 | bool ignore = flagInfo[0].GetCustomAttribute(typeof(JsonIgnoreAttribute)) != null; 240 | if (ignore) 241 | writer.WriteNull(); 242 | else 243 | writer.WriteValue(SerializeValue(e.ToString(), t)); 244 | } 245 | } 246 | 247 | private static bool GetIsNullable(Type objectType) => (objectType.GetTypeInfo().IsGenericType && objectType.GetGenericTypeDefinition() == typeof(Nullable<>)); 248 | 249 | private object DeserializeValue(string value, Type type) 250 | { 251 | string enumText = value; 252 | // Check EnumMember Values first 253 | string[] flags = type.GetTypeInfo().GetEnumNames(); 254 | foreach (string flag in flags) 255 | { 256 | var flagEnum = (Enum)Enum.Parse(type, flag); 257 | var flagInfo = type.GetTypeInfo().GetMember(flag); 258 | var att = (EnumMemberAttribute)flagInfo[0].GetCustomAttribute(typeof(EnumMemberAttribute)); 259 | if (att != null && att.Value.Equals(enumText, StringComparison.CurrentCultureIgnoreCase)) 260 | return flagEnum; 261 | } 262 | 263 | // Remove SplitWordsWith from value so they can be matched to CamelCase Enum values 264 | if (OutputSplitWords != null) 265 | enumText = enumText.Replace(OutputSplitWords, ""); 266 | 267 | return (Enum)Enum.Parse(enumType: type, value: enumText, ignoreCase: true); 268 | } 269 | 270 | private string SerializeValue(string value, Type type) 271 | { 272 | string v = value; 273 | var enumInfo = type.GetTypeInfo().GetMember(v); 274 | 275 | if (enumInfo != null && enumInfo.Length == 1) 276 | { 277 | var att = (EnumMemberAttribute)enumInfo[0].GetCustomAttribute(typeof(EnumMemberAttribute)); 278 | if (att != null) 279 | return att.Value; 280 | } 281 | 282 | if (OutputSplitWords != null) 283 | v = v.CamelCaseToRegular(OutputSplitWords); 284 | 285 | switch (OutputCase) 286 | { 287 | case StringCases.Lowercase: 288 | v = v.ToLower(); 289 | break; 290 | 291 | case StringCases.Uppercase: 292 | v = v.ToUpper(); 293 | break; 294 | } 295 | 296 | return v; 297 | } 298 | 299 | #endregion Methods 300 | } 301 | 302 | public static class StringExtensions 303 | { 304 | /// 305 | /// Converts a string that is in CamelCase to a string array of separate words. 306 | /// 307 | /// The source string to convert. 308 | /// String array to words 309 | /// 310 | /// The following code: 311 | /// 312 | /// "ThisIsInCamelCase".CamelCaseToArray(); 313 | /// 314 | /// Result: 315 | /// ["This", "Is", "In", "Camel", "Case"] 316 | /// 317 | /// 318 | internal static string[] CamelCaseToArray(this string source) 319 | { 320 | return Regex.Matches(source, @"(^[a-z\d]+|[A-Z\d]+(?![a-z])|[A-Z][a-z\d]+)") 321 | .OfType() 322 | .Select(m => m.Value) 323 | .ToArray(); 324 | } 325 | 326 | /// 327 | /// Converts a string that is in CamelCase to a regular string. 328 | /// 329 | /// The source string to convert. 330 | /// The separator to use between words. 331 | /// 332 | /// The following code: 333 | /// 334 | /// "ThisIsInCamelCase".CamelCaseToRegular(); 335 | /// 336 | /// Result: 337 | /// "This Is In Camel Case" 338 | /// 339 | /// 340 | internal static string CamelCaseToRegular(this string source, string separator = " ") 341 | { 342 | string[] s = CamelCaseToArray(source); 343 | return string.Join(separator, s); 344 | } 345 | } 346 | } -------------------------------------------------------------------------------- /tests/Resources/Encoding/ANSI Cyrillic.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salaros/config-parser/3ed0da9ae156228154d816f12c85c8f7684c7c65/tests/Resources/Encoding/ANSI Cyrillic.txt -------------------------------------------------------------------------------- /tests/Resources/Encoding/ANSI Latin1.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salaros/config-parser/3ed0da9ae156228154d816f12c85c8f7684c7c65/tests/Resources/Encoding/ANSI Latin1.txt -------------------------------------------------------------------------------- /tests/Resources/Encoding/UTF16-BE.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salaros/config-parser/3ed0da9ae156228154d816f12c85c8f7684c7c65/tests/Resources/Encoding/UTF16-BE.txt -------------------------------------------------------------------------------- /tests/Resources/Encoding/UTF16-BE.txt.json: -------------------------------------------------------------------------------- 1 | { 2 | "Culture":"", 3 | "Encoding":{ 4 | "CodePage":1201 5 | }, 6 | "NewLine":"\n" 7 | } -------------------------------------------------------------------------------- /tests/Resources/Encoding/UTF16-LE.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salaros/config-parser/3ed0da9ae156228154d816f12c85c8f7684c7c65/tests/Resources/Encoding/UTF16-LE.txt -------------------------------------------------------------------------------- /tests/Resources/Encoding/UTF16-LE.txt.json: -------------------------------------------------------------------------------- 1 | { 2 | "Culture":"", 3 | "Encoding":{ 4 | "CodePage":1200 5 | }, 6 | "NewLine":"\n" 7 | } -------------------------------------------------------------------------------- /tests/Resources/Encoding/UTF32-BE.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salaros/config-parser/3ed0da9ae156228154d816f12c85c8f7684c7c65/tests/Resources/Encoding/UTF32-BE.txt -------------------------------------------------------------------------------- /tests/Resources/Encoding/UTF32-BE.txt.json: -------------------------------------------------------------------------------- 1 | { 2 | "Culture":"", 3 | "Encoding":{ 4 | "CodePage":12001 5 | }, 6 | "NewLine":"\n" 7 | } -------------------------------------------------------------------------------- /tests/Resources/Encoding/UTF7.txt: -------------------------------------------------------------------------------- 1 | +AFs-LoremIpsum+AF0- 2 | +1VytbcW0- +AD0- +rW27/Ky9yBzHWA- +vBzIBMdE- +xwTVXA- +yRHGlMgVzEXHWA- +whi5vcXQ- +rQDVWMXs- +swDRtbg5x1g- +x5C7OMXQ- +x1HVWK4w- +xwTVWMXs- +rW27/Ky9yBzHkLs41ozHWLl8- +tFg- +whg- +x4iy5A-. 3 | +A5UDuwO7A7cDvQO5A7oDrA- +AD0- +A7UDrwO9A7EDuQ- +A7EDwAO7A6w- +A60DvQOx- +A7oDtQOvA7wDtQO9A78- +A8cDyQPBA68Dwg- +A70DzAO3A7wDsQ- +A7MDuQOx- +A8QDvwPFA8I- +A7UDwAOxA7MDswO1A7sDvAOxA8QDrwO1A8I- +A8QDtwPC- +A8QDxQPAA78DswPBA7EDxgOvA7EDwg- +A7oDsQO5- +A8MDxAO/A7kDxwO1A7kDvwO4A7UDwwOvA7EDwg- 4 | +Ti1lhw- +AD0- +Tl958E5xZXBQR2WHYhaABVTRUUNlh2cs/ww- +Zi9TcFI3U8pjknJImIZX32JAXjh1KHaEhlpi32WHW1cwAg- 5 | +ZeVnLIqe- +AD0- +ZcUw7U6sl1JSKTC7MOAw7F8xZTkw1TDoMLls4l6cMEswcDB8YQ+QATBnMHyKv2OyW98wXzC5ZeWJf5HNMLEwojDKT09qSzDmMOAw3zCvmAZfhTB1MEswkzB8TrpZaIyvk+EwWTBzMF0wAg- 6 | +CTkJPwkCCSYJQA- +AD0- +CRsJKgk+CQg- +CRQJMA- +CQUJFQlNCTcJMA- +CS8JSwkcCSgJPg- +CQkJJglNCS8JSwkX- +CRUJPg- +CQ8JFQ- +CTgJPgknCT4JMAkj- +CSEJLglA- +CSoJPgkg- +CTkJSA- 7 | +BdAF4AXSBdwF2QXq- +AD0- +BdYF1QXUBdk- +BeIF1QXRBdMF1A- +Bd4F0QXVBeEF4QXq- +BekF0wXiBeoF1Q- +BekF3A- +BdQF5wXVBegF0A- +BeoF1AXZBdQ- +Bd4F1QXhBdcF6g- +BeIF3A- +BdkF0wXZ- +BdgF5wXYBeE- +BecF6AXZBdA- +BdsF0AXpBeg- +BdQF1QXQ- +BdkF0QXZBdg- +BdEF5AXoBdkF4QXqBdU- 8 | +BCAEQwRBBEEEOgQ4BDk- +AD0- Lorem ipsum +IBM- +BD8EQQQ1BDIENAQ+--+BDsEMARCBDgEPQRBBDoEOAQ5- +BEIENQQ6BEEEQg-, +BDoEPgRCBD4EQARLBDk- +BDgEQQQ/BD4EOwRMBDcEQwQ1BEIEQQRP- +BDQEOwRP- +BDIENQQx- +BDQEOAQ3BDAEOQQ9BDA-, +BEIEOAQ/BD4EMwRABDAERAQ4BDg- 9 | -------------------------------------------------------------------------------- /tests/Resources/Encoding/UTF7.txt.json: -------------------------------------------------------------------------------- 1 | { 2 | "Culture":"", 3 | "Encoding":{ 4 | "CodePage":65000 5 | }, 6 | "NewLine":"\n" 7 | } -------------------------------------------------------------------------------- /tests/Resources/Encoding/UTF8-Without-BOM.txt: -------------------------------------------------------------------------------- 1 | [LoremIpsum] 2 | 한국어 = 국민경제의 발전을 위한 중요정책의 수립에 관하여 대통령의 자문에 응하기 위하여 국민경제자문회의를 둘 수 있다. 3 | Ελληνικά = είναι απλά ένα κείμενο χωρίς νόημα για τους επαγγελματίες της τυπογραφίας και στοιχειοθεσίας 4 | 中文 = 也称乱数假文或者哑元文本, 是印刷及排版领域所常用的虚拟文字。 5 | 日本語 = 旅ロ京青利セムレ弱改フヨス波府かばぼ意送でぼ調掲察たス日西重ケアナ住橋ユムミク順待ふかんぼ人奨貯鏡すびそ。 6 | हिंदी = छपाई और अक्षर योजना उद्योग का एक साधारण डमी पाठ है 7 | אנגלית = זוהי עובדה מבוססת שדעתו של הקורא תהיה מוסחת על ידי טקטס קריא כאשר הוא יביט בפריסתו 8 | Русский = Lorem ipsum – псевдо-латинский текст, который используется для веб дизайна, типографии 9 | -------------------------------------------------------------------------------- /tests/Resources/Encoding/UTF8-Without-BOM.txt.json: -------------------------------------------------------------------------------- 1 | { 2 | "Culture":"", 3 | "Encoding":{ 4 | "CodePage":65001, 5 | "WithPreamble":false 6 | }, 7 | "NewLine":"\n" 8 | } -------------------------------------------------------------------------------- /tests/Resources/Encoding/UTF8.txt: -------------------------------------------------------------------------------- 1 | [LoremIpsum] 2 | 한국어 = 국민경제의 발전을 위한 중요정책의 수립에 관하여 대통령의 자문에 응하기 위하여 국민경제자문회의를 둘 수 있다. 3 | Ελληνικά = είναι απλά ένα κείμενο χωρίς νόημα για τους επαγγελματίες της τυπογραφίας και στοιχειοθεσίας 4 | 中文 = 也称乱数假文或者哑元文本, 是印刷及排版领域所常用的虚拟文字。 5 | 日本語 = 旅ロ京青利セムレ弱改フヨス波府かばぼ意送でぼ調掲察たス日西重ケアナ住橋ユムミク順待ふかんぼ人奨貯鏡すびそ。 6 | हिंदी = छपाई और अक्षर योजना उद्योग का एक साधारण डमी पाठ है 7 | אנגלית = זוהי עובדה מבוססת שדעתו של הקורא תהיה מוסחת על ידי טקטס קריא כאשר הוא יביט בפריסתו 8 | Русский = Lorem ipsum – псевдо-латинский текст, который используется для веб дизайна, типографии 9 | -------------------------------------------------------------------------------- /tests/Resources/Encoding/UTF8.txt.json: -------------------------------------------------------------------------------- 1 | { 2 | "Culture":"", 3 | "Encoding":{ 4 | "CodePage":65001 5 | }, 6 | "NewLine":"\n" 7 | } -------------------------------------------------------------------------------- /tests/Resources/RealWorld/CONFIG.SYS: -------------------------------------------------------------------------------- 1 | DOS=HIGH,UMB 2 | DEVICE=C:\DOS\HIMEM.SYS 3 | DEVICE=C:\DOS\EMM386.EXE RAM 4 | DEVICEHIGH=C:\DOS\ANSI.SYS 5 | FILES=30 6 | SHELL=C:\DOS\COMMAND.COM C:\DOS /E:512 /P -------------------------------------------------------------------------------- /tests/Resources/RealWorld/CONFIG.SYS.json: -------------------------------------------------------------------------------- 1 | { 2 | "MultiLineValues": [ 3 | "AllowEmptyTopSection" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /tests/Resources/RealWorld/FALLOUT.INI: -------------------------------------------------------------------------------- 1 | [General] 2 | SStartingCell= 3 | SCharGenQuest=0001f388 4 | SStartingCellY= 5 | SStartingCellX= 6 | SStartingWorld= 7 | 8 | STestFile10= 9 | STestFile9= 10 | STestFile8= 11 | STestFile7= 12 | STestFile6= 13 | STestFile5= 14 | STestFile4= 15 | STestFile3= 16 | STestFile2= 17 | STestFile1=Fallout3.esm 18 | 19 | sEssentialFileCacheList=Data\Fallout.esm|Data2\Fallout.esm, Data\Music\Special\MainTitle.mp3, Data\Fallout - Sound.bsa|Fallout - Sound.bsa, Data\Fallout - Voices.bsa|Fallout - Voices.bsa, Data\Fallout - MenuVoices.bsa|Fallout - MenuVoices.bsa 20 | sUnessentialFileCacheList=Data\Fallout - Meshes.bsa|Data2\Fallout - Meshes.bsa, Data\Fallout - Textures.bsa|Data2\Fallout - Textures.bsa, Data\Music\Dungeon\*.xma, Data\Music\Base\*.mp3, Data\Music\Battle\*.mp3, Data\Music\Explore\*.mp3, Data\Music\Public\*.mp3, Data\Music\Special\*.mp3 21 | bPreCullActors=1 22 | bTaskletActorSceneGraphUpdates=0 23 | bTaskletActorAnimMovementUpdates=1 24 | bAnimationUseBlendFromPose=1 25 | bEnableProfile=0 26 | bDrawSpellContact=0 27 | bRunMiddleLowLevelProcess=1 28 | iHoursToSleep=3 29 | bActorLookWithHavok=0 30 | SMainMenuMusicTrack=special\maintitle.mp3 31 | bUseEyeEnvMapping=1 32 | bFixFaceNormals=0 33 | bUseFaceGenHeads=1 34 | bFaceMipMaps=1 35 | bFaceGenTexturing=1 36 | SBetaCommentFileName=\\vault\Fallout\Fallout3\Beta_Comment.txt 37 | bDefaultCOCPlacement=0 38 | uGridDistantCount=20 39 | uGridsToLoad=5 40 | fGlobalTimeMultiplier=1.0000 41 | bNewAnimation=1 42 | bFixAIPackagesOnLoad=0 43 | bForceReloadOnEssentialCharacterDeath=1 44 | bKeepPluginWhenMerging=0 45 | bCreate Maps Enable=0 46 | SLocalSavePath=Saves\ 47 | SLocalMasterPath=Data\ 48 | bDisableDuplicateReferenceCheck=1 49 | bTintMipMaps=0 50 | uInterior Cell Buffer=3 51 | uExterior Cell Buffer=36 52 | iIntroSequencePriority=3 53 | bPreloadIntroSequence=1 54 | fStaticScreenWaitTime=3.0000 55 | SMainMenuMovieIntro= 56 | SIntroSequence= 57 | sIntroMovie=Fallout INTRO Vsk.bik 58 | iFPSClamp=0 59 | bRunVTuneTest=0 60 | STestFile1= 61 | bActivateAllQuestScripts=0 62 | bUseThreadedBlood=1 63 | bUseThreadedMorpher=1 64 | bBorderRegionsEnabled=1 65 | bDisableHeadTracking=0 66 | bTrackAllDeaths=0 67 | uiFaceGenMaxEGTDataSize=67108864 68 | uiFaceGenMaxEGMDataSize=67108864 69 | bPreemptivelyUnloadCells=0 70 | iNumBitsForFullySeen=248 71 | iPreloadSizeLimit=26214400 72 | bUseHardDriveCache=0 73 | bEnableBoundingVolumeOcclusion=1 74 | bDisplayBoundingVolumes=0 75 | bUseThreadedTempEffects=1 76 | bUseThreadedParticleSystem=1 77 | bExternalLODDataFiles=1 78 | bCheckCellOffsetsOnInit=0 79 | uGridDistantTreeRange=5 80 | bCreateShaderPackage=0 81 | bWarnOnMissingFileEntry=0 82 | bAllowScriptedAutosave=0 83 | uGridDistantTreeRangeCity=4 84 | uGridDistantCountCity=4 85 | iSaveGameBackupCount=1 86 | bDisplayMissingContentDialogue=1 87 | SSaveGameSafeCellID=2AEEA 88 | bUseThreadedAI=1 89 | INumHWThreads=4 90 | bChangeTimeMultSlowly=1 91 | bCheckPurgedTextureList=0 92 | bAnimateDoorPhysics=0 93 | sLanguage=ENGLISH 94 | 95 | [Display] 96 | fDecalLifetime=10.0000 97 | bEquippedTorchesCastShadows=0 98 | bReportBadTangentSpace=0 99 | bStaticMenuBackground=1 100 | bForcePow2Textures=0 101 | bForce1XShaders=0 102 | bHighQuality20Lighting=0 103 | bAllow20HairShader=1 104 | bAllowScreenShot=1 105 | iMultiSample=0 106 | bDoTallGrassEffect=1 107 | bForceMultiPass=1 108 | bDoTexturePass=1 109 | bDoSpecularPass=1 110 | bDoDiffusePass=1 111 | bDoAmbientPass=1 112 | bImageSpaceEffects=1 113 | bDoCanopyShadowPass=1 114 | bDrawShadows=0 115 | bUseRefractionShader=1 116 | bUse Shaders=1 117 | iNPatchNOrder=0 118 | iNPatchPOrder=0 119 | iNPatches=0 120 | iLocation Y=5 121 | iLocation X=5 122 | bFull Screen=1 123 | iAdapter=0 124 | iScreenShotIndex=0 125 | SScreenShotBaseName=ScreenShot 126 | iAutoViewMinDistance=2000 127 | iAutoViewHiFrameRate=40 128 | iAutoViewLowFrameRate=20 129 | bAutoViewDistance=0 130 | fDefaultFOV=95.0000 131 | fNearDistance=5 132 | fFarDistance=1000.0000 133 | iDebugTextLeftRightOffset=10 134 | iDebugTextTopBottomOffset=20 135 | bShowMenuTextureUse=1 136 | fLightLODDefaultStartFade=1000.0 137 | fLightLODRange=500.0 138 | fLightLODMinStartFade=200.0 139 | fLightLODMaxStartFade=3500.0 140 | fShadowLODDefaultStartFade=200.0 141 | fShadowLODRange=200.0 142 | fShadowLODMinStartFade=100.0 143 | fShadowLODMaxStartFade=1000.0 144 | fSpecularLODDefaultStartFade=500.0 145 | fSpecularLODRange=300.0 146 | fSpecularLODMinStartFade=200.0 147 | fSpecularLODMaxStartFade=2000.0 148 | fGamma=1.0000 149 | bAllow30Shaders=0 150 | iTexMipMapMinimum=0 151 | bDoStaticAndArchShadows=0 152 | bDoActorShadows=1 153 | fNoLODFarDistancePct=1.0000 154 | fNoLODFarDistanceMax=10240.0000 155 | fNoLODFarDistanceMin=100.0000 156 | fEyeEnvMapLOD2=800.0000 157 | fEyeEnvMapLOD1=500.0000 158 | fEnvMapLOD2=1800.0000 159 | fEnvMapLOD1=1500.0000 160 | fGammaMax=0.6000 161 | fGammaMin=1.4000 162 | iMaxDecalsPerFrame=10 163 | iActorShadowCount=4 164 | bIgnoreResolutionCheck=0 165 | fSpecualrStartMax=1000.0000 166 | fSpecularStartMin=0.0000 167 | iActorShadowIntMax=10 168 | iActorShadowIntMin=0 169 | iActorShadowExtMax=10 170 | iActorShadowExtMin=0 171 | bDynamicWindowReflections=1 172 | fShadowFadeTime=1.0000 173 | iPresentInterval=0 174 | bDecalsOnSkinnedGeometry=1 175 | uVideoDeviceIdentifierPart4=0 176 | uVideoDeviceIdentifierPart3=0 177 | uVideoDeviceIdentifierPart2=0 178 | uVideoDeviceIdentifierPart1=0 179 | iShadowFilter=0 180 | bAllowPartialPrecision=1 181 | iShadowMapResolution=256 182 | bShadowsOnGrass=0 183 | bActorSelfShadowing=0 184 | iActorShadowCountInt=2 185 | iActorShadowCountExt=2 186 | fPipboy1stPersonFOV=47.0 187 | fDefault1stPersonFOV=55.0000 188 | bLODNoiseAniso=1 189 | iMaxAnisotropy=8 190 | fLandLOFadeSeconds=15.0 191 | 192 | [Controls] 193 | bAlwaysRunByDefault=1 194 | bBackground Mouse=0 195 | bBackground Keyboard=1 196 | fForegroundMouseAccelBase=0 197 | fForegroundMouseAccelTop=0 198 | fForegroundMouseBase=0 199 | fForegroundMouseMult=0 200 | 201 | [Water] 202 | bUseWaterShader=0 203 | bUseWaterReflections=0 204 | bUseWaterRefractions=0 205 | bUseWaterDepth=1 206 | bUseWaterHiRes=0 207 | bUseWaterDisplacements=1 208 | bUseWaterLOD=1 209 | bReflectExplosions=0 210 | bAutoWaterSilhouetteReflections=0 211 | bForceHighDetailReflections=0 212 | bForceLowDetailReflections=0 213 | fTileTextureDivisor=4.7500 214 | fSurfaceTileSize=2048.0000 215 | fNearWaterOutdoorTolerance=1024.0000 216 | fNearWaterIndoorTolerance=512.0000 217 | fNearWaterUnderwaterVolume=0.9000 218 | fNearWaterUnderwaterFreq=0.3000 219 | uNearWaterPoints=8 220 | uNearWaterRadius=1000 221 | uSurfaceFPS=12 222 | 223 | [Audio] 224 | fASFadeInTime=3.0 225 | fASFadeOutTime=10.0 226 | fRegionLoopFadeInTime=5.0 227 | fRegionLoopFadeOutTime=5.0 228 | fAudioDebugDelay=0.0 229 | bEnableAudio=1 230 | bEnableAudioCache=1 231 | bMultiThreadAudio=1 232 | bEnableEnviroEffectsOnPC=0 233 | ; cache sizes in kilobytes 234 | iAudioCacheSize=2048 235 | iMaxSizeForCachedSound=256 236 | bUseAudioDebugInformation=1 237 | fAudioDebugDelay=0.0000 238 | fDefaultMasterVolume=1.0000 239 | fDefaultFootVolume=0.5000 240 | fDefaultMusicVolume=0.3000 241 | fDefaultRadioVolume=0.5000 242 | fDefaultEffectsVolume=1.0000 243 | fDefaultVoiceVolume=0.7500 244 | iMaxImpactSoundCount=32 245 | fMaxFootstepDistance=1100.0000 246 | fPlayerFootVolume=0.6500 247 | iCollisionSoundTimeDelta=150 248 | iRadioUpdateInterval=250 249 | fMinSoundVel=90.0000 250 | fDialogMinDistance=125.00 251 | fDialogMaxDistance=1800.00 252 | fMainMenuMusicVolume=0.6 253 | fDBVoiceAttenuationIn2D=2.0 254 | fCollisionSoundHeavyThreshold=60.0 255 | fDialogueFadeDecibels=6.0 256 | fDialogueFadeSecondsIn=2.0 257 | fDialogueFadeSecondsOut=1.0 258 | fDialogueHeadPitchExaggeration=2.0 259 | fDialogueHeadRollExaggeration=2.0 260 | fDialogueHeadYawExaggeration=2.0 261 | fHardLandingDamageThreshold=500.0 262 | fWoodMediumMassMin=7.0 263 | fWoodLargeMassMin=15.0 264 | fStoneMediumMassMin=5.0 265 | fStoneLargeMassMin=30.0 266 | fEarthMediumMassMin=5.0 267 | fEarthLargeMassMin=30.0 268 | fSkinMediumMassMin=5.0 269 | fSkinLargeMassMin=30.0 270 | fMetalMediumMassMin=8.0 271 | fMetalLargeMassMin=25.0 272 | fRadioDialogMute=0.50 273 | fFilterDistortionGain=-7.5 274 | fFilterPEQGain=-15.0 275 | fFilterdBAttenuation=11.5 276 | 277 | [Pathfinding] 278 | bDrawPathsDefault=0 279 | bPathMovementOnly=0 280 | bDrawSmoothFailures=0 281 | bDebugSmoothing=0 282 | bSmoothPaths=1 283 | bSnapToAngle=0 284 | bDebugAvoidance=0 285 | bDisableAvoidance=0 286 | bBackgroundPathing=1 287 | bUseObstacleAvoidance=1 288 | bBackgroundNavmeshUpdate=1 289 | 290 | [MAIN] 291 | bEnableBorderRegion=1 292 | fLowPerfCombatantVoiceDistance=1000.0000 293 | iDetectionHighNumPicks=40 294 | fQuestScriptDelayTime=5.0000 295 | bCloneModelsInBackground=0 296 | iLastHDRSetting=-1 297 | 298 | [HAVOK] 299 | bDisablePlayerCollision=0 300 | fJumpAnimDelay=0.7500 301 | bTreeTops=0 302 | iSimType=1 303 | bPreventHavokAddAll=0 304 | bPreventHavokAddClutter=0 305 | fMaxTime=0.016 306 | bHavokDebug=0 307 | fRF=1000.0000 308 | fOD=0.9000 309 | fSE=0.3000 310 | fSD=0.9800 311 | iResetCounter=5 312 | fMoveLimitMass=95.0000 313 | iUpdateType=0 314 | bHavokPick=0 315 | fCameraCasterSize=10.0000 316 | iHavokSkipFrameCountTEST=0 317 | iNumHavokThreads=1 318 | fChaseDeltaMult=0.0500 319 | bAddBipedWhenKeyframed=1 320 | fQuadrupedPitchMult=1.0000 321 | iEntityBatchRemoveRate=100 322 | iMaxPicks=40 323 | 324 | [RagdollAnim] 325 | bRagdollFeedback=1 326 | fCameraDist=1000.0 327 | fHierarchyGain=0.17 328 | fVelocityDamping=0.0 329 | fAccelerationGain=1.0 330 | fVelocityGain=0.6 331 | fPositionGain=0.05 332 | fPositionMaxLinearVelocity=14.0 333 | fPositionMaxAngularVelocity=18.0 334 | fSnapGain=0.1 335 | fSnapMaxLinearVelocity=3.0 336 | fSnapMaxAngularVelocity=0.3 337 | fSnapMaxLinearDistance=0.3 338 | fSnapMaxAngularDistance=1.0 339 | 340 | [FootIK] 341 | fOnOffGain=0.5 342 | fGroundAscendingGain=0.4 343 | fGroundDescendingGain=0.4 344 | fFootRaisedGain=0.9000 345 | fFootPlantedGain=1.0000 346 | bFootPlacementOn=1 347 | fPelvisUpDownBias=0.75 348 | fPelvisOffsetDamping=0.2 349 | fVertErrorGain=0.5 350 | fOriginalGroundHeightMS=-0.11 351 | fAnkleOffset=0.2000 352 | fRagdollFeedback=0.7 353 | 354 | [LookIK] 355 | fLookAtTargetGain=0.3 356 | fLookAtGain=0.045 357 | 358 | [Interface] 359 | fKeyRepeatInterval=50.0000 360 | fKeyRepeatTime=500.0000 361 | fActivatePickSphereRadius=16.0000 362 | fMenuModeAnimBlend=0.0000 363 | iSafeZoneXWide=15 364 | iSafeZoneYWide=15 365 | iSafeZoneX=15 366 | iSafeZoneY=15 367 | bAllowConsole=1 368 | bActivatePickUseGamebryoPick=0 369 | bUseFuzzyPicking=1 370 | fMenuBGBlurRadius=2.0000 371 | fMenuPlayerLightDiffuseBlue=0.8000 372 | fMenuPlayerLightDiffuseGreen=0.8000 373 | fMenuPlayerLightDiffuseRed=0.8000 374 | fMenuPlayerLightAmbientBlue=0.2500 375 | fMenuPlayerLightAmbientGreen=0.2500 376 | fMenuPlayerLightAmbientRed=0.2500 377 | iMaxViewCasterPicksGamebryo=10 378 | iMaxViewCasterPicksHavok=10 379 | iMaxViewCasterPicksFuzzy=5 380 | fInterfaceTintB=0.8824 381 | fInterfaceTintG=0.9843 382 | fInterfaceTintR=0.6314 383 | bUseImageSpaceMenuFX=0 384 | 385 | iSystemColorTerminalRed=33 386 | iSystemColorTerminalGreen=231 387 | iSystemColorTerminalBlue=121 388 | 389 | iSystemColorSystemRed=26 390 | iSystemColorSystemGreen=255 391 | iSystemColorSystemBlue=128 392 | 393 | iSystemColorMainMenuRed=199 394 | iSystemColorMainMenuGreen=255 395 | iSystemColorMainMenuBlue=165 396 | 397 | iSystemColorPipboyRed=26 398 | iSystemColorPipboyGreen=255 399 | iSystemColorPipboyBlue=128 400 | 401 | iSystemColorHUDAltRed=255 402 | iSystemColorHUDAltGreen=67 403 | iSystemColorHUDAltBlue=42 404 | 405 | iSystemColorHUDMainRed=26 406 | iSystemColorHUDMainGreen=255 407 | iSystemColorHUDMainBlue=128 408 | 409 | fRSMFaceSliderDefaultMin=-3.5 410 | fRSMFaceSliderDefaultMax=3.5 411 | 412 | fPopUpBackgroundOpacity=0.87 413 | fMenuBackgroundOpacity=0.76 414 | bHideUnavailablePerks=0 415 | 416 | 417 | [Loading] 418 | sWelcomeScreen1=loading_screen01 419 | sWelcomeScreen2=loading_screen_bethsoft 420 | sWelcomeScreen3=loading_screen_BGS 421 | sWelcomeScreen4=loading_screen_legal 422 | sMainMenuBackground=main_background 423 | sTitleMusic=MainTitle 424 | sInitialSound=fx\ui\loadscreen\initial\ui_loadscreen_initial.wav 425 | iMaxScreens=4 426 | iMaxScreens_MainMenu=20 427 | fLoadingTextUpdateInterval=10.0000 428 | fLoadingBkgdUpdateInterval=10.0000 429 | fMainMenuBkgdUpdateInterval=10.0000 430 | fLoadingInitUpdateInterval=5.0000 431 | iNumLocationSpecificScreens=1 432 | 433 | 434 | [Menu] 435 | fCreditsScrollSpeed=40.0000 436 | iConsoleTextYPos=940 437 | iConsoleTextXPos=30 438 | iConsoleVisibleLines=23 439 | iConsoleHistorySize=9001 440 | rDebugTextColor=255,251,233 441 | iConsoleFont=2 442 | iDebugTextFont=3 443 | 444 | [GamePlay] 445 | bHealthBarShowing=0 446 | fHealthBarFadeOutSpeed=1.0000 447 | fHealthBarSpeed=80.0000 448 | fHealthBarHeight=4.0000 449 | fHealthBarWidth=40.0000 450 | fHealthBarEmittanceFadeTime=0.5000 451 | fHealthBarEmittanceTime=1.5000 452 | bAllowHavokGrabTheLiving=0 453 | bEssentialTakeNoDamage=1 454 | iDetectionPicks=21 455 | 456 | [Fonts] 457 | sFontFile_1=Textures\Fonts\Glow_Monofonto_Large.fnt 458 | sFontFile_2=Textures\Fonts\Monofonto_Large.fnt 459 | sFontFile_3=Textures\Fonts\Glow_Monofonto_Medium.fnt 460 | sFontFile_4=Textures\Fonts\Monofonto_VeryLarge02_Dialogs2.fnt 461 | sFontFile_5=Textures\Fonts\Fixedsys_Comp_uniform_width.fnt 462 | sFontFile_6=Textures\Fonts\Glow_Monofonto_VL_dialogs.fnt 463 | sFontFile_7=Textures\Fonts\Baked-in_Monofonto_Large.fnt 464 | sFontFile_8=Textures\Fonts\Glow_Futura_Caps_Large.fnt 465 | 466 | [SpeedTree] 467 | iTreeClonesAllowed=1 468 | fCanopyShadowGrassMult=1.0000 469 | iCanopyShadowScale=512 470 | fTreeForceMaxBudAngle=-1.0000 471 | fTreeForceMinBudAngle=-1.0000 472 | fTreeForceLeafDimming=-1.0000 473 | fTreeForceBranchDimming=-1.0000 474 | fTreeForceCS=-1.0000 475 | fTreeForceLLA=-1.0000 476 | fTreeLODExponent=1.0000 477 | bEnableTrees=1 478 | bForceFullLOD=0 479 | fLODTreeMipMapLODBias=-0.7500 480 | fLocalTreeMipMapLODBias=-0.2500 481 | 482 | [Debug] 483 | bDebugFaceGenCriticalSection=0 484 | bDebugFaceGenMultithreading=0 485 | bDebugSaveBuffer=0 486 | 487 | [BackgroundLoad] 488 | bBackgroundPathing=1 489 | bUseMultiThreadedFaceGen=1 490 | bBackgroundCellLoads=1 491 | iAnimaitonClonePerLoop=5 492 | bUseMultiThreadedTrees=1 493 | iExteriorPriority=50 494 | iBackgroundLoadFaceMult=200 495 | fBackgroundLoadingPerLoop=20.0000 496 | fBackgroundLoadClonedPerLoop=5.0000 497 | iBackgroundLoadExtraMaxFPS=20 498 | iBackgroundLoadExtraMinFPS=10 499 | iBackgroundLoadExtraMax=3000 500 | iBackgroundLoadExtraMin=5 501 | iBackgroundLoadExtraMilliseconds=2 502 | iBackgroundLoadTreeMilliseconds=7 503 | iBackgroundLoadMilliseconds=1 504 | iBackgroundLoadLoading=1 505 | bUseBackgroundFileLoader=0 506 | bBackgroundLoadLipFiles=0 507 | bLoadBackgroundFaceGen=0 508 | bLoadHelmetsInBackground=1 509 | iAnimationClonePerLoop=5 510 | bSelectivePurgeUnusedOnFastTravel=0 511 | bCloneModelsInBackground=0 512 | 513 | [LOD] 514 | fLODLandDropAmount=230.0000 515 | fLodDistance=500.0000 516 | bUseFaceGenLOD=0 517 | iLODTextureTiling=2 518 | iLODTextureSizePow2=8 519 | fLODNormalTextureBlend=0.5000 520 | bDisplayLODLand=1 521 | bDisplayLODBuildings=0 522 | bLODPopTrees=0 523 | bLODPopActors=0 524 | bLODPopItems=0 525 | bLODPopObjects=0 526 | fLODFadeOutMultItems=3 527 | fLODFadeOutMultObjects=5 528 | fLODFadeOutMultActors=6 529 | fLODMultLandscape=1.0000 530 | fLODMultTrees=0.5000 531 | fLODMultActors=1.0000 532 | fLODMultItems=1.0000 533 | fLODMultObjects=5 534 | iFadeNodeMinNearDistance=500 535 | fLODFadeOutPercent=0.6000 536 | fFadeOutThreshold=0.3000 537 | fFadeInThreshold=0.7000 538 | fFadeInTimet=2.0 539 | fFadeOutTime=2.0 540 | fDistanceMultiplier=1 541 | fLODBoundRadiusMult=10 542 | fObjectLODMax=15.0 543 | fObjectLODMin=1.0 544 | fObjectLODDefault=5 545 | fItemLODMax=15.0 546 | fItemLODMin=1.0 547 | fItemLODDefault=2 548 | fActorLODMax=15.0 549 | fActorLODMin=2.0 550 | fActorLODDefault=5 551 | fTreeLODMax=2.0000 552 | fTreeLODMin=0.0200 553 | fTreeLODDefault=0.5000 554 | bLODUseCombinedLandNormalMaps=1 555 | bForceHideLODLand=0 556 | fLODLandVerticalBias=0.0000 557 | fTalkingDistance=1000.0000 558 | iBoneLODForce=-1 559 | fLODQuadMinLoadDistance=65536.0000 560 | bDisplayLODTrees=1 561 | bDisplayLODBuildings=1 562 | fLODFadeOutActorMultInterior=1.0000 563 | fLODFadeOutItemMultInterior=1.0000 564 | fLODFadeOutObjectMultInterior=1.0000 565 | fLODFadeOutActorMultCity=1.0000 566 | fLODFadeOutItemMultCity=1.0000 567 | fLODFadeOutObjectMultCity=1.0000 568 | fLODFadeOutActorMultComplex=1.0000 569 | fLODFadeOutItemMultComplex=1.0000 570 | fLODFadeOutObjectMultComplex=1.0000 571 | 572 | [Weather] 573 | fSunGlareSize=800.0000 574 | fSunBaseSize=750.0000 575 | bPrecipitation=1 576 | fAlphaReduce=1.0000 577 | SBumpFadeColor=255,255,255,255 578 | SLerpCloseColor=255,255,255,255 579 | SEnvReduceColor=255,255,255,255 580 | 581 | [Voice] 582 | SFileTypeLTF=ltf 583 | SFileTypeLip=lip 584 | SFileTypeSource=wav 585 | SFileTypeGame=ogg 586 | 587 | [Grass] 588 | iMinGrassSize=80 589 | bGrassPointLighting=0 590 | bDrawShaderGrass=1 591 | iGrassDensityEvalSize=2 592 | iMaxGrassTypesPerTexure=2 593 | fWaveOffsetRange=1.7500 594 | fGrassWindMagnitudeMax=125.0000 595 | fGrassWindMagnitudeMin=5.0000 596 | fTexturePctThreshold=0.0000 597 | fGrassMinStartFadeDistance=0.0 598 | fGrassMaxStartFadeDistance=7000.0 599 | fGrassDefaultStartFadeDistance=3500.0 600 | fGrassFadeRange=1000.0 601 | 602 | [Landscape] 603 | bCurrentCellOnly=0 604 | bPreventSafetyCheck=0 605 | fLandTextureTilingMult=2.0000 606 | fLandFriction=2.5000 607 | iLandBorder2B=0 608 | iLandBorder2G=0 609 | iLandBorder2R=0 610 | iLandBorder1B=0 611 | iLandBorder1G=255 612 | iLandBorder1R=255 613 | SDefaultLandDiffuseTexture=DirtWasteland01.dds 614 | SDefaultLandNormalTexture=DirtWasteland01_N.dds 615 | 616 | [bLightAttenuation] 617 | fQuadraticRadiusMult=1.0000 618 | fLinearRadiusMult=1.0000 619 | bOutQuadInLin=0 620 | fConstantValue=0.0000 621 | fQuadraticValue=16.0000 622 | fLinearValue=3.0000 623 | uQuadraticMethod=2 624 | uLinearMethod=1 625 | fFlickerMovement=8.0000 626 | bUseQuadratic=1 627 | bUseLinear=0 628 | bUseConstant=0 629 | 630 | [BlurShaderHDRInterior] 631 | fTargetLUM=1.0000 632 | fUpperLUMClamp=1.0000 633 | fEmissiveHDRMult=1.0000 634 | fEyeAdaptSpeed=0.5000 635 | fBrightScale=2.2500 636 | fBrightClamp=0.2250 637 | fBlurRadius=7.0000 638 | iNumBlurpasses=1 639 | 640 | [BlurShaderHDR] 641 | fTargetLUM=1.0000 642 | fUpperLUMClamp=1.0000 643 | fGrassDimmer=1.5000 644 | fTreeDimmer=1.0000 645 | fEmissiveHDRMult=1.0000 646 | fEyeAdaptSpeed=0.5000 647 | fSunlightDimmer=1.5000 648 | fSIEmmisiveMult=1.0000 649 | fSISpecularMult=1.0000 650 | fSkyBrightness=0.5000 651 | fSunBrightness=0.0000 652 | fBrightScale=2.2500 653 | fBrightClamp=0.2250 654 | fBlurRadius=7.0000 655 | iNumBlurpasses=1 656 | iBlendType=2 657 | bDoHighDynamicRange=1 658 | 659 | [BlurShader] 660 | fSunlightDimmer=1.0000 661 | fSIEmmisiveMult=1.0000 662 | fSISpecularMult=1.0000 663 | fSkyBrightness=0.5000 664 | fSunBrightness=0.0000 665 | fAlphaAddExterior=0.2000 666 | fAlphaAddInterior=0.7000 667 | iBlurTexSize=256 668 | fBlurRadius=0.0300 669 | iNumBlurpasses=1 670 | iBlendType=2 671 | bUseBlurShader=1 672 | 673 | [GethitShader] 674 | fBlurAmmount=0.5000 675 | fBlockedTexOffset=0.0010 676 | fHitTexOffset=0.0050 677 | 678 | [MESSAGES] 679 | bBlockMessageBoxes=0 680 | bSkipProgramFlows=1 681 | bAllowYesToAll=1 682 | bDisableWarning=1 683 | iFileLogging=0 684 | bSkipInitializationFlows=1 685 | bUseWindowsMessageBox=0 686 | 687 | [DistantLOD] 688 | bUseLODLandData=0 689 | fFadeDistance=12288.0000 690 | iDistantLODGroupWidth=8 691 | 692 | [GeneralWarnings] 693 | SGeneralMasterMismatchWarning=One or more plugins could not find the correct versions of the master files they depend on. Errors may occur during load or game play. Check the "Warnings.txt" file for more information. 694 | 695 | SMasterMismatchWarning=One of the files that "%s" is dependent on has changed since the last save. 696 | This may result in errors. Saving again will clear this message 697 | but not necessarily fix any errors. 698 | 699 | [Archive] 700 | SMasterMiscArchiveFileName=Fallout - Misc.bsa 701 | SMasterVoicesArchiveFileName1=Fallout - Voices.bsa 702 | SMasterVoicesArchiveFileName2=Fallout - MenuVoices.bsa 703 | SMasterSoundsArchiveFileName=Fallout - Sound.bsa 704 | SMasterTexturesArchiveFileName1=Fallout - Textures.bsa 705 | SMasterMeshesArchiveFileName=Fallout - Meshes.bsa 706 | SInvalidationFile=ArchiveInvalidation.txt 707 | iRetainFilenameOffsetTable=1 708 | iRetainFilenameStringTable=1 709 | iRetainDirectoryStringTable=1 710 | bCheckRuntimeCollisions=0 711 | bInvalidateOlderFiles=0 712 | bUseArchives=1 713 | SArchiveList=Fallout - Textures.bsa, Fallout - Meshes.bsa, Fallout - Voices.bsa, Fallout - Sound.bsa, Fallout - MenuVoices.bsa, Fallout - Misc.bsa 714 | 715 | [CameraPath] 716 | iTake=0 717 | SDirectoryName=TestCameraPath 718 | iFPS=60 719 | SNif=Test\CameraPath.nif 720 | 721 | [Absorb] 722 | fAbsorbGlowColorB=1.0000 723 | fAbsorbGlowColorG=0.6000 724 | fAbsorbGlowColorR=0.0000 725 | fAbsorbCoreColorB=1.0000 726 | fAbsorbCoreColorG=1.0000 727 | fAbsorbCoreColorR=1.0000 728 | iAbsorbNumBolts=1 729 | fAbsorbBoltGrowWidth=0.0000 730 | fAbsorbBoltSmallWidth=7.0000 731 | fAbsorbTortuosityVariance=2.0000 732 | fAbsorbSegmentVariance=7.0000 733 | fAbsorbBoltsRadius=5.0000 734 | 735 | [TestAllCells] 736 | bFileShowTextures=1 737 | bFileShowIcons=1 738 | bFileSkipIconChecks=0 739 | bFileTestLoad=0 740 | bFileNeededMessage=1 741 | bFileGoneMessage=1 742 | bFileSkipModelChecks=0 743 | bFileCheckModelCollision=0 744 | 745 | [CopyProtectionStrings] 746 | SCopyProtectionMessage2=Insert the Fallout Disc. 747 | SCopyProtectionTitle2=Fallout Disc Not Found 748 | SCopyProtectionMessage=Unable to find a CD-ROM/DVD drive on this computer. 749 | SCopyProtectionTitle=CD-ROM Drive Not Found 750 | 751 | [Pipboy] 752 | fBlurRadiusPipboy=3.5 753 | fBlurIntensityPipboy=0.25 754 | fScanlineScalePipboy=50 755 | bEnableFlickerPipboy=1 756 | bUsePipboyMode=1 757 | 758 | [InterfaceFX] 759 | fDefaultBurstDuration=200 760 | fDefaultBurstIntensity=2 761 | fMiniBurstDuration=200 762 | fMiniBurstIntensity=1.5 763 | 764 | ;pulse effect 765 | fPulseBrightenIntensity=0.25 766 | fPulseRadiusIntensity=0.5 767 | fPulseRate=0.0006 768 | 769 | ;pipboy menu transitions 770 | fVertHoldChance=0.08 771 | fShudderChance=0.20 772 | 773 | fScanlineScaleMenus=50.0000 774 | bEnableFlickerMenus=1 775 | bEnableScanlinesMenus=1 776 | bEnableScanlinesPipboy=1 777 | fBlurRadiusMenus=0.3000 778 | fBrightenMenus=1.7000 779 | fBrightenPipboy=1.3000 780 | bUseImageSpaceMenuFX=1 781 | fBlurIntensityHUD=1.2000 782 | fBlurRadiusHUD=2.0000 783 | fScanlineFrequencyHUD=0.0000 784 | 785 | fScreenLightBaseIntensity=0.6 786 | fScreenLightRadius=6 787 | 788 | [RenderedTerminal] 789 | bUseRenderedTerminals=1 790 | fRenderedTerminalFOV=0.15 791 | fRenderedTerminalZoom=36 792 | bDoRenderedTerminalScanlines=1 793 | fRenderedTerminalScanlineScale=130.000000 794 | fRenderedTerminalHPos=0.0 795 | fRenderedTerminalVPos=0.38 796 | fScreenLightBaseIntensity=1.2 797 | fScreenLightRadius=80 798 | fScreenLightColorR=0.68 799 | fScreenLightColorG=0.74 800 | fScreenLightColorB=0.62 801 | 802 | fRaceSexMenuHPos=0.0 803 | fRaceSexMenuVPos=-0.6 804 | fRaceSexMenuZoom=70.0 805 | fRaceSexMenuScale=0.5 806 | 807 | [Decals] 808 | uMaxDecalCount=100 809 | bProfileDecals=0 810 | bDecalOcclusionQuery=1 811 | 812 | [TerrainManager] 813 | fSplitDistanceMult=0.75 814 | fBlockMorphDistanceMult=0.70 815 | bUseNewTerrainSystem=1 816 | bUseDistantObjectBlocks=1 817 | fBlockLoadDistance=125000.0 818 | fDefaultBlockLoadDistanceLow=50000.0 819 | fLowBlockLoadDistanceLow=25000.0 820 | fHighBlockLoadDistanceLow=50000.0 821 | fDefaultTreeLoadDistance=25000.0 822 | fLowTreeLoadDistance=10000.0 823 | fHighTreeLoadDistance=40000.0 824 | 825 | [VATS] 826 | fVATSLightLevelMin=20.0 827 | fVATSLightLevelMax=65.0 828 | fVATSLightAngle=0.0 829 | fVATSLightDistance=100.0 830 | fVATSLightElevation=100.0 831 | fVatsLightColorR=0.35 832 | fVatsLightColorG=0.35 833 | fVatsLightColorB=0.35 834 | 835 | [ScreenSplatter] 836 | bScreenSplatterEnabled=1 837 | -------------------------------------------------------------------------------- /tests/Resources/RealWorld/FALLOUT.INI.json: -------------------------------------------------------------------------------- 1 | { 2 | "MultiLineValues": [ 3 | "Simple" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /tests/Resources/RealWorld/Gothic.INI: -------------------------------------------------------------------------------- 1 | ; 2 | ; G O T H I C 2 3 | ; 4 | ; INI-File 5 | ; 6 | ; contains different settings 7 | ; ... some can be modified in gothics menu 8 | ; ... some not (feel free to hack, but don't cry ... :) 9 | ; ... others won't take any effect (they will be reset during gameplay) 10 | ; ... and a few may cause a crash or some other funny things :) 11 | ; 12 | ; Be careful but DON'T PANIC !! 13 | ; 14 | 15 | 16 | 17 | [PERFORMANCE] 18 | 19 | recalc=0 20 | ; ... indicates if your performance-settings should be recalculated (1) {analyses you computer} or not (0). Replays Intro-Video. 21 | 22 | sightValue=14 23 | ; ... range of visibility: 0=20% ... 14=300%, default is 4 (100%) 24 | 25 | modelDetail=1 26 | ; ... detail of models (LODing) from 0.0 to 1.0, default is 0.5 27 | 28 | 29 | 30 | [GAME] 31 | 32 | animatedWindows=1 33 | ; ... turn fading of game-internal windows(views) off (0) or on (1), default is 1 34 | 35 | camLookaroundInverse=0 36 | ; ... inverts the camera-lookaround for UP and DOWN-direction (for both: mouse and keyboard) 37 | 38 | bloodDetail=2 39 | ; ... details of blood (0 = off), use values from 0 to 3 40 | 41 | extendedVideoKeys=0 42 | ; ... enables extra keys for videoplay: HOME (restart), RIGHT (step forward), UP, DOWN (volume), Q(uiet), default is 0 43 | 44 | scaleVideos=1 45 | ; ... disable scaling of videos (0) if you have problems with your graphics-adapter, default is on (1) 46 | 47 | cameraLightRange=0 48 | ; ... range of cameralight in cm, default is 0 (no camera-light) 49 | 50 | invShowArrows=1 51 | ; ... show arrows beside inventory if there are more items above or beyond, default is 1 52 | 53 | invSwitchToFirstCategory=0 54 | ; ... switch to first category (weapons) in trading-screen, when moving to your heroes inventory, default is 0 55 | 56 | enableMouse=1 57 | ; ... enable your mouse for gothic, default is 0 58 | 59 | mouseSensitivity=0.5 60 | ; ... mouseSpeed in game between 0.0 and 1.0, default is 0.5 61 | 62 | playLogoVideos=1 63 | ; ... if set to 0 no intro logo videos will be played 64 | 65 | skyEffects=1 66 | ; ... turn weather-effects (rain) on (1) or off (0), default is 1 67 | 68 | highlightMeleeFocus=2 69 | ; ... here you can turn on an optional focus highlight effect during fighting 70 | 71 | highlightInteractFocus=0 72 | ; ... here you can turn on an optional focus highlight during interactions 73 | 74 | useGothic1Controls=1 75 | ; ... if you set this one to 0 you will have another fight interface (one key to attack). 76 | ; we feel the gothic 1 interface is more challenging, so we set the old controls to default 77 | ; with the new interface, the focus nsc stays locked until you move the mouse. in this mode 78 | ; the side attacks are being accessed with additional side attack keys. 79 | 80 | disallowVideoInput=0 81 | ; ... set to 1 if you dont want to have keyboard control over video sequences (default: 0) 82 | 83 | keyDelayRate=150 84 | ; ... sets the keyboard repeat delay rate in msec (default: 150) 85 | 86 | enableJoystick=0 87 | ; ... enables joystick support in gothic (default: 1) set to 0 if you encounter problems (rapid fire etc.) 88 | 89 | keyDelayFirst=0 90 | ; ... delay for first keyboard repeat in msec (default: 0) 91 | 92 | subTitles=1 93 | ; ... choose if you want to see windows with spoken words (1) or not (0), default is 0 94 | 95 | subTitlesAmbient=1 96 | ; ... set to 1 if you dont want to have subtitles for ambient talks (default: 1) [disabled if subTitles is off] 97 | 98 | subTitlesPlayer=1 99 | ; ... activates (1) or deactivates (0) subtitles for the hero (default: 1) [disabled if subTitles is off] 100 | 101 | subTitlesNoise=0 102 | ; ... activates (1) or deactivates (0) subtitles for surroundings npc ambient infos and talks (default: 0) [disabled if subTitles is off] 103 | 104 | invMaxColumns=5 105 | ; ... determins how many colums you can see with you inventory (default: 5) [0: limited by resolution] 106 | 107 | invMaxRows=0 108 | ; ... determins how many rows you can see with you inventory (default: 0: limited by resolution) 109 | 110 | invSplitScreen=1 111 | ; ... determins if you can see a second inventory during object interaction and trading. TAB will toggle inventory focus or close your inventory depending on the setting 112 | 113 | invCatOrder=COMBAT,POTION,FOOD,ARMOR,MAGIC,RUNE,DOCS,OTHER,NONE 114 | ; ... determins the inventory item group order. 115 | 116 | gametextAutoScroll=1000 117 | ; ... with this value you can tune the scroll time in msec of the various in game infos (default: 1000) 118 | 119 | usePotionKeys=0 120 | ; ... with this value you are allowed to use the potion keys if set to "1". potionkeys do not work and are not visible in the keyboard settings if you leave this to "0" 121 | ; we feel potion shortkeys suck in gameplay, so you will manually have to enable them here 122 | 123 | useQuickSaveKeys=0 124 | ; ... with this value set to "1" you quicksave and quickload slots will be enabled in the savegame screen. press "F5" to quicksave and "F9" to quickload 125 | ; this feature is not testet good enough yet, and therefore it is disabled for goldmaster. you may enable it at your own risk by setting it to "1" 126 | 127 | useSpeechReverbLevel=2 128 | ; ... with this setting you can enable several reverb-settings for in-game-speech. 0: no reverb, 1: slight reverb, 2: full reverb (default: 2) 129 | 130 | keyboardLayout=00020409 131 | ; ... currently there are two supported keyboard layouts: 00000407 - German, 00020409 - US-International 132 | ; ( see http://www.microsoft.com/globaldev/keyboards/keyboards.asp , dead keys are not supportet at all ) 133 | 134 | pickLockScramble=0 135 | ; ... you can increase the feeling of lockpicking if you enable scrambling the combination on loading an savegame 136 | ; the value is the maximum length of combination which will be scrambled, 0 = off (default) 137 | 138 | PATCHVERSION=5 139 | SHORTKEY1FARPLANEDIST=0.8 140 | SHORTKEY2FARPLANEDIST=1.2 141 | SHORTKEY3FARPLANEDIST=2 142 | SHORTKEY4FARPLANEDIST=3 143 | zShowWeaponTrails=1 144 | itemEffects=1 145 | spawnRemoveNpcOnlyIfEmpty=0 146 | 147 | 148 | [VIDEO] 149 | 150 | zVidDevice=0 151 | ; ... index of graphic-device beginning with zero. 152 | 153 | zVidResFullscreenX=1440 154 | zVidResFullscreenY=900 155 | zVidResFullscreenBPP=16 156 | ; ... used resolution 157 | 158 | zStartupWindowed=0 159 | ; ... should the game be started as a window-application? Just for debugging! 160 | ; ... ATTENTION: Not all resolution work in window-mode!!! 161 | 162 | zVidBrightness=0.5 163 | ; ... brightness from 0.0 (dark) to 1.0 (bright) 164 | 165 | zVidContrast=0.5 166 | ; ... contrast from 0.0 (low contrast) to 1.0 (high contrast) 167 | 168 | zVidGamma=0.5 169 | ; ... gamma from 0.0 (dark) to 1.0 (bright) 170 | 171 | zTexMaxSize=16384 172 | ; ... size of texture in pixels, default is 16384 (max) 173 | 174 | 175 | 176 | [SOUND] 177 | 178 | soundVolume=1 179 | musicVolume=0.200000003 180 | ; ... volume of sound and music, ranges between 0.0 (off) and 1.0 (noisy) 181 | 182 | musicEnabled=1 183 | ; ... enables (1) or disables (0) music. Gothic needs less memory without music. 184 | 185 | soundEnabled=1 186 | ; ... enables (1) or disables (0) sound. 187 | 188 | soundUseReverb=1 189 | ; ... enables (1) or disables (0) in game reverb effects in indoor locations. 190 | 191 | extendedProviders=0 192 | ; ... enables (1) or disables (0) some unsupported sound providers in the menu (Dolby Surround and Intel RSX; use at your own risk) 193 | 194 | 195 | 196 | [RENDERER_D3D] 197 | 198 | zFogDisabled=0 199 | ; ... diables fog. set this to 1 if you have any problem with fogging 200 | 201 | zFogRadial=1 202 | ; ... enables radial fog. this could be somehow slower on some grafic cards, but looks smoother. set to "0" if you have any problems with it 203 | ; some cards without T&L don't support radial fog. On these cards, (although they are unsupported) it may be wise to deactivate radial fog. 204 | 205 | zVidRefreshRate=0 206 | ; ... overrides the windows default refresh rate. enter a value above 75 to make your eyes happier (default: 0) 207 | ; Attention: could collide with various refresh rate tools as nvmax, nvidia refresh rate fix, etc.. if you enter any value above "0" 208 | 209 | zForceZBuffer=0 210 | ; ... gothic first tries to activate a w buffer if your cards supports it. however, some cards have problems with gothics way to access the w buffer 211 | ; you can force z buffering here by setting the value to "1" 212 | 213 | zEnableTaskSwitch=1 214 | ; ... enables (1) or disables (0) going to windowed/pause mode if gothic 2 looses focus (e.g. on ALT-Tab) 215 | 216 | geforce3HackWBufferBug=1 217 | ; ... some geforce 3 or geforce 4 cards have problems with gothics way to access the w buffer, resulting in flickering polys 218 | ; in the distant. with this setting set to "1" these cards automatically use a z buffer, loosing some precision near the camera but without the flickering polys. 219 | ; the driver version 12.41 does not have this problem. if you you have this version installed you may set this to 0 in order to activate the better looking 220 | ; w buffer. Driver versions later than 30.82 may not have this problem either. 221 | 222 | 223 | zSyncAmbientCol=0 224 | ; ... some grafic drivers have problems with gothics way to access the ambient lightning on a per object base but want the ambient 225 | ; light on a per scene base. this is a driver bug! if there occurs heavily lightning flickering with objects, you might set this setting 226 | ; to "1" to synchronize the ambient color after each object. this forces the driver to flush the scene after each objects which can 227 | ; seriously degrade performance (especially if you activate antialiasing!) 228 | 229 | radeonHackAmbientColBug=0 230 | ; ... the radeon 9700 has known problems with accessing the ambient lightning on a per object base, thus using the above "zSyncAmbientCol" 231 | ; Feature automatically. By activating the workaround for this card, performance may drop about 10%. Fullscene antialiasing does not work 232 | ; fast enough on this card until ATI fixes the ambient col driver bug. 233 | ; if you set this setting to "0" and no object lightning flickering occurs, ATI has probably managed to fix the problem and you may enable antialiasing 234 | 235 | 236 | [SKY_OUTDOOR] 237 | 238 | zDayColor0=82 109 198 239 | zDayColor1=255 255 0 240 | zDayColor2=18 16 60 241 | zDayColor3=134 104 125 242 | zDayColor0_OW=90 80 80 243 | zDayColor1_OW=90 80 80 244 | zDayColor2_OW=90 80 80 245 | zDayColor3_OW=90 80 80 246 | ; ... these values tune the different sky colors during different daytimes 247 | 248 | zSkyDome=1 249 | ; ... here you can define if you want a smooth sky sphere instead of a sky plane. enter a "0" here if you want more performance. (default:1) 250 | 251 | zColorizeSky=1 252 | ; ... with this value you can make the skysphere even more beautiful (set it to "0" for a plus of performance) (default:1) 253 | 254 | zSunName=unsun5.tga 255 | zSunSize=200 256 | zSunAlpha=230 257 | zMoonName=moon.tga 258 | zMoonSize=400 259 | zMoonAlpha=255 260 | ; ... these values tune the different sizes and alpha intensitys of the sky planets. you should leave them as they are :) 261 | 262 | zRainWindScale=0.003 263 | ; ... this value tunes how wind affects the rain. looks great with higher values, but occasional you will see rain drops in indoor locations 264 | 265 | zNearFogScale=1 266 | zFarFogScale=1 267 | ; ... these settings tune the far- and near-fog distances (default: 1, range: 0.0 - 1.0) 268 | 269 | 270 | 271 | [ENGINE] 272 | 273 | zDetailTexturesEnabled=1 274 | ; ... here you can define if the engine should support detail textures (default: 1) 275 | 276 | zSubdivSurfacesEnabled=0 277 | ; ... with this setting you can activate subdiving surface for progressive meshes (untestet, default: 0) 278 | 279 | zTexCacheOutTimeMSec=240000 280 | zTexCacheSizeMaxBytes=32000000 281 | zSndCacheOutTimeMSec=10000 282 | zSndCacheSizeMaxBytes=20000000 283 | ; ... with these settings you can tune the memory usage of the texture and sound resources. 284 | ; if you have more ram than 512 MB, greater values will improve performance 285 | 286 | zVobFarClipZScale=14 287 | ; ... with this setting you can tune the object visibility range. (range: 1..3) default: 1 288 | 289 | zFarClipAlphaFade=1 290 | ; ... enables (1) or disables (0) water distance fade and camera angle transparency dependencies. disabling improves performance 291 | 292 | zEnvMapTextureName=zflare1.tga 293 | ; ... texture name for the object env effects 294 | 295 | zWaterAniEnabled=1 296 | ; ... enables (1) or disables (0) water waves. disabling improves performance 297 | 298 | zWaterEnvMapTextureName=cloudenv_bright.tga 299 | ; ... texture name for the water env effect 300 | 301 | zWaterEnvMapAniFPS=0 302 | ; ... animation speed in for an optional water env texture 303 | 304 | zHighLightScale=0 305 | ; ... enables (1) or disables (0) item highlight swell (default: 0) 306 | 307 | ZMAXFPS=0 308 | ; ... some strange gfx hardware may have problems with gothic's way accessing the game-timer. you may limit the maximum fps rate with entering any value 309 | ; above 1. (The spacer needs a reasonably value here especially for editing very small ZENs) 310 | 311 | zSmoothTimer=1 312 | ; ... enables (1) or disables (0) smoothing of the in-game timer so that animations will look smoother during short sloppy framerates 313 | ; (default: 1) 314 | 315 | zVidEnableAntiAliasing=0 316 | ; ... enables (1) or disables (0) edge antialiasing. this is driver dependant and a performance hit. 317 | 318 | zSmoothModelRootNode=1 319 | ; ... enables (1) or disables (0) model moving smooting (default: 1) 320 | 321 | zMouseRotationScale=2.0 322 | ; ... this value affects the npc turning speed while using your mouse. Attention: can seriously affect gameplay if setting to unreasonably values (default: 2.0) 323 | 324 | zDontSwitchToThirdPerson=0 325 | ; ... enables (1) or disables (0) auto-switching the camera to 3rd person during dialogs, interactions and combat. 326 | ; Attention: seriously affects gameplay if setting to "1", as everything can be done in 1st person, untested feature but fun 327 | 328 | zCacheInAllNSCAtNewGame=0 329 | ; ... with this value setting to "0" you can achive a plus of startup time, as several humans won't be loaded in memory on startup 330 | 331 | zCloudShadowScale=1 332 | ; ... this value enables (1) or disables (0) the cloudshadow effect during raining. range: (0.0-1.0) default: 0.0. attention: performance hog! 333 | 334 | zTexAnisotropicFiltering=0 335 | ; ... enables (1) or disables (0) anisotropic filtering for textures. this is driver dependant and a performance hit, but improves texture sharpness 336 | ; default: 0 337 | 338 | NOAMBIENTPFX=0 339 | ; ... enables (0) or disables (1) rendering of ambient particles during gameplay. if you have a card with a lesser fillrate, you should set this to "1" 340 | ; in order to improve speed 341 | 342 | zVobPointLight=1 343 | ; ... enables (1) or disables (0) additional dynamic lights for indoor objects, greatly improving details. you should left this as it is, although in can improve indoor performance. 344 | 345 | ZNEARVALUE=-1 346 | ; ... with this setting you may fine-tune the distant-value of the near clipping plane. some cards may accept more aggresive near z values then the default calculated 347 | ; by gothic. (w buffering uses alway a value of 1, so you don't need to fine-tune this setting) (default: -1, let the value determin by renderer) 348 | 349 | zSkyRenderFirst=1 350 | ; ... enables (0) or disables (1) an additional way to workaround the flickering poly in the distant on geforce 3 or geforce 4 cards. 351 | ; if you set this to "0" the sky will be renderer after the normal game world thus overlaying the flickering polys. this does only work with 32 bit 352 | ; color enabled and if you set the value "geforce3HackWBufferBug" to "0". the drawback is that the sky is slightly distorted, but this should be the best 353 | ; workaround for most geforce 3/4 users as the flicker polys are more annoying. moreover you can't see through walls with this workaround any more 354 | ; (default: 1) 355 | 356 | zMaxFPS=0 357 | ; ... some rare gfx hardware may have problems with gothics way to access the timer, resulting in jerky animations. 358 | ; with this setting set to a fixed value (e.g. 20) you can avoid choppy animations on those systems 359 | ; the spacer needs a fixed value here in order to work properly during editing small ZEN Files 360 | 361 | zAmbientPFXEnabled=1 362 | ; ... enables (1) or disables (0) rendering of ambient particles. rendering ambient particles greatly limits your fillrate, so if you have a card with less 363 | ; fill-rate capabilities (e.g. geforce 2 MX versions) you may set this to "0" to improve performance. (default: 1) 364 | 365 | zAmbientVobsEnabled=1 366 | ; ... enables (1) or disables (0) rendering of ambient objects. not used in gothic 2 367 | 368 | zEnvMappingEnabled=1 369 | ; ... enables (1) or disables (0) rendering of environmental effects (aka shiny/reflective surfaces). improves performance if deactivated (default: 1) 370 | 371 | zKillSysKeys=0 372 | ; ... enables (1) or disables (0) the window keys as ALT-TAB, ALT-ESC, etc... GOTHIC handles focus-loss by going to windowed-pause mode, so 373 | ; there is no real need to deactivate the keys (moreover, disallowing those keys is more of a hack than a feature). 374 | ; this feature is untested and unsupported. 375 | 376 | zSmoothMouse=3 377 | ; ... with this setting you can smooth your mouse movements by averaging the last [n] frame moves. higher values result in laggier but smoother mouse response. 378 | ; (default: 3) ATTENTION: modifying this value may result in different gameplay. 379 | 380 | zMusic16ChannelsOnly=0 381 | ; ... if you have 256 MB or less memory, you can force the music system to use only 16 channels, thus killing several instruments and performances. 382 | ; ATTENTION: setting this to "1" reduces music quality but can improve performance. If music is not important for you, you have the choice to only 383 | ; use 16 channels. 384 | 385 | zInventoryItemsDistanceScale=1.3 386 | ; ... some rare grafic cards have a high near clipping value resulting in inventory items not being visible (esp. if you have the cursor focus on it) 387 | ; with entering a value above "0" you can scale the item distances from the camera in order to make the items smaller, but visible 388 | ; (e.g. with a value of 2.0 the items will be twice as far away from the camera) 389 | ; range: 0..1000. (default: 1.3) 390 | 391 | zWindEnabled=1 392 | ; ... enables (1) or disables (0) in-game wind for objects/trees etc. improves performance (especially on slow cpu's) (default: 1) 393 | 394 | zWindCycleTime=4 395 | zWindCycleTimeVar=2 396 | zWindStrength=70 397 | zWindStrengthVar=40 398 | zWindAngleVelo=0.9 399 | zWindAngleVeloVar=0.8 400 | ; ... these settings tune the wind effect, you should leave them as they are (altough funny things can happen;) 401 | 402 | zSunMaxScreenBlendScale=0.8 403 | zRayTurboPolyTreshold=500 404 | 405 | 406 | 407 | [KEYS] 408 | keyEnd=0100 409 | keyHeal=2300 410 | keyPotion=1900 411 | keyLockTarget=4f00 412 | keyParade=cf000d02 413 | keyActionRight=d100 414 | keyActionLeft=d300 415 | keyUp=c8001100 416 | keyDown=d0001f00 417 | keyLeft=cb001000 418 | keyRight=cd001200 419 | keyStrafeLeft=d3001e00 420 | keyStrafeRight=d1002000 421 | keyAction=1d000c02 422 | keySlow=2a003600 423 | keySMove=38009d00 424 | keyWeapon=39000e02 425 | keySneak=2d00 426 | keyLook=13005200 427 | keyLookFP=21005300 428 | keyInventory=0f000e00 429 | keyShowStatus=30002e00 430 | keyShowLog=31002600 431 | keyShowMap=3200 432 | 433 | [KEYSDEFAULT0] 434 | keyEnd=0100 435 | keyHeal=2300 436 | keyPotion=1900 437 | keyLockTarget=4f00 438 | keyParade=cf000d02 439 | keyActionRight=d100 440 | keyActionLeft=d300 441 | keyUp=c8001100 442 | keyDown=d0001f00 443 | keyLeft=cb001000 444 | keyRight=cd001200 445 | keyStrafeLeft=d3001e00 446 | keyStrafeRight=d1002000 447 | keyAction=1d000c02 448 | keySlow=2a003600 449 | keySMove=38009d00 450 | keyWeapon=39000e02 451 | keySneak=2d00 452 | keyLook=13005200 453 | keyLookFP=21005300 454 | keyInventory=0f000e00 455 | keyShowStatus=30002e00 456 | keyShowLog=31002600 457 | keyShowMap=3200 458 | 459 | [KEYSDEFAULT1] 460 | keyEnd=0100 461 | keyHeal=2300 462 | keyPotion=1900 463 | keyLockTarget=4f00 464 | keyParade=cf000d02 465 | keyActionRight=d100 466 | keyActionLeft=d300 467 | keyUp=c8001100 468 | keyDown=d0001f00 469 | keyLeft=1000 470 | keyRight=1200 471 | keyStrafeLeft=cb001e00 472 | keyStrafeRight=cd002000 473 | keyAction=1d000c02 474 | keySlow=2a003600 475 | keySMove=38009d00 476 | keyWeapon=39000e02 477 | keySneak=2d00 478 | keyLook=13005200 479 | keyLookFP=21005300 480 | keyInventory=0f000e00 481 | keyShowStatus=30002e00 482 | keyShowLog=31002600 483 | keyShowMap=3200 484 | 485 | 486 | [INTERNAL] 487 | idComputerName=DELL-INSPIRON-5 488 | idUserName=Salaros 489 | extendedMenu=0 490 | gameStarts=7 491 | perfQualityIndex=0 492 | gameStartFailed=0 493 | gameAbnormalExit=0 494 | menuShowVersion=1 495 | gamePath= 496 | gameScript= 497 | gameCompile=1.0 498 | playerInstanceName= 499 | menuAction=LEAVE_GAME 500 | debugAllChannels=0 501 | debugAllInstances=0 502 | debugChannels= 503 | cutscenesDisabled=0 504 | texDetailIndex=1 505 | vidResIndex=15 506 | soundProviderIndex=0 507 | soundSampleRateIndex=1 508 | soundSpeakerIndex=1 509 | logStatistics=0 510 | zFastSaveGames=1 511 | -------------------------------------------------------------------------------- /tests/Resources/RealWorld/ROTK.ini: -------------------------------------------------------------------------------- 1 | [input0] 2 | map=ROTKDefault 3 | mode=KB 4 | InputPolling=1 5 | [input1] 6 | map=ROTKDefault 7 | mode=KB 8 | [input_KB_BASE_0] 9 | ROOT_MAP = ROTKDefault 10 | CTRL_BUTTON_RIGHT_TOP = KEYID_E 11 | CTRL_BUTTON_RIGHT_DPAD_UP = MOUSEID_BUTTON_2 12 | CTRL_BUTTON_RIGHT_DPAD_UP = KEYID_NUMPAD8 13 | CTRL_BUTTON_RIGHT_BOTTOM = KEYID_SPACE 14 | CTRL_BUTTON_RIGHT_DPAD_LEFT = MOUSEID_BUTTON_3 15 | CTRL_BUTTON_RIGHT_DPAD_LEFT = KEYID_NUMPAD4 16 | CTRL_BUTTON_RIGHT_DPAD_RIGHT = KEYID_LCONTROL 17 | CTRL_BUTTON_RIGHT_DPAD_RIGHT = KEYID_NUMPAD6 18 | CTRL_BUTTON_LEFT_TOP = KEYID_LSHIFT 19 | CTRL_BUTTON_RIGHT_DPAD_DOWN = MOUSEID_BUTTON_1 20 | CTRL_BUTTON_RIGHT_DPAD_DOWN = KEYID_NUMPAD2 21 | CTRL_BUTTON_START = KEYID_ESC 22 | CTRL_BUTTON_LEFT_BOTTOM = KEYID_TAB 23 | CTRL_BUTTON_SELECT = KEYID_BACK 24 | CTRL_BUTTON_LEFT_STICK = KEYID_F5 25 | LEFT_ANALOG_X = MOUSE(200),0 26 | LEFT_ANALOG_Y = MOUSE(200),0 27 | LEFT_ANALOG_EX_AUTO_NORTH = KEYID_W 28 | LEFT_ANALOG_EX_AUTO_WEST = KEYID_A 29 | LEFT_ANALOG_EX_AUTO_SOUTH = KEYID_S 30 | LEFT_ANALOG_EX_AUTO_EAST = KEYID_D 31 | MOUSE_CLAMP_POS = 0,0,0,0,1,200 32 | [input_KB_BASE_1] 33 | ROOT_MAP = ROTKDefault 34 | CTRL_BUTTON_RIGHT_TOP = KEYID_E 35 | CTRL_BUTTON_RIGHT_DPAD_UP = MOUSEID_BUTTON_2 36 | CTRL_BUTTON_RIGHT_DPAD_UP = KEYID_NUMPAD8 37 | CTRL_BUTTON_RIGHT_BOTTOM = KEYID_SPACE 38 | CTRL_BUTTON_RIGHT_BOTTOM = MOUSEID_BUTTON_3 39 | CTRL_BUTTON_RIGHT_DPAD_LEFT = KEYID_Q 40 | CTRL_BUTTON_RIGHT_DPAD_LEFT = KEYID_NUMPAD4 41 | CTRL_BUTTON_RIGHT_DPAD_RIGHT = KEYID_LCONTROL 42 | CTRL_BUTTON_RIGHT_DPAD_RIGHT = KEYID_NUMPAD6 43 | CTRL_BUTTON_LEFT_TOP = KEYID_LSHIFT 44 | CTRL_BUTTON_RIGHT_DPAD_DOWN = MOUSEID_BUTTON_1 45 | CTRL_BUTTON_RIGHT_DPAD_DOWN = KEYID_NUMPAD2 46 | CTRL_BUTTON_START = KEYID_ESC 47 | CTRL_BUTTON_LEFT_BOTTOM = KEYID_TAB 48 | CTRL_BUTTON_SELECT = KEYID_BACK 49 | CTRL_BUTTON_LEFT_STICK = KEYID_F5 50 | LEFT_ANALOG_X = MOUSE(200),0 51 | LEFT_ANALOG_Y = MOUSE(200),0 52 | LEFT_ANALOG_EX_AUTO_NORTH = KEYID_W 53 | LEFT_ANALOG_EX_AUTO_WEST = KEYID_A 54 | LEFT_ANALOG_EX_AUTO_SOUTH = KEYID_S 55 | LEFT_ANALOG_EX_AUTO_EAST = KEYID_D 56 | MOUSE_CLAMP_POS = 0,0,0,0,1,200 57 | [GamePlay] 58 | Difficulty=0 59 | Subtitles=0 60 | Player1Indicator=0 61 | Player2Indicator=0 62 | [Video] 63 | AdapterNumber=0 64 | Width=1024 65 | Gamma=0.850000 66 | Enable32Bit=1 67 | EnableShadows=1 68 | EnableSimpleShadows=0 69 | AlternateCameras=1 70 | LowResTexture=0 71 | SfxMode=2 72 | [Audio] 73 | Volume_Music=100 74 | Volume_Voice=100 75 | Volume_Sfx=100 76 | AudioMode=0 77 | Software_Stream_Buffers=0 78 | -------------------------------------------------------------------------------- /tests/Resources/RealWorld/main.cf.default: -------------------------------------------------------------------------------- 1 | # Global Postfix configuration file. This file lists only a subset 2 | # of all parameters. For the syntax, and for a complete parameter 3 | # list, see the postconf(5) manual page (command: "man 5 postconf"). 4 | # 5 | # For common configuration examples, see BASIC_CONFIGURATION_README 6 | # and STANDARD_CONFIGURATION_README. To find these documents, use 7 | # the command "postconf html_directory readme_directory", or go to 8 | # http://www.postfix.org/. 9 | # 10 | # For best results, change no more than 2-3 parameters at a time, 11 | # and test if Postfix still works after every change. 12 | 13 | # SOFT BOUNCE 14 | # 15 | # The soft_bounce parameter provides a limited safety net for 16 | # testing. When soft_bounce is enabled, mail will remain queued that 17 | # would otherwise bounce. This parameter disables locally-generated 18 | # bounces, and prevents the SMTP server from rejecting mail permanently 19 | # (by changing 5xx replies into 4xx replies). However, soft_bounce 20 | # is no cure for address rewriting mistakes or mail routing mistakes. 21 | # 22 | #soft_bounce = no 23 | 24 | # LOCAL PATHNAME INFORMATION 25 | # 26 | # The queue_directory specifies the location of the Postfix queue. 27 | # This is also the root directory of Postfix daemons that run chrooted. 28 | # See the files in examples/chroot-setup for setting up Postfix chroot 29 | # environments on different UNIX systems. 30 | # 31 | queue_directory = /var/spool/postfix 32 | 33 | # The command_directory parameter specifies the location of all 34 | # postXXX commands. 35 | # 36 | command_directory = /usr/sbin 37 | 38 | # The daemon_directory parameter specifies the location of all Postfix 39 | # daemon programs (i.e. programs listed in the master.cf file). This 40 | # directory must be owned by root. 41 | # 42 | daemon_directory = /usr/libexec/postfix 43 | 44 | # QUEUE AND PROCESS OWNERSHIP 45 | # 46 | # The mail_owner parameter specifies the owner of the Postfix queue 47 | # and of most Postfix daemon processes. Specify the name of a user 48 | # account THAT DOES NOT SHARE ITS USER OR GROUP ID WITH OTHER ACCOUNTS 49 | # AND THAT OWNS NO OTHER FILES OR PROCESSES ON THE SYSTEM. In 50 | # particular, don't specify nobody or daemon. PLEASE USE A DEDICATED 51 | # USER. 52 | # 53 | mail_owner = postfix 54 | 55 | # The default_privs parameter specifies the default rights used by 56 | # the local delivery agent for delivery to external file or command. 57 | # These rights are used in the absence of a recipient user context. 58 | # DO NOT SPECIFY A PRIVILEGED USER OR THE POSTFIX OWNER. 59 | # 60 | #default_privs = nobody 61 | 62 | # INTERNET HOST AND DOMAIN NAMES 63 | # 64 | # The myhostname parameter specifies the internet hostname of this 65 | # mail system. The default is to use the fully-qualified domain name 66 | # from gethostname(). $myhostname is used as a default value for many 67 | # other configuration parameters. 68 | # 69 | #myhostname = host.domain.tld 70 | #myhostname = virtual.domain.tld 71 | 72 | # The mydomain parameter specifies the local internet domain name. 73 | # The default is to use $myhostname minus the first component. 74 | # $mydomain is used as a default value for many other configuration 75 | # parameters. 76 | # 77 | #mydomain = domain.tld 78 | 79 | # SENDING MAIL 80 | # 81 | # The myorigin parameter specifies the domain that locally-posted 82 | # mail appears to come from. The default is to append $myhostname, 83 | # which is fine for small sites. If you run a domain with multiple 84 | # machines, you should (1) change this to $mydomain and (2) set up 85 | # a domain-wide alias database that aliases each user to 86 | # user@that.users.mailhost. 87 | # 88 | # For the sake of consistency between sender and recipient addresses, 89 | # myorigin also specifies the default domain name that is appended 90 | # to recipient addresses that have no @domain part. 91 | # 92 | #myorigin = $myhostname 93 | #myorigin = $mydomain 94 | 95 | # RECEIVING MAIL 96 | 97 | # The inet_interfaces parameter specifies the network interface 98 | # addresses that this mail system receives mail on. By default, 99 | # the software claims all active interfaces on the machine. The 100 | # parameter also controls delivery of mail to user@[ip.address]. 101 | # 102 | # See also the proxy_interfaces parameter, for network addresses that 103 | # are forwarded to us via a proxy or network address translator. 104 | # 105 | # Note: you need to stop/start Postfix when this parameter changes. 106 | # 107 | #inet_interfaces = all 108 | #inet_interfaces = $myhostname 109 | #inet_interfaces = $myhostname, localhost 110 | inet_interfaces = localhost 111 | 112 | # The proxy_interfaces parameter specifies the network interface 113 | # addresses that this mail system receives mail on by way of a 114 | # proxy or network address translation unit. This setting extends 115 | # the address list specified with the inet_interfaces parameter. 116 | # 117 | # You must specify your proxy/NAT addresses when your system is a 118 | # backup MX host for other domains, otherwise mail delivery loops 119 | # will happen when the primary MX host is down. 120 | # 121 | #proxy_interfaces = 122 | #proxy_interfaces = 1.2.3.4 123 | 124 | # The mydestination parameter specifies the list of domains that this 125 | # machine considers itself the final destination for. 126 | # 127 | # These domains are routed to the delivery agent specified with the 128 | # local_transport parameter setting. By default, that is the UNIX 129 | # compatible delivery agent that lookups all recipients in /etc/passwd 130 | # and /etc/aliases or their equivalent. 131 | # 132 | # The default is $myhostname + localhost.$mydomain. On a mail domain 133 | # gateway, you should also include $mydomain. 134 | # 135 | # Do not specify the names of virtual domains - those domains are 136 | # specified elsewhere (see VIRTUAL_README). 137 | # 138 | # Do not specify the names of domains that this machine is backup MX 139 | # host for. Specify those names via the relay_domains settings for 140 | # the SMTP server, or use permit_mx_backup if you are lazy (see 141 | # STANDARD_CONFIGURATION_README). 142 | # 143 | # The local machine is always the final destination for mail addressed 144 | # to user@[the.net.work.address] of an interface that the mail system 145 | # receives mail on (see the inet_interfaces parameter). 146 | # 147 | # Specify a list of host or domain names, /file/name or type:table 148 | # patterns, separated by commas and/or whitespace. A /file/name 149 | # pattern is replaced by its contents; a type:table is matched when 150 | # a name matches a lookup key (the right-hand side is ignored). 151 | # Continue long lines by starting the next line with whitespace. 152 | # 153 | # See also below, section "REJECTING MAIL FOR UNKNOWN LOCAL USERS". 154 | # 155 | #mydestination = $myhostname, localhost.$mydomain, localhost 156 | #mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain 157 | #mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain, 158 | # mail.$mydomain, www.$mydomain, ftp.$mydomain 159 | 160 | # REJECTING MAIL FOR UNKNOWN LOCAL USERS 161 | # 162 | # The local_recipient_maps parameter specifies optional lookup tables 163 | # with all names or addresses of users that are local with respect 164 | # to $mydestination, $inet_interfaces or $proxy_interfaces. 165 | # 166 | # If this parameter is defined, then the SMTP server will reject 167 | # mail for unknown local users. This parameter is defined by default. 168 | # 169 | # To turn off local recipient checking in the SMTP server, specify 170 | # local_recipient_maps = (i.e. empty). 171 | # 172 | # The default setting assumes that you use the default Postfix local 173 | # delivery agent for local delivery. You need to update the 174 | # local_recipient_maps setting if: 175 | # 176 | # - You define $mydestination domain recipients in files other than 177 | # /etc/passwd, /etc/aliases, or the $virtual_alias_maps files. 178 | # For example, you define $mydestination domain recipients in 179 | # the $virtual_mailbox_maps files. 180 | # 181 | # - You redefine the local delivery agent in master.cf. 182 | # 183 | # - You redefine the "local_transport" setting in main.cf. 184 | # 185 | # - You use the "luser_relay", "mailbox_transport", or "fallback_transport" 186 | # feature of the Postfix local delivery agent (see local(8)). 187 | # 188 | # Details are described in the LOCAL_RECIPIENT_README file. 189 | # 190 | # Beware: if the Postfix SMTP server runs chrooted, you probably have 191 | # to access the passwd file via the proxymap service, in order to 192 | # overcome chroot restrictions. The alternative, having a copy of 193 | # the system passwd file in the chroot jail is just not practical. 194 | # 195 | # The right-hand side of the lookup tables is conveniently ignored. 196 | # In the left-hand side, specify a bare username, an @domain.tld 197 | # wild-card, or specify a user@domain.tld address. 198 | # 199 | #local_recipient_maps = unix:passwd.byname $alias_maps 200 | #local_recipient_maps = proxy:unix:passwd.byname $alias_maps 201 | #local_recipient_maps = 202 | 203 | # The unknown_local_recipient_reject_code specifies the SMTP server 204 | # response code when a recipient domain matches $mydestination or 205 | # ${proxy,inet}_interfaces, while $local_recipient_maps is non-empty 206 | # and the recipient address or address local-part is not found. 207 | # 208 | # The default setting is 550 (reject mail) but it is safer to start 209 | # with 450 (try again later) until you are certain that your 210 | # local_recipient_maps settings are OK. 211 | # 212 | unknown_local_recipient_reject_code = 550 213 | 214 | # TRUST AND RELAY CONTROL 215 | 216 | # The mynetworks parameter specifies the list of "trusted" SMTP 217 | # clients that have more privileges than "strangers". 218 | # 219 | # In particular, "trusted" SMTP clients are allowed to relay mail 220 | # through Postfix. See the smtpd_recipient_restrictions parameter 221 | # in postconf(5). 222 | # 223 | # You can specify the list of "trusted" network addresses by hand 224 | # or you can let Postfix do it for you (which is the default). 225 | # 226 | # By default (mynetworks_style = subnet), Postfix "trusts" SMTP 227 | # clients in the same IP subnetworks as the local machine. 228 | # On Linux, this does works correctly only with interfaces specified 229 | # with the "ifconfig" command. 230 | # 231 | # Specify "mynetworks_style = class" when Postfix should "trust" SMTP 232 | # clients in the same IP class A/B/C networks as the local machine. 233 | # Don't do this with a dialup site - it would cause Postfix to "trust" 234 | # your entire provider's network. Instead, specify an explicit 235 | # mynetworks list by hand, as described below. 236 | # 237 | # Specify "mynetworks_style = host" when Postfix should "trust" 238 | # only the local machine. 239 | # 240 | #mynetworks_style = class 241 | #mynetworks_style = subnet 242 | #mynetworks_style = host 243 | 244 | # Alternatively, you can specify the mynetworks list by hand, in 245 | # which case Postfix ignores the mynetworks_style setting. 246 | # 247 | # Specify an explicit list of network/netmask patterns, where the 248 | # mask specifies the number of bits in the network part of a host 249 | # address. 250 | # 251 | # You can also specify the absolute pathname of a pattern file instead 252 | # of listing the patterns here. Specify type:table for table-based lookups 253 | # (the value on the table right-hand side is not used). 254 | # 255 | #mynetworks = 168.100.189.0/28, 127.0.0.0/8 256 | #mynetworks = $config_directory/mynetworks 257 | #mynetworks = hash:/etc/postfix/network_table 258 | 259 | # The relay_domains parameter restricts what destinations this system will 260 | # relay mail to. See the smtpd_recipient_restrictions description in 261 | # postconf(5) for detailed information. 262 | # 263 | # By default, Postfix relays mail 264 | # - from "trusted" clients (IP address matches $mynetworks) to any destination, 265 | # - from "untrusted" clients to destinations that match $relay_domains or 266 | # subdomains thereof, except addresses with sender-specified routing. 267 | # The default relay_domains value is $mydestination. 268 | # 269 | # In addition to the above, the Postfix SMTP server by default accepts mail 270 | # that Postfix is final destination for: 271 | # - destinations that match $inet_interfaces or $proxy_interfaces, 272 | # - destinations that match $mydestination 273 | # - destinations that match $virtual_alias_domains, 274 | # - destinations that match $virtual_mailbox_domains. 275 | # These destinations do not need to be listed in $relay_domains. 276 | # 277 | # Specify a list of hosts or domains, /file/name patterns or type:name 278 | # lookup tables, separated by commas and/or whitespace. Continue 279 | # long lines by starting the next line with whitespace. A file name 280 | # is replaced by its contents; a type:name table is matched when a 281 | # (parent) domain appears as lookup key. 282 | # 283 | # NOTE: Postfix will not automatically forward mail for domains that 284 | # list this system as their primary or backup MX host. See the 285 | # permit_mx_backup restriction description in postconf(5). 286 | # 287 | #relay_domains = $mydestination 288 | 289 | # INTERNET OR INTRANET 290 | 291 | # The relayhost parameter specifies the default host to send mail to 292 | # when no entry is matched in the optional transport(5) table. When 293 | # no relayhost is given, mail is routed directly to the destination. 294 | # 295 | # On an intranet, specify the organizational domain name. If your 296 | # internal DNS uses no MX records, specify the name of the intranet 297 | # gateway host instead. 298 | # 299 | # In the case of SMTP, specify a domain, host, host:port, [host]:port, 300 | # [address] or [address]:port; the form [host] turns off MX lookups. 301 | # 302 | # If you're connected via UUCP, see also the default_transport parameter. 303 | # 304 | #relayhost = $mydomain 305 | #relayhost = [gateway.my.domain] 306 | #relayhost = [mailserver.isp.tld] 307 | #relayhost = uucphost 308 | #relayhost = [an.ip.add.ress] 309 | 310 | # REJECTING UNKNOWN RELAY USERS 311 | # 312 | # The relay_recipient_maps parameter specifies optional lookup tables 313 | # with all addresses in the domains that match $relay_domains. 314 | # 315 | # If this parameter is defined, then the SMTP server will reject 316 | # mail for unknown relay users. This feature is off by default. 317 | # 318 | # The right-hand side of the lookup tables is conveniently ignored. 319 | # In the left-hand side, specify an @domain.tld wild-card, or specify 320 | # a user@domain.tld address. 321 | # 322 | #relay_recipient_maps = hash:/etc/postfix/relay_recipients 323 | 324 | # INPUT RATE CONTROL 325 | # 326 | # The in_flow_delay configuration parameter implements mail input 327 | # flow control. This feature is turned on by default, although it 328 | # still needs further development (it's disabled on SCO UNIX due 329 | # to an SCO bug). 330 | # 331 | # A Postfix process will pause for $in_flow_delay seconds before 332 | # accepting a new message, when the message arrival rate exceeds the 333 | # message delivery rate. With the default 100 SMTP server process 334 | # limit, this limits the mail inflow to 100 messages a second more 335 | # than the number of messages delivered per second. 336 | # 337 | # Specify 0 to disable the feature. Valid delays are 0..10. 338 | # 339 | #in_flow_delay = 1s 340 | 341 | # ADDRESS REWRITING 342 | # 343 | # The ADDRESS_REWRITING_README document gives information about 344 | # address masquerading or other forms of address rewriting including 345 | # username->Firstname.Lastname mapping. 346 | 347 | # ADDRESS REDIRECTION (VIRTUAL DOMAIN) 348 | # 349 | # The VIRTUAL_README document gives information about the many forms 350 | # of domain hosting that Postfix supports. 351 | 352 | # "USER HAS MOVED" BOUNCE MESSAGES 353 | # 354 | # See the discussion in the ADDRESS_REWRITING_README document. 355 | 356 | # TRANSPORT MAP 357 | # 358 | # See the discussion in the ADDRESS_REWRITING_README document. 359 | 360 | # ALIAS DATABASE 361 | # 362 | # The alias_maps parameter specifies the list of alias databases used 363 | # by the local delivery agent. The default list is system dependent. 364 | # 365 | # On systems with NIS, the default is to search the local alias 366 | # database, then the NIS alias database. See aliases(5) for syntax 367 | # details. 368 | # 369 | # If you change the alias database, run "postalias /etc/aliases" (or 370 | # wherever your system stores the mail alias file), or simply run 371 | # "newaliases" to build the necessary DBM or DB file. 372 | # 373 | # It will take a minute or so before changes become visible. Use 374 | # "postfix reload" to eliminate the delay. 375 | # 376 | #alias_maps = dbm:/etc/aliases 377 | #alias_maps = hash:/etc/aliases 378 | #alias_maps = hash:/etc/aliases, nis:mail.aliases 379 | #alias_maps = netinfo:/aliases 380 | 381 | # The alias_database parameter specifies the alias database(s) that 382 | # are built with "newaliases" or "sendmail -bi". This is a separate 383 | # configuration parameter, because alias_maps (see above) may specify 384 | # tables that are not necessarily all under control by Postfix. 385 | # 386 | #alias_database = dbm:/etc/aliases 387 | #alias_database = dbm:/etc/mail/aliases 388 | #alias_database = hash:/etc/aliases 389 | #alias_database = hash:/etc/aliases, hash:/opt/majordomo/aliases 390 | 391 | # ADDRESS EXTENSIONS (e.g., user+foo) 392 | # 393 | # The recipient_delimiter parameter specifies the separator between 394 | # user names and address extensions (user+foo). See canonical(5), 395 | # local(8), relocated(5) and virtual(5) for the effects this has on 396 | # aliases, canonical, virtual, relocated and .forward file lookups. 397 | # Basically, the software tries user+foo and .forward+foo before 398 | # trying user and .forward. 399 | # 400 | #recipient_delimiter = + 401 | 402 | # DELIVERY TO MAILBOX 403 | # 404 | # The home_mailbox parameter specifies the optional pathname of a 405 | # mailbox file relative to a user's home directory. The default 406 | # mailbox file is /var/spool/mail/user or /var/mail/user. Specify 407 | # "Maildir/" for qmail-style delivery (the / is required). 408 | # 409 | #home_mailbox = Mailbox 410 | #home_mailbox = Maildir/ 411 | 412 | # The mail_spool_directory parameter specifies the directory where 413 | # UNIX-style mailboxes are kept. The default setting depends on the 414 | # system type. 415 | # 416 | #mail_spool_directory = /var/mail 417 | #mail_spool_directory = /var/spool/mail 418 | 419 | # The mailbox_command parameter specifies the optional external 420 | # command to use instead of mailbox delivery. The command is run as 421 | # the recipient with proper HOME, SHELL and LOGNAME environment settings. 422 | # Exception: delivery for root is done as $default_user. 423 | # 424 | # Other environment variables of interest: USER (recipient username), 425 | # EXTENSION (address extension), DOMAIN (domain part of address), 426 | # and LOCAL (the address localpart). 427 | # 428 | # Unlike other Postfix configuration parameters, the mailbox_command 429 | # parameter is not subjected to $parameter substitutions. This is to 430 | # make it easier to specify shell syntax (see example below). 431 | # 432 | # Avoid shell meta characters because they will force Postfix to run 433 | # an expensive shell process. Procmail alone is expensive enough. 434 | # 435 | # IF YOU USE THIS TO DELIVER MAIL SYSTEM-WIDE, YOU MUST SET UP AN 436 | # ALIAS THAT FORWARDS MAIL FOR ROOT TO A REAL USER. 437 | # 438 | #mailbox_command = /some/where/procmail 439 | #mailbox_command = /some/where/procmail -a "$EXTENSION" 440 | 441 | # The mailbox_transport specifies the optional transport in master.cf 442 | # to use after processing aliases and .forward files. This parameter 443 | # has precedence over the mailbox_command, fallback_transport and 444 | # luser_relay parameters. 445 | # 446 | # Specify a string of the form transport:nexthop, where transport is 447 | # the name of a mail delivery transport defined in master.cf. The 448 | # :nexthop part is optional. For more details see the sample transport 449 | # configuration file. 450 | # 451 | # NOTE: if you use this feature for accounts not in the UNIX password 452 | # file, then you must update the "local_recipient_maps" setting in 453 | # the main.cf file, otherwise the SMTP server will reject mail for 454 | # non-UNIX accounts with "User unknown in local recipient table". 455 | # 456 | #mailbox_transport = lmtp:unix:/file/name 457 | #mailbox_transport = cyrus 458 | 459 | # The fallback_transport specifies the optional transport in master.cf 460 | # to use for recipients that are not found in the UNIX passwd database. 461 | # This parameter has precedence over the luser_relay parameter. 462 | # 463 | # Specify a string of the form transport:nexthop, where transport is 464 | # the name of a mail delivery transport defined in master.cf. The 465 | # :nexthop part is optional. For more details see the sample transport 466 | # configuration file. 467 | # 468 | # NOTE: if you use this feature for accounts not in the UNIX password 469 | # file, then you must update the "local_recipient_maps" setting in 470 | # the main.cf file, otherwise the SMTP server will reject mail for 471 | # non-UNIX accounts with "User unknown in local recipient table". 472 | # 473 | #fallback_transport = lmtp:unix:/file/name 474 | #fallback_transport = cyrus 475 | #fallback_transport = 476 | 477 | # The luser_relay parameter specifies an optional destination address 478 | # for unknown recipients. By default, mail for unknown@$mydestination, 479 | # unknown@[$inet_interfaces] or unknown@[$proxy_interfaces] is returned 480 | # as undeliverable. 481 | # 482 | # The following expansions are done on luser_relay: $user (recipient 483 | # username), $shell (recipient shell), $home (recipient home directory), 484 | # $recipient (full recipient address), $extension (recipient address 485 | # extension), $domain (recipient domain), $local (entire recipient 486 | # localpart), $recipient_delimiter. Specify ${name?value} or 487 | # ${name:value} to expand value only when $name does (does not) exist. 488 | # 489 | # luser_relay works only for the default Postfix local delivery agent. 490 | # 491 | # NOTE: if you use this feature for accounts not in the UNIX password 492 | # file, then you must specify "local_recipient_maps =" (i.e. empty) in 493 | # the main.cf file, otherwise the SMTP server will reject mail for 494 | # non-UNIX accounts with "User unknown in local recipient table". 495 | # 496 | #luser_relay = $user@other.host 497 | #luser_relay = $local@other.host 498 | #luser_relay = admin+$local 499 | 500 | # JUNK MAIL CONTROLS 501 | # 502 | # The controls listed here are only a very small subset. The file 503 | # SMTPD_ACCESS_README provides an overview. 504 | 505 | # The header_checks parameter specifies an optional table with patterns 506 | # that each logical message header is matched against, including 507 | # headers that span multiple physical lines. 508 | # 509 | # By default, these patterns also apply to MIME headers and to the 510 | # headers of attached messages. With older Postfix versions, MIME and 511 | # attached message headers were treated as body text. 512 | # 513 | # For details, see "man header_checks". 514 | # 515 | #header_checks = regexp:/etc/postfix/header_checks 516 | 517 | # FAST ETRN SERVICE 518 | # 519 | # Postfix maintains per-destination logfiles with information about 520 | # deferred mail, so that mail can be flushed quickly with the SMTP 521 | # "ETRN domain.tld" command, or by executing "sendmail -qRdomain.tld". 522 | # See the ETRN_README document for a detailed description. 523 | # 524 | # The fast_flush_domains parameter controls what destinations are 525 | # eligible for this service. By default, they are all domains that 526 | # this server is willing to relay mail to. 527 | # 528 | #fast_flush_domains = $relay_domains 529 | 530 | # SHOW SOFTWARE VERSION OR NOT 531 | # 532 | # The smtpd_banner parameter specifies the text that follows the 220 533 | # code in the SMTP server's greeting banner. Some people like to see 534 | # the mail version advertised. By default, Postfix shows no version. 535 | # 536 | # You MUST specify $myhostname at the start of the text. That is an 537 | # RFC requirement. Postfix itself does not care. 538 | # 539 | #smtpd_banner = $myhostname ESMTP $mail_name 540 | #smtpd_banner = $myhostname ESMTP $mail_name ($mail_version) 541 | 542 | # PARALLEL DELIVERY TO THE SAME DESTINATION 543 | # 544 | # How many parallel deliveries to the same user or domain? With local 545 | # delivery, it does not make sense to do massively parallel delivery 546 | # to the same user, because mailbox updates must happen sequentially, 547 | # and expensive pipelines in .forward files can cause disasters when 548 | # too many are run at the same time. With SMTP deliveries, 10 549 | # simultaneous connections to the same domain could be sufficient to 550 | # raise eyebrows. 551 | # 552 | # Each message delivery transport has its XXX_destination_concurrency_limit 553 | # parameter. The default is $default_destination_concurrency_limit for 554 | # most delivery transports. For the local delivery agent the default is 2. 555 | 556 | #local_destination_concurrency_limit = 2 557 | #default_destination_concurrency_limit = 20 558 | 559 | # DEBUGGING CONTROL 560 | # 561 | # The debug_peer_level parameter specifies the increment in verbose 562 | # logging level when an SMTP client or server host name or address 563 | # matches a pattern in the debug_peer_list parameter. 564 | # 565 | debug_peer_level = 2 566 | 567 | # The debug_peer_list parameter specifies an optional list of domain 568 | # or network patterns, /file/name patterns or type:name tables. When 569 | # an SMTP client or server host name or address matches a pattern, 570 | # increase the verbose logging level by the amount specified in the 571 | # debug_peer_level parameter. 572 | # 573 | #debug_peer_list = 127.0.0.1 574 | #debug_peer_list = some.domain 575 | 576 | # The debugger_command specifies the external command that is executed 577 | # when a Postfix daemon program is run with the -D option. 578 | # 579 | # Use "command .. & sleep 5" so that the debugger can attach before 580 | # the process marches on. If you use an X-based debugger, be sure to 581 | # set up your XAUTHORITY environment variable before starting Postfix. 582 | # 583 | debugger_command = 584 | PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin 585 | xxgdb $daemon_directory/$process_name $process_id & sleep 5 586 | 587 | # If you can't use X, use this to capture the call stack when a 588 | # daemon crashes. The result is in a file in the configuration 589 | # directory, and is named after the process name and the process ID. 590 | # 591 | # debugger_command = 592 | # PATH=/bin:/usr/bin:/usr/local/bin; export PATH; (echo cont; 593 | # echo where) | gdb $daemon_directory/$process_name $process_id 2>&1 594 | # >$config_directory/$process_name.$process_id.log & sleep 5 595 | # 596 | # Another possibility is to run gdb under a detached screen session. 597 | # To attach to the screen sesssion, su root and run "screen -r 598 | # " where uniquely matches one of the detached 599 | # sessions (from "screen -list"). 600 | # 601 | # debugger_command = 602 | # PATH=/bin:/usr/bin:/sbin:/usr/sbin; export PATH; screen 603 | # -dmS $process_name gdb $daemon_directory/$process_name 604 | # $process_id & sleep 1 605 | 606 | # INSTALL-TIME CONFIGURATION INFORMATION 607 | # 608 | # The following parameters are used when installing a new Postfix version. 609 | # 610 | # sendmail_path: The full pathname of the Postfix sendmail command. 611 | # This is the Sendmail-compatible mail posting interface. 612 | # 613 | sendmail_path = 614 | 615 | # newaliases_path: The full pathname of the Postfix newaliases command. 616 | # This is the Sendmail-compatible command to build alias databases. 617 | # 618 | newaliases_path = 619 | 620 | # mailq_path: The full pathname of the Postfix mailq command. This 621 | # is the Sendmail-compatible mail queue listing command. 622 | # 623 | mailq_path = 624 | 625 | # setgid_group: The group for mail submission and queue management 626 | # commands. This must be a group name with a numerical group ID that 627 | # is not shared with other accounts, not even with the Postfix account. 628 | # 629 | setgid_group = 630 | 631 | # html_directory: The location of the Postfix HTML documentation. 632 | # 633 | html_directory = 634 | 635 | # manpage_directory: The location of the Postfix on-line manual pages. 636 | # 637 | manpage_directory = 638 | 639 | # sample_directory: The location of the Postfix sample configuration files. 640 | # This parameter is obsolete as of Postfix 2.1. 641 | # 642 | sample_directory = 643 | 644 | # readme_directory: The location of the Postfix README files. 645 | # 646 | readme_directory = 647 | -------------------------------------------------------------------------------- /tests/Resources/RealWorld/main.cf.default.json: -------------------------------------------------------------------------------- 1 | { 2 | "MultiLineValues": [ 3 | "AllowEmptyTopSection" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /tests/Resources/RealWorld/mysqld.cnf: -------------------------------------------------------------------------------- 1 | [mysqld] 2 | user = mysql 3 | pid-file = /var/run/mysqld/mysqld.pid 4 | skip-external-locking 5 | old_passwords = 1 6 | skip-bdb 7 | # we don't need ACID today 8 | skip-innodb -------------------------------------------------------------------------------- /tests/Resources/RealWorld/mysqld.cnf.json: -------------------------------------------------------------------------------- 1 | { 2 | "MultiLineValues": [ 3 | "AllowValuelessKeys" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /tests/Resources/RealWorld/openssl.cnf: -------------------------------------------------------------------------------- 1 | # 2 | # OpenSSL example configuration file. 3 | # This is mostly being used for generation of certificate requests. 4 | # 5 | 6 | # This definition stops the following lines choking if HOME isn't 7 | # defined. 8 | HOME = . 9 | RANDFILE = $ENV::HOME/.rnd 10 | 11 | # Extra OBJECT IDENTIFIER info: 12 | #oid_file = $ENV::HOME/.oid 13 | oid_section = new_oids 14 | 15 | # To use this configuration file with the "-extfile" option of the 16 | # "openssl x509" utility, name here the section containing the 17 | # X.509v3 extensions to use: 18 | # extensions = 19 | # (Alternatively, use a configuration file that has only 20 | # X.509v3 extensions in its main [= default] section.) 21 | 22 | [ new_oids ] 23 | 24 | # We can add new OIDs in here for use by 'ca', 'req' and 'ts'. 25 | # Add a simple OID like this: 26 | # testoid1=1.2.3.4 27 | # Or use config file substitution like this: 28 | # testoid2=${testoid1}.5.6 29 | 30 | # Policies used by the TSA examples. 31 | tsa_policy1 = 1.2.3.4.1 32 | tsa_policy2 = 1.2.3.4.5.6 33 | tsa_policy3 = 1.2.3.4.5.7 34 | 35 | #################################################################### 36 | [ ca ] 37 | default_ca = CA_default # The default ca section 38 | 39 | #################################################################### 40 | [ CA_default ] 41 | 42 | dir = ./demoCA # Where everything is kept 43 | certs = $dir/certs # Where the issued certs are kept 44 | crl_dir = $dir/crl # Where the issued crl are kept 45 | database = $dir/index.txt # database index file. 46 | #unique_subject = no # Set to 'no' to allow creation of 47 | # several ctificates with same subject. 48 | new_certs_dir = $dir/newcerts # default place for new certs. 49 | 50 | certificate = $dir/cacert.pem # The CA certificate 51 | serial = $dir/serial # The current serial number 52 | crlnumber = $dir/crlnumber # the current crl number 53 | # must be commented out to leave a V1 CRL 54 | crl = $dir/crl.pem # The current CRL 55 | private_key = $dir/private/cakey.pem# The private key 56 | RANDFILE = $dir/private/.rand # private random number file 57 | 58 | x509_extensions = usr_cert # The extentions to add to the cert 59 | 60 | # Comment out the following two lines for the "traditional" 61 | # (and highly broken) format. 62 | name_opt = ca_default # Subject Name options 63 | cert_opt = ca_default # Certificate field options 64 | 65 | # Extension copying option: use with caution. 66 | # copy_extensions = copy 67 | 68 | # Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs 69 | # so this is commented out by default to leave a V1 CRL. 70 | # crlnumber must also be commented out to leave a V1 CRL. 71 | # crl_extensions = crl_ext 72 | 73 | default_days = 365 # how long to certify for 74 | default_crl_days= 30 # how long before next CRL 75 | default_md = default # use public key default MD 76 | preserve = no # keep passed DN ordering 77 | 78 | # A few difference way of specifying how similar the request should look 79 | # For type CA, the listed attributes must be the same, and the optional 80 | # and supplied fields are just that :-) 81 | policy = policy_match 82 | 83 | # For the CA policy 84 | [ policy_match ] 85 | countryName = match 86 | stateOrProvinceName = match 87 | organizationName = match 88 | organizationalUnitName = optional 89 | commonName = supplied 90 | emailAddress = optional 91 | 92 | # For the 'anything' policy 93 | # At this point in time, you must list all acceptable 'object' 94 | # types. 95 | [ policy_anything ] 96 | countryName = optional 97 | stateOrProvinceName = optional 98 | localityName = optional 99 | organizationName = optional 100 | organizationalUnitName = optional 101 | commonName = supplied 102 | emailAddress = optional 103 | 104 | #################################################################### 105 | [ req ] 106 | default_bits = 2048 107 | default_keyfile = privkey.pem 108 | distinguished_name = req_distinguished_name 109 | attributes = req_attributes 110 | x509_extensions = v3_ca # The extentions to add to the self signed cert 111 | 112 | # Passwords for private keys if not present they will be prompted for 113 | # input_password = secret 114 | # output_password = secret 115 | 116 | # This sets a mask for permitted string types. There are several options. 117 | # default: PrintableString, T61String, BMPString. 118 | # pkix : PrintableString, BMPString (PKIX recommendation before 2004) 119 | # utf8only: only UTF8Strings (PKIX recommendation after 2004). 120 | # nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). 121 | # MASK:XXXX a literal mask value. 122 | # WARNING: ancient versions of Netscape crash on BMPStrings or UTF8Strings. 123 | string_mask = utf8only 124 | 125 | # req_extensions = v3_req # The extensions to add to a certificate request 126 | 127 | [ req_distinguished_name ] 128 | countryName = Country Name (2 letter code) 129 | countryName_default = AU 130 | countryName_min = 2 131 | countryName_max = 2 132 | 133 | stateOrProvinceName = State or Province Name (full name) 134 | stateOrProvinceName_default = Some-State 135 | 136 | localityName = Locality Name (eg, city) 137 | 138 | 0.organizationName = Organization Name (eg, company) 139 | 0.organizationName_default = Internet Widgits Pty Ltd 140 | 141 | # we can do this but it is not needed normally :-) 142 | #1.organizationName = Second Organization Name (eg, company) 143 | #1.organizationName_default = World Wide Web Pty Ltd 144 | 145 | organizationalUnitName = Organizational Unit Name (eg, section) 146 | #organizationalUnitName_default = 147 | 148 | commonName = Common Name (e.g. server FQDN or YOUR name) 149 | commonName_max = 64 150 | 151 | emailAddress = Email Address 152 | emailAddress_max = 64 153 | 154 | # SET-ex3 = SET extension number 3 155 | 156 | [ req_attributes ] 157 | challengePassword = A challenge password 158 | challengePassword_min = 4 159 | challengePassword_max = 20 160 | 161 | unstructuredName = An optional company name 162 | 163 | [ usr_cert ] 164 | 165 | # These extensions are added when 'ca' signs a request. 166 | 167 | # This goes against PKIX guidelines but some CAs do it and some software 168 | # requires this to avoid interpreting an end user certificate as a CA. 169 | 170 | basicConstraints=CA:FALSE 171 | 172 | # Here are some examples of the usage of nsCertType. If it is omitted 173 | # the certificate can be used for anything *except* object signing. 174 | 175 | # This is OK for an SSL server. 176 | # nsCertType = server 177 | 178 | # For an object signing certificate this would be used. 179 | # nsCertType = objsign 180 | 181 | # For normal client use this is typical 182 | # nsCertType = client, email 183 | 184 | # and for everything including object signing: 185 | # nsCertType = client, email, objsign 186 | 187 | # This is typical in keyUsage for a client certificate. 188 | # keyUsage = nonRepudiation, digitalSignature, keyEncipherment 189 | 190 | # This will be displayed in Netscape's comment listbox. 191 | nsComment = "OpenSSL Generated Certificate" 192 | 193 | # PKIX recommendations harmless if included in all certificates. 194 | subjectKeyIdentifier=hash 195 | authorityKeyIdentifier=keyid,issuer 196 | 197 | # This stuff is for subjectAltName and issuerAltname. 198 | # Import the email address. 199 | # subjectAltName=email:copy 200 | # An alternative to produce certificates that aren't 201 | # deprecated according to PKIX. 202 | # subjectAltName=email:move 203 | 204 | # Copy subject details 205 | # issuerAltName=issuer:copy 206 | 207 | #nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem 208 | #nsBaseUrl 209 | #nsRevocationUrl 210 | #nsRenewalUrl 211 | #nsCaPolicyUrl 212 | #nsSslServerName 213 | 214 | # This is required for TSA certificates. 215 | # extendedKeyUsage = critical,timeStamping 216 | 217 | [ v3_req ] 218 | 219 | # Extensions to add to a certificate request 220 | 221 | basicConstraints = CA:FALSE 222 | keyUsage = nonRepudiation, digitalSignature, keyEncipherment 223 | 224 | [ v3_ca ] 225 | 226 | 227 | # Extensions for a typical CA 228 | 229 | 230 | # PKIX recommendation. 231 | 232 | subjectKeyIdentifier=hash 233 | 234 | authorityKeyIdentifier=keyid:always,issuer 235 | 236 | # This is what PKIX recommends but some broken software chokes on critical 237 | # extensions. 238 | #basicConstraints = critical,CA:true 239 | # So we do this instead. 240 | basicConstraints = CA:true 241 | 242 | # Key usage: this is typical for a CA certificate. However since it will 243 | # prevent it being used as an test self-signed certificate it is best 244 | # left out by default. 245 | # keyUsage = cRLSign, keyCertSign 246 | 247 | # Some might want this also 248 | # nsCertType = sslCA, emailCA 249 | 250 | # Include email address in subject alt name: another PKIX recommendation 251 | # subjectAltName=email:copy 252 | # Copy issuer details 253 | # issuerAltName=issuer:copy 254 | 255 | # DER hex encoding of an extension: beware experts only! 256 | # obj=DER:02:03 257 | # Where 'obj' is a standard or added object 258 | # You can even override a supported extension: 259 | # basicConstraints= critical, DER:30:03:01:01:FF 260 | 261 | [ crl_ext ] 262 | 263 | # CRL extensions. 264 | # Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. 265 | 266 | # issuerAltName=issuer:copy 267 | authorityKeyIdentifier=keyid:always 268 | 269 | [ proxy_cert_ext ] 270 | # These extensions should be added when creating a proxy certificate 271 | 272 | # This goes against PKIX guidelines but some CAs do it and some software 273 | # requires this to avoid interpreting an end user certificate as a CA. 274 | 275 | basicConstraints=CA:FALSE 276 | 277 | # Here are some examples of the usage of nsCertType. If it is omitted 278 | # the certificate can be used for anything *except* object signing. 279 | 280 | # This is OK for an SSL server. 281 | # nsCertType = server 282 | 283 | # For an object signing certificate this would be used. 284 | # nsCertType = objsign 285 | 286 | # For normal client use this is typical 287 | # nsCertType = client, email 288 | 289 | # and for everything including object signing: 290 | # nsCertType = client, email, objsign 291 | 292 | # This is typical in keyUsage for a client certificate. 293 | # keyUsage = nonRepudiation, digitalSignature, keyEncipherment 294 | 295 | # This will be displayed in Netscape's comment listbox. 296 | nsComment = "OpenSSL Generated Certificate" 297 | 298 | # PKIX recommendations harmless if included in all certificates. 299 | subjectKeyIdentifier=hash 300 | authorityKeyIdentifier=keyid,issuer 301 | 302 | # This stuff is for subjectAltName and issuerAltname. 303 | # Import the email address. 304 | # subjectAltName=email:copy 305 | # An alternative to produce certificates that aren't 306 | # deprecated according to PKIX. 307 | # subjectAltName=email:move 308 | 309 | # Copy subject details 310 | # issuerAltName=issuer:copy 311 | 312 | #nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem 313 | #nsBaseUrl 314 | #nsRevocationUrl 315 | #nsRenewalUrl 316 | #nsCaPolicyUrl 317 | #nsSslServerName 318 | 319 | # This really needs to be in place for it to be a proxy certificate. 320 | proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo 321 | 322 | #################################################################### 323 | [ tsa ] 324 | 325 | default_tsa = tsa_config1 # the default TSA section 326 | 327 | [ tsa_config1 ] 328 | 329 | # These are used by the TSA reply generation only. 330 | dir = ./demoCA # TSA root directory 331 | serial = $dir/tsaserial # The current serial number (mandatory) 332 | crypto_device = builtin # OpenSSL engine to use for signing 333 | signer_cert = $dir/tsacert.pem # The TSA signing certificate 334 | # (optional) 335 | certs = $dir/cacert.pem # Certificate chain to include in reply 336 | # (optional) 337 | signer_key = $dir/private/tsakey.pem # The TSA private key (optional) 338 | 339 | default_policy = tsa_policy1 # Policy if request did not specify it 340 | # (optional) 341 | other_policies = tsa_policy2, tsa_policy3 # acceptable policies (optional) 342 | digests = md5, sha1 # Acceptable message digests (mandatory) 343 | accuracy = secs:1, millisecs:500, microsecs:100 # (optional) 344 | clock_precision_digits = 0 # number of digits after dot. (optional) 345 | ordering = yes # Is ordering defined for timestamps? 346 | # (optional, default: no) 347 | tsa_name = yes # Must the TSA name be included in the reply? 348 | # (optional, default: no) 349 | ess_cert_id_chain = no # Must the ESS cert id chain be included? 350 | # (optional, default: no) 351 | -------------------------------------------------------------------------------- /tests/Resources/RealWorld/openssl.cnf.json: -------------------------------------------------------------------------------- 1 | { 2 | "MultiLineValues": [ 3 | "AllowEmptyTopSection" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /tests/Resources/RealWorld/redis.conf: -------------------------------------------------------------------------------- 1 | bind 11.1.1.11 2 | port 12345 3 | protected-mode no 4 | daemonize yes 5 | supervised no 6 | loglevel notice 7 | databases 16 8 | 9 | tcp-backlog 16000 10 | timeout 0 11 | tcp-keepalive 60 12 | maxclients 16000 13 | 14 | maxmemory 6144MB 15 | maxmemory-policy volatile-lru 16 | save 300 10 17 | 18 | stop-writes-on-bgsave-error no 19 | rdbcompression yes 20 | rdbchecksum yes 21 | 22 | slave-serve-stale-data yes 23 | slave-read-only yes 24 | slave-priority 100 25 | repl-ping-slave-period 10 26 | repl-disable-tcp-nodelay no 27 | min-slaves-to-write 0 28 | min-slaves-max-lag 0 29 | 30 | appendonly no 31 | appendfsync everysec 32 | aof-rewrite-incremental-fsync yes 33 | auto-aof-rewrite-percentage 100 34 | auto-aof-rewrite-min-size 64mb 35 | no-appendfsync-on-rewrite no 36 | 37 | hash-max-ziplist-entries 512 38 | hash-max-ziplist-value 64 39 | 40 | list-max-ziplist-entries 512 41 | list-max-ziplist-value 64 42 | 43 | set-max-intset-entries 512 44 | 45 | zset-max-ziplist-entries 128 46 | zset-max-ziplist-value 64 47 | activerehashing yes 48 | client-output-buffer-limit normal 0 0 0 49 | client-output-buffer-limit slave 512mb 128mb 120 50 | client-output-buffer-limit pubsub 32mb 8mb 60 51 | 52 | cluster-enabled yes 53 | cluster-node-timeout 30000 54 | cluster-slave-validity-factor 10 55 | cluster-migration-barrier 1 56 | cluster-require-full-coverage yes -------------------------------------------------------------------------------- /tests/Resources/RealWorld/redis.conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "KeyValueSeparator": " ", 3 | "MultiLineValues": [ 4 | "AllowValuelessKeys", 5 | "AllowEmptyTopSection" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /tests/Resources/RealWorld/skinr.help.ini: -------------------------------------------------------------------------------- 1 | [overview] 2 | title = "Overview" 3 | weight = 0 4 | 5 | [syntax] 6 | title = "Syntax" 7 | weight = 1 8 | 9 | [css-js] 10 | title = "CSS, Stylesheets & JavaScript" 11 | parent = syntax 12 | weight = 1 13 | 14 | [features] 15 | title = "Features" 16 | parent = syntax 17 | weight = 2 18 | 19 | [templates] 20 | title = "Templates" 21 | parent = syntax 22 | weight = 5 23 | 24 | [examples] 25 | title = "Examples" 26 | parent = syntax 27 | weight = 6 28 | 29 | # test comment -------------------------------------------------------------------------------- /tests/Resources/RealWorld/wakatime.cfg: -------------------------------------------------------------------------------- 1 | [settings] 2 | api_key=00000000-0000-0000-0000-000000000000 3 | proxy= 4 | debug=false 5 | exclude= 6 | ^/var/ 7 | ^/tmp/ 8 | ^/private/ 9 | COMMIT_EDITMSG$ 10 | PULLREQ_EDITMSG$ 11 | MERGE_MSG$ 12 | 13 | [projectmap] 14 | Projects/Web/Customer/YRT/(.*)/=YRT 15 | Projects/Web/Customer/SEL/(.*)/=SEL 16 | Projects/Web/Customer/EX/example.com(.*)/=Example 17 | Projects/Web/Customer/EX/attribution.example.com/(.*)/=EXP survey 18 | AnotherCustomer.Configurator.(.*) = Configurator 19 | AnotherCustomer.App.Publisher = Publisher 20 | -------------------------------------------------------------------------------- /tests/Resources/RealWorld/wakatime.cfg.json: -------------------------------------------------------------------------------- 1 | { 2 | "MultiLineValues": [ 3 | "Simple" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /tests/Resources/Structure/from-scratch.conf: -------------------------------------------------------------------------------- 1 | [section1] 2 | string=value 3 | 4 | [section2] 5 | bool=true 6 | 7 | [section3] 8 | doble=0.2 -------------------------------------------------------------------------------- /tests/Resources/Structure/indented.ini: -------------------------------------------------------------------------------- 1 |  [Sections Can Be Indented] 2 | can_values_be_as_well = True 3 | does_that_mean_anything_special = False 4 | purpose = formatting for readability 5 | multiline_values = are 6 | handled just fine as 7 | long as they are indented 8 | deeper than the first line 9 | of a value 10 | 11 | # Did I mention we can indent comments, too? -------------------------------------------------------------------------------- /tests/Resources/Structure/interpolation.conf: -------------------------------------------------------------------------------- 1 | [Paths] 2 | home_dir: /Users 3 | my_dir: ${home_dir}/lumberjack 4 | my_pictures: ${my_dir}/Pictures 5 | 6 | [Common] 7 | home_dir: /Users 8 | library_dir: /Library 9 | system_dir: /System 10 | macports_dir: /opt/local 11 | 12 | [Frameworks] 13 | Python: 3.2 14 | path: ${Common:system_dir}/Library/Frameworks/ 15 | 16 | [Arthur] 17 | nickname: Two Sheds 18 | last_name: Jackson 19 | my_dir: ${Common:home_dir}/twosheds 20 | my_pictures: ${my_dir}/Pictures 21 | python_dir: ${Frameworks:path}/Python/Versions/${Frameworks:Python} -------------------------------------------------------------------------------- /tests/Resources/Structure/multi-line-delimited.ini: -------------------------------------------------------------------------------- 1 | [Multiline Values] 2 | chorus="I'm a lumberjack, and I'm okay 3 | I sleep all night and I work all day 4 | " -------------------------------------------------------------------------------- /tests/Resources/Structure/multi-line.ini: -------------------------------------------------------------------------------- 1 | [Multiline Values] 2 | chorus=I'm a lumberjack, and I'm okay 3 | I sleep all night and I work all day -------------------------------------------------------------------------------- /tests/Resources/Structure/only-comments.ini: -------------------------------------------------------------------------------- 1 | [You can use comments] 2 | # like this 3 | ; or this 4 | 5 | # By default only in an empty line. 6 | # Inline comments can be harmful because they prevent users 7 | # from using the delimiting characters as parts of values. 8 | # That being said, this can be customized. 9 | -------------------------------------------------------------------------------- /tests/Resources/Structure/simple-keys.ini: -------------------------------------------------------------------------------- 1 | [Simple Values] 2 | key=value 3 | spaces in keys=allowed 4 | spaces in values=allowed as well 5 | spaces around the delimiter = obviously -------------------------------------------------------------------------------- /tests/Resources/Values/array.cnf: -------------------------------------------------------------------------------- 1 | [settings] 2 | exclude = 3 | ^/var/ 4 | ^/tmp/ 5 | ^/private/ 6 | COMMIT_EDITMSG$ 7 | PULLREQ_EDITMSG$ 8 | MERGE_MSG$ -------------------------------------------------------------------------------- /tests/Resources/Values/boolean.ini: -------------------------------------------------------------------------------- 1 | [Simple] 2 | empty= 3 | numericTrue=1 4 | numericFalse=0 5 | textTrue = true 6 | textFalse = false 7 | 8 | [YesNo] 9 | sampleYes=Yes 10 | sampleNo=no 11 | 12 | [OnOff] 13 | sampleOn=on 14 | sampleOff=Off 15 | 16 | [EnabledDisabled] 17 | sampleOn=Enabled 18 | sampleOff=disabled 19 | 20 | [ValoriItaliani] 21 | positivo = vero 22 | sampleOff = falso 23 | -------------------------------------------------------------------------------- /tests/Resources/Values/double.conf: -------------------------------------------------------------------------------- 1 | [Works] 2 | empty= 3 | integer=1 4 | usual=0.000001 5 | withD=0.6D 6 | engineeringNotation = 1.7E+3 7 | float = 4.5f 8 | thousands=1,000 9 | dollars=$2,999 10 | 11 | [ItalianLocalized] 12 | withComa = 9,3 13 | 14 | [DoesntWork] 15 | random = sdgfery56d 16 | --------------------------------------------------------------------------------