├── .gitignore
├── LICENSE
├── README.md
├── demo
├── main.cpp
├── mysql_demo.sln
├── mysql_demo.vcxproj
├── mysql_demo.vcxproj.filters
├── mysql_demo.vcxproj.user
├── vs2019_mysql_demo.sln
├── vs2019_mysql_demo.vcxproj
├── vs2019_mysql_demo.vcxproj.filters
└── vs2019_mysql_demo.vcxproj.user
└── mysql_modern_cpp
├── fmt
├── chrono.h
├── color.h
├── compile.h
├── core.h
├── format-inl.h
├── format.h
├── locale.h
├── os.h
├── ostream.h
├── posix.h
├── printf.h
└── ranges.h
├── mysql_modern_cpp.hpp
└── pfr
├── core.hpp
├── detail
├── cast_to_layout_compatible.hpp
├── config.hpp
├── core.hpp
├── core14_classic.hpp
├── core14_loophole.hpp
├── core17.hpp
├── core17_generated.hpp
├── detectors.hpp
├── fields_count.hpp
├── for_each_field_impl.hpp
├── functional.hpp
├── io.hpp
├── make_flat_tuple_of_references.hpp
├── make_integer_sequence.hpp
├── offset_based_getter.hpp
├── rvalue_t.hpp
├── sequence_tuple.hpp
├── size_array.hpp
├── size_t_.hpp
├── stdtuple.hpp
├── tie_from_structure_tuple.hpp
└── unsafe_declval.hpp
├── functions_for.hpp
├── functors.hpp
├── io.hpp
├── io_fields.hpp
├── ops.hpp
├── ops_fields.hpp
├── pfr.hpp
└── tuple_size.hpp
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | # *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Mono auto generated files
17 | mono_crash.*
18 |
19 | # Build results
20 | [Dd]ebug/
21 | [Dd]ebugPublic/
22 | [Rr]elease/
23 | [Rr]eleases/
24 | x64/
25 | x86/
26 | [Aa][Rr][Mm]/
27 | [Aa][Rr][Mm]64/
28 | bld/
29 | [Bb]in/
30 | [Oo]bj/
31 | [Ll]og/
32 | [Ll]ogs/
33 |
34 | # Visual Studio 2015/2017 cache/options directory
35 | .vs/
36 | # Uncomment if you have tasks that create the project's static files in wwwroot
37 | #wwwroot/
38 |
39 | # Visual Studio 2017 auto generated files
40 | Generated\ Files/
41 |
42 | # MSTest test Results
43 | [Tt]est[Rr]esult*/
44 | [Bb]uild[Ll]og.*
45 |
46 | # NUnit
47 | *.VisualState.xml
48 | TestResult.xml
49 | nunit-*.xml
50 |
51 | # Build Results of an ATL Project
52 | [Dd]ebugPS/
53 | [Rr]eleasePS/
54 | dlldata.c
55 |
56 | # Benchmark Results
57 | BenchmarkDotNet.Artifacts/
58 |
59 | # .NET Core
60 | project.lock.json
61 | project.fragment.lock.json
62 | artifacts/
63 |
64 | # StyleCop
65 | StyleCopReport.xml
66 |
67 | # Files built by Visual Studio
68 | *_i.c
69 | *_p.c
70 | *_h.h
71 | *.ilk
72 | *.meta
73 | *.obj
74 | *.iobj
75 | *.pch
76 | *.pdb
77 | *.ipdb
78 | *.pgc
79 | *.pgd
80 | *.rsp
81 | *.sbr
82 | *.tlb
83 | *.tli
84 | *.tlh
85 | *.tmp
86 | *.tmp_proj
87 | *_wpftmp.csproj
88 | *.log
89 | *.vspscc
90 | *.vssscc
91 | .builds
92 | *.pidb
93 | *.svclog
94 | *.scc
95 |
96 | # Chutzpah Test files
97 | _Chutzpah*
98 |
99 | # Visual C++ cache files
100 | ipch/
101 | *.aps
102 | *.ncb
103 | *.opendb
104 | *.opensdf
105 | *.sdf
106 | *.cachefile
107 | *.VC.db
108 | *.VC.VC.opendb
109 |
110 | # Visual Studio profiler
111 | *.psess
112 | *.vsp
113 | *.vspx
114 | *.sap
115 |
116 | # Visual Studio Trace Files
117 | *.e2e
118 |
119 | # TFS 2012 Local Workspace
120 | $tf/
121 |
122 | # Guidance Automation Toolkit
123 | *.gpState
124 |
125 | # ReSharper is a .NET coding add-in
126 | _ReSharper*/
127 | *.[Rr]e[Ss]harper
128 | *.DotSettings.user
129 |
130 | # TeamCity is a build add-in
131 | _TeamCity*
132 |
133 | # DotCover is a Code Coverage Tool
134 | *.dotCover
135 |
136 | # AxoCover is a Code Coverage Tool
137 | .axoCover/*
138 | !.axoCover/settings.json
139 |
140 | # Visual Studio code coverage results
141 | *.coverage
142 | *.coveragexml
143 |
144 | # NCrunch
145 | _NCrunch_*
146 | .*crunch*.local.xml
147 | nCrunchTemp_*
148 |
149 | # MightyMoose
150 | *.mm.*
151 | AutoTest.Net/
152 |
153 | # Web workbench (sass)
154 | .sass-cache/
155 |
156 | # Installshield output folder
157 | [Ee]xpress/
158 |
159 | # DocProject is a documentation generator add-in
160 | DocProject/buildhelp/
161 | DocProject/Help/*.HxT
162 | DocProject/Help/*.HxC
163 | DocProject/Help/*.hhc
164 | DocProject/Help/*.hhk
165 | DocProject/Help/*.hhp
166 | DocProject/Help/Html2
167 | DocProject/Help/html
168 |
169 | # Click-Once directory
170 | publish/
171 |
172 | # Publish Web Output
173 | *.[Pp]ublish.xml
174 | *.azurePubxml
175 | # Note: Comment the next line if you want to checkin your web deploy settings,
176 | # but database connection strings (with potential passwords) will be unencrypted
177 | *.pubxml
178 | *.publishproj
179 |
180 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
181 | # checkin your Azure Web App publish settings, but sensitive information contained
182 | # in these scripts will be unencrypted
183 | PublishScripts/
184 |
185 | # NuGet Packages
186 | *.nupkg
187 | # NuGet Symbol Packages
188 | *.snupkg
189 | # The packages folder can be ignored because of Package Restore
190 | **/[Pp]ackages/*
191 | # except build/, which is used as an MSBuild target.
192 | !**/[Pp]ackages/build/
193 | # Uncomment if necessary however generally it will be regenerated when needed
194 | #!**/[Pp]ackages/repositories.config
195 | # NuGet v3's project.json files produces more ignorable files
196 | *.nuget.props
197 | *.nuget.targets
198 |
199 | # Microsoft Azure Build Output
200 | csx/
201 | *.build.csdef
202 |
203 | # Microsoft Azure Emulator
204 | ecf/
205 | rcf/
206 |
207 | # Windows Store app package directories and files
208 | AppPackages/
209 | BundleArtifacts/
210 | Package.StoreAssociation.xml
211 | _pkginfo.txt
212 | *.appx
213 | *.appxbundle
214 | *.appxupload
215 |
216 | # Visual Studio cache files
217 | # files ending in .cache can be ignored
218 | *.[Cc]ache
219 | # but keep track of directories ending in .cache
220 | !?*.[Cc]ache/
221 |
222 | # Others
223 | ClientBin/
224 | ~$*
225 | *~
226 | *.dbmdl
227 | *.dbproj.schemaview
228 | *.jfm
229 | *.pfx
230 | *.publishsettings
231 | orleans.codegen.cs
232 |
233 | # Including strong name files can present a security risk
234 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
235 | #*.snk
236 |
237 | # Since there are multiple workflows, uncomment next line to ignore bower_components
238 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
239 | #bower_components/
240 |
241 | # RIA/Silverlight projects
242 | Generated_Code/
243 |
244 | # Backup & report files from converting an old project file
245 | # to a newer Visual Studio version. Backup files are not needed,
246 | # because we have git ;-)
247 | _UpgradeReport_Files/
248 | Backup*/
249 | UpgradeLog*.XML
250 | UpgradeLog*.htm
251 | ServiceFabricBackup/
252 | *.rptproj.bak
253 |
254 | # SQL Server files
255 | *.mdf
256 | *.ldf
257 | *.ndf
258 |
259 | # Business Intelligence projects
260 | *.rdl.data
261 | *.bim.layout
262 | *.bim_*.settings
263 | *.rptproj.rsuser
264 | *- [Bb]ackup.rdl
265 | *- [Bb]ackup ([0-9]).rdl
266 | *- [Bb]ackup ([0-9][0-9]).rdl
267 |
268 | # Microsoft Fakes
269 | FakesAssemblies/
270 |
271 | # GhostDoc plugin setting file
272 | *.GhostDoc.xml
273 |
274 | # Node.js Tools for Visual Studio
275 | .ntvs_analysis.dat
276 | node_modules/
277 |
278 | # Visual Studio 6 build log
279 | *.plg
280 |
281 | # Visual Studio 6 workspace options file
282 | *.opt
283 |
284 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
285 | *.vbw
286 |
287 | # Visual Studio LightSwitch build output
288 | **/*.HTMLClient/GeneratedArtifacts
289 | **/*.DesktopClient/GeneratedArtifacts
290 | **/*.DesktopClient/ModelManifest.xml
291 | **/*.Server/GeneratedArtifacts
292 | **/*.Server/ModelManifest.xml
293 | _Pvt_Extensions
294 |
295 | # Paket dependency manager
296 | .paket/paket.exe
297 | paket-files/
298 |
299 | # FAKE - F# Make
300 | .fake/
301 |
302 | # CodeRush personal settings
303 | .cr/personal
304 |
305 | # Python Tools for Visual Studio (PTVS)
306 | __pycache__/
307 | *.pyc
308 |
309 | # Cake - Uncomment if you are using it
310 | # tools/**
311 | # !tools/packages.config
312 |
313 | # Tabs Studio
314 | *.tss
315 |
316 | # Telerik's JustMock configuration file
317 | *.jmconfig
318 |
319 | # BizTalk build output
320 | *.btp.cs
321 | *.btm.cs
322 | *.odx.cs
323 | *.xsd.cs
324 |
325 | # OpenCover UI analysis results
326 | OpenCover/
327 |
328 | # Azure Stream Analytics local run output
329 | ASALocalRun/
330 |
331 | # MSBuild Binary and Structured Log
332 | *.binlog
333 |
334 | # NVidia Nsight GPU debugger configuration file
335 | *.nvuser
336 |
337 | # MFractors (Xamarin productivity tool) working folder
338 | .mfractor/
339 |
340 | # Local History for Visual Studio
341 | .localhistory/
342 |
343 | # BeatPulse healthcheck temp database
344 | healthchecksdb
345 |
346 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
347 | MigrationBackup/
348 |
349 | # Ionide (cross platform F# VS Code tools) working folder
350 | .ionide/
351 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # mysql_modern_cpp
2 | A simple C++ class for operating mysql database
3 |
4 |
5 |
6 | [](https://996.icu)
7 | [](https://github.com/996icu/996.ICU/blob/master/LICENSE)
8 |
9 | * header only,基于C++17,依赖fmt库(fmt库也是header only的,而且fmt库是即将进入c++20标准的format库);
10 |
11 | ```c++
12 | struct user
13 | {
14 | std::string name;
15 | int age{};
16 | std::tm birth{};
17 |
18 | template
19 | bool orm(Recordset & rs)
20 | {
21 | return rs(name, age, birth);
22 | }
23 | };
24 |
25 | mysql::database db;
26 | db.connect("localhost", "root", "123456", "mir3_user");
27 | db.set_charset("gbk");
28 |
29 | // R"()" 是 c++ 11 的 raw string 语法,避免字符串换行时还要在行尾添加反斜杠
30 | db << R"(CREATE TABLE `tbl_user` (
31 | `name` VARCHAR(20) NOT NULL,
32 | `age` INT NULL DEFAULT NULL,
33 | `birth` DATETIME NULL DEFAULT NULL,
34 | PRIMARY KEY(`name`)
35 | )
36 | COLLATE = 'gbk_chinese_ci'
37 | ENGINE = InnoDB
38 | ;)";
39 |
40 | // "db << ..." 这种操作符方式会生成一个临时变量 当这个临时变量销毁时会在析构函数中自动执行sql语句
41 | // 注意这种情况下执行sql语句时如果出现错误不会进到示例这里最后面的catch块中
42 | db << "insert into tbl_user (name,age) values (?, ?);"
43 | << "admin"
44 | << 102;
45 | db << "update tbl_user set age=?,birth=? where name=?;"
46 | << nullptr
47 | << nullptr
48 | << "admin";
49 | db << "update tbl_user set age=?,birth=? where name=?;"
50 | << 55
51 | << "1990-03-14 15:15:15"
52 | << "admin";
53 |
54 | user u;
55 | // 查询数据到自定义结构体中
56 | db << "select name,age,birth from tbl_user where name=?" << "admin" >> u;
57 | db.execute("select name,age,birth from tbl_user where name=?", "admin").fetch(u);
58 | db << "select name,age,birth from tbl_user" >> [](user u)
59 | {
60 | printf("%s %d\n", u.name.data(), u.age);
61 | };
62 |
63 | // 自定义结构体的信息添加到数据库中
64 | u.name += std::to_string(std::rand());
65 | db << "insert into tbl_user (name,age,birth) values (?,?,?)" << u;
66 |
67 |
68 | db << "delete from tbl_user where name=?;"
69 | << "tester";
70 |
71 | // 直接调用 db.execute 会直接执行sql语句 如果出现错误可以进到示例这里最后面的catch块中
72 | db.execute("insert into tbl_user values (?, ?, ?);", "tester", 32, "2020-03-14 10:10:10");
73 |
74 | std::string name, age, birth;
75 |
76 | int count = 0;
77 | db << "select count(*) from tbl_user;"
78 | >> count;
79 |
80 | db << "select name from tbl_user where age=55;"
81 | >> name;
82 |
83 | std::tm tm_birth{}; // 将获取到的日期存储到c++语言的结构体tm中
84 | db << "select birth from tbl_user where name=?;"
85 | << name
86 | >> tm_birth;
87 |
88 | const char * inject_name = "admin' or 1=1 or '1=1"; // sql 注入
89 | db << "select count(*) from tbl_user where name=?;"
90 | << inject_name
91 | >> count;
92 |
93 | // 将获取的内容存储到绑定数据中 这样你可以直接操作数据的缓冲区buffer
94 | // 但此时必须要用auto rs = 这种方式将recordset临时变量保存起来
95 | // 否则operator>>结束后临时变量就销毁了 binder 指针指向的内容就是非法的了
96 | mysql::binder * binder = nullptr;
97 | auto rs = db << "select birth from tbl_user where name='admin';";
98 | rs >> binder;
99 | MYSQL_TIME * time = (MYSQL_TIME *)(binder->buffer.get());
100 | printf("%d-%d-%d %d:%d:%d\n", time->year, time->month, time->day, time->hour, time->minute, time->second);
101 |
102 | // 查询到数据后直接调用 lambda 回调函数,有多少行数据,就会调用多少次
103 | (db << "select name,age,birth from tbl_user where age>?;")
104 | << 10
105 | >> [](std::string_view name, int age, std::string birth)
106 | {
107 | printf("%s %d %s\n", name.data(), age, birth.data());
108 | };
109 |
110 | db << "select age,birth from tbl_user;"
111 | >> std::tie(age, birth);
112 |
113 | db.execute("select name,age,birth from tbl_user where name=?;", name) >>
114 | [](std::string_view name, int age, std::string birth)
115 | {
116 | };
117 |
118 | // set_fields_format 用来设置返回的字符串的格式,注意只有返回字符串时才起作用
119 | // c++ 20 的format语法
120 | // {:>15} 表示右对齐 共占15个字符的宽度
121 | // {:04} 共占4个字符的宽度 如果不足4个字符在前面补0
122 | rs = (db << "select name,age,birth from tbl_user;");
123 | // 总共select了三列数据,所以set_fields_format必须要设置三个格式信息
124 | // 可以调用set_fields_format设置格式,如果调用了就必须有几列,就填几个格式信息
125 | // 也可以不调用set_fields_format,此时会使用默认的格式
126 | rs.set_fields_format("{:>15}", "{:04}", "{:%Y-%m-%d %H:%M:%S}");
127 | auto rs2 = std::move(rs);
128 | // 按照自己的要求一行一行的获取数据
129 | while (rs2.fetch(name, age, binder))
130 | {
131 | MYSQL_TIME * time = (MYSQL_TIME *)(binder->buffer.get());
132 | printf("%s %s %d-%d-%d\n", name.data(), age.data(), time->year, time->month, time->day);
133 | }
134 |
135 | std::tuple tup;
136 | db << "select age,birth from tbl_user;"
137 | >> tup;
138 | auto &[_age, _birth] = tup;
139 | printf("%d %s\n", _age, birth.data());
140 | ```
141 |
142 |
143 |
144 |
--------------------------------------------------------------------------------
/demo/main.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * > Compile:
3 | * g++ -c -x c++ /root/main.cpp -I /usr/local/include -I /usr/include/mysql -g2 -gdwarf-2 -o "/root/mysql_demo.o" -Wall -Wswitch -W"no-deprecated-declarations" -W"empty-body" -Wconversion -W"return-type" -Wparentheses -W"no-format" -Wuninitialized -W"unreachable-code" -W"unused-function" -W"unused-value" -W"unused-variable" -O0 -fno-strict-aliasing -fno-omit-frame-pointer -fthreadsafe-statics -fexceptions -frtti -std=c++17
4 | * > Link:
5 | * g++ -o "/root/mysql_demo.out" -Wl,--no-undefined -Wl,-L/usr/local/lib -L/usr/lib64/mysql -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -lpthread -lrt -ldl /root/mysql_demo.o -lmysqlclient
6 | */
7 |
8 | #include
9 | #include
10 |
11 | #include
12 | #include
13 |
14 | #include "mysql_modern_cpp.hpp"
15 |
16 | #include
17 |
18 | #if defined(_MSC_VER)
19 | #if defined(_DEBUG)
20 | #pragma comment(lib,"libmysql.lib")
21 | #else
22 | #pragma comment(lib,"libmysql.lib")
23 | #endif
24 | #endif
25 |
26 | using namespace std;
27 |
28 | struct user
29 | {
30 | std::string name;
31 | int age{};
32 | //std::tm birth{};
33 | std::chrono::system_clock::time_point birth{};
34 |
35 | template
36 | bool orm(Recordset & rs)
37 | {
38 | bool result = true;
39 | pfr::for_each_field(*this, [&](auto& field)
40 | {
41 | result &= rs(field);
42 | });
43 | return result;
44 | //return rs(name, age, birth);
45 | }
46 | };
47 |
48 | int main(int argc, char* argv[])
49 | {
50 | #if defined(_WIN32)
51 | _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
52 | #endif
53 |
54 | try
55 | {
56 | mysql::error_code ec;
57 | mysql::database db;
58 | db.bind_error_callback([](mysql::error_code ec)
59 | {
60 | fmt::print("{} {}\n", ec.val, ec.msg);
61 | });
62 | db.connect("localhost", "root", "123456", "mir3_user");
63 | db.set_charset("gbk");
64 |
65 | (db << "show variables like 'character%';").set_fields_format("{:30}", "{}")
66 | >> [](std::string name, std::string value)
67 | {
68 | printf("%s %s\n", name.data(), value.data());
69 | };
70 |
71 | // R"()" 是 c++ 11 的 raw string 语法,避免字符串换行时还要在行尾添加反斜杠
72 | db << R"(CREATE TABLE `tbl_user` (
73 | `name` VARCHAR(20) NOT NULL,
74 | `age` INT NULL DEFAULT NULL,
75 | `birth` DATETIME NULL DEFAULT NULL,
76 | PRIMARY KEY(`name`)
77 | )
78 | COLLATE = 'gbk_chinese_ci'
79 | ENGINE = InnoDB
80 | ;)";
81 |
82 | // "db << ..." 这种操作符方式会生成一个临时变量 当这个临时变量销毁时会在析构函数中自动执行sql语句
83 | // 注意这种情况下执行sql语句时如果出现错误不会进到示例这里最后面的catch块中
84 | db << "insert into tbl_user (name,age) values (?, ?);"
85 | << "admin"
86 | << 102;
87 | db << "update tbl_user set age=?,birth=? where name=?;"
88 | << nullptr
89 | << nullptr
90 | << "admin";
91 | db << "update tbl_user set age=?,birth=? where name=?;"
92 | << 55
93 | << "1990-03-14 15:15:15"
94 | << "admin";
95 |
96 | user u;
97 | // 查询数据到自定义结构体中
98 | db << "select name,age,birth from tbl_user where name=?" << "admin" >> u;
99 | db.execute("select name,age,birth from tbl_user where name=?", "admin").fetch(u);
100 | db << "select name,age,birth from tbl_user" >> [](user u)
101 | {
102 | printf("%s %d\n", u.name.data(), u.age);
103 | };
104 |
105 | // 自定义结构体的信息添加到数据库中
106 | u.name += std::to_string(std::rand());
107 | db.execute(ec, "insert into tbl_user (name,age,birth) values (?, ?, ?);", u);
108 | db << "insert into tbl_user (name,age,birth) values (?,?,?)" << u;
109 | db << "insert into tbl_user values (?, ?, ?);" << u;
110 |
111 | db << "delete from tbl_user where name=?;"
112 | << "hanmeimei";
113 |
114 | // 直接调用 db.execute 会直接执行sql语句 如果出现错误可以进到示例这里最后面的catch块中
115 | db.execute(ec, "insert into tbl_user values (?, ?, ?);", "hanmeimei", 32, "2020-03-14 10:10:10");
116 |
117 | std::string name, age, birth;
118 |
119 | int count = 0;
120 | db << "select count(*) from tbl_user;"
121 | >> count;
122 |
123 | db << "select name from tbl_user where age=55;"
124 | >> name;
125 |
126 | std::tm tm_birth{}; // 将获取到的日期存储到c++语言的结构体tm中
127 | db << "select birth from tbl_user where name=?;"
128 | << name
129 | >> tm_birth;
130 |
131 | const char * inject_name = "admin' or 1=1 or '1=1"; // sql 注入
132 | db << "select count(*) from tbl_user where name=?;"
133 | << inject_name
134 | >> count;
135 |
136 | // 将获取的内容存储到绑定数据中 这样你可以直接操作数据的缓冲区buffer
137 | // 但此时必须要用auto rs = 这种方式将recordset临时变量保存起来
138 | // 否则operator>>结束后临时变量就销毁了 binder 指针指向的内容就是非法的了
139 | mysql::binder * binder = nullptr;
140 | auto rs = db << "select birth from tbl_user where name='admin';";
141 | rs >> binder;
142 | MYSQL_TIME * time = (MYSQL_TIME *)(binder->buffer.get());
143 | printf("%d-%d-%d %d:%d:%d\n", time->year, time->month, time->day, time->hour, time->minute, time->second);
144 |
145 | // 查询到数据后直接调用 lambda 回调函数,有多少行数据,就会调用多少次
146 | (db << "select name,age,birth from tbl_user where age>?;")
147 | << 10
148 | >> [](std::string_view name, int age, std::string birth)
149 | {
150 | printf("%s %d %s\n", name.data(), age, birth.data());
151 | };
152 |
153 | db << "select age,birth from tbl_user;"
154 | >> std::tie(age, birth);
155 |
156 | db.execute("select name,age,birth from tbl_user where name=?;", name) >>
157 | [](std::string_view name, int age, std::string birth)
158 | {
159 | };
160 |
161 | // set_fields_format 用来设置返回的字符串的格式,注意只有返回字符串时才起作用
162 | // c++ 20 的format语法
163 | // {:>15} 表示右对齐 共占15个字符的宽度
164 | // {:04} 共占4个字符的宽度 如果不足4个字符在前面补0
165 | rs = (db << "select name,age,birth from tbl_user;");
166 | // 总共select了三列数据,所以set_fields_format必须要设置三个格式信息
167 | // 可以调用set_fields_format设置格式,如果调用了就必须有几列,就填几个格式信息
168 | // 也可以不调用set_fields_format,此时会使用默认的格式
169 | rs.set_fields_format("{:>15}", "{:04}", "{:%Y-%m-%d %H:%M:%S}");
170 | auto rs2 = std::move(rs);
171 | // 按照自己的要求一行一行的获取数据
172 | while (rs2.fetch(name, age, binder))
173 | {
174 | MYSQL_TIME * time = (MYSQL_TIME *)(binder->buffer.get());
175 | printf("%s %s %d-%d-%d\n", name.data(), age.data(), time->year, time->month, time->day);
176 | }
177 |
178 | std::tuple tup;
179 | db << "select age,birth from tbl_user;"
180 | >> tup;
181 | auto &[_age, _birth] = tup;
182 | printf("%d %s\n", _age, birth.data());
183 | }
184 | catch(std::exception& e)
185 | {
186 | printf("%s\n", e.what());
187 | }
188 |
189 | #if defined(_WIN32)
190 | system("pause");
191 | #endif
192 | return 0;
193 | }
194 |
--------------------------------------------------------------------------------
/demo/mysql_demo.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28307.539
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mysql_demo", "mysql_demo.vcxproj", "{A632DF24-BA17-4608-8443-447EB3DCE9D6}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|x64 = Debug|x64
11 | Debug|x86 = Debug|x86
12 | Release|x64 = Release|x64
13 | Release|x86 = Release|x86
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {A632DF24-BA17-4608-8443-447EB3DCE9D6}.Debug|x64.ActiveCfg = Debug|x64
17 | {A632DF24-BA17-4608-8443-447EB3DCE9D6}.Debug|x64.Build.0 = Debug|x64
18 | {A632DF24-BA17-4608-8443-447EB3DCE9D6}.Debug|x86.ActiveCfg = Debug|Win32
19 | {A632DF24-BA17-4608-8443-447EB3DCE9D6}.Debug|x86.Build.0 = Debug|Win32
20 | {A632DF24-BA17-4608-8443-447EB3DCE9D6}.Release|x64.ActiveCfg = Release|x64
21 | {A632DF24-BA17-4608-8443-447EB3DCE9D6}.Release|x64.Build.0 = Release|x64
22 | {A632DF24-BA17-4608-8443-447EB3DCE9D6}.Release|x86.ActiveCfg = Release|Win32
23 | {A632DF24-BA17-4608-8443-447EB3DCE9D6}.Release|x86.Build.0 = Release|Win32
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {17E5124C-F8FA-4E82-BBC0-1BE948D2847C}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/demo/mysql_demo.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 |
23 |
24 |
25 | 15.0
26 | {A632DF24-BA17-4608-8443-447EB3DCE9D6}
27 | mysqldemo
28 | 10.0.17763.0
29 |
30 |
31 |
32 | Application
33 | true
34 | v141
35 | MultiByte
36 |
37 |
38 | Application
39 | false
40 | v141
41 | true
42 | MultiByte
43 |
44 |
45 | Application
46 | true
47 | v141
48 | MultiByte
49 |
50 |
51 | Application
52 | false
53 | v141
54 | true
55 | MultiByte
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 | Level3
79 | Disabled
80 | true
81 | true
82 | D:\programs\mysql-8.0.19-winx64\include;../mysql_modern_cpp;%(AdditionalIncludeDirectories)
83 | MultiThreadedDebugDLL
84 | stdcpp17
85 |
86 |
87 | Console
88 |
89 |
90 |
91 |
92 | Level3
93 | Disabled
94 | true
95 | true
96 | D:\programs\mysql-8.0.19-winx64\include;../mysql_modern_cpp;%(AdditionalIncludeDirectories)
97 | MultiThreadedDebugDLL
98 | stdcpp17
99 |
100 |
101 | D:\programs\mysql-8.0.19-winx64\lib;%(AdditionalLibraryDirectories)
102 | Console
103 |
104 |
105 |
106 |
107 | Level3
108 | MaxSpeed
109 | true
110 | true
111 | true
112 | true
113 | D:\programs\mysql-8.0.19-winx64\include;../mysql_modern_cpp;%(AdditionalIncludeDirectories)
114 | MultiThreaded
115 | stdcpp17
116 |
117 |
118 | true
119 | true
120 | Console
121 |
122 |
123 |
124 |
125 | Level3
126 | MaxSpeed
127 | true
128 | true
129 | true
130 | true
131 | D:\programs\mysql-8.0.19-winx64\include;../mysql_modern_cpp;%(AdditionalIncludeDirectories)
132 | MultiThreaded
133 | stdcpp17
134 |
135 |
136 | true
137 | true
138 | D:\programs\mysql-8.0.19-winx64\lib;%(AdditionalLibraryDirectories)
139 | Console
140 |
141 |
142 |
143 |
144 |
145 |
--------------------------------------------------------------------------------
/demo/mysql_demo.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | 源文件
20 |
21 |
22 |
--------------------------------------------------------------------------------
/demo/mysql_demo.vcxproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/demo/vs2019_mysql_demo.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.30309.148
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vs2019_mysql_demo", "vs2019_mysql_demo.vcxproj", "{843EFD29-F3D7-40DD-9203-5A148A4E20A5}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|x64 = Debug|x64
11 | Debug|x86 = Debug|x86
12 | Release|x64 = Release|x64
13 | Release|x86 = Release|x86
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {843EFD29-F3D7-40DD-9203-5A148A4E20A5}.Debug|x64.ActiveCfg = Debug|x64
17 | {843EFD29-F3D7-40DD-9203-5A148A4E20A5}.Debug|x64.Build.0 = Debug|x64
18 | {843EFD29-F3D7-40DD-9203-5A148A4E20A5}.Debug|x86.ActiveCfg = Debug|Win32
19 | {843EFD29-F3D7-40DD-9203-5A148A4E20A5}.Debug|x86.Build.0 = Debug|Win32
20 | {843EFD29-F3D7-40DD-9203-5A148A4E20A5}.Release|x64.ActiveCfg = Release|x64
21 | {843EFD29-F3D7-40DD-9203-5A148A4E20A5}.Release|x64.Build.0 = Release|x64
22 | {843EFD29-F3D7-40DD-9203-5A148A4E20A5}.Release|x86.ActiveCfg = Release|Win32
23 | {843EFD29-F3D7-40DD-9203-5A148A4E20A5}.Release|x86.Build.0 = Release|Win32
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {31B2E1CF-148C-477E-8070-1F34055B305C}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/demo/vs2019_mysql_demo.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | 16.0
23 | Win32Proj
24 | {843efd29-f3d7-40dd-9203-5a148a4e20a5}
25 | vs2019mysqldemo
26 | 10.0
27 |
28 |
29 |
30 | Application
31 | true
32 | v142
33 | Unicode
34 |
35 |
36 | Application
37 | false
38 | v142
39 | true
40 | Unicode
41 |
42 |
43 | Application
44 | true
45 | v142
46 | Unicode
47 |
48 |
49 | Application
50 | false
51 | v142
52 | true
53 | Unicode
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | true
75 |
76 |
77 | false
78 |
79 |
80 | true
81 |
82 |
83 | false
84 |
85 |
86 |
87 | Level3
88 | true
89 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
90 | true
91 | D:\programs\mysql-8.0.19-winx64\include;../mysql_modern_cpp;%(AdditionalIncludeDirectories)
92 | stdcpp17
93 |
94 |
95 | Console
96 | true
97 |
98 |
99 |
100 |
101 | Level3
102 | true
103 | true
104 | true
105 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
106 | true
107 | D:\programs\mysql-8.0.19-winx64\include;../mysql_modern_cpp;%(AdditionalIncludeDirectories)
108 | stdcpp17
109 |
110 |
111 | Console
112 | true
113 | true
114 | true
115 |
116 |
117 |
118 |
119 | Level3
120 | true
121 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
122 | true
123 | D:\programs\mysql-8.0.19-winx64\include;../mysql_modern_cpp;%(AdditionalIncludeDirectories)
124 | stdcpp17
125 |
126 |
127 | Console
128 | true
129 | D:\Programs\mysql-8.0.19-winx64\lib;%(AdditionalLibraryDirectories)
130 |
131 |
132 |
133 |
134 | Level3
135 | true
136 | true
137 | true
138 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
139 | true
140 | D:\programs\mysql-8.0.19-winx64\include;../mysql_modern_cpp;%(AdditionalIncludeDirectories)
141 | stdcpp17
142 |
143 |
144 | Console
145 | true
146 | true
147 | true
148 | D:\Programs\mysql-8.0.19-winx64\lib;%(AdditionalLibraryDirectories)
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
--------------------------------------------------------------------------------
/demo/vs2019_mysql_demo.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/demo/vs2019_mysql_demo.vcxproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/mysql_modern_cpp/fmt/color.h:
--------------------------------------------------------------------------------
1 | // Formatting library for C++ - color support
2 | //
3 | // Copyright (c) 2018 - present, Victor Zverovich and fmt contributors
4 | // All rights reserved.
5 | //
6 | // For the license information refer to format.h.
7 |
8 | #ifndef FMT_COLOR_H_
9 | #define FMT_COLOR_H_
10 |
11 | #include "format.h"
12 |
13 | FMT_BEGIN_NAMESPACE
14 |
15 | enum class color : uint32_t {
16 | alice_blue = 0xF0F8FF, // rgb(240,248,255)
17 | antique_white = 0xFAEBD7, // rgb(250,235,215)
18 | aqua = 0x00FFFF, // rgb(0,255,255)
19 | aquamarine = 0x7FFFD4, // rgb(127,255,212)
20 | azure = 0xF0FFFF, // rgb(240,255,255)
21 | beige = 0xF5F5DC, // rgb(245,245,220)
22 | bisque = 0xFFE4C4, // rgb(255,228,196)
23 | black = 0x000000, // rgb(0,0,0)
24 | blanched_almond = 0xFFEBCD, // rgb(255,235,205)
25 | blue = 0x0000FF, // rgb(0,0,255)
26 | blue_violet = 0x8A2BE2, // rgb(138,43,226)
27 | brown = 0xA52A2A, // rgb(165,42,42)
28 | burly_wood = 0xDEB887, // rgb(222,184,135)
29 | cadet_blue = 0x5F9EA0, // rgb(95,158,160)
30 | chartreuse = 0x7FFF00, // rgb(127,255,0)
31 | chocolate = 0xD2691E, // rgb(210,105,30)
32 | coral = 0xFF7F50, // rgb(255,127,80)
33 | cornflower_blue = 0x6495ED, // rgb(100,149,237)
34 | cornsilk = 0xFFF8DC, // rgb(255,248,220)
35 | crimson = 0xDC143C, // rgb(220,20,60)
36 | cyan = 0x00FFFF, // rgb(0,255,255)
37 | dark_blue = 0x00008B, // rgb(0,0,139)
38 | dark_cyan = 0x008B8B, // rgb(0,139,139)
39 | dark_golden_rod = 0xB8860B, // rgb(184,134,11)
40 | dark_gray = 0xA9A9A9, // rgb(169,169,169)
41 | dark_green = 0x006400, // rgb(0,100,0)
42 | dark_khaki = 0xBDB76B, // rgb(189,183,107)
43 | dark_magenta = 0x8B008B, // rgb(139,0,139)
44 | dark_olive_green = 0x556B2F, // rgb(85,107,47)
45 | dark_orange = 0xFF8C00, // rgb(255,140,0)
46 | dark_orchid = 0x9932CC, // rgb(153,50,204)
47 | dark_red = 0x8B0000, // rgb(139,0,0)
48 | dark_salmon = 0xE9967A, // rgb(233,150,122)
49 | dark_sea_green = 0x8FBC8F, // rgb(143,188,143)
50 | dark_slate_blue = 0x483D8B, // rgb(72,61,139)
51 | dark_slate_gray = 0x2F4F4F, // rgb(47,79,79)
52 | dark_turquoise = 0x00CED1, // rgb(0,206,209)
53 | dark_violet = 0x9400D3, // rgb(148,0,211)
54 | deep_pink = 0xFF1493, // rgb(255,20,147)
55 | deep_sky_blue = 0x00BFFF, // rgb(0,191,255)
56 | dim_gray = 0x696969, // rgb(105,105,105)
57 | dodger_blue = 0x1E90FF, // rgb(30,144,255)
58 | fire_brick = 0xB22222, // rgb(178,34,34)
59 | floral_white = 0xFFFAF0, // rgb(255,250,240)
60 | forest_green = 0x228B22, // rgb(34,139,34)
61 | fuchsia = 0xFF00FF, // rgb(255,0,255)
62 | gainsboro = 0xDCDCDC, // rgb(220,220,220)
63 | ghost_white = 0xF8F8FF, // rgb(248,248,255)
64 | gold = 0xFFD700, // rgb(255,215,0)
65 | golden_rod = 0xDAA520, // rgb(218,165,32)
66 | gray = 0x808080, // rgb(128,128,128)
67 | green = 0x008000, // rgb(0,128,0)
68 | green_yellow = 0xADFF2F, // rgb(173,255,47)
69 | honey_dew = 0xF0FFF0, // rgb(240,255,240)
70 | hot_pink = 0xFF69B4, // rgb(255,105,180)
71 | indian_red = 0xCD5C5C, // rgb(205,92,92)
72 | indigo = 0x4B0082, // rgb(75,0,130)
73 | ivory = 0xFFFFF0, // rgb(255,255,240)
74 | khaki = 0xF0E68C, // rgb(240,230,140)
75 | lavender = 0xE6E6FA, // rgb(230,230,250)
76 | lavender_blush = 0xFFF0F5, // rgb(255,240,245)
77 | lawn_green = 0x7CFC00, // rgb(124,252,0)
78 | lemon_chiffon = 0xFFFACD, // rgb(255,250,205)
79 | light_blue = 0xADD8E6, // rgb(173,216,230)
80 | light_coral = 0xF08080, // rgb(240,128,128)
81 | light_cyan = 0xE0FFFF, // rgb(224,255,255)
82 | light_golden_rod_yellow = 0xFAFAD2, // rgb(250,250,210)
83 | light_gray = 0xD3D3D3, // rgb(211,211,211)
84 | light_green = 0x90EE90, // rgb(144,238,144)
85 | light_pink = 0xFFB6C1, // rgb(255,182,193)
86 | light_salmon = 0xFFA07A, // rgb(255,160,122)
87 | light_sea_green = 0x20B2AA, // rgb(32,178,170)
88 | light_sky_blue = 0x87CEFA, // rgb(135,206,250)
89 | light_slate_gray = 0x778899, // rgb(119,136,153)
90 | light_steel_blue = 0xB0C4DE, // rgb(176,196,222)
91 | light_yellow = 0xFFFFE0, // rgb(255,255,224)
92 | lime = 0x00FF00, // rgb(0,255,0)
93 | lime_green = 0x32CD32, // rgb(50,205,50)
94 | linen = 0xFAF0E6, // rgb(250,240,230)
95 | magenta = 0xFF00FF, // rgb(255,0,255)
96 | maroon = 0x800000, // rgb(128,0,0)
97 | medium_aquamarine = 0x66CDAA, // rgb(102,205,170)
98 | medium_blue = 0x0000CD, // rgb(0,0,205)
99 | medium_orchid = 0xBA55D3, // rgb(186,85,211)
100 | medium_purple = 0x9370DB, // rgb(147,112,219)
101 | medium_sea_green = 0x3CB371, // rgb(60,179,113)
102 | medium_slate_blue = 0x7B68EE, // rgb(123,104,238)
103 | medium_spring_green = 0x00FA9A, // rgb(0,250,154)
104 | medium_turquoise = 0x48D1CC, // rgb(72,209,204)
105 | medium_violet_red = 0xC71585, // rgb(199,21,133)
106 | midnight_blue = 0x191970, // rgb(25,25,112)
107 | mint_cream = 0xF5FFFA, // rgb(245,255,250)
108 | misty_rose = 0xFFE4E1, // rgb(255,228,225)
109 | moccasin = 0xFFE4B5, // rgb(255,228,181)
110 | navajo_white = 0xFFDEAD, // rgb(255,222,173)
111 | navy = 0x000080, // rgb(0,0,128)
112 | old_lace = 0xFDF5E6, // rgb(253,245,230)
113 | olive = 0x808000, // rgb(128,128,0)
114 | olive_drab = 0x6B8E23, // rgb(107,142,35)
115 | orange = 0xFFA500, // rgb(255,165,0)
116 | orange_red = 0xFF4500, // rgb(255,69,0)
117 | orchid = 0xDA70D6, // rgb(218,112,214)
118 | pale_golden_rod = 0xEEE8AA, // rgb(238,232,170)
119 | pale_green = 0x98FB98, // rgb(152,251,152)
120 | pale_turquoise = 0xAFEEEE, // rgb(175,238,238)
121 | pale_violet_red = 0xDB7093, // rgb(219,112,147)
122 | papaya_whip = 0xFFEFD5, // rgb(255,239,213)
123 | peach_puff = 0xFFDAB9, // rgb(255,218,185)
124 | peru = 0xCD853F, // rgb(205,133,63)
125 | pink = 0xFFC0CB, // rgb(255,192,203)
126 | plum = 0xDDA0DD, // rgb(221,160,221)
127 | powder_blue = 0xB0E0E6, // rgb(176,224,230)
128 | purple = 0x800080, // rgb(128,0,128)
129 | rebecca_purple = 0x663399, // rgb(102,51,153)
130 | red = 0xFF0000, // rgb(255,0,0)
131 | rosy_brown = 0xBC8F8F, // rgb(188,143,143)
132 | royal_blue = 0x4169E1, // rgb(65,105,225)
133 | saddle_brown = 0x8B4513, // rgb(139,69,19)
134 | salmon = 0xFA8072, // rgb(250,128,114)
135 | sandy_brown = 0xF4A460, // rgb(244,164,96)
136 | sea_green = 0x2E8B57, // rgb(46,139,87)
137 | sea_shell = 0xFFF5EE, // rgb(255,245,238)
138 | sienna = 0xA0522D, // rgb(160,82,45)
139 | silver = 0xC0C0C0, // rgb(192,192,192)
140 | sky_blue = 0x87CEEB, // rgb(135,206,235)
141 | slate_blue = 0x6A5ACD, // rgb(106,90,205)
142 | slate_gray = 0x708090, // rgb(112,128,144)
143 | snow = 0xFFFAFA, // rgb(255,250,250)
144 | spring_green = 0x00FF7F, // rgb(0,255,127)
145 | steel_blue = 0x4682B4, // rgb(70,130,180)
146 | tan = 0xD2B48C, // rgb(210,180,140)
147 | teal = 0x008080, // rgb(0,128,128)
148 | thistle = 0xD8BFD8, // rgb(216,191,216)
149 | tomato = 0xFF6347, // rgb(255,99,71)
150 | turquoise = 0x40E0D0, // rgb(64,224,208)
151 | violet = 0xEE82EE, // rgb(238,130,238)
152 | wheat = 0xF5DEB3, // rgb(245,222,179)
153 | white = 0xFFFFFF, // rgb(255,255,255)
154 | white_smoke = 0xF5F5F5, // rgb(245,245,245)
155 | yellow = 0xFFFF00, // rgb(255,255,0)
156 | yellow_green = 0x9ACD32 // rgb(154,205,50)
157 | }; // enum class color
158 |
159 | enum class terminal_color : uint8_t {
160 | black = 30,
161 | red,
162 | green,
163 | yellow,
164 | blue,
165 | magenta,
166 | cyan,
167 | white,
168 | bright_black = 90,
169 | bright_red,
170 | bright_green,
171 | bright_yellow,
172 | bright_blue,
173 | bright_magenta,
174 | bright_cyan,
175 | bright_white
176 | };
177 |
178 | enum class emphasis : uint8_t {
179 | bold = 1,
180 | italic = 1 << 1,
181 | underline = 1 << 2,
182 | strikethrough = 1 << 3
183 | };
184 |
185 | // rgb is a struct for red, green and blue colors.
186 | // Using the name "rgb" makes some editors show the color in a tooltip.
187 | struct rgb {
188 | FMT_CONSTEXPR rgb() : r(0), g(0), b(0) {}
189 | FMT_CONSTEXPR rgb(uint8_t r_, uint8_t g_, uint8_t b_) : r(r_), g(g_), b(b_) {}
190 | FMT_CONSTEXPR rgb(uint32_t hex)
191 | : r((hex >> 16) & 0xFF), g((hex >> 8) & 0xFF), b(hex & 0xFF) {}
192 | FMT_CONSTEXPR rgb(color hex)
193 | : r((uint32_t(hex) >> 16) & 0xFF),
194 | g((uint32_t(hex) >> 8) & 0xFF),
195 | b(uint32_t(hex) & 0xFF) {}
196 | uint8_t r;
197 | uint8_t g;
198 | uint8_t b;
199 | };
200 |
201 | namespace detail {
202 |
203 | // color is a struct of either a rgb color or a terminal color.
204 | struct color_type {
205 | FMT_CONSTEXPR color_type() FMT_NOEXCEPT : is_rgb(), value{} {}
206 | FMT_CONSTEXPR color_type(color rgb_color) FMT_NOEXCEPT : is_rgb(true),
207 | value{} {
208 | value.rgb_color = static_cast(rgb_color);
209 | }
210 | FMT_CONSTEXPR color_type(rgb rgb_color) FMT_NOEXCEPT : is_rgb(true), value{} {
211 | value.rgb_color = (static_cast(rgb_color.r) << 16) |
212 | (static_cast(rgb_color.g) << 8) | rgb_color.b;
213 | }
214 | FMT_CONSTEXPR color_type(terminal_color term_color) FMT_NOEXCEPT : is_rgb(),
215 | value{} {
216 | value.term_color = static_cast(term_color);
217 | }
218 | bool is_rgb;
219 | union color_union {
220 | uint8_t term_color;
221 | uint32_t rgb_color;
222 | } value;
223 | };
224 | } // namespace detail
225 |
226 | // Experimental text formatting support.
227 | class text_style {
228 | public:
229 | FMT_CONSTEXPR text_style(emphasis em = emphasis()) FMT_NOEXCEPT
230 | : set_foreground_color(),
231 | set_background_color(),
232 | ems(em) {}
233 |
234 | FMT_CONSTEXPR text_style& operator|=(const text_style& rhs) {
235 | if (!set_foreground_color) {
236 | set_foreground_color = rhs.set_foreground_color;
237 | foreground_color = rhs.foreground_color;
238 | } else if (rhs.set_foreground_color) {
239 | if (!foreground_color.is_rgb || !rhs.foreground_color.is_rgb)
240 | FMT_THROW(format_error("can't OR a terminal color"));
241 | foreground_color.value.rgb_color |= rhs.foreground_color.value.rgb_color;
242 | }
243 |
244 | if (!set_background_color) {
245 | set_background_color = rhs.set_background_color;
246 | background_color = rhs.background_color;
247 | } else if (rhs.set_background_color) {
248 | if (!background_color.is_rgb || !rhs.background_color.is_rgb)
249 | FMT_THROW(format_error("can't OR a terminal color"));
250 | background_color.value.rgb_color |= rhs.background_color.value.rgb_color;
251 | }
252 |
253 | ems = static_cast(static_cast(ems) |
254 | static_cast(rhs.ems));
255 | return *this;
256 | }
257 |
258 | friend FMT_CONSTEXPR text_style operator|(text_style lhs,
259 | const text_style& rhs) {
260 | return lhs |= rhs;
261 | }
262 |
263 | FMT_CONSTEXPR text_style& operator&=(const text_style& rhs) {
264 | if (!set_foreground_color) {
265 | set_foreground_color = rhs.set_foreground_color;
266 | foreground_color = rhs.foreground_color;
267 | } else if (rhs.set_foreground_color) {
268 | if (!foreground_color.is_rgb || !rhs.foreground_color.is_rgb)
269 | FMT_THROW(format_error("can't AND a terminal color"));
270 | foreground_color.value.rgb_color &= rhs.foreground_color.value.rgb_color;
271 | }
272 |
273 | if (!set_background_color) {
274 | set_background_color = rhs.set_background_color;
275 | background_color = rhs.background_color;
276 | } else if (rhs.set_background_color) {
277 | if (!background_color.is_rgb || !rhs.background_color.is_rgb)
278 | FMT_THROW(format_error("can't AND a terminal color"));
279 | background_color.value.rgb_color &= rhs.background_color.value.rgb_color;
280 | }
281 |
282 | ems = static_cast(static_cast(ems) &
283 | static_cast(rhs.ems));
284 | return *this;
285 | }
286 |
287 | friend FMT_CONSTEXPR text_style operator&(text_style lhs,
288 | const text_style& rhs) {
289 | return lhs &= rhs;
290 | }
291 |
292 | FMT_CONSTEXPR bool has_foreground() const FMT_NOEXCEPT {
293 | return set_foreground_color;
294 | }
295 | FMT_CONSTEXPR bool has_background() const FMT_NOEXCEPT {
296 | return set_background_color;
297 | }
298 | FMT_CONSTEXPR bool has_emphasis() const FMT_NOEXCEPT {
299 | return static_cast(ems) != 0;
300 | }
301 | FMT_CONSTEXPR detail::color_type get_foreground() const FMT_NOEXCEPT {
302 | FMT_ASSERT(has_foreground(), "no foreground specified for this style");
303 | return foreground_color;
304 | }
305 | FMT_CONSTEXPR detail::color_type get_background() const FMT_NOEXCEPT {
306 | FMT_ASSERT(has_background(), "no background specified for this style");
307 | return background_color;
308 | }
309 | FMT_CONSTEXPR emphasis get_emphasis() const FMT_NOEXCEPT {
310 | FMT_ASSERT(has_emphasis(), "no emphasis specified for this style");
311 | return ems;
312 | }
313 |
314 | private:
315 | FMT_CONSTEXPR text_style(bool is_foreground,
316 | detail::color_type text_color) FMT_NOEXCEPT
317 | : set_foreground_color(),
318 | set_background_color(),
319 | ems() {
320 | if (is_foreground) {
321 | foreground_color = text_color;
322 | set_foreground_color = true;
323 | } else {
324 | background_color = text_color;
325 | set_background_color = true;
326 | }
327 | }
328 |
329 | friend FMT_CONSTEXPR_DECL text_style fg(detail::color_type foreground)
330 | FMT_NOEXCEPT;
331 | friend FMT_CONSTEXPR_DECL text_style bg(detail::color_type background)
332 | FMT_NOEXCEPT;
333 |
334 | detail::color_type foreground_color;
335 | detail::color_type background_color;
336 | bool set_foreground_color;
337 | bool set_background_color;
338 | emphasis ems;
339 | };
340 |
341 | FMT_CONSTEXPR text_style fg(detail::color_type foreground) FMT_NOEXCEPT {
342 | return text_style(/*is_foreground=*/true, foreground);
343 | }
344 |
345 | FMT_CONSTEXPR text_style bg(detail::color_type background) FMT_NOEXCEPT {
346 | return text_style(/*is_foreground=*/false, background);
347 | }
348 |
349 | FMT_CONSTEXPR text_style operator|(emphasis lhs, emphasis rhs) FMT_NOEXCEPT {
350 | return text_style(lhs) | rhs;
351 | }
352 |
353 | namespace detail {
354 |
355 | template struct ansi_color_escape {
356 | FMT_CONSTEXPR ansi_color_escape(detail::color_type text_color,
357 | const char* esc) FMT_NOEXCEPT {
358 | // If we have a terminal color, we need to output another escape code
359 | // sequence.
360 | if (!text_color.is_rgb) {
361 | bool is_background = esc == detail::data::background_color;
362 | uint32_t value = text_color.value.term_color;
363 | // Background ASCII codes are the same as the foreground ones but with
364 | // 10 more.
365 | if (is_background) value += 10u;
366 |
367 | size_t index = 0;
368 | buffer[index++] = static_cast('\x1b');
369 | buffer[index++] = static_cast('[');
370 |
371 | if (value >= 100u) {
372 | buffer[index++] = static_cast('1');
373 | value %= 100u;
374 | }
375 | buffer[index++] = static_cast('0' + value / 10u);
376 | buffer[index++] = static_cast('0' + value % 10u);
377 |
378 | buffer[index++] = static_cast('m');
379 | buffer[index++] = static_cast('\0');
380 | return;
381 | }
382 |
383 | for (int i = 0; i < 7; i++) {
384 | buffer[i] = static_cast(esc[i]);
385 | }
386 | rgb color(text_color.value.rgb_color);
387 | to_esc(color.r, buffer + 7, ';');
388 | to_esc(color.g, buffer + 11, ';');
389 | to_esc(color.b, buffer + 15, 'm');
390 | buffer[19] = static_cast(0);
391 | }
392 | FMT_CONSTEXPR ansi_color_escape(emphasis em) FMT_NOEXCEPT {
393 | uint8_t em_codes[4] = {};
394 | uint8_t em_bits = static_cast(em);
395 | if (em_bits & static_cast(emphasis::bold)) em_codes[0] = 1;
396 | if (em_bits & static_cast(emphasis::italic)) em_codes[1] = 3;
397 | if (em_bits & static_cast(emphasis::underline)) em_codes[2] = 4;
398 | if (em_bits & static_cast(emphasis::strikethrough))
399 | em_codes[3] = 9;
400 |
401 | size_t index = 0;
402 | for (int i = 0; i < 4; ++i) {
403 | if (!em_codes[i]) continue;
404 | buffer[index++] = static_cast('\x1b');
405 | buffer[index++] = static_cast('[');
406 | buffer[index++] = static_cast('0' + em_codes[i]);
407 | buffer[index++] = static_cast('m');
408 | }
409 | buffer[index++] = static_cast(0);
410 | }
411 | FMT_CONSTEXPR operator const Char*() const FMT_NOEXCEPT { return buffer; }
412 |
413 | FMT_CONSTEXPR const Char* begin() const FMT_NOEXCEPT { return buffer; }
414 | FMT_CONSTEXPR const Char* end() const FMT_NOEXCEPT {
415 | return buffer + std::char_traits::length(buffer);
416 | }
417 |
418 | private:
419 | Char buffer[7u + 3u * 4u + 1u];
420 |
421 | static FMT_CONSTEXPR void to_esc(uint8_t c, Char* out,
422 | char delimiter) FMT_NOEXCEPT {
423 | out[0] = static_cast('0' + c / 100);
424 | out[1] = static_cast('0' + c / 10 % 10);
425 | out[2] = static_cast('0' + c % 10);
426 | out[3] = static_cast(delimiter);
427 | }
428 | };
429 |
430 | template
431 | FMT_CONSTEXPR ansi_color_escape make_foreground_color(
432 | detail::color_type foreground) FMT_NOEXCEPT {
433 | return ansi_color_escape(foreground, detail::data::foreground_color);
434 | }
435 |
436 | template
437 | FMT_CONSTEXPR ansi_color_escape make_background_color(
438 | detail::color_type background) FMT_NOEXCEPT {
439 | return ansi_color_escape(background, detail::data::background_color);
440 | }
441 |
442 | template
443 | FMT_CONSTEXPR ansi_color_escape make_emphasis(emphasis em) FMT_NOEXCEPT {
444 | return ansi_color_escape(em);
445 | }
446 |
447 | template
448 | inline void fputs(const Char* chars, FILE* stream) FMT_NOEXCEPT {
449 | std::fputs(chars, stream);
450 | }
451 |
452 | template <>
453 | inline void fputs(const wchar_t* chars, FILE* stream) FMT_NOEXCEPT {
454 | std::fputws(chars, stream);
455 | }
456 |
457 | template inline void reset_color(FILE* stream) FMT_NOEXCEPT {
458 | fputs(detail::data::reset_color, stream);
459 | }
460 |
461 | template <> inline void reset_color(FILE* stream) FMT_NOEXCEPT {
462 | fputs(detail::data::wreset_color, stream);
463 | }
464 |
465 | template
466 | inline void reset_color(basic_memory_buffer& buffer) FMT_NOEXCEPT {
467 | const char* begin = data::reset_color;
468 | const char* end = begin + sizeof(data::reset_color) - 1;
469 | buffer.append(begin, end);
470 | }
471 |
472 | template
473 | void vformat_to(basic_memory_buffer& buf, const text_style& ts,
474 | basic_string_view format_str,
475 | basic_format_args> args) {
476 | bool has_style = false;
477 | if (ts.has_emphasis()) {
478 | has_style = true;
479 | auto emphasis = detail::make_emphasis(ts.get_emphasis());
480 | buf.append(emphasis.begin(), emphasis.end());
481 | }
482 | if (ts.has_foreground()) {
483 | has_style = true;
484 | auto foreground = detail::make_foreground_color(ts.get_foreground());
485 | buf.append(foreground.begin(), foreground.end());
486 | }
487 | if (ts.has_background()) {
488 | has_style = true;
489 | auto background = detail::make_background_color(ts.get_background());
490 | buf.append(background.begin(), background.end());
491 | }
492 | detail::vformat_to(buf, format_str, args);
493 | if (has_style) detail::reset_color(buf);
494 | }
495 | } // namespace detail
496 |
497 | template >
498 | void vprint(std::FILE* f, const text_style& ts, const S& format,
499 | basic_format_args> args) {
500 | basic_memory_buffer buf;
501 | detail::vformat_to(buf, ts, to_string_view(format), args);
502 | buf.push_back(Char(0));
503 | detail::fputs(buf.data(), f);
504 | }
505 |
506 | /**
507 | Formats a string and prints it to the specified file stream using ANSI
508 | escape sequences to specify text formatting.
509 | Example:
510 | fmt::print(fmt::emphasis::bold | fg(fmt::color::red),
511 | "Elapsed time: {0:.2f} seconds", 1.23);
512 | */
513 | template ::value)>
515 | void print(std::FILE* f, const text_style& ts, const S& format_str,
516 | const Args&... args) {
517 | detail::check_format_string(format_str);
518 | using context = buffer_context>;
519 | format_arg_store as{args...};
520 | vprint(f, ts, format_str, basic_format_args(as));
521 | }
522 |
523 | /**
524 | Formats a string and prints it to stdout using ANSI escape sequences to
525 | specify text formatting.
526 | Example:
527 | fmt::print(fmt::emphasis::bold | fg(fmt::color::red),
528 | "Elapsed time: {0:.2f} seconds", 1.23);
529 | */
530 | template ::value)>
532 | void print(const text_style& ts, const S& format_str, const Args&... args) {
533 | return print(stdout, ts, format_str, args...);
534 | }
535 |
536 | template >
537 | inline std::basic_string vformat(
538 | const text_style& ts, const S& format_str,
539 | basic_format_args>> args) {
540 | basic_memory_buffer buf;
541 | detail::vformat_to(buf, ts, to_string_view(format_str), args);
542 | return fmt::to_string(buf);
543 | }
544 |
545 | /**
546 | \rst
547 | Formats arguments and returns the result as a string using ANSI
548 | escape sequences to specify text formatting.
549 |
550 | **Example**::
551 |
552 | #include
553 | std::string message = fmt::format(fmt::emphasis::bold | fg(fmt::color::red),
554 | "The answer is {}", 42);
555 | \endrst
556 | */
557 | template >
558 | inline std::basic_string format(const text_style& ts, const S& format_str,
559 | const Args&... args) {
560 | return vformat(ts, to_string_view(format_str),
561 | detail::make_args_checked(format_str, args...));
562 | }
563 |
564 | FMT_END_NAMESPACE
565 |
566 | #endif // FMT_COLOR_H_
567 |
--------------------------------------------------------------------------------
/mysql_modern_cpp/fmt/locale.h:
--------------------------------------------------------------------------------
1 | // Formatting library for C++ - std::locale support
2 | //
3 | // Copyright (c) 2012 - present, Victor Zverovich
4 | // All rights reserved.
5 | //
6 | // For the license information refer to format.h.
7 |
8 | #ifndef FMT_LOCALE_H_
9 | #define FMT_LOCALE_H_
10 |
11 | #include
12 |
13 | #include "format.h"
14 |
15 | FMT_BEGIN_NAMESPACE
16 |
17 | namespace detail {
18 | template
19 | typename buffer_context::iterator vformat_to(
20 | const std::locale& loc, buffer& buf,
21 | basic_string_view format_str,
22 | basic_format_args>> args) {
23 | using af = arg_formatter::iterator, Char>;
24 | return vformat_to(std::back_inserter(buf), to_string_view(format_str),
25 | args, detail::locale_ref(loc));
26 | }
27 |
28 | template
29 | std::basic_string vformat(
30 | const std::locale& loc, basic_string_view format_str,
31 | basic_format_args>> args) {
32 | basic_memory_buffer buffer;
33 | detail::vformat_to(loc, buffer, format_str, args);
34 | return fmt::to_string(buffer);
35 | }
36 | } // namespace detail
37 |
38 | template >
39 | inline std::basic_string vformat(
40 | const std::locale& loc, const S& format_str,
41 | basic_format_args>> args) {
42 | return detail::vformat(loc, to_string_view(format_str), args);
43 | }
44 |
45 | template >
46 | inline std::basic_string format(const std::locale& loc,
47 | const S& format_str, Args&&... args) {
48 | return detail::vformat(
49 | loc, to_string_view(format_str),
50 | detail::make_args_checked(format_str, args...));
51 | }
52 |
53 | template ::value, char_t>>
56 | inline OutputIt vformat_to(
57 | OutputIt out, const std::locale& loc, const S& format_str,
58 | format_args_t, Char> args) {
59 | using af = detail::arg_formatter;
60 | return vformat_to(out, to_string_view(format_str), args,
61 | detail::locale_ref(loc));
62 | }
63 |
64 | template ::value&&
66 | detail::is_string::value)>
67 | inline OutputIt format_to(OutputIt out, const std::locale& loc,
68 | const S& format_str, Args&&... args) {
69 | detail::check_format_string(format_str);
70 | using context = format_context_t>;
71 | format_arg_store as{args...};
72 | return vformat_to(out, loc, to_string_view(format_str),
73 | basic_format_args(as));
74 | }
75 |
76 | FMT_END_NAMESPACE
77 |
78 | #endif // FMT_LOCALE_H_
79 |
--------------------------------------------------------------------------------
/mysql_modern_cpp/fmt/os.h:
--------------------------------------------------------------------------------
1 | // Formatting library for C++ - optional OS-specific functionality
2 | //
3 | // Copyright (c) 2012 - present, Victor Zverovich
4 | // All rights reserved.
5 | //
6 | // For the license information refer to format.h.
7 |
8 | #ifndef FMT_OS_H_
9 | #define FMT_OS_H_
10 |
11 | #if defined(__MINGW32__) || defined(__CYGWIN__)
12 | // Workaround MinGW bug https://sourceforge.net/p/mingw/bugs/2024/.
13 | # undef __STRICT_ANSI__
14 | #endif
15 |
16 | #include
17 | #include // for locale_t
18 | #include
19 | #include
20 | #include // for strtod_l
21 |
22 | #if defined __APPLE__ || defined(__FreeBSD__)
23 | # include // for LC_NUMERIC_MASK on OS X
24 | #endif
25 |
26 | #include "format.h"
27 |
28 | // UWP doesn't provide _pipe.
29 | #if FMT_HAS_INCLUDE("winapifamily.h")
30 | # include
31 | #endif
32 | #if FMT_HAS_INCLUDE("fcntl.h") && \
33 | (!defined(WINAPI_FAMILY) || (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP))
34 | # include // for O_RDONLY
35 | # define FMT_USE_FCNTL 1
36 | #else
37 | # define FMT_USE_FCNTL 0
38 | #endif
39 |
40 | #ifndef FMT_POSIX
41 | # if defined(_WIN32) && !defined(__MINGW32__)
42 | // Fix warnings about deprecated symbols.
43 | # define FMT_POSIX(call) _##call
44 | # else
45 | # define FMT_POSIX(call) call
46 | # endif
47 | #endif
48 |
49 | // Calls to system functions are wrapped in FMT_SYSTEM for testability.
50 | #ifdef FMT_SYSTEM
51 | # define FMT_POSIX_CALL(call) FMT_SYSTEM(call)
52 | #else
53 | # define FMT_SYSTEM(call) ::call
54 | # ifdef _WIN32
55 | // Fix warnings about deprecated symbols.
56 | # define FMT_POSIX_CALL(call) ::_##call
57 | # else
58 | # define FMT_POSIX_CALL(call) ::call
59 | # endif
60 | #endif
61 |
62 | // Retries the expression while it evaluates to error_result and errno
63 | // equals to EINTR.
64 | #ifndef _WIN32
65 | # define FMT_RETRY_VAL(result, expression, error_result) \
66 | do { \
67 | (result) = (expression); \
68 | } while ((result) == (error_result) && errno == EINTR)
69 | #else
70 | # define FMT_RETRY_VAL(result, expression, error_result) result = (expression)
71 | #endif
72 |
73 | #define FMT_RETRY(result, expression) FMT_RETRY_VAL(result, expression, -1)
74 |
75 | FMT_BEGIN_NAMESPACE
76 |
77 | /**
78 | \rst
79 | A reference to a null-terminated string. It can be constructed from a C
80 | string or ``std::string``.
81 |
82 | You can use one of the following type aliases for common character types:
83 |
84 | +---------------+-----------------------------+
85 | | Type | Definition |
86 | +===============+=============================+
87 | | cstring_view | basic_cstring_view |
88 | +---------------+-----------------------------+
89 | | wcstring_view | basic_cstring_view |
90 | +---------------+-----------------------------+
91 |
92 | This class is most useful as a parameter type to allow passing
93 | different types of strings to a function, for example::
94 |
95 | template
96 | std::string format(cstring_view format_str, const Args & ... args);
97 |
98 | format("{}", 42);
99 | format(std::string("{}"), 42);
100 | \endrst
101 | */
102 | template class basic_cstring_view {
103 | private:
104 | const Char* data_;
105 |
106 | public:
107 | /** Constructs a string reference object from a C string. */
108 | basic_cstring_view(const Char* s) : data_(s) {}
109 |
110 | /**
111 | \rst
112 | Constructs a string reference from an ``std::string`` object.
113 | \endrst
114 | */
115 | basic_cstring_view(const std::basic_string& s) : data_(s.c_str()) {}
116 |
117 | /** Returns the pointer to a C string. */
118 | const Char* c_str() const { return data_; }
119 | };
120 |
121 | using cstring_view = basic_cstring_view;
122 | using wcstring_view = basic_cstring_view;
123 |
124 | // An error code.
125 | class error_code {
126 | private:
127 | int value_;
128 |
129 | public:
130 | explicit error_code(int value = 0) FMT_NOEXCEPT : value_(value) {}
131 |
132 | int get() const FMT_NOEXCEPT { return value_; }
133 | };
134 |
135 | #ifdef _WIN32
136 | namespace detail {
137 | // A converter from UTF-16 to UTF-8.
138 | // It is only provided for Windows since other systems support UTF-8 natively.
139 | class utf16_to_utf8 {
140 | private:
141 | memory_buffer buffer_;
142 |
143 | public:
144 | utf16_to_utf8() {}
145 | FMT_API explicit utf16_to_utf8(wstring_view s);
146 | operator string_view() const { return string_view(&buffer_[0], size()); }
147 | size_t size() const { return buffer_.size() - 1; }
148 | const char* c_str() const { return &buffer_[0]; }
149 | std::string str() const { return std::string(&buffer_[0], size()); }
150 |
151 | // Performs conversion returning a system error code instead of
152 | // throwing exception on conversion error. This method may still throw
153 | // in case of memory allocation error.
154 | FMT_API int convert(wstring_view s);
155 | };
156 |
157 | FMT_API void format_windows_error(buffer& out, int error_code,
158 | string_view message) FMT_NOEXCEPT;
159 | } // namespace detail
160 |
161 | /** A Windows error. */
162 | class windows_error : public system_error {
163 | private:
164 | FMT_API void init(int error_code, string_view format_str, format_args args);
165 |
166 | public:
167 | /**
168 | \rst
169 | Constructs a :class:`fmt::windows_error` object with the description
170 | of the form
171 |
172 | .. parsed-literal::
173 | **: **
174 |
175 | where ** is the formatted message and ** is the
176 | system message corresponding to the error code.
177 | *error_code* is a Windows error code as given by ``GetLastError``.
178 | If *error_code* is not a valid error code such as -1, the system message
179 | will look like "error -1".
180 |
181 | **Example**::
182 |
183 | // This throws a windows_error with the description
184 | // cannot open file 'madeup': The system cannot find the file specified.
185 | // or similar (system message may vary).
186 | const char *filename = "madeup";
187 | LPOFSTRUCT of = LPOFSTRUCT();
188 | HFILE file = OpenFile(filename, &of, OF_READ);
189 | if (file == HFILE_ERROR) {
190 | throw fmt::windows_error(GetLastError(),
191 | "cannot open file '{}'", filename);
192 | }
193 | \endrst
194 | */
195 | template
196 | windows_error(int error_code, string_view message, const Args&... args) {
197 | init(error_code, message, make_format_args(args...));
198 | }
199 | };
200 |
201 | // Reports a Windows error without throwing an exception.
202 | // Can be used to report errors from destructors.
203 | FMT_API void report_windows_error(int error_code,
204 | string_view message) FMT_NOEXCEPT;
205 | #endif // _WIN32
206 |
207 | // A buffered file.
208 | class buffered_file {
209 | private:
210 | FILE* file_;
211 |
212 | friend class file;
213 |
214 | explicit buffered_file(FILE* f) : file_(f) {}
215 |
216 | public:
217 | buffered_file(const buffered_file&) = delete;
218 | void operator=(const buffered_file&) = delete;
219 |
220 | // Constructs a buffered_file object which doesn't represent any file.
221 | buffered_file() FMT_NOEXCEPT : file_(nullptr) {}
222 |
223 | // Destroys the object closing the file it represents if any.
224 | FMT_API ~buffered_file() FMT_NOEXCEPT;
225 |
226 | public:
227 | buffered_file(buffered_file&& other) FMT_NOEXCEPT : file_(other.file_) {
228 | other.file_ = nullptr;
229 | }
230 |
231 | buffered_file& operator=(buffered_file&& other) {
232 | close();
233 | file_ = other.file_;
234 | other.file_ = nullptr;
235 | return *this;
236 | }
237 |
238 | // Opens a file.
239 | FMT_API buffered_file(cstring_view filename, cstring_view mode);
240 |
241 | // Closes the file.
242 | FMT_API void close();
243 |
244 | // Returns the pointer to a FILE object representing this file.
245 | FILE* get() const FMT_NOEXCEPT { return file_; }
246 |
247 | // We place parentheses around fileno to workaround a bug in some versions
248 | // of MinGW that define fileno as a macro.
249 | FMT_API int(fileno)() const;
250 |
251 | void vprint(string_view format_str, format_args args) {
252 | fmt::vprint(file_, format_str, args);
253 | }
254 |
255 | template
256 | inline void print(string_view format_str, const Args&... args) {
257 | vprint(format_str, make_format_args(args...));
258 | }
259 | };
260 |
261 | #if FMT_USE_FCNTL
262 | // A file. Closed file is represented by a file object with descriptor -1.
263 | // Methods that are not declared with FMT_NOEXCEPT may throw
264 | // fmt::system_error in case of failure. Note that some errors such as
265 | // closing the file multiple times will cause a crash on Windows rather
266 | // than an exception. You can get standard behavior by overriding the
267 | // invalid parameter handler with _set_invalid_parameter_handler.
268 | class file {
269 | private:
270 | int fd_; // File descriptor.
271 |
272 | // Constructs a file object with a given descriptor.
273 | explicit file(int fd) : fd_(fd) {}
274 |
275 | public:
276 | // Possible values for the oflag argument to the constructor.
277 | enum {
278 | RDONLY = FMT_POSIX(O_RDONLY), // Open for reading only.
279 | WRONLY = FMT_POSIX(O_WRONLY), // Open for writing only.
280 | RDWR = FMT_POSIX(O_RDWR), // Open for reading and writing.
281 | CREATE = FMT_POSIX(O_CREAT) // Create if the file doesn't exist.
282 | };
283 |
284 | // Constructs a file object which doesn't represent any file.
285 | file() FMT_NOEXCEPT : fd_(-1) {}
286 |
287 | // Opens a file and constructs a file object representing this file.
288 | FMT_API file(cstring_view path, int oflag);
289 |
290 | public:
291 | file(const file&) = delete;
292 | void operator=(const file&) = delete;
293 |
294 | file(file&& other) FMT_NOEXCEPT : fd_(other.fd_) { other.fd_ = -1; }
295 |
296 | file& operator=(file&& other) FMT_NOEXCEPT {
297 | close();
298 | fd_ = other.fd_;
299 | other.fd_ = -1;
300 | return *this;
301 | }
302 |
303 | // Destroys the object closing the file it represents if any.
304 | FMT_API ~file() FMT_NOEXCEPT;
305 |
306 | // Returns the file descriptor.
307 | int descriptor() const FMT_NOEXCEPT { return fd_; }
308 |
309 | // Closes the file.
310 | FMT_API void close();
311 |
312 | // Returns the file size. The size has signed type for consistency with
313 | // stat::st_size.
314 | FMT_API long long size() const;
315 |
316 | // Attempts to read count bytes from the file into the specified buffer.
317 | FMT_API size_t read(void* buffer, size_t count);
318 |
319 | // Attempts to write count bytes from the specified buffer to the file.
320 | FMT_API size_t write(const void* buffer, size_t count);
321 |
322 | // Duplicates a file descriptor with the dup function and returns
323 | // the duplicate as a file object.
324 | FMT_API static file dup(int fd);
325 |
326 | // Makes fd be the copy of this file descriptor, closing fd first if
327 | // necessary.
328 | FMT_API void dup2(int fd);
329 |
330 | // Makes fd be the copy of this file descriptor, closing fd first if
331 | // necessary.
332 | FMT_API void dup2(int fd, error_code& ec) FMT_NOEXCEPT;
333 |
334 | // Creates a pipe setting up read_end and write_end file objects for reading
335 | // and writing respectively.
336 | FMT_API static void pipe(file& read_end, file& write_end);
337 |
338 | // Creates a buffered_file object associated with this file and detaches
339 | // this file object from the file.
340 | FMT_API buffered_file fdopen(const char* mode);
341 | };
342 |
343 | // Returns the memory page size.
344 | long getpagesize();
345 |
346 | class direct_buffered_file;
347 |
348 | template
349 | void print(direct_buffered_file& f, const S& format_str,
350 | const Args&... args);
351 |
352 | // A buffered file with a direct buffer access and no synchronization.
353 | class direct_buffered_file {
354 | private:
355 | file file_;
356 |
357 | enum { buffer_size = 4096 };
358 | char buffer_[buffer_size];
359 | int pos_;
360 |
361 | void flush() {
362 | if (pos_ == 0) return;
363 | file_.write(buffer_, pos_);
364 | pos_ = 0;
365 | }
366 |
367 | int free_capacity() const { return buffer_size - pos_; }
368 |
369 | public:
370 | direct_buffered_file(cstring_view path, int oflag)
371 | : file_(path, oflag), pos_(0) {}
372 |
373 | ~direct_buffered_file() {
374 | flush();
375 | }
376 |
377 | void close() {
378 | flush();
379 | file_.close();
380 | }
381 |
382 | template
383 | friend void print(direct_buffered_file& f, const S& format_str,
384 | const Args&... args) {
385 | // We could avoid double buffering.
386 | auto buf = fmt::memory_buffer();
387 | fmt::format_to(std::back_inserter(buf), format_str, args...);
388 | auto remaining_pos = 0;
389 | auto remaining_size = buf.size();
390 | while (remaining_size > detail::to_unsigned(f.free_capacity())) {
391 | auto size = f.free_capacity();
392 | memcpy(f.buffer_ + f.pos_, buf.data() + remaining_pos, size);
393 | f.pos_ += size;
394 | f.flush();
395 | remaining_pos += size;
396 | remaining_size -= size;
397 | }
398 | memcpy(f.buffer_ + f.pos_, buf.data() + remaining_pos, remaining_size);
399 | f.pos_ += static_cast(remaining_size);
400 | }
401 | };
402 | #endif // FMT_USE_FCNTL
403 |
404 | #ifdef FMT_LOCALE
405 | // A "C" numeric locale.
406 | class locale {
407 | private:
408 | # ifdef _WIN32
409 | using locale_t = _locale_t;
410 |
411 | static void freelocale(locale_t loc) { _free_locale(loc); }
412 |
413 | static double strtod_l(const char* nptr, char** endptr, _locale_t loc) {
414 | return _strtod_l(nptr, endptr, loc);
415 | }
416 | # endif
417 |
418 | locale_t locale_;
419 |
420 | public:
421 | using type = locale_t;
422 | locale(const locale&) = delete;
423 | void operator=(const locale&) = delete;
424 |
425 | locale() {
426 | # ifndef _WIN32
427 | locale_ = FMT_SYSTEM(newlocale(LC_NUMERIC_MASK, "C", nullptr));
428 | # else
429 | locale_ = _create_locale(LC_NUMERIC, "C");
430 | # endif
431 | if (!locale_) FMT_THROW(system_error(errno, "cannot create locale"));
432 | }
433 | ~locale() { freelocale(locale_); }
434 |
435 | type get() const { return locale_; }
436 |
437 | // Converts string to floating-point number and advances str past the end
438 | // of the parsed input.
439 | double strtod(const char*& str) const {
440 | char* end = nullptr;
441 | double result = strtod_l(str, &end, locale_);
442 | str = end;
443 | return result;
444 | }
445 | };
446 | using Locale FMT_DEPRECATED_ALIAS = locale;
447 | #endif // FMT_LOCALE
448 | FMT_END_NAMESPACE
449 |
450 | #endif // FMT_OS_H_
451 |
--------------------------------------------------------------------------------
/mysql_modern_cpp/fmt/ostream.h:
--------------------------------------------------------------------------------
1 | // Formatting library for C++ - std::ostream support
2 | //
3 | // Copyright (c) 2012 - present, Victor Zverovich
4 | // All rights reserved.
5 | //
6 | // For the license information refer to format.h.
7 |
8 | #ifndef FMT_OSTREAM_H_
9 | #define FMT_OSTREAM_H_
10 |
11 | #include
12 |
13 | #include "format.h"
14 |
15 | FMT_BEGIN_NAMESPACE
16 |
17 | template class basic_printf_parse_context;
18 | template class basic_printf_context;
19 |
20 | namespace detail {
21 |
22 | template class formatbuf : public std::basic_streambuf {
23 | private:
24 | using int_type = typename std::basic_streambuf::int_type;
25 | using traits_type = typename std::basic_streambuf::traits_type;
26 |
27 | buffer& buffer_;
28 |
29 | public:
30 | formatbuf(buffer& buf) : buffer_(buf) {}
31 |
32 | protected:
33 | // The put-area is actually always empty. This makes the implementation
34 | // simpler and has the advantage that the streambuf and the buffer are always
35 | // in sync and sputc never writes into uninitialized memory. The obvious
36 | // disadvantage is that each call to sputc always results in a (virtual) call
37 | // to overflow. There is no disadvantage here for sputn since this always
38 | // results in a call to xsputn.
39 |
40 | int_type overflow(int_type ch = traits_type::eof()) FMT_OVERRIDE {
41 | if (!traits_type::eq_int_type(ch, traits_type::eof()))
42 | buffer_.push_back(static_cast(ch));
43 | return ch;
44 | }
45 |
46 | std::streamsize xsputn(const Char* s, std::streamsize count) FMT_OVERRIDE {
47 | buffer_.append(s, s + count);
48 | return count;
49 | }
50 | };
51 |
52 | template struct test_stream : std::basic_ostream {
53 | private:
54 | // Hide all operator<< from std::basic_ostream.
55 | void_t<> operator<<(null<>);
56 | void_t<> operator<<(const Char*);
57 |
58 | template ::value &&
59 | !std::is_enum::value)>
60 | void_t<> operator<<(T);
61 | };
62 |
63 | // Checks if T has a user-defined operator<< (e.g. not a member of
64 | // std::ostream).
65 | template class is_streamable {
66 | private:
67 | template
68 | static bool_constant&>()
69 | << std::declval()),
70 | void_t<>>::value>
71 | test(int);
72 |
73 | template static std::false_type test(...);
74 |
75 | using result = decltype(test(0));
76 |
77 | public:
78 | static const bool value = result::value;
79 | };
80 |
81 | // Write the content of buf to os.
82 | template
83 | void write_buffer(std::basic_ostream& os, buffer& buf) {
84 | const Char* buf_data = buf.data();
85 | using unsigned_streamsize = std::make_unsigned::type;
86 | unsigned_streamsize size = buf.size();
87 | unsigned_streamsize max_size = to_unsigned(max_value());
88 | do {
89 | unsigned_streamsize n = size <= max_size ? size : max_size;
90 | os.write(buf_data, static_cast(n));
91 | buf_data += n;
92 | size -= n;
93 | } while (size != 0);
94 | }
95 |
96 | template
97 | void format_value(buffer& buf, const T& value,
98 | locale_ref loc = locale_ref()) {
99 | formatbuf format_buf(buf);
100 | std::basic_ostream output(&format_buf);
101 | #if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
102 | if (loc) output.imbue(loc.get());
103 | #endif
104 | output << value;
105 | output.exceptions(std::ios_base::failbit | std::ios_base::badbit);
106 | buf.resize(buf.size());
107 | }
108 |
109 | // Formats an object of type T that has an overloaded ostream operator<<.
110 | template
111 | struct fallback_formatter::value>>
112 | : private formatter, Char> {
113 | FMT_CONSTEXPR auto parse(basic_format_parse_context& ctx)
114 | -> decltype(ctx.begin()) {
115 | return formatter, Char>::parse(ctx);
116 | }
117 | template >::value)>
120 | auto parse(ParseCtx& ctx) -> decltype(ctx.begin()) {
121 | return ctx.begin();
122 | }
123 |
124 | template
125 | auto format(const T& value, basic_format_context& ctx)
126 | -> OutputIt {
127 | basic_memory_buffer buffer;
128 | format_value(buffer, value, ctx.locale());
129 | basic_string_view str(buffer.data(), buffer.size());
130 | return formatter, Char>::format(str, ctx);
131 | }
132 | template
133 | auto format(const T& value, basic_printf_context& ctx)
134 | -> OutputIt {
135 | basic_memory_buffer buffer;
136 | format_value(buffer, value, ctx.locale());
137 | return std::copy(buffer.begin(), buffer.end(), ctx.out());
138 | }
139 | };
140 | } // namespace detail
141 |
142 | template
143 | void vprint(std::basic_ostream& os, basic_string_view format_str,
144 | basic_format_args>> args) {
145 | basic_memory_buffer buffer;
146 | detail::vformat_to(buffer, format_str, args);
147 | detail::write_buffer(os, buffer);
148 | }
149 |
150 | /**
151 | \rst
152 | Prints formatted data to the stream *os*.
153 |
154 | **Example**::
155 |
156 | fmt::print(cerr, "Don't {}!", "panic");
157 | \endrst
158 | */
159 | template ::value, char_t>>
161 | void print(std::basic_ostream& os, const S& format_str, Args&&... args) {
162 | vprint(os, to_string_view(format_str),
163 | detail::make_args_checked(format_str, args...));
164 | }
165 | FMT_END_NAMESPACE
166 |
167 | #endif // FMT_OSTREAM_H_
168 |
--------------------------------------------------------------------------------
/mysql_modern_cpp/fmt/posix.h:
--------------------------------------------------------------------------------
1 | #include "os.h"
2 | #warning "fmt/posix.h is deprecated; use fmt/os.h instead"
3 |
--------------------------------------------------------------------------------
/mysql_modern_cpp/fmt/ranges.h:
--------------------------------------------------------------------------------
1 | // Formatting library for C++ - experimental range support
2 | //
3 | // Copyright (c) 2012 - present, Victor Zverovich
4 | // All rights reserved.
5 | //
6 | // For the license information refer to format.h.
7 | //
8 | // Copyright (c) 2018 - present, Remotion (Igor Schulz)
9 | // All Rights Reserved
10 | // {fmt} support for ranges, containers and types tuple interface.
11 |
12 | #ifndef FMT_RANGES_H_
13 | #define FMT_RANGES_H_
14 |
15 | #include
16 | #include
17 |
18 | #include "format.h"
19 |
20 | // output only up to N items from the range.
21 | #ifndef FMT_RANGE_OUTPUT_LENGTH_LIMIT
22 | # define FMT_RANGE_OUTPUT_LENGTH_LIMIT 256
23 | #endif
24 |
25 | FMT_BEGIN_NAMESPACE
26 |
27 | template struct formatting_base {
28 | template
29 | FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
30 | return ctx.begin();
31 | }
32 | };
33 |
34 | template
35 | struct formatting_range : formatting_base {
36 | static FMT_CONSTEXPR_DECL const size_t range_length_limit =
37 | FMT_RANGE_OUTPUT_LENGTH_LIMIT; // output only up to N items from the
38 | // range.
39 | Char prefix;
40 | Char delimiter;
41 | Char postfix;
42 | formatting_range() : prefix('{'), delimiter(','), postfix('}') {}
43 | static FMT_CONSTEXPR_DECL const bool add_delimiter_spaces = true;
44 | static FMT_CONSTEXPR_DECL const bool add_prepostfix_space = false;
45 | };
46 |
47 | template
48 | struct formatting_tuple : formatting_base {
49 | Char prefix;
50 | Char delimiter;
51 | Char postfix;
52 | formatting_tuple() : prefix('('), delimiter(','), postfix(')') {}
53 | static FMT_CONSTEXPR_DECL const bool add_delimiter_spaces = true;
54 | static FMT_CONSTEXPR_DECL const bool add_prepostfix_space = false;
55 | };
56 |
57 | namespace detail {
58 |
59 | template
60 | OutputIterator copy(const RangeT& range, OutputIterator out) {
61 | for (auto it = range.begin(), end = range.end(); it != end; ++it)
62 | *out++ = *it;
63 | return out;
64 | }
65 |
66 | template
67 | OutputIterator copy(const char* str, OutputIterator out) {
68 | while (*str) *out++ = *str++;
69 | return out;
70 | }
71 |
72 | template
73 | OutputIterator copy(char ch, OutputIterator out) {
74 | *out++ = ch;
75 | return out;
76 | }
77 |
78 | /// Return true value if T has std::string interface, like std::string_view.
79 | template class is_like_std_string {
80 | template
81 | static auto (check)(U* p)
82 | -> decltype((void)p->find('a'), p->length(), (void)p->data(), int());
83 | template static void (check)(...);
84 |
85 | public:
86 | static FMT_CONSTEXPR_DECL const bool value =
87 | is_string::value || !std::is_void(nullptr))>::value;
88 | };
89 |
90 | template
91 | struct is_like_std_string> : std::true_type {};
92 |
93 | template struct conditional_helper {};
94 |
95 | template struct is_range_ : std::false_type {};
96 |
97 | #if !FMT_MSC_VER || FMT_MSC_VER > 1800
98 | template
99 | struct is_range_<
100 | T, conditional_t().begin()),
102 | decltype(std::declval().end())>,
103 | void>> : std::true_type {};
104 | #endif
105 |
106 | /// tuple_size and tuple_element check.
107 | template class is_tuple_like_ {
108 | template
109 | static auto (check)(U* p) -> decltype(std::tuple_size::value, int());
110 | template static void (check)(...);
111 |
112 | public:
113 | static FMT_CONSTEXPR_DECL const bool value =
114 | !std::is_void(nullptr))>::value;
115 | };
116 |
117 | // Check for integer_sequence
118 | #if defined(__cpp_lib_integer_sequence) || FMT_MSC_VER >= 1900
119 | template
120 | using integer_sequence = std::integer_sequence;
121 | template using index_sequence = std::index_sequence;
122 | template using make_index_sequence = std::make_index_sequence;
123 | #else
124 | template struct integer_sequence {
125 | using value_type = T;
126 |
127 | static FMT_CONSTEXPR size_t size() { return sizeof...(N); }
128 | };
129 |
130 | template using index_sequence = integer_sequence;
131 |
132 | template
133 | struct make_integer_sequence : make_integer_sequence {};
134 | template
135 | struct make_integer_sequence : integer_sequence {};
136 |
137 | template
138 | using make_index_sequence = make_integer_sequence;
139 | #endif
140 |
141 | template
142 | void for_each(index_sequence, Tuple&& tup, F&& f) FMT_NOEXCEPT {
143 | using std::get;
144 | // using free function get(T) now.
145 | const int _[] = {0, ((void)f(get(tup)), 0)...};
146 | (void)_; // blocks warnings
147 | }
148 |
149 | template
150 | FMT_CONSTEXPR make_index_sequence::value> get_indexes(
151 | T const&) {
152 | return {};
153 | }
154 |
155 | template void for_each(Tuple&& tup, F&& f) {
156 | const auto indexes = get_indexes(tup);
157 | for_each(indexes, std::forward(tup), std::forward(f));
158 | }
159 |
160 | template ::type>::value)>
162 | FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const Arg&) {
163 | return add_space ? " {}" : "{}";
164 | }
165 |
166 | template ::type>::value)>
168 | FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const Arg&) {
169 | return add_space ? " \"{}\"" : "\"{}\"";
170 | }
171 |
172 | FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const char*) {
173 | return add_space ? " \"{}\"" : "\"{}\"";
174 | }
175 | FMT_CONSTEXPR const wchar_t* format_str_quoted(bool add_space, const wchar_t*) {
176 | return add_space ? L" \"{}\"" : L"\"{}\"";
177 | }
178 |
179 | FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const char) {
180 | return add_space ? " '{}'" : "'{}'";
181 | }
182 | FMT_CONSTEXPR const wchar_t* format_str_quoted(bool add_space, const wchar_t) {
183 | return add_space ? L" '{}'" : L"'{}'";
184 | }
185 |
186 | } // namespace detail
187 |
188 | template struct is_tuple_like {
189 | static FMT_CONSTEXPR_DECL const bool value =
190 | detail::is_tuple_like_::value && !detail::is_range_::value;
191 | };
192 |
193 | template
194 | struct formatter::value>> {
195 | private:
196 | // C++11 generic lambda for format()
197 | template