 |
|

27.03.2021, 18:28
|
|
Участник форума
Регистрация: 03.08.2019
Сообщений: 168
С нами:
3568604
Репутация:
48
|
|
Ох блять, чет я седня дохуя любопытный
Мне нужно создать ini файл для сохранения в них настроек плагина, но загвоздка в том, что перерыв все, я не смог найти нормального варианта сохранения и чтения файла
Если вы знаете способ работы с ini - прошу, пишите сюда
Заранее спасибо
|
|
|

28.03.2021, 11:13
|
|
Познающий
Регистрация: 18.09.2019
Сообщений: 31
С нами:
3502227
Репутация:
63
|
|
Делал class лично для себя, для облегчения работы с mINI. Не нужно быть ♂dungeon master♂ чтобы разобраться в его работе, но для настоящих ♂boss of the gym♂ оставил пример по работе с ним.
Сообщение от Спойлер
CConfig.h:
Код:
#pragma once
// #include
#include
class
CConfig
{
public
:
// Инициализация класса
void
Init
(
std
::
string iniName
)
;
/////////// read ///////////
// Возращает число
int
GetInt
(
std
::
string stKey1
,
std
::
string stKey2
)
;
// Возращает дробное число
float
GetFloat
(
std
::
string stKey1
,
std
::
string stKey2
)
;
// Возращает true или false
bool
GetBool
(
std
::
string stKey1
,
std
::
string stKey2
)
;
// Возращает std::string
std
::
string
GetString
(
std
::
string stKey1
,
std
::
string stKey2
)
;
// Возращает const char*
const
char
*
GetConstChar
(
std
::
string stKey1
,
std
::
string stKey2
)
;
// Возращает char
char
GetChar
(
std
::
string stKey1
,
std
::
string stKey2
)
;
/////////// write ///////////
// Записывает число в ini файл
void
WriteInt
(
std
::
string stKey1
,
std
::
string stKey2
,
int
iInt
)
;
// Записывает дробное число в ini файл
void
WriteFloat
(
std
::
string stKey1
,
std
::
string stKey2
,
float
fFloat
)
;
// Записывает true или false в ini файл
void
WriteBool
(
std
::
string stKey1
,
std
::
string stKey2
,
bool
bBool
)
;
// Записывает std::string в ini файл
void
WriteString
(
std
::
string stKey1
,
std
::
string stKey2
,
std
::
string stString
)
;
// Записывает const char* в ini файл
void
WriteString
(
std
::
string stKey1
,
std
::
string stKey2
,
const
char
*
cnhString
)
;
// Записывает char в ini файл
void
WriteString
(
std
::
string stKey1
,
std
::
string stKey2
,
char
chString
)
;
private
:
// Сохраняет ini структуру в файл
void
Save
(
)
;
// Загружает ini структуру в переменную
void
Refresh
(
)
;
}
;
CConfig.cpp:
Код:
#include "CConfig.h"
#include "ini.h"
std
::
string stIniNameFile
;
mINI
::
INIStructure ini
;
void
CConfig
::
Init
(
std
::
string iniName
)
{
stIniNameFile
=
iniName
;
this
->
Refresh
(
)
;
}
/////// private ////////
void
CConfig
::
Refresh
(
)
{
mINI
::
INIFile
fileInstance
(
stIniNameFile
)
;
fileInstance
.
read
(
ini
)
;
}
void
CConfig
::
Save
(
)
{
mINI
::
INIFile
fileInstance
(
stIniNameFile
)
;
fileInstance
.
write
(
ini
)
;
}
/////// public ////////
/////// read ///////
int
CConfig
::
GetInt
(
std
::
string stKey1
,
std
::
string stKey2
)
{
this
->
Refresh
(
)
;
int
iReturnInteger
=
NULL
;
int
iErrorCode
=
sscanf
(
ini
[
stKey1
]
[
stKey2
]
.
c_str
(
)
,
"%d"
,
&
iReturnInteger
)
;
if
(
iErrorCode
!=
EOF
&&
iErrorCode
!=
NULL
)
return
iReturnInteger
;
return
-
1
;
}
float
CConfig
::
GetFloat
(
std
::
string stKey1
,
std
::
string stKey2
)
{
this
->
Refresh
(
)
;
float
fReturnFloat
=
NULL
;
int
iErrorCode
=
sscanf
(
ini
[
stKey1
]
[
stKey2
]
.
c_str
(
)
,
"%f"
,
&
fReturnFloat
)
;
if
(
iErrorCode
!=
EOF
&&
iErrorCode
!=
NULL
)
return
fReturnFloat
;
return
-
1
;
}
bool
CConfig
::
GetBool
(
std
::
string stKey1
,
std
::
string stKey2
)
{
this
->
Refresh
(
)
;
int
iReturnBool
=
NULL
;
int
iErrorCode
=
sscanf
(
ini
[
stKey1
]
[
stKey2
]
.
c_str
(
)
,
"%d"
,
&
iReturnBool
)
;
if
(
iErrorCode
!=
EOF
&&
iErrorCode
!=
NULL
)
if
(
iReturnBool
==
1
)
return
true
;
return
false
;
}
std
::
string CConfig
::
GetString
(
std
::
string stKey1
,
std
::
string stKey2
)
{
this
->
Refresh
(
)
;
return
ini
[
stKey1
]
[
stKey2
]
;
}
const
char
*
CConfig
::
GetConstChar
(
std
::
string stKey1
,
std
::
string stKey2
)
{
this
->
Refresh
(
)
;
return
ini
[
stKey1
]
[
stKey2
]
.
c_str
(
)
;
}
char
CConfig
::
GetChar
(
std
::
string stKey1
,
std
::
string stKey2
)
{
this
->
Refresh
(
)
;
std
::
string stGetString
=
ini
[
stKey1
]
[
stKey2
]
;
char
*
chReturnChar
;
strcpy
(
chReturnChar
,
stGetString
.
c_str
(
)
)
;
return
*
chReturnChar
;
}
/////// write ///////
#include
void
CConfig
::
WriteInt
(
std
::
string stKey1
,
std
::
string stKey2
,
int
iInt
)
{
ini
[
stKey1
]
[
stKey2
]
=
std
::
to_string
(
iInt
)
;
this
->
Save
(
)
;
}
void
CConfig
::
WriteFloat
(
std
::
string stKey1
,
std
::
string stKey2
,
float
fFloat
)
{
ini
[
stKey1
]
[
stKey2
]
=
std
::
to_string
(
fFloat
)
;
this
->
Save
(
)
;
}
void
CConfig
::
WriteBool
(
std
::
string stKey1
,
std
::
string stKey2
,
bool
bBool
)
{
if
(
bBool
)
ini
[
stKey1
]
[
stKey2
]
=
std
::
to_string
(
1
)
;
else
ini
[
stKey1
]
[
stKey2
]
=
std
::
to_string
(
0
)
;
this
->
Save
(
)
;
}
void
CConfig
::
WriteString
(
std
::
string stKey1
,
std
::
string stKey2
,
std
::
string stString
)
{
ini
[
stKey1
]
[
stKey2
]
=
stString
;
this
->
Save
(
)
;
}
void
CConfig
::
WriteString
(
std
::
string stKey1
,
std
::
string stKey2
,
const
char
*
cnhString
)
{
ini
[
stKey1
]
[
stKey2
]
=
cnhString
;
this
->
Save
(
)
;
}
void
CConfig
::
WriteString
(
std
::
string stKey1
,
std
::
string stKey2
,
char
chString
)
{
ini
[
stKey1
]
[
stKey2
]
=
chString
;
this
->
Save
(
)
;
}
ini.h:
[CODE]
/*
* The MIT License (MIT)
* Copyright (c) 2018 Danijel Durakovic
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
///////////////////////////////////////////////////////////////////////////////
//
// /mINI/ v0.9.7
// An INI file reader and writer for the modern age.
//
///////////////////////////////////////////////////////////////////////////////
//
// A tiny utility library for manipulating INI files with a straightforward
// API and a minimal footprint. It conforms to the (somewhat) standard INI
// format - sections and keys are case insensitive and all leading and
// trailing whitespace is ignored. Comments are lines that begin with a
// semicolon. Trailing comments are allowed on section lines.
//
// Files are read on demand, upon which data is kept in memory and the file
// is closed. This utility supports lazy writing, which only writes changes
// and updates to a file and preserves custom formatting and comments. A lazy
// write invoked by a write() call will read the output file, find what
// changes have been made and update the file accordingly. If you only need to
// generate files, use generate() instead. Section and key order is preserved
// on read, write and insert.
//
///////////////////////////////////////////////////////////////////////////////
//
// /* BASIC USAGE EXAMPLE: */
//
// /* read from file */
// mINI::INIFile file("myfile.ini");
// mINI::INIStructure ini;
// file.read(ini);
//
// /* read value; gets a reference to actual value in the structure.
// if key or section don't exist, a new empty value will be created */
// std::string& value = ini["section"]["key"];
//
// /* read value safely; gets a copy of value in the structure.
// does not alter the structure */
// std::string value = ini.get("section").get("key");
//
// /* set or update values */
// ini["section"]["key"] = "value";
//
// /* set multiple values */
// ini["section2"].set({
// {"key1", "value1"},
// {"key2", "value2"}
// });
//
// /* write updates back to file, preserving comments and formatting */
// file.write(ini);
//
// /* or generate a file (overwrites the original) */
// file.generate(ini);
//
///////////////////////////////////////////////////////////////////////////////
//
// Long live the INI file!!!
//
///////////////////////////////////////////////////////////////////////////////
#ifndef MINI_INI_H_
#define MINI_INI_H_
#include
#include
#include
#include
#include
#include
#include
#include
#include
namespace
mINI
{
namespace
INIStringUtil
{
const
std
::
string whitespaceDelimiters
=
" \t\n\r\f\v"
;
inline
void
trim
(
std
::
string
&
str
)
{
str
.
erase
(
str
.
find_last_not_of
(
whitespaceDelimiters
)
+
1
)
;
str
.
erase
(
0
,
str
.
find_first_not_of
(
whitespaceDelimiters
)
)
;
}
#ifndef MINI_CASE_SENSITIVE
inline
void
toLower
(
std
::
string
&
str
)
{
std
::
transform
(
str
.
begin
(
)
,
str
.
end
(
)
,
str
.
begin
(
)
,
::
tolower
)
;
}
#endif
inline
void
replace
(
std
::
string
&
str
,
std
::
string
const
&
a
,
std
::
string
const
&
b
)
{
if
(
!
a
.
empty
(
)
)
{
std
::
size_t pos
=
0
;
while
(
(
pos
=
str
.
find
(
a
,
pos
)
)
!=
std
::
string
::
npos
)
{
str
.
replace
(
pos
,
a
.
size
(
)
,
b
)
;
pos
+=
b
.
size
(
)
;
}
}
}
#ifdef _WIN32
const
std
::
string endl
=
"\r\n"
;
#else
const
std
::
string endl
=
"\n"
;
#endif
}
;
template
class
INIMap
{
private
:
using
T_DataIndexMap
=
std
::
unordered_map
;
using
T_DataItem
=
std
::
pair
;
using
T_DataContainer
=
std
::
vector
;
using
T_MultiArgs
=
typename
std
::
vector
>
;
T_DataIndexMap dataIndexMap
;
T_DataContainer data
;
inline
std
::
size_t
setEmpty
(
std
::
string
&
key
)
{
std
::
size_t index
=
data
.
size
(
)
;
dataIndexMap
[
key
]
=
index
;
data
.
emplace_back
(
key
,
T
(
)
)
;
return
index
;
}
public
:
using
const_iterator
=
typename
T_DataContainer
::
const_iterator
;
INIMap
(
)
{
}
INIMap
(
INIMap
const
&
other
)
{
std
::
size_t data_size
=
other
.
data
.
size
(
)
;
for
(
std
::
size_t i
=
0
;
i
second
:
setEmpty
(
key
)
;
return
data
[
index
]
.
second
;
}
T
get
(
std
::
string key
)
const
{
INIStringUtil
::
trim
(
key
)
;
#ifndef MINI_CASE_SENSITIVE
INIStringUtil
::
toLower
(
key
)
;
#endif
auto
it
=
dataIndexMap
.
find
(
key
)
;
if
(
it
==
dataIndexMap
.
end
(
)
)
{
return
T
(
)
;
}
return
T
(
data
[
it
->
second
]
.
second
)
;
}
bool
has
(
std
::
string key
)
const
{
INIStringUtil
::
trim
(
key
)
;
#ifndef MINI_CASE_SENSITIVE
INIStringUtil
::
toLower
(
key
)
;
#endif
return
(
dataIndexMap
.
count
(
key
)
==
1
)
;
}
void
set
(
std
::
string key
,
T obj
)
{
INIStringUtil
::
trim
(
key
)
;
#ifndef MINI_CASE_SENSITIVE
INIStringUtil
::
toLower
(
key
)
;
#endif
auto
it
=
dataIndexMap
.
find
(
key
)
;
if
(
it
!=
dataIndexMap
.
end
(
)
)
{
data
[
it
->
second
]
.
second
=
obj
;
}
else
{
dataIndexMap
[
key
]
=
data
.
size
(
)
;
data
.
emplace_back
(
key
,
obj
)
;
}
}
void
set
(
T_MultiArgs
const
&
multiArgs
)
{
for
(
auto
const
&
it
:
multiArgs
)
{
auto
const
&
key
=
it
.
first
;
auto
const
&
obj
=
it
.
second
;
set
(
key
,
obj
)
;
}
}
bool
remove
(
std
::
string key
)
{
INIStringUtil
::
trim
(
key
)
;
#ifndef MINI_CASE_SENSITIVE
INIStringUtil
::
toLower
(
key
)
;
#endif
auto
it
=
dataIndexMap
.
find
(
key
)
;
if
(
it
!=
dataIndexMap
.
end
(
)
)
{
std
::
size_t index
=
it
->
second
;
data
.
erase
(
data
.
begin
(
)
+
index
)
;
dataIndexMap
.
erase
(
it
)
;
for
(
auto
&
it2
:
dataIndexMap
)
{
auto
&
vi
=
it2
.
second
;
if
(
vi
>
index
)
{
vi
--
;
}
}
return
true
;
}
return
false
;
}
void
clear
(
)
{
data
.
clear
(
)
;
dataIndexMap
.
clear
(
)
;
}
std
::
size_t
size
(
)
const
{
return
data
.
size
(
)
;
}
const_iterator
begin
(
)
const
{
return
data
.
begin
(
)
;
}
const_iterator
end
(
)
const
{
return
data
.
end
(
)
;
}
}
;
using
INIStructure
=
INIMap
>
;
namespace
INIParser
{
using
T_ParseValues
=
std
::
pair
;
enum
class
PDataType
:
char
{
PDATA_NONE
,
PDATA_COMMENT
,
PDATA_SECTION
,
PDATA_KEYVALUE
,
PDATA_UNKNOWN
}
;
inline
PDataType
parseLine
(
std
::
string line
,
T_ParseValues
&
parseData
)
{
parseData
.
first
.
clear
(
)
;
parseData
.
second
.
clear
(
)
;
INIStringUtil
::
trim
(
line
)
;
if
(
line
.
empty
(
)
)
{
return
PDataType
::
PDATA_NONE
;
}
char
firstCharacter
=
line
[
0
]
;
if
(
firstCharacter
==
';'
)
{
return
PDataType
::
PDATA_COMMENT
;
}
if
(
firstCharacter
==
'['
)
{
auto
commentAt
=
line
.
find_first_of
(
';'
)
;
if
(
commentAt
!=
std
::
string
::
npos
)
{
line
=
line
.
substr
(
0
,
commentAt
)
;
}
auto
closingBracketAt
=
line
.
find_last_of
(
']'
)
;
if
(
closingBracketAt
!=
std
::
string
::
npos
)
{
auto
section
=
line
.
substr
(
1
,
closingBracketAt
-
1
)
;
INIStringUtil
::
trim
(
section
)
;
parseData
.
first
=
section
;
return
PDataType
::
PDATA_SECTION
;
}
}
auto
lineNorm
=
line
;
INIStringUtil
::
replace
(
lineNorm
,
"\\="
,
" "
)
;
auto
equalsAt
=
lineNorm
.
find_first_of
(
'='
)
;
if
(
equalsAt
!=
std
::
string
::
npos
)
{
auto
key
=
line
.
substr
(
0
,
equalsAt
)
;
INIStringUtil
::
trim
(
key
)
;
INIStringUtil
::
replace
(
key
,
"\\="
,
"="
)
;
auto
value
=
line
.
substr
(
equalsAt
+
1
)
;
INIStringUtil
::
trim
(
value
)
;
parseData
.
first
=
key
;
parseData
.
second
=
value
;
return
PDataType
::
PDATA_KEYVALUE
;
}
return
PDataType
::
PDATA_UNKNOWN
;
}
}
;
class
INIReader
{
public
:
using
T_LineData
=
std
::
vector
;
using
T_LineDataPtr
=
std
::
shared_ptr
;
private
:
std
::
ifstream fileReadStream
;
T_LineDataPtr lineData
;
T_LineData
readFile
(
)
{
std
::
string fileContents
;
fileReadStream
.
seekg
(
0
,
std
::
ios
::
end
)
;
fileContents
.
resize
(
fileReadStream
.
tellg
(
)
)
;
fileReadStream
.
seekg
(
0
,
std
::
ios
::
beg
)
;
std
::
size_t fileSize
=
fileContents
.
size
(
)
;
fileReadStream
.
read
(
&
fileContents
[
0
]
,
fileSize
)
;
fileReadStream
.
close
(
)
;
T_LineData output
;
if
(
fileSize
==
0
)
{
return
output
;
}
std
::
string buffer
;
buffer
.
reserve
(
50
)
;
for
(
std
::
size_t i
=
0
;
i
(
)
;
}
}
~
INIReader
(
)
{
}
bool
operator
>>
(
INIStructure
&
data
)
{
if
(
!
fileReadStream
.
is_open
(
)
)
{
return
false
;
}
T_LineData fileLines
=
readFile
(
)
;
std
::
string section
;
bool
inSection
=
false
;
INIParser
::
T_ParseValues parseData
;
for
(
auto
const
&
line
:
fileLines
)
{
auto
parseResult
=
INIParser
::
parseLine
(
line
,
parseData
)
;
if
(
parseResult
==
INIParser
::
PDataType
::
PDATA_SECTION
)
{
inSection
=
true
;
data
[
section
=
parseData
.
first
]
;
}
else
if
(
inSection
&&
parseResult
==
INIParser
::
PDataType
::
PDATA_KEYVALUE
)
{
auto
const
&
key
=
parseData
.
first
;
auto
const
&
value
=
parseData
.
second
;
data
[
section
]
[
key
]
=
value
;
}
if
(
lineData
&&
parseResult
!=
INIParser
::
PDataType
::
PDATA_UNKNOWN
)
{
if
(
parseResult
==
INIParser
::
PDataType
::
PDATA_KEYVALUE
&&
!
inSection
)
{
continue
;
}
lineData
->
emplace_back
(
line
)
;
}
}
return
true
;
}
T_LineDataPtr
getLines
(
)
{
return
lineData
;
}
}
;
class
INIGenerator
{
private
:
std
::
ofstream fileWriteStream
;
public
:
bool
prettyPrint
=
false
;
INIGenerator
(
std
::
string
const
&
filename
)
{
fileWriteStream
.
open
(
filename
,
std
::
ios
::
out
|
std
::
ios
::
binary
)
;
}
~
INIGenerator
(
)
{
}
bool
operator
first
;
auto
const
&
collection
=
it
->
second
;
fileWriteStream
first
;
INIStringUtil
::
replace
(
key
,
"="
,
"\\="
)
;
auto
value
=
it2
->
second
;
INIStringUtil
::
trim
(
value
)
;
fileWriteStream
;
using
T_LineDataPtr
=
std
::
shared_ptr
;
std
::
string filename
;
T_LineData
getLazyOutput
(
T_LineDataPtr
const
&
lineData
,
INIStructure
&
data
,
INIStructure
&
original
)
{
T_LineData output
;
INIParser
::
T_ParseValues parseData
;
std
::
string sectionCurrent
;
bool
parsingSection
=
false
;
bool
continueToNextSection
=
false
;
bool
discardNextEmpty
=
false
;
bool
writeNewKeys
=
false
;
std
::
size_t lastKeyLine
=
0
;
for
(
auto
line
=
lineData
->
begin
(
)
;
line
!=
lineData
->
end
(
)
;
++
line
)
{
if
(
!
writeNewKeys
)
{
auto
parseResult
=
INIParser
::
parseLine
(
*
line
,
parseData
)
;
if
(
parseResult
==
INIParser
::
PDataType
::
PDATA_SECTION
)
{
if
(
parsingSection
)
{
writeNewKeys
=
true
;
parsingSection
=
false
;
--
line
;
continue
;
}
sectionCurrent
=
parseData
.
first
;
if
(
data
.
has
(
sectionCurrent
)
)
{
parsingSection
=
true
;
continueToNextSection
=
false
;
discardNextEmpty
=
false
;
output
.
emplace_back
(
*
line
)
;
lastKeyLine
=
output
.
size
(
)
;
}
else
{
continueToNextSection
=
true
;
discardNextEmpty
=
true
;
continue
;
}
}
else
if
(
parseResult
==
INIParser
::
PDataType
::
PDATA_KEYVALUE
)
{
if
(
continueToNextSection
)
{
continue
;
}
if
(
data
.
has
(
sectionCurrent
)
)
{
auto
&
collection
=
data
[
sectionCurrent
]
;
auto
const
&
key
=
parseData
.
first
;
auto
const
&
value
=
parseData
.
second
;
if
(
collection
.
has
(
key
)
)
{
auto
outputValue
=
collection
[
key
]
;
if
(
value
==
outputValue
)
{
output
.
emplace_back
(
*
line
)
;
}
else
{
INIStringUtil
::
trim
(
outputValue
)
;
auto
lineNorm
=
*
line
;
INIStringUtil
::
replace
(
lineNorm
,
"\\="
,
" "
)
;
auto
equalsAt
=
lineNorm
.
find_first_of
(
'='
)
;
auto
valueAt
=
lineNorm
.
find_first_not_of
(
INIStringUtil
::
whitespaceDelimiters
,
equalsAt
+
1
)
;
std
::
string outputLine
=
line
->
substr
(
0
,
valueAt
)
;
if
(
prettyPrint
&&
equalsAt
+
1
==
valueAt
)
{
outputLine
+=
" "
;
}
outputLine
+=
outputValue
;
output
.
emplace_back
(
outputLine
)
;
}
lastKeyLine
=
output
.
size
(
)
;
}
}
}
else
{
if
(
discardNextEmpty
&&
line
->
empty
(
)
)
{
discardNextEmpty
=
false
;
}
else
if
(
parseResult
!=
INIParser
::
PDataType
::
PDATA_UNKNOWN
)
{
output
.
emplace_back
(
*
line
)
;
}
}
}
if
(
writeNewKeys
||
std
::
next
(
line
)
==
lineData
->
end
(
)
)
{
T_LineData linesToAdd
;
if
(
data
.
has
(
sectionCurrent
)
&&
original
.
has
(
sectionCurrent
)
)
{
auto
const
&
collection
=
data
[
sectionCurrent
]
;
auto
const
&
collectionOriginal
=
original
[
sectionCurrent
]
;
for
(
auto
const
&
it
:
collection
)
{
auto
key
=
it
.
first
;
if
(
collectionOriginal
.
has
(
key
)
)
{
continue
;
}
auto
value
=
it
.
second
;
INIStringUtil
::
replace
(
key
,
"="
,
"\\="
)
;
INIStringUtil
::
trim
(
value
)
;
linesToAdd
.
emplace_back
(
key
+
(
(
prettyPrint
)
?
" = "
:
"="
)
+
value
)
;
}
}
if
(
!
linesToAdd
.
empty
(
)
)
{
output
.
insert
(
output
.
begin
(
)
+
lastKeyLine
,
linesToAdd
.
begin
(
)
,
linesToAdd
.
end
(
)
)
;
}
if
(
writeNewKeys
)
{
writeNewKeys
=
false
;
--
line
;
}
}
}
for
(
auto
const
&
it
:
data
)
{
auto
const
&
section
=
it
.
first
;
if
(
original
.
has
(
section
)
)
{
continue
;
}
if
(
prettyPrint
&&
output
.
size
(
)
>
0
&&
!
output
.
back
(
)
.
empty
(
)
)
{
output
.
emplace_back
(
)
;
}
output
.
emplace_back
(
"["
+
section
+
"]"
)
;
auto
const
&
collection
=
it
.
second
;
for
(
auto
const
&
it2
:
collection
)
{
auto
key
=
it2
.
first
;
auto
value
=
it2
.
second
;
INIStringUtil
::
replace
(
key
,
"="
,
"\\="
)
;
INIStringUtil
::
trim
(
value
)
;
output
.
emplace_back
(
key
+
(
(
prettyPrint
)
?
" = "
:
"="
)
+
value
)
;
}
}
return
output
;
}
public
:
bool
prettyPrint
=
false
;
INIWriter
(
std
::
string
const
&
filename
)
:
filename
(
filename
)
{
}
~
INIWriter
(
)
{
}
bool
operator
>
originalData
)
)
{
lineData
=
reader
.
getLines
(
)
;
}
}
if
(
!
readSuccess
)
{
return
false
;
}
T_LineData output
=
getLazyOutput
(
lineData
,
data
,
originalData
)
;
std
::
ofstream
fileWriteStream
(
filename
,
std
::
ios
::
out
|
std
::
ios
::
binary
)
;
if
(
fileWriteStream
.
is_open
(
)
)
{
if
(
output
.
size
(
)
)
{
auto
line
=
output
.
begin
(
)
;
for
(
;
;
)
{
fileWriteStream
>
data
;
}
bool
generate
(
INIStructure
const
&
data
,
bool
pretty
=
false
)
const
{
if
(
filename
.
empty
(
)
)
{
return
false
;
}
INIGenerator
generator
(
filename
)
;
generator
.
prettyPrint
=
pretty
;
return
generator
Сообщение от Спойлер
DLLMain.cpp:
Код:
#include "DLLMain.hpp"
CConfig
*
pConfig
;
int
WINAPI
vExample
(
void
*
p
)
{
/*
Вроде бы, если ini файла нет, то он создаться сам. (но это не точно)
Полный путь до ini файла вписывать не нужно, а можно просто вписать имя.
Лучше использовать не ini файл, а реестр.
Его можно взять тута - https://github.com/KiN4StAt/BulletTracer/tree/master/fast
*/
pConfig
->
Init
(
"Example.ini"
)
;
std
::
cout
GetBool
(
"MAIN"
,
"bState"
)
)
std
::
cout
(
vExample
)
,
hModule
,
0
,
nullptr
)
;
break
;
}
}
return
TRUE
;
}
DLLMain.hpp:
Код:
#include
#include "CConfig.h"
extern
CConfig
*
pConfig
;
Example.ini:
|
|
|

28.03.2021, 15:25
|
|
Участник форума
Регистрация: 21.07.2020
Сообщений: 280
С нами:
3059886
Репутация:
68
|
|
Сообщение от Tim4ukys Official
Делал class лично для себя, для облегчения работы с mINI. Не нужно быть ♂dungeon master♂ чтобы разобраться в его работе, но для настоящих ♂boss of the gym♂ оставил пример по работе с ним.
Сообщение от Спойлер
CConfig.h:
Код:
#pragma once
// #include
#include
class
CConfig
{
public
:
// Инициализация класса
void
Init
(
std
::
string iniName
)
;
/////////// read ///////////
// Возращает число
int
GetInt
(
std
::
string stKey1
,
std
::
string stKey2
)
;
// Возращает дробное число
float
GetFloat
(
std
::
string stKey1
,
std
::
string stKey2
)
;
// Возращает true или false
bool
GetBool
(
std
::
string stKey1
,
std
::
string stKey2
)
;
// Возращает std::string
std
::
string
GetString
(
std
::
string stKey1
,
std
::
string stKey2
)
;
// Возращает const char*
const
char
*
GetConstChar
(
std
::
string stKey1
,
std
::
string stKey2
)
;
// Возращает char
char
GetChar
(
std
::
string stKey1
,
std
::
string stKey2
)
;
/////////// write ///////////
// Записывает число в ini файл
void
WriteInt
(
std
::
string stKey1
,
std
::
string stKey2
,
int
iInt
)
;
// Записывает дробное число в ini файл
void
WriteFloat
(
std
::
string stKey1
,
std
::
string stKey2
,
float
fFloat
)
;
// Записывает true или false в ini файл
void
WriteBool
(
std
::
string stKey1
,
std
::
string stKey2
,
bool
bBool
)
;
// Записывает std::string в ini файл
void
WriteString
(
std
::
string stKey1
,
std
::
string stKey2
,
std
::
string stString
)
;
// Записывает const char* в ini файл
void
WriteString
(
std
::
string stKey1
,
std
::
string stKey2
,
const
char
*
cnhString
)
;
// Записывает char в ini файл
void
WriteString
(
std
::
string stKey1
,
std
::
string stKey2
,
char
chString
)
;
private
:
// Сохраняет ini структуру в файл
void
Save
(
)
;
// Загружает ini структуру в переменную
void
Refresh
(
)
;
}
;
CConfig.cpp:
Код:
#include "CConfig.h"
#include "ini.h"
std
::
string stIniNameFile
;
mINI
::
INIStructure ini
;
void
CConfig
::
Init
(
std
::
string iniName
)
{
stIniNameFile
=
iniName
;
this
->
Refresh
(
)
;
}
/////// private ////////
void
CConfig
::
Refresh
(
)
{
mINI
::
INIFile
fileInstance
(
stIniNameFile
)
;
fileInstance
.
read
(
ini
)
;
}
void
CConfig
::
Save
(
)
{
mINI
::
INIFile
fileInstance
(
stIniNameFile
)
;
fileInstance
.
write
(
ini
)
;
}
/////// public ////////
/////// read ///////
int
CConfig
::
GetInt
(
std
::
string stKey1
,
std
::
string stKey2
)
{
this
->
Refresh
(
)
;
int
iReturnInteger
=
NULL
;
int
iErrorCode
=
sscanf
(
ini
[
stKey1
]
[
stKey2
]
.
c_str
(
)
,
"%d"
,
&
iReturnInteger
)
;
if
(
iErrorCode
!=
EOF
&&
iErrorCode
!=
NULL
)
return
iReturnInteger
;
return
-
1
;
}
float
CConfig
::
GetFloat
(
std
::
string stKey1
,
std
::
string stKey2
)
{
this
->
Refresh
(
)
;
float
fReturnFloat
=
NULL
;
int
iErrorCode
=
sscanf
(
ini
[
stKey1
]
[
stKey2
]
.
c_str
(
)
,
"%f"
,
&
fReturnFloat
)
;
if
(
iErrorCode
!=
EOF
&&
iErrorCode
!=
NULL
)
return
fReturnFloat
;
return
-
1
;
}
bool
CConfig
::
GetBool
(
std
::
string stKey1
,
std
::
string stKey2
)
{
this
->
Refresh
(
)
;
int
iReturnBool
=
NULL
;
int
iErrorCode
=
sscanf
(
ini
[
stKey1
]
[
stKey2
]
.
c_str
(
)
,
"%d"
,
&
iReturnBool
)
;
if
(
iErrorCode
!=
EOF
&&
iErrorCode
!=
NULL
)
if
(
iReturnBool
==
1
)
return
true
;
return
false
;
}
std
::
string CConfig
::
GetString
(
std
::
string stKey1
,
std
::
string stKey2
)
{
this
->
Refresh
(
)
;
return
ini
[
stKey1
]
[
stKey2
]
;
}
const
char
*
CConfig
::
GetConstChar
(
std
::
string stKey1
,
std
::
string stKey2
)
{
this
->
Refresh
(
)
;
return
ini
[
stKey1
]
[
stKey2
]
.
c_str
(
)
;
}
char
CConfig
::
GetChar
(
std
::
string stKey1
,
std
::
string stKey2
)
{
this
->
Refresh
(
)
;
std
::
string stGetString
=
ini
[
stKey1
]
[
stKey2
]
;
char
*
chReturnChar
;
strcpy
(
chReturnChar
,
stGetString
.
c_str
(
)
)
;
return
*
chReturnChar
;
}
/////// write ///////
#include
void
CConfig
::
WriteInt
(
std
::
string stKey1
,
std
::
string stKey2
,
int
iInt
)
{
ini
[
stKey1
]
[
stKey2
]
=
std
::
to_string
(
iInt
)
;
this
->
Save
(
)
;
}
void
CConfig
::
WriteFloat
(
std
::
string stKey1
,
std
::
string stKey2
,
float
fFloat
)
{
ini
[
stKey1
]
[
stKey2
]
=
std
::
to_string
(
fFloat
)
;
this
->
Save
(
)
;
}
void
CConfig
::
WriteBool
(
std
::
string stKey1
,
std
::
string stKey2
,
bool
bBool
)
{
if
(
bBool
)
ini
[
stKey1
]
[
stKey2
]
=
std
::
to_string
(
1
)
;
else
ini
[
stKey1
]
[
stKey2
]
=
std
::
to_string
(
0
)
;
this
->
Save
(
)
;
}
void
CConfig
::
WriteString
(
std
::
string stKey1
,
std
::
string stKey2
,
std
::
string stString
)
{
ini
[
stKey1
]
[
stKey2
]
=
stString
;
this
->
Save
(
)
;
}
void
CConfig
::
WriteString
(
std
::
string stKey1
,
std
::
string stKey2
,
const
char
*
cnhString
)
{
ini
[
stKey1
]
[
stKey2
]
=
cnhString
;
this
->
Save
(
)
;
}
void
CConfig
::
WriteString
(
std
::
string stKey1
,
std
::
string stKey2
,
char
chString
)
{
ini
[
stKey1
]
[
stKey2
]
=
chString
;
this
->
Save
(
)
;
}
ini.h:
[CODE]
/*
* The MIT License (MIT)
* Copyright (c) 2018 Danijel Durakovic
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
///////////////////////////////////////////////////////////////////////////////
//
// /mINI/ v0.9.7
// An INI file reader and writer for the modern age.
//
///////////////////////////////////////////////////////////////////////////////
//
// A tiny utility library for manipulating INI files with a straightforward
// API and a minimal footprint. It conforms to the (somewhat) standard INI
// format - sections and keys are case insensitive and all leading and
// trailing whitespace is ignored. Comments are lines that begin with a
// semicolon. Trailing comments are allowed on section lines.
//
// Files are read on demand, upon which data is kept in memory and the file
// is closed. This utility supports lazy writing, which only writes changes
// and updates to a file and preserves custom formatting and comments. A lazy
// write invoked by a write() call will read the output file, find what
// changes have been made and update the file accordingly. If you only need to
// generate files, use generate() instead. Section and key order is preserved
// on read, write and insert.
//
///////////////////////////////////////////////////////////////////////////////
//
// /* BASIC USAGE EXAMPLE: */
//
// /* read from file */
// mINI::INIFile file("myfile.ini");
// mINI::INIStructure ini;
// file.read(ini);
//
// /* read value; gets a reference to actual value in the structure.
// if key or section don't exist, a new empty value will be created */
// std::string& value = ini["section"]["key"];
//
// /* read value safely; gets a copy of value in the structure.
// does not alter the structure */
// std::string value = ini.get("section").get("key");
//
// /* set or update values */
// ini["section"]["key"] = "value";
//
// /* set multiple values */
// ini["section2"].set({
// {"key1", "value1"},
// {"key2", "value2"}
// });
//
// /* write updates back to file, preserving comments and formatting */
// file.write(ini);
//
// /* or generate a file (overwrites the original) */
// file.generate(ini);
//
///////////////////////////////////////////////////////////////////////////////
//
// Long live the INI file!!!
//
///////////////////////////////////////////////////////////////////////////////
#ifndef MINI_INI_H_
#define MINI_INI_H_
#include
#include
#include
#include
#include
#include
#include
#include
#include
namespace
mINI
{
namespace
INIStringUtil
{
const
std
::
string whitespaceDelimiters
=
" \t\n\r\f\v"
;
inline
void
trim
(
std
::
string
&
str
)
{
str
.
erase
(
str
.
find_last_not_of
(
whitespaceDelimiters
)
+
1
)
;
str
.
erase
(
0
,
str
.
find_first_not_of
(
whitespaceDelimiters
)
)
;
}
#ifndef MINI_CASE_SENSITIVE
inline
void
toLower
(
std
::
string
&
str
)
{
std
::
transform
(
str
.
begin
(
)
,
str
.
end
(
)
,
str
.
begin
(
)
,
::
tolower
)
;
}
#endif
inline
void
replace
(
std
::
string
&
str
,
std
::
string
const
&
a
,
std
::
string
const
&
b
)
{
if
(
!
a
.
empty
(
)
)
{
std
::
size_t pos
=
0
;
while
(
(
pos
=
str
.
find
(
a
,
pos
)
)
!=
std
::
string
::
npos
)
{
str
.
replace
(
pos
,
a
.
size
(
)
,
b
)
;
pos
+=
b
.
size
(
)
;
}
}
}
#ifdef _WIN32
const
std
::
string endl
=
"\r\n"
;
#else
const
std
::
string endl
=
"\n"
;
#endif
}
;
template
class
INIMap
{
private
:
using
T_DataIndexMap
=
std
::
unordered_map
;
using
T_DataItem
=
std
::
pair
;
using
T_DataContainer
=
std
::
vector
;
using
T_MultiArgs
=
typename
std
::
vector
>
;
T_DataIndexMap dataIndexMap
;
T_DataContainer data
;
inline
std
::
size_t
setEmpty
(
std
::
string
&
key
)
{
std
::
size_t index
=
data
.
size
(
)
;
dataIndexMap
[
key
]
=
index
;
data
.
emplace_back
(
key
,
T
(
)
)
;
return
index
;
}
public
:
using
const_iterator
=
typename
T_DataContainer
::
const_iterator
;
INIMap
(
)
{
}
INIMap
(
INIMap
const
&
other
)
{
std
::
size_t data_size
=
other
.
data
.
size
(
)
;
for
(
std
::
size_t i
=
0
;
i
second
:
setEmpty
(
key
)
;
return
data
[
index
]
.
second
;
}
T
get
(
std
::
string key
)
const
{
INIStringUtil
::
trim
(
key
)
;
#ifndef MINI_CASE_SENSITIVE
INIStringUtil
::
toLower
(
key
)
;
#endif
auto
it
=
dataIndexMap
.
find
(
key
)
;
if
(
it
==
dataIndexMap
.
end
(
)
)
{
return
T
(
)
;
}
return
T
(
data
[
it
->
second
]
.
second
)
;
}
bool
has
(
std
::
string key
)
const
{
INIStringUtil
::
trim
(
key
)
;
#ifndef MINI_CASE_SENSITIVE
INIStringUtil
::
toLower
(
key
)
;
#endif
return
(
dataIndexMap
.
count
(
key
)
==
1
)
;
}
void
set
(
std
::
string key
,
T obj
)
{
INIStringUtil
::
trim
(
key
)
;
#ifndef MINI_CASE_SENSITIVE
INIStringUtil
::
toLower
(
key
)
;
#endif
auto
it
=
dataIndexMap
.
find
(
key
)
;
if
(
it
!=
dataIndexMap
.
end
(
)
)
{
data
[
it
->
second
]
.
second
=
obj
;
}
else
{
dataIndexMap
[
key
]
=
data
.
size
(
)
;
data
.
emplace_back
(
key
,
obj
)
;
}
}
void
set
(
T_MultiArgs
const
&
multiArgs
)
{
for
(
auto
const
&
it
:
multiArgs
)
{
auto
const
&
key
=
it
.
first
;
auto
const
&
obj
=
it
.
second
;
set
(
key
,
obj
)
;
}
}
bool
remove
(
std
::
string key
)
{
INIStringUtil
::
trim
(
key
)
;
#ifndef MINI_CASE_SENSITIVE
INIStringUtil
::
toLower
(
key
)
;
#endif
auto
it
=
dataIndexMap
.
find
(
key
)
;
if
(
it
!=
dataIndexMap
.
end
(
)
)
{
std
::
size_t index
=
it
->
second
;
data
.
erase
(
data
.
begin
(
)
+
index
)
;
dataIndexMap
.
erase
(
it
)
;
for
(
auto
&
it2
:
dataIndexMap
)
{
auto
&
vi
=
it2
.
second
;
if
(
vi
>
index
)
{
vi
--
;
}
}
return
true
;
}
return
false
;
}
void
clear
(
)
{
data
.
clear
(
)
;
dataIndexMap
.
clear
(
)
;
}
std
::
size_t
size
(
)
const
{
return
data
.
size
(
)
;
}
const_iterator
begin
(
)
const
{
return
data
.
begin
(
)
;
}
const_iterator
end
(
)
const
{
return
data
.
end
(
)
;
}
}
;
using
INIStructure
=
INIMap
>
;
namespace
INIParser
{
using
T_ParseValues
=
std
::
pair
;
enum
class
PDataType
:
char
{
PDATA_NONE
,
PDATA_COMMENT
,
PDATA_SECTION
,
PDATA_KEYVALUE
,
PDATA_UNKNOWN
}
;
inline
PDataType
parseLine
(
std
::
string line
,
T_ParseValues
&
parseData
)
{
parseData
.
first
.
clear
(
)
;
parseData
.
second
.
clear
(
)
;
INIStringUtil
::
trim
(
line
)
;
if
(
line
.
empty
(
)
)
{
return
PDataType
::
PDATA_NONE
;
}
char
firstCharacter
=
line
[
0
]
;
if
(
firstCharacter
==
';'
)
{
return
PDataType
::
PDATA_COMMENT
;
}
if
(
firstCharacter
==
'['
)
{
auto
commentAt
=
line
.
find_first_of
(
';'
)
;
if
(
commentAt
!=
std
::
string
::
npos
)
{
line
=
line
.
substr
(
0
,
commentAt
)
;
}
auto
closingBracketAt
=
line
.
find_last_of
(
']'
)
;
if
(
closingBracketAt
!=
std
::
string
::
npos
)
{
auto
section
=
line
.
substr
(
1
,
closingBracketAt
-
1
)
;
INIStringUtil
::
trim
(
section
)
;
parseData
.
first
=
section
;
return
PDataType
::
PDATA_SECTION
;
}
}
auto
lineNorm
=
line
;
INIStringUtil
::
replace
(
lineNorm
,
"\\="
,
" "
)
;
auto
equalsAt
=
lineNorm
.
find_first_of
(
'='
)
;
if
(
equalsAt
!=
std
::
string
::
npos
)
{
auto
key
=
line
.
substr
(
0
,
equalsAt
)
;
INIStringUtil
::
trim
(
key
)
;
INIStringUtil
::
replace
(
key
,
"\\="
,
"="
)
;
auto
value
=
line
.
substr
(
equalsAt
+
1
)
;
INIStringUtil
::
trim
(
value
)
;
parseData
.
first
=
key
;
parseData
.
second
=
value
;
return
PDataType
::
PDATA_KEYVALUE
;
}
return
PDataType
::
PDATA_UNKNOWN
;
}
}
;
class
INIReader
{
public
:
using
T_LineData
=
std
::
vector
;
using
T_LineDataPtr
=
std
::
shared_ptr
;
private
:
std
::
ifstream fileReadStream
;
T_LineDataPtr lineData
;
T_LineData
readFile
(
)
{
std
::
string fileContents
;
fileReadStream
.
seekg
(
0
,
std
::
ios
::
end
)
;
fileContents
.
resize
(
fileReadStream
.
tellg
(
)
)
;
fileReadStream
.
seekg
(
0
,
std
::
ios
::
beg
)
;
std
::
size_t fileSize
=
fileContents
.
size
(
)
;
fileReadStream
.
read
(
&
fileContents
[
0
]
,
fileSize
)
;
fileReadStream
.
close
(
)
;
T_LineData output
;
if
(
fileSize
==
0
)
{
return
output
;
}
std
::
string buffer
;
buffer
.
reserve
(
50
)
;
for
(
std
::
size_t i
=
0
;
i
(
)
;
}
}
~
INIReader
(
)
{
}
bool
operator
>>
(
INIStructure
&
data
)
{
if
(
!
fileReadStream
.
is_open
(
)
)
{
return
false
;
}
T_LineData fileLines
=
readFile
(
)
;
std
::
string section
;
bool
inSection
=
false
;
INIParser
::
T_ParseValues parseData
;
for
(
auto
const
&
line
:
fileLines
)
{
auto
parseResult
=
INIParser
::
parseLine
(
line
,
parseData
)
;
if
(
parseResult
==
INIParser
::
PDataType
::
PDATA_SECTION
)
{
inSection
=
true
;
data
[
section
=
parseData
.
first
]
;
}
else
if
(
inSection
&&
parseResult
==
INIParser
::
PDataType
::
PDATA_KEYVALUE
)
{
auto
const
&
key
=
parseData
.
first
;
auto
const
&
value
=
parseData
.
second
;
data
[
section
]
[
key
]
=
value
;
}
if
(
lineData
&&
parseResult
!=
INIParser
::
PDataType
::
PDATA_UNKNOWN
)
{
if
(
parseResult
==
INIParser
::
PDataType
::
PDATA_KEYVALUE
&&
!
inSection
)
{
continue
;
}
lineData
->
emplace_back
(
line
)
;
}
}
return
true
;
}
T_LineDataPtr
getLines
(
)
{
return
lineData
;
}
}
;
class
INIGenerator
{
private
:
std
::
ofstream fileWriteStream
;
public
:
bool
prettyPrint
=
false
;
INIGenerator
(
std
::
string
const
&
filename
)
{
fileWriteStream
.
open
(
filename
,
std
::
ios
::
out
|
std
::
ios
::
binary
)
;
}
~
INIGenerator
(
)
{
}
bool
operator
first
;
auto
const
&
collection
=
it
->
second
;
fileWriteStream
first
;
INIStringUtil
::
replace
(
key
,
"="
,
"\\="
)
;
auto
value
=
it2
->
second
;
INIStringUtil
::
trim
(
value
)
;
fileWriteStream
;
using
T_LineDataPtr
=
std
::
shared_ptr
;
std
::
string filename
;
T_LineData
getLazyOutput
(
T_LineDataPtr
const
&
lineData
,
INIStructure
&
data
,
INIStructure
&
original
)
{
T_LineData output
;
INIParser
::
T_ParseValues parseData
;
std
::
string sectionCurrent
;
bool
parsingSection
=
false
;
bool
continueToNextSection
=
false
;
bool
discardNextEmpty
=
false
;
bool
writeNewKeys
=
false
;
std
::
size_t lastKeyLine
=
0
;
for
(
auto
line
=
lineData
->
begin
(
)
;
line
!=
lineData
->
end
(
)
;
++
line
)
{
if
(
!
writeNewKeys
)
{
auto
parseResult
=
INIParser
::
parseLine
(
*
line
,
parseData
)
;
if
(
parseResult
==
INIParser
::
PDataType
::
PDATA_SECTION
)
{
if
(
parsingSection
)
{
writeNewKeys
=
true
;
parsingSection
=
false
;
--
line
;
continue
;
}
sectionCurrent
=
parseData
.
first
;
if
(
data
.
has
(
sectionCurrent
)
)
{
parsingSection
=
true
;
continueToNextSection
=
false
;
discardNextEmpty
=
false
;
output
.
emplace_back
(
*
line
)
;
lastKeyLine
=
output
.
size
(
)
;
}
else
{
continueToNextSection
=
true
;
discardNextEmpty
=
true
;
continue
;
}
}
else
if
(
parseResult
==
INIParser
::
PDataType
::
PDATA_KEYVALUE
)
{
if
(
continueToNextSection
)
{
continue
;
}
if
(
data
.
has
(
sectionCurrent
)
)
{
auto
&
collection
=
data
[
sectionCurrent
]
;
auto
const
&
key
=
parseData
.
first
;
auto
const
&
value
=
parseData
.
second
;
if
(
collection
.
has
(
key
)
)
{
auto
outputValue
=
collection
[
key
]
;
if
(
value
==
outputValue
)
{
output
.
emplace_back
(
*
line
)
;
}
else
{
INIStringUtil
::
trim
(
outputValue
)
;
auto
lineNorm
=
*
line
;
INIStringUtil
::
replace
(
lineNorm
,
"\\="
,
" "
)
;
auto
equalsAt
=
lineNorm
.
find_first_of
(
'='
)
;
auto
valueAt
=
lineNorm
.
find_first_not_of
(
INIStringUtil
::
whitespaceDelimiters
,
equalsAt
+
1
)
;
std
::
string outputLine
=
line
->
substr
(
0
,
valueAt
)
;
if
(
prettyPrint
&&
equalsAt
+
1
==
valueAt
)
{
outputLine
+=
" "
;
}
outputLine
+=
outputValue
;
output
.
emplace_back
(
outputLine
)
;
}
lastKeyLine
=
output
.
size
(
)
;
}
}
}
else
{
if
(
discardNextEmpty
&&
line
->
empty
(
)
)
{
discardNextEmpty
=
false
;
}
else
if
(
parseResult
!=
INIParser
::
PDataType
::
PDATA_UNKNOWN
)
{
output
.
emplace_back
(
*
line
)
;
}
}
}
if
(
writeNewKeys
||
std
::
next
(
line
)
==
lineData
->
end
(
)
)
{
T_LineData linesToAdd
;
if
(
data
.
has
(
sectionCurrent
)
&&
original
.
has
(
sectionCurrent
)
)
{
auto
const
&
collection
=
data
[
sectionCurrent
]
;
auto
const
&
collectionOriginal
=
original
[
sectionCurrent
]
;
for
(
auto
const
&
it
:
collection
)
{
auto
key
=
it
.
first
;
if
(
collectionOriginal
.
has
(
key
)
)
{
continue
;
}
auto
value
=
it
.
second
;
INIStringUtil
::
replace
(
key
,
"="
,
"\\="
)
;
INIStringUtil
::
trim
(
value
)
;
linesToAdd
.
emplace_back
(
key
+
(
(
prettyPrint
)
?
" = "
:
"="
)
+
value
)
;
}
}
if
(
!
linesToAdd
.
empty
(
)
)
{
output
.
insert
(
output
.
begin
(
)
+
lastKeyLine
,
linesToAdd
.
begin
(
)
,
linesToAdd
.
end
(
)
)
;
}
if
(
writeNewKeys
)
{
writeNewKeys
=
false
;
--
line
;
}
}
}
for
(
auto
const
&
it
:
data
)
{
auto
const
&
section
=
it
.
first
;
if
(
original
.
has
(
section
)
)
{
continue
;
}
if
(
prettyPrint
&&
output
.
size
(
)
>
0
&&
!
output
.
back
(
)
.
empty
(
)
)
{
output
.
emplace_back
(
)
;
}
output
.
emplace_back
(
"["
+
section
+
"]"
)
;
auto
const
&
collection
=
it
.
second
;
for
(
auto
const
&
it2
:
collection
)
{
auto
key
=
it2
.
first
;
auto
value
=
it2
.
second
;
INIStringUtil
::
replace
(
key
,
"="
,
"\\="
)
;
INIStringUtil
::
trim
(
value
)
;
output
.
emplace_back
(
key
+
(
(
prettyPrint
)
?
" = "
:
"="
)
+
value
)
;
}
}
return
output
;
}
public
:
bool
prettyPrint
=
false
;
INIWriter
(
std
::
string
const
&
filename
)
:
filename
(
filename
)
{
}
~
INIWriter
(
)
{
}
bool
operator
>
originalData
)
)
{
lineData
=
reader
.
getLines
(
)
;
}
}
if
(
!
readSuccess
)
{
return
false
;
}
T_LineData output
=
getLazyOutput
(
lineData
,
data
,
originalData
)
;
std
::
ofstream
fileWriteStream
(
filename
,
std
::
ios
::
out
|
std
::
ios
::
binary
)
;
if
(
fileWriteStream
.
is_open
(
)
)
{
if
(
output
.
size
(
)
)
{
auto
line
=
output
.
begin
(
)
;
for
(
;
;
)
{
fileWriteStream
>
data
;
}
bool
generate
(
INIStructure
const
&
data
,
bool
pretty
=
false
)
const
{
if
(
filename
.
empty
(
)
)
{
return
false
;
}
INIGenerator
generator
(
filename
)
;
generator
.
prettyPrint
=
pretty
;
return
generator
Сообщение от Спойлер
DLLMain.cpp:
Код:
#include "DLLMain.hpp"
CConfig
*
pConfig
;
int
WINAPI
vExample
(
void
*
p
)
{
/*
Вроде бы, если ini файла нет, то он создаться сам. (но это не точно)
Полный путь до ini файла вписывать не нужно, а можно просто вписать имя.
Лучше использовать не ini файл, а реестр.
Его можно взять тута - https://github.com/KiN4StAt/BulletTracer/tree/master/fast
*/
pConfig
->
Init
(
"Example.ini"
)
;
std
::
cout
GetBool
(
"MAIN"
,
"bState"
)
)
std
::
cout
(
vExample
)
,
hModule
,
0
,
nullptr
)
;
break
;
}
}
return
TRUE
;
}
DLLMain.hpp:
Код:
#include
#include "CConfig.h"
extern
CConfig
*
pConfig
;
Example.ini:
pMozze скинул выше вариант,и без лишних марок
|
|
|

28.03.2021, 17:54
|
|
Познающий
Регистрация: 18.09.2019
Сообщений: 31
С нами:
3502227
Репутация:
63
|
|
Сообщение от ]GsH[MeG@LaDo[N]
pMozze скинул выше вариант,и без лишних марок
Ага, спасибо, я же в глаза е***ь и без тебя не вижу, что он скинул.
Не хочешь - не использую, хочешь - использую. Я рад за него, что он такой молодец, скинул, объяснил.
+ моего класса в том, что в нём разберётся любой даун, даже тот, кто только начинает, и я оставил хотя бы пример.
И да, в комментарии(в example) написал, что гораздо лучше использовать класс для работы с реестром от SR_team, и он точно лучше чем способ который скинул pMozze.
Пускай он сам разберётся в этой теме, как это устроено на примерах. Чем больше примеров он найдёт, тем больше он поймет.
SC6UT, если там есть баг, то тыкни пальцем, т.к. я 100 раз использовал это и 100 раз всё работало. + мой знакомый его использовал и у него тоже всё прекрасно работает. Чёт мне самому стало интересно где там баг.
|
|
|

28.03.2021, 17:58
|
|
Участник форума
Регистрация: 03.08.2019
Сообщений: 168
С нами:
3568604
Репутация:
48
|
|
Сообщение от Tim4ukys Official
Ага, спасибо, я же в глаза е***ь и без тебя не вижу, что он скинул.
Не хочешь - не использую, хочешь - использую. Я рад за него, что он такой молодец, скинул, объяснил.
+ моего класса в том, что в нём разберётся любой даун, даже тот, кто только начинает, и я оставил хотя бы пример.
И да, в комментарии(в example) написал, что гораздо лучше использовать класс для работы с реестром от SR_team, и он точно лучше чем способ который скинул pMozze.
Пускай он сам разберётся в этой теме, как это устроено на примерах. Чем больше примеров он найдёт, тем больше он поймет.
SC6UT, если там есть баг, то тыкни пальцем, т.к. я 100 раз использовал это и 100 раз всё работало. + мой знакомый его использовал и у него тоже всё прекрасно работает. Чёт мне самому стало интересно где там баг.
Ну твой вариант лучше тем, что ты можешь получить разные типы данных с ini файла. На том примере, что мне скинули первом, мне пришлось изрядно повозиться, чтоб получить булево значение, но все таки все работает
Также, можешь получить значение ключа без указателей, как в первом варианте
Тут да, с тобой соглашусь, но для меня было приятностью просто посидеть и поразмыслить о том, как все работает
За пример спасибо, в дальнейших проектах буду юзать твой вариант
Пока обойдусь тем, что мне сначала скинули
|
|
|

28.03.2021, 18:10
|
|
Постоянный
Регистрация: 03.05.2020
Сообщений: 385
С нами:
3174020
Репутация:
213
|
|
Сообщение от Tim4ukys Official
баг
использовать функцию вместо констрактора показалось странным, смысл тогда от класса? да и в принципе реализация довольно странная, поэтому и поставил реакцию.
|
|
|

28.03.2021, 18:35
|
|
Флудер
Регистрация: 18.03.2013
Сообщений: 4,080
С нами:
6921957
Репутация:
183
|
|
Сообщение от ]GsH[MeG@LaDo[N]
pMozze скинул выше вариант,и без лишних марок
Неудобное С-шные функции он скинул.
Build software better, together
GitHub is where people build software. More than 150 million people use GitHub to discover, fork, and contribute to over 420 million projects.
github.com
Для автора хуевая туча либ.
|
|
|

28.03.2021, 21:11
|
|
Участник форума
Регистрация: 21.07.2020
Сообщений: 280
С нами:
3059886
Репутация:
68
|
|
Сообщение от Tim4ukys Official
Ага, спасибо, я же в глаза е***ь и без тебя не вижу, что он скинул.
Не хочешь - не использую, хочешь - использую. Я рад за него, что он такой молодец, скинул, объяснил.
+ моего класса в том, что в нём разберётся любой даун, даже тот, кто только начинает, и я оставил хотя бы пример.
И да, в комментарии(в example) написал, что гораздо лучше использовать класс для работы с реестром от SR_team, и он точно лучше чем способ который скинул pMozze.
Пускай он сам разберётся в этой теме, как это устроено на примерах. Чем больше примеров он найдёт, тем больше он поймет.
SC6UT, если там есть баг, то тыкни пальцем, т.к. я 100 раз использовал это и 100 раз всё работало. + мой знакомый его использовал и у него тоже всё прекрасно работает. Чёт мне самому стало интересно где там баг.
пиздец ты мне тут расписал.А если нужен пример то вот

|
|
|

28.03.2021, 21:37
|
|
Участник форума
Регистрация: 03.08.2019
Сообщений: 168
С нами:
3568604
Репутация:
48
|
|
Сообщение от ]GsH[MeG@LaDo[N]
пиздец ты мне тут расписал.А если нужен пример то вот
Подскажи, как достать булево значение пожалуйста
|
|
|

28.03.2021, 21:52
|
|
Участник форума
Регистрация: 21.07.2020
Сообщений: 280
С нами:
3059886
Репутация:
68
|
|
Сообщение от ANZR
Подскажи, как достать булево значение пожалуйста
ну булевые значение это 0 - false,1 - true,а вот как именно true и false я не ебу

|
|
|
|
 |
|
Предыдущая тема
Следующая тема
|
Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
|
|
|
|