├── .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 | 996.icu 6 | [![996.icu](https://img.shields.io/badge/link-996.icu-red.svg)](https://996.icu) 7 | [![LICENSE](https://img.shields.io/badge/license-Anti%20996-blue.svg)](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 struct format_each { 198 | template void operator()(const T& v) { 199 | if (i > 0) { 200 | if (formatting.add_prepostfix_space) { 201 | *out++ = ' '; 202 | } 203 | out = detail::copy(formatting.delimiter, out); 204 | } 205 | out = format_to(out, 206 | detail::format_str_quoted( 207 | (formatting.add_delimiter_spaces && i > 0), v), 208 | v); 209 | ++i; 210 | } 211 | 212 | formatting_tuple& formatting; 213 | size_t& i; 214 | typename std::add_lvalue_reference().out())>::type out; 216 | }; 217 | 218 | public: 219 | formatting_tuple formatting; 220 | 221 | template 222 | FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { 223 | return formatting.parse(ctx); 224 | } 225 | 226 | template 227 | auto format(const TupleT& values, FormatContext& ctx) -> decltype(ctx.out()) { 228 | auto out = ctx.out(); 229 | size_t i = 0; 230 | detail::copy(formatting.prefix, out); 231 | 232 | detail::for_each(values, format_each{formatting, i, out}); 233 | if (formatting.add_prepostfix_space) { 234 | *out++ = ' '; 235 | } 236 | detail::copy(formatting.postfix, out); 237 | 238 | return ctx.out(); 239 | } 240 | }; 241 | 242 | template struct is_range { 243 | static FMT_CONSTEXPR_DECL const bool value = 244 | detail::is_range_::value && !detail::is_like_std_string::value && 245 | !std::is_convertible>::value && 246 | !std::is_constructible, T>::value; 247 | }; 248 | 249 | template 250 | struct formatter::value>> { 252 | formatting_range formatting; 253 | 254 | template 255 | FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { 256 | return formatting.parse(ctx); 257 | } 258 | 259 | template 260 | typename FormatContext::iterator format(const RangeT& values, 261 | FormatContext& ctx) { 262 | auto out = detail::copy(formatting.prefix, ctx.out()); 263 | size_t i = 0; 264 | auto it = values.begin(); 265 | auto end = values.end(); 266 | for (; it != end; ++it) { 267 | if (i > 0) { 268 | if (formatting.add_prepostfix_space) *out++ = ' '; 269 | out = detail::copy(formatting.delimiter, out); 270 | } 271 | out = format_to(out, 272 | detail::format_str_quoted( 273 | (formatting.add_delimiter_spaces && i > 0), *it), 274 | *it); 275 | if (++i > formatting.range_length_limit) { 276 | out = format_to(out, " ... "); 277 | break; 278 | } 279 | } 280 | if (formatting.add_prepostfix_space) *out++ = ' '; 281 | return detail::copy(formatting.postfix, out); 282 | } 283 | }; 284 | 285 | template struct tuple_arg_join : detail::view { 286 | const std::tuple& tuple; 287 | basic_string_view sep; 288 | 289 | tuple_arg_join(const std::tuple& t, basic_string_view s) 290 | : tuple{t}, sep{s} {} 291 | }; 292 | 293 | template 294 | struct formatter, Char> { 295 | template 296 | FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { 297 | return ctx.begin(); 298 | } 299 | 300 | template 301 | typename FormatContext::iterator format( 302 | const tuple_arg_join& value, FormatContext& ctx) { 303 | return format(value, ctx, detail::make_index_sequence{}); 304 | } 305 | 306 | private: 307 | template 308 | typename FormatContext::iterator format( 309 | const tuple_arg_join& value, FormatContext& ctx, 310 | detail::index_sequence) { 311 | return format_args(value, ctx, std::get(value.tuple)...); 312 | } 313 | 314 | template 315 | typename FormatContext::iterator format_args( 316 | const tuple_arg_join&, FormatContext& ctx) { 317 | // NOTE: for compilers that support C++17, this empty function instantiation 318 | // can be replaced with a constexpr branch in the variadic overload. 319 | return ctx.out(); 320 | } 321 | 322 | template 323 | typename FormatContext::iterator format_args( 324 | const tuple_arg_join& value, FormatContext& ctx, 325 | const Arg& arg, const Args&... args) { 326 | using base = formatter::type, Char>; 327 | auto out = ctx.out(); 328 | out = base{}.format(arg, ctx); 329 | if (sizeof...(Args) > 0) { 330 | out = std::copy(value.sep.begin(), value.sep.end(), out); 331 | ctx.advance_to(out); 332 | return format_args(value, ctx, args...); 333 | } 334 | return out; 335 | } 336 | }; 337 | 338 | /** 339 | \rst 340 | Returns an object that formats `tuple` with elements separated by `sep`. 341 | 342 | **Example**:: 343 | 344 | std::tuple t = {1, 'a'}; 345 | fmt::print("{}", fmt::join(t, ", ")); 346 | // Output: "1, a" 347 | \endrst 348 | */ 349 | template 350 | FMT_CONSTEXPR tuple_arg_join join(const std::tuple& tuple, 351 | string_view sep) { 352 | return {tuple, sep}; 353 | } 354 | 355 | template 356 | FMT_CONSTEXPR tuple_arg_join join(const std::tuple& tuple, 357 | wstring_view sep) { 358 | return {tuple, sep}; 359 | } 360 | 361 | /** 362 | \rst 363 | Returns an object that formats `initializer_list` with elements separated by 364 | `sep`. 365 | 366 | **Example**:: 367 | 368 | fmt::print("{}", fmt::join({1, 2, 3}, ", ")); 369 | // Output: "1, 2, 3" 370 | \endrst 371 | */ 372 | template 373 | arg_join join(std::initializer_list list, 374 | string_view sep) { 375 | return join(std::begin(list), std::end(list), sep); 376 | } 377 | 378 | template 379 | arg_join join(std::initializer_list list, 380 | wstring_view sep) { 381 | return join(std::begin(list), std::end(list), sep); 382 | } 383 | 384 | FMT_END_NAMESPACE 385 | 386 | #endif // FMT_RANGES_H_ 387 | -------------------------------------------------------------------------------- /mysql_modern_cpp/pfr/core.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016-2020 Antony Polukhin 2 | // 3 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 4 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | #ifndef ASIO2_PFR_CORE_HPP 7 | #define ASIO2_PFR_CORE_HPP 8 | #pragma once 9 | 10 | #include 11 | 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include 21 | #include // metaprogramming stuff 22 | 23 | #include 24 | 25 | /// \file pfr/core.hpp 26 | /// Contains all the basic tuple-like interfaces \forcedlink{get}, \forcedlink{tuple_size}, \forcedlink{tuple_element_t}, and others. 27 | /// 28 | /// \b Synopsis: 29 | 30 | namespace pfr { 31 | 32 | /// \brief Returns reference or const reference to a field with index `I` in \aggregate `val`. 33 | /// 34 | /// \b Example: 35 | /// \code 36 | /// struct my_struct { int i, short s; }; 37 | /// my_struct s {10, 11}; 38 | /// assert(pfr::get<0>(s) == 10); 39 | /// pfr::get<1>(s) = 0; 40 | /// \endcode 41 | template 42 | constexpr decltype(auto) get(const T& val) noexcept { 43 | return detail::sequence_tuple::get( detail::tie_as_tuple(val) ); 44 | } 45 | 46 | 47 | /// \overload get 48 | template 49 | constexpr decltype(auto) get(T& val 50 | #if !ASIO2_PFR_USE_CPP17 51 | , std::enable_if_t::value>* = nullptr 52 | #endif 53 | ) noexcept { 54 | return detail::sequence_tuple::get( detail::tie_as_tuple(val) ); 55 | } 56 | 57 | #if !ASIO2_PFR_USE_CPP17 58 | /// \overload get 59 | template 60 | constexpr auto get(T&, std::enable_if_t::value>* = nullptr) noexcept { 61 | static_assert(sizeof(T) && false, "====================> PFR: Calling pfr::get on non const non assignable type is allowed only in C++17"); 62 | return 0; 63 | } 64 | #endif 65 | 66 | 67 | /// \overload get 68 | template 69 | constexpr auto get(T&& val, std::enable_if_t< std::is_rvalue_reference::value>* = 0) noexcept { 70 | return std::move(detail::sequence_tuple::get( detail::tie_as_tuple(val) )); 71 | } 72 | 73 | 74 | /// \brief `tuple_element` has a member typedef `type` that returns the type of a field with index I in \aggregate T. 75 | /// 76 | /// \b Example: 77 | /// \code 78 | /// std::vector< pfr::tuple_element<0, my_structure>::type > v; 79 | /// \endcode 80 | template 81 | using tuple_element = detail::sequence_tuple::tuple_element()) ) >; 82 | 83 | 84 | /// \brief Type of a field with index `I` in \aggregate `T`. 85 | /// 86 | /// \b Example: 87 | /// \code 88 | /// std::vector< pfr::tuple_element_t<0, my_structure> > v; 89 | /// \endcode 90 | template 91 | using tuple_element_t = typename tuple_element::type; 92 | 93 | 94 | /// \brief Creates a `std::tuple` from fields of an \aggregate `val`. 95 | /// 96 | /// \b Example: 97 | /// \code 98 | /// struct my_struct { int i, short s; }; 99 | /// my_struct s {10, 11}; 100 | /// std::tuple t = make_tuple(s); 101 | /// assert(get<0>(t) == 10); 102 | /// \endcode 103 | template 104 | constexpr auto structure_to_tuple(const T& val) noexcept { 105 | return detail::make_stdtuple_from_tietuple( 106 | detail::tie_as_tuple(val), 107 | detail::make_index_sequence< tuple_size_v >() 108 | ); 109 | } 110 | 111 | 112 | /// \brief std::tie` like function that ties fields of a structure. 113 | /// 114 | /// \returns a `std::tuple` with lvalue and const lvalue references to fields of an \aggregate `val`. 115 | /// 116 | /// \b Example: 117 | /// \code 118 | /// void foo(const int&, const short&); 119 | /// struct my_struct { int i, short s; }; 120 | /// 121 | /// const my_struct const_s{1, 2}; 122 | /// std::apply(foo, structure_tie(const_s)); 123 | /// 124 | /// my_struct s; 125 | /// structure_tie(s) = std::tuple{10, 11}; 126 | /// assert(s.s == 11); 127 | /// \endcode 128 | template 129 | constexpr auto structure_tie(const T& val) noexcept { 130 | return detail::make_conststdtiedtuple_from_tietuple( 131 | detail::tie_as_tuple(const_cast(val)), 132 | detail::make_index_sequence< tuple_size_v >() 133 | ); 134 | } 135 | 136 | 137 | /// \overload structure_tie 138 | template 139 | constexpr auto structure_tie(T& val 140 | #if !ASIO2_PFR_USE_CPP17 141 | , std::enable_if_t::value>* = nullptr 142 | #endif 143 | ) noexcept { 144 | return detail::make_stdtiedtuple_from_tietuple( 145 | detail::tie_as_tuple(val), 146 | detail::make_index_sequence< tuple_size_v >() 147 | ); 148 | } 149 | 150 | #if !ASIO2_PFR_USE_CPP17 151 | /// \overload structure_tie 152 | template 153 | constexpr auto structure_tie(T&, std::enable_if_t::value>* = nullptr) noexcept { 154 | static_assert(sizeof(T) && false, "====================> PFR: Calling pfr::structure_tie on non const non assignable type is allowed only in C++17"); 155 | return 0; 156 | } 157 | #endif 158 | 159 | 160 | /// \overload structure_tie 161 | template 162 | constexpr auto structure_tie(T&&, std::enable_if_t< std::is_rvalue_reference::value>* = 0) noexcept { 163 | static_assert(sizeof(T) && false, "====================> PFR: Calling pfr::structure_tie on rvalue references is forbidden"); 164 | return 0; 165 | } 166 | 167 | /// Calls `func` for each field of a `value`. 168 | /// 169 | /// \param func must have one of the following signatures: 170 | /// * any_return_type func(U&& field) // field of value is perfect forwarded to function 171 | /// * any_return_type func(U&& field, std::size_t i) 172 | /// * any_return_type func(U&& value, I i) // Here I is an `std::integral_constant` 173 | /// 174 | /// \param value To each field of this variable will be the `func` applied. 175 | /// 176 | /// \b Example: 177 | /// \code 178 | /// struct my_struct { int i, short s; }; 179 | /// int sum = 0; 180 | /// for_each_field(my_struct{20, 22}, [&sum](const auto& field) { sum += field; }); 181 | /// assert(sum == 42); 182 | /// \endcode 183 | template 184 | void for_each_field(T&& value, F&& func) { 185 | constexpr std::size_t fields_count_val = pfr::detail::fields_count>(); 186 | 187 | ::pfr::detail::for_each_field_dispatcher( 188 | value, 189 | [f = std::forward(func)](auto&& t) mutable { 190 | // MSVC related workaround. Its lambdas do not capture constexprs. 191 | constexpr std::size_t fields_count_val_in_lambda 192 | = pfr::detail::fields_count>(); 193 | 194 | ::pfr::detail::for_each_field_impl( 195 | t, 196 | std::forward(f), 197 | detail::make_index_sequence{}, 198 | std::is_rvalue_reference{} 199 | ); 200 | }, 201 | detail::make_index_sequence{} 202 | ); 203 | } 204 | 205 | /// \brief std::tie-like function that allows assigning to tied values from aggregates. 206 | /// 207 | /// \returns an object with lvalue references to `args...`; on assignment of an \aggregate value to that 208 | /// object each field of an aggregate is assigned to the corresponding `args...` reference. 209 | /// 210 | /// \b Example: 211 | /// \code 212 | /// auto f() { 213 | /// struct { struct { int x, y } p; short s; } res { { 4, 5 }, 6 }; 214 | /// return res; 215 | /// } 216 | /// auto [p, s] = f(); 217 | /// tie_from_structure(p, s) = f(); 218 | /// \endcode 219 | template 220 | constexpr detail::tie_from_structure_tuple tie_from_structure(Elements&... args) noexcept { 221 | return detail::tie_from_structure_tuple(args...); 222 | } 223 | 224 | } // namespace pfr 225 | 226 | #endif // ASIO2_PFR_CORE_HPP 227 | -------------------------------------------------------------------------------- /mysql_modern_cpp/pfr/detail/cast_to_layout_compatible.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016-2020 Antony Polukhin 2 | // 3 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 4 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | #ifndef ASIO2_PFR_DETAIL_CAST_TO_LAYOUT_COMPATIBLE_HPP 7 | #define ASIO2_PFR_DETAIL_CAST_TO_LAYOUT_COMPATIBLE_HPP 8 | #pragma once 9 | 10 | #include 11 | 12 | #include 13 | #include // metaprogramming stuff 14 | #include 15 | 16 | namespace pfr { namespace detail { 17 | 18 | template 19 | constexpr void static_assert_layout_compatible() noexcept { 20 | static_assert( 21 | std::alignment_of::value == std::alignment_of::value, 22 | "====================> PFR: Alignment check failed, probably your structure has user-defined alignment for the whole structure or for some of the fields." 23 | ); 24 | static_assert(sizeof(T) == sizeof(U), "====================> PFR: Size check failed, probably your structure has bitfields or user-defined alignment."); 25 | } 26 | 27 | /// @cond 28 | #ifdef __GNUC__ 29 | #define MAY_ALIAS __attribute__((__may_alias__)) 30 | #else 31 | #define MAY_ALIAS 32 | #endif 33 | /// @endcond 34 | 35 | template 36 | MAY_ALIAS const To& cast_to_layout_compatible(const From& val) noexcept { 37 | MAY_ALIAS const To* const t = reinterpret_cast( std::addressof(val) ); 38 | detail::static_assert_layout_compatible(); 39 | return *t; 40 | } 41 | 42 | template 43 | MAY_ALIAS const volatile To& cast_to_layout_compatible(const volatile From& val) noexcept { 44 | MAY_ALIAS const volatile To* const t = reinterpret_cast( std::addressof(val) ); 45 | detail::static_assert_layout_compatible(); 46 | return *t; 47 | } 48 | 49 | 50 | template 51 | MAY_ALIAS volatile To& cast_to_layout_compatible(volatile From& val) noexcept { 52 | MAY_ALIAS volatile To* const t = reinterpret_cast( std::addressof(val) ); 53 | detail::static_assert_layout_compatible(); 54 | return *t; 55 | } 56 | 57 | 58 | template 59 | MAY_ALIAS To& cast_to_layout_compatible(From& val) noexcept { 60 | MAY_ALIAS To* const t = reinterpret_cast( std::addressof(val) ); 61 | detail::static_assert_layout_compatible(); 62 | return *t; 63 | } 64 | 65 | template 66 | To&& cast_to_layout_compatible(rvalue_t val) noexcept = delete; 67 | 68 | #undef MAY_ALIAS 69 | 70 | 71 | }} // namespace pfr::detail 72 | 73 | #endif // ASIO2_PFR_DETAIL_CAST_TO_LAYOUT_COMPATIBLE_HPP 74 | -------------------------------------------------------------------------------- /mysql_modern_cpp/pfr/detail/config.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016-2020 Antony Polukhin 2 | // 3 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 4 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | #ifndef ASIO2_PFR_DETAIL_CONFIG_HPP 7 | #define ASIO2_PFR_DETAIL_CONFIG_HPP 8 | #pragma once 9 | 10 | #include // to get non standard platform macro definitions (__GLIBCXX__ for example) 11 | 12 | // Reminder: 13 | // * MSVC++ 14.2 _MSC_VER == 1927 <- Loophole is known to work (Visual Studio ????) 14 | // * MSVC++ 14.1 _MSC_VER == 1916 <- Loophole is known to NOT work (Visual Studio 2017) 15 | // * MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015) 16 | // * MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013) 17 | 18 | #if defined(_MSC_VER) 19 | # if !defined(_MSVC_LANG) || _MSC_VER <= 1900 20 | # error PFR library requires more modern MSVC compiler. 21 | # endif 22 | #elif __cplusplus < 201402L 23 | # error PFR library requires at least C++14. 24 | #endif 25 | 26 | #ifndef ASIO2_PFR_USE_LOOPHOLE 27 | # if defined(_MSC_VER) 28 | # if _MSC_VER >= 1927 29 | # define ASIO2_PFR_USE_LOOPHOLE 1 30 | # else 31 | # define ASIO2_PFR_USE_LOOPHOLE 0 32 | # endif 33 | # elif defined(__clang_major__) && __clang_major__ >= 8 34 | # define ASIO2_PFR_USE_LOOPHOLE 0 35 | # else 36 | # define ASIO2_PFR_USE_LOOPHOLE 1 37 | # endif 38 | #endif 39 | 40 | #ifndef ASIO2_PFR_USE_CPP17 41 | # ifdef __cpp_structured_bindings 42 | # define ASIO2_PFR_USE_CPP17 1 43 | # elif defined(_MSVC_LANG) 44 | # if _MSVC_LANG >= 201703L 45 | # define ASIO2_PFR_USE_CPP17 1 46 | # else 47 | # define ASIO2_PFR_USE_CPP17 0 48 | # if !ASIO2_PFR_USE_LOOPHOLE 49 | # error PFR requires /std:c++latest or /std:c++17 flags on your compiler. 50 | # endif 51 | # endif 52 | # else 53 | # define ASIO2_PFR_USE_CPP17 0 54 | # endif 55 | #endif 56 | 57 | #ifndef ASIO2_PFR_USE_STD_MAKE_INTEGRAL_SEQUENCE 58 | // Assume that libstdc++ since GCC-7.3 does not have linear instantiation depth in std::make_integral_sequence 59 | # if defined( __GLIBCXX__) && __GLIBCXX__ >= 20180101 60 | # define ASIO2_PFR_USE_STD_MAKE_INTEGRAL_SEQUENCE 1 61 | # elif defined(_MSC_VER) 62 | # define ASIO2_PFR_USE_STD_MAKE_INTEGRAL_SEQUENCE 1 63 | //# elif other known working lib 64 | # else 65 | # define ASIO2_PFR_USE_STD_MAKE_INTEGRAL_SEQUENCE 0 66 | # endif 67 | #endif 68 | 69 | #if defined(__has_cpp_attribute) 70 | # if __has_cpp_attribute(maybe_unused) 71 | # define ASIO2_PFR_MAYBE_UNUSED [[maybe_unused]] 72 | # endif 73 | #endif 74 | 75 | #ifndef ASIO2_PFR_MAYBE_UNUSED 76 | # define ASIO2_PFR_MAYBE_UNUSED 77 | #endif 78 | 79 | 80 | #endif // ASIO2_PFR_DETAIL_CONFIG_HPP 81 | -------------------------------------------------------------------------------- /mysql_modern_cpp/pfr/detail/core.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016-2020 Antony Polukhin 2 | // 3 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 4 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | #ifndef ASIO2_PFR_DETAIL_CORE_HPP 7 | #define ASIO2_PFR_DETAIL_CORE_HPP 8 | #pragma once 9 | 10 | #include 11 | 12 | // Each core provides `pfr::detail::tie_as_tuple` and 13 | // `pfr::detail::for_each_field_dispatcher` functions. 14 | // 15 | // The whole PFR library is build on top of those two functions. 16 | #if ASIO2_PFR_USE_CPP17 17 | # include 18 | #elif ASIO2_PFR_USE_LOOPHOLE 19 | # include 20 | #else 21 | # include 22 | #endif 23 | 24 | #endif // ASIO2_PFR_DETAIL_CORE_HPP 25 | -------------------------------------------------------------------------------- /mysql_modern_cpp/pfr/detail/core14_loophole.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2018 Alexandr Poltavsky, Antony Polukhin. 2 | // Copyright (c) 2019-2020 Antony Polukhin. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 | 7 | 8 | // The Great Type Loophole (C++14) 9 | // Initial implementation by Alexandr Poltavsky, http://alexpolt.github.io 10 | // 11 | // Description: 12 | // The Great Type Loophole is a technique that allows to exchange type information with template 13 | // instantiations. Basically you can assign and read type information during compile time. 14 | // Here it is used to detect data members of a data type. I described it for the first time in 15 | // this blog post http://alexpolt.github.io/type-loophole.html . 16 | // 17 | // This technique exploits the http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2118 18 | // CWG 2118. Stateful metaprogramming via friend injection 19 | // Note: CWG agreed that such techniques should be ill-formed, although the mechanism for prohibiting them is as yet undetermined. 20 | 21 | #ifndef ASIO2_PFR_DETAIL_CORE14_LOOPHOLE_HPP 22 | #define ASIO2_PFR_DETAIL_CORE14_LOOPHOLE_HPP 23 | 24 | #include 25 | 26 | #include 27 | #include 28 | 29 | #include // still needed for enums 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | 39 | #ifdef __clang__ 40 | # pragma clang diagnostic push 41 | # pragma clang diagnostic ignored "-Wmissing-braces" 42 | # pragma clang diagnostic ignored "-Wundefined-inline" 43 | # pragma clang diagnostic ignored "-Wundefined-internal" 44 | # pragma clang diagnostic ignored "-Wmissing-field-initializers" 45 | #elif defined(__GNUC__) 46 | # pragma GCC diagnostic push 47 | # pragma GCC diagnostic ignored "-Wnon-template-friend" 48 | #endif 49 | 50 | 51 | namespace pfr { namespace detail { 52 | 53 | // tag generates friend declarations and helps with overload resolution. 54 | // There are two types: one with the auto return type, which is the way we read types later. 55 | // The second one is used in the detection of instantiations without which we'd get multiple 56 | // definitions. 57 | 58 | template 59 | struct tag { 60 | friend auto loophole(tag); 61 | }; 62 | 63 | // The definitions of friend functions. 64 | template 65 | struct fn_def_lref { 66 | friend auto loophole(tag) { 67 | // Standard Library containers do not SFINAE on invalid copy constructor. Because of that std::vector> reports that it is copyable, 68 | // which leads to an instantiation error at this place. 69 | // 70 | // To workaround the issue, we check that the type U is movable, and move it in that case. 71 | using no_extents_t = std::remove_all_extents_t; 72 | return static_cast< std::conditional_t::value, no_extents_t&&, no_extents_t&> >( 73 | pfr::detail::unsafe_declval() 74 | ); 75 | } 76 | }; 77 | template 78 | struct fn_def_rref { 79 | friend auto loophole(tag) { return std::move(pfr::detail::unsafe_declval< std::remove_all_extents_t& >()); } 80 | }; 81 | 82 | 83 | // Those specializations are to avoid multiple definition errors. 84 | template 85 | struct fn_def_lref {}; 86 | 87 | template 88 | struct fn_def_rref {}; 89 | 90 | 91 | // This has a templated conversion operator which in turn triggers instantiations. 92 | // Important point, using sizeof seems to be more reliable. Also default template 93 | // arguments are "cached" (I think). To fix that I provide a U template parameter to 94 | // the ins functions which do the detection using constexpr friend functions and SFINAE. 95 | template 96 | struct loophole_ubiq_lref { 97 | template static std::size_t ins(...); 98 | template{})) > static char ins(int); 99 | 100 | template(0)) == sizeof(char)>)> 101 | constexpr operator U&() const&& noexcept; // `const&&` here helps to avoid ambiguity in loophole instantiations. optional_like test validate that behavior. 102 | }; 103 | 104 | template 105 | struct loophole_ubiq_rref { 106 | template static std::size_t ins(...); 107 | template{})) > static char ins(int); 108 | 109 | template(0)) == sizeof(char)>)> 110 | constexpr operator U&&() const&& noexcept; // `const&&` here helps to avoid ambiguity in loophole instantiations. optional_like test validate that behavior. 111 | }; 112 | 113 | 114 | // This is a helper to turn a data structure into a tuple. 115 | template 116 | struct loophole_type_list_lref; 117 | 118 | template 119 | struct loophole_type_list_lref< T, std::index_sequence > 120 | // Instantiating loopholes: 121 | : sequence_tuple::tuple< decltype(T{ loophole_ubiq_lref{}... }, 0) > 122 | { 123 | using type = sequence_tuple::tuple< decltype(loophole(tag{}))... >; 124 | }; 125 | 126 | 127 | template 128 | struct loophole_type_list_rref; 129 | 130 | template 131 | struct loophole_type_list_rref< T, std::index_sequence > 132 | // Instantiating loopholes: 133 | : sequence_tuple::tuple< decltype(T{ loophole_ubiq_rref{}... }, 0) > 134 | { 135 | using type = sequence_tuple::tuple< decltype(loophole(tag{}))... >; 136 | }; 137 | 138 | 139 | // Lazily returns loophole_type_list_{lr}ref. 140 | template 141 | struct loophole_type_list_selector { 142 | using type = loophole_type_list_lref; 143 | }; 144 | 145 | template 146 | struct loophole_type_list_selector { 147 | using type = loophole_type_list_rref; 148 | }; 149 | 150 | template 151 | auto tie_as_tuple_loophole_impl(T& lvalue) noexcept { 152 | using type = std::remove_cv_t>; 153 | using indexes = detail::make_index_sequence()>; 154 | using loophole_type_list = typename detail::loophole_type_list_selector< 155 | std::is_copy_constructible>::value, type, indexes 156 | >::type; 157 | using tuple_type = typename loophole_type_list::type; 158 | 159 | return pfr::detail::make_flat_tuple_of_references( 160 | lvalue, 161 | offset_based_getter{}, 162 | size_t_<0>{}, 163 | size_t_{} 164 | ); 165 | } 166 | 167 | template 168 | auto tie_as_tuple(T& val) noexcept { 169 | static_assert( 170 | !std::is_union::value, 171 | "====================> PFR: For safety reasons it is forbidden to reflect unions. See `Reflection of unions` section in the docs for more info." 172 | ); 173 | return pfr::detail::tie_as_tuple_loophole_impl( 174 | val 175 | ); 176 | } 177 | 178 | template 179 | void for_each_field_dispatcher(T& t, F&& f, std::index_sequence) { 180 | static_assert( 181 | !std::is_union::value, 182 | "====================> PFR: For safety reasons it is forbidden to reflect unions. See `Reflection of unions` section in the docs for more info." 183 | ); 184 | std::forward(f)( 185 | pfr::detail::tie_as_tuple_loophole_impl(t) 186 | ); 187 | } 188 | 189 | }} // namespace pfr::detail 190 | 191 | 192 | #ifdef __clang__ 193 | # pragma clang diagnostic pop 194 | #elif defined(__GNUC__) 195 | # pragma GCC diagnostic pop 196 | #endif 197 | 198 | 199 | #endif // ASIO2_PFR_DETAIL_CORE14_LOOPHOLE_HPP 200 | 201 | -------------------------------------------------------------------------------- /mysql_modern_cpp/pfr/detail/core17.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016-2020 Antony Polukhin 2 | // 3 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 4 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | 7 | #ifndef ASIO2_PFR_DETAIL_CORE17_HPP 8 | #define ASIO2_PFR_DETAIL_CORE17_HPP 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | namespace pfr { namespace detail { 16 | 17 | #ifndef _MSC_VER // MSVC fails to compile the following code, but compiles the structured bindings in core17_generated.hpp 18 | struct do_not_define_std_tuple_size_for_me { 19 | bool test1 = true; 20 | }; 21 | 22 | template 23 | constexpr bool do_structured_bindings_work() noexcept { // ******************************************* IN CASE OF ERROR READ THE FOLLOWING LINES IN pfr/detail/core17.hpp FILE: 24 | T val{}; 25 | const auto& [a] = val; // ******************************************* IN CASE OF ERROR READ THE FOLLOWING LINES IN pfr/detail/core17.hpp FILE: 26 | 27 | /**************************************************************************** 28 | * 29 | * It looks like your compiler or Standard Library can not handle C++17 30 | * structured bindings. 31 | * 32 | * Workaround: Define ASIO2_PFR_USE_CPP17 to 0 33 | * It will disable the C++17 features for PFR library. 34 | * 35 | * Sorry for the inconvenience caused. 36 | * 37 | ****************************************************************************/ 38 | 39 | return a; 40 | } 41 | 42 | static_assert( 43 | do_structured_bindings_work(), 44 | "====================> PFR: Your compiler can not handle C++17 structured bindings. Read the above comments for workarounds." 45 | ); 46 | #endif // #ifndef _MSC_VER 47 | 48 | template 49 | constexpr auto tie_as_tuple(T& val) noexcept { 50 | static_assert( 51 | !std::is_union::value, 52 | "====================> PFR: For safety reasons it is forbidden to reflect unions. See `Reflection of unions` section in the docs for more info." 53 | ); 54 | typedef size_t_()> fields_count_tag; 55 | return pfr::detail::tie_as_tuple(val, fields_count_tag{}); 56 | } 57 | 58 | template 59 | void for_each_field_dispatcher(T& t, F&& f, std::index_sequence) { 60 | static_assert( 61 | !std::is_union::value, 62 | "====================> PFR: For safety reasons it is forbidden to reflect unions. See `Reflection of unions` section in the docs for more info." 63 | ); 64 | std::forward(f)( 65 | detail::tie_as_tuple(t) 66 | ); 67 | } 68 | 69 | }} // namespace pfr::detail 70 | 71 | #endif // ASIO2_PFR_DETAIL_CORE17_HPP 72 | -------------------------------------------------------------------------------- /mysql_modern_cpp/pfr/detail/detectors.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016-2020 Antony Polukhin 2 | // 3 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 4 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | #ifndef ASIO2_PFR_DETAIL_DETECTORS_HPP 7 | #define ASIO2_PFR_DETAIL_DETECTORS_HPP 8 | #pragma once 9 | 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | namespace pfr { namespace detail { 16 | ///////////////////// `value` is true if Detector does not compile (SFINAE) 17 | struct can_not_apply{}; 18 | 19 | template