HOME FORUMS MEMBERS RECENT POSTS LOG IN  
× Авторизация
Имя пользователя:
Пароль:
Нет аккаунта? Регистрация
Баннер 1   Баннер 2
НОВЫЕ ТОРГОВАЯ НОВОСТИ ЧАТ
loading...
Скрыть
Вернуться   ANTICHAT > ПРОГРАММИРОВАНИЕ > Общие вопросы программирования
   
Ответ
 
Опции темы Поиск в этой теме Опции просмотра

  #1  
Старый 27.03.2021, 18:28
ANZR
Участник форума
Регистрация: 03.08.2019
Сообщений: 168
С нами: 3568604

Репутация: 48
По умолчанию

Ох блять, чет я седня дохуя любопытный

Мне нужно создать ini файл для сохранения в них настроек плагина, но загвоздка в том, что перерыв все, я не смог найти нормального варианта сохранения и чтения файла

Если вы знаете способ работы с ini - прошу, пишите сюда

Заранее спасибо​
 
Ответить с цитированием

  #2  
Старый 28.03.2021, 11:13
gaZmanoV
Познающий
Регистрация: 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:





Код:
[MAIN]
bState = "1"


 
Ответить с цитированием

  #3  
Старый 28.03.2021, 15:25
MeG@LaDo[N] ^_^
Участник форума
Регистрация: 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:





Код:
[MAIN]
bState = "1"


pMozze скинул выше вариант,и без лишних марок​
 
Ответить с цитированием

  #4  
Старый 28.03.2021, 17:54
gaZmanoV
Познающий
Регистрация: 18.09.2019
Сообщений: 31
С нами: 3502227

Репутация: 63
По умолчанию

Цитата:
Сообщение от ]GsH[MeG@LaDo[N]  

pMozze скинул выше вариант,и без лишних марок​
Ага, спасибо, я же в глаза е***ь и без тебя не вижу, что он скинул.

Не хочешь - не использую, хочешь - использую. Я рад за него, что он такой молодец, скинул, объяснил.

+ моего класса в том, что в нём разберётся любой даун, даже тот, кто только начинает, и я оставил хотя бы пример.

И да, в комментарии(в example) написал, что гораздо лучше использовать класс для работы с реестром от SR_team, и он точно лучше чем способ который скинул pMozze.

Пускай он сам разберётся в этой теме, как это устроено на примерах. Чем больше примеров он найдёт, тем больше он поймет.

SC6UT, если там есть баг, то тыкни пальцем, т.к. я 100 раз использовал это и 100 раз всё работало. + мой знакомый его использовал и у него тоже всё прекрасно работает. Чёт мне самому стало интересно где там баг.
 
Ответить с цитированием

  #5  
Старый 28.03.2021, 17:58
ANZR
Участник форума
Регистрация: 03.08.2019
Сообщений: 168
С нами: 3568604

Репутация: 48
По умолчанию

Цитата:
Сообщение от Tim4ukys Official  

Ага, спасибо, я же в глаза е***ь и без тебя не вижу, что он скинул.
Не хочешь - не использую, хочешь - использую. Я рад за него, что он такой молодец, скинул, объяснил.

+ моего класса в том, что в нём разберётся любой даун, даже тот, кто только начинает, и я оставил хотя бы пример.
И да, в комментарии(в example) написал, что гораздо лучше использовать класс для работы с реестром от SR_team, и он точно лучше чем способ который скинул pMozze.
Пускай он сам разберётся в этой теме, как это устроено на примерах. Чем больше примеров он найдёт, тем больше он поймет.

SC6UT, если там есть баг, то тыкни пальцем, т.к. я 100 раз использовал это и 100 раз всё работало. + мой знакомый его использовал и у него тоже всё прекрасно работает. Чёт мне самому стало интересно где там баг.
Ну твой вариант лучше тем, что ты можешь получить разные типы данных с ini файла. На том примере, что мне скинули первом, мне пришлось изрядно повозиться, чтоб получить булево значение, но все таки все работает

Также, можешь получить значение ключа без указателей, как в первом варианте

Тут да, с тобой соглашусь, но для меня было приятностью просто посидеть и поразмыслить о том, как все работает

За пример спасибо, в дальнейших проектах буду юзать твой вариант

Пока обойдусь тем, что мне сначала скинули
 
Ответить с цитированием

  #6  
Старый 28.03.2021, 18:10
sc6ut
Постоянный
Регистрация: 03.05.2020
Сообщений: 385
С нами: 3174020

Репутация: 213
По умолчанию

Цитата:
Сообщение от Tim4ukys Official  

баг
использовать функцию вместо констрактора показалось странным, смысл тогда от класса? да и в принципе реализация довольно странная, поэтому и поставил реакцию.
 
Ответить с цитированием

  #7  
Старый 28.03.2021, 18:35
Dark_Knight
Флудер
Регистрация: 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


Для автора хуевая туча либ.
 
Ответить с цитированием

  #8  
Старый 28.03.2021, 21:11
MeG@LaDo[N] ^_^
Участник форума
Регистрация: 21.07.2020
Сообщений: 280
С нами: 3059886

Репутация: 68
По умолчанию

Цитата:
Сообщение от Tim4ukys Official  

Ага, спасибо, я же в глаза е***ь и без тебя не вижу, что он скинул.
Не хочешь - не использую, хочешь - использую. Я рад за него, что он такой молодец, скинул, объяснил.

+ моего класса в том, что в нём разберётся любой даун, даже тот, кто только начинает, и я оставил хотя бы пример.
И да, в комментарии(в example) написал, что гораздо лучше использовать класс для работы с реестром от SR_team, и он точно лучше чем способ который скинул pMozze.
Пускай он сам разберётся в этой теме, как это устроено на примерах. Чем больше примеров он найдёт, тем больше он поймет.

SC6UT, если там есть баг, то тыкни пальцем, т.к. я 100 раз использовал это и 100 раз всё работало. + мой знакомый его использовал и у него тоже всё прекрасно работает. Чёт мне самому стало интересно где там баг.
пиздец ты мне тут расписал.А если нужен пример то вот







 
Ответить с цитированием

  #9  
Старый 28.03.2021, 21:37
ANZR
Участник форума
Регистрация: 03.08.2019
Сообщений: 168
С нами: 3568604

Репутация: 48
По умолчанию

Цитата:
Сообщение от ]GsH[MeG@LaDo[N]  

пиздец ты мне тут расписал.А если нужен пример то вот
Подскажи, как достать булево значение пожалуйста
 
Ответить с цитированием

  #10  
Старый 28.03.2021, 21:52
MeG@LaDo[N] ^_^
Участник форума
Регистрация: 21.07.2020
Сообщений: 280
С нами: 3059886

Репутация: 68
По умолчанию

Цитата:
Сообщение от ANZR  

Подскажи, как достать булево значение пожалуйста
ну булевые значение это 0 - false,1 - true,а вот как именно true и false я не ебу
 
Ответить с цитированием
Ответ



Предыдущая тема Следующая тема

Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
 


Быстрый переход




ANTICHAT ™ © 2001- Antichat Kft.