simpleble 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (341) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +88 -0
  3. data/LICENSE.txt +21 -0
  4. data/README.md +350 -0
  5. data/ext/simpleble/extconf.rb +57 -0
  6. data/ext/simpleble/simpleble_ruby.c +682 -0
  7. data/lib/simpleble/adapter.rb +10 -0
  8. data/lib/simpleble/characteristic.rb +36 -0
  9. data/lib/simpleble/descriptor.rb +8 -0
  10. data/lib/simpleble/exceptions.rb +25 -0
  11. data/lib/simpleble/peripheral.rb +64 -0
  12. data/lib/simpleble/service.rb +16 -0
  13. data/lib/simpleble/version.rb +3 -0
  14. data/lib/simpleble.rb +40 -0
  15. data/vendor/simpleble/build_simplecble/CMakeFiles/4.0.3/CompilerIdCXX/CMakeCXXCompilerId.cpp +920 -0
  16. data/vendor/simpleble/build_simplecble/CMakeFiles/4.0.3/CompilerIdCXX/apple-sdk.cpp +1 -0
  17. data/vendor/simpleble/build_simplecble/CMakeFiles/4.1.0/CompilerIdCXX/CMakeCXXCompilerId.cpp +949 -0
  18. data/vendor/simpleble/build_simplecble/CMakeFiles/4.1.0/CompilerIdCXX/apple-sdk.cpp +1 -0
  19. data/vendor/simpleble/build_simplecble/export/simplecble/export.h +43 -0
  20. data/vendor/simpleble/build_simplecble/simpleble/export/simpleble/export.h +43 -0
  21. data/vendor/simpleble/dependencies/external/kvn/kvn_bytearray.h +222 -0
  22. data/vendor/simpleble/dependencies/external/kvn/kvn_safe_callback.hpp +66 -0
  23. data/vendor/simpleble/dependencies/external/kvn/logfwd.hpp +35 -0
  24. data/vendor/simpleble/dependencies/internal/fmt/args.h +220 -0
  25. data/vendor/simpleble/dependencies/internal/fmt/base.h +2962 -0
  26. data/vendor/simpleble/dependencies/internal/fmt/chrono.h +2338 -0
  27. data/vendor/simpleble/dependencies/internal/fmt/color.h +610 -0
  28. data/vendor/simpleble/dependencies/internal/fmt/compile.h +539 -0
  29. data/vendor/simpleble/dependencies/internal/fmt/core.h +5 -0
  30. data/vendor/simpleble/dependencies/internal/fmt/format-inl.h +1949 -0
  31. data/vendor/simpleble/dependencies/internal/fmt/format.h +4244 -0
  32. data/vendor/simpleble/dependencies/internal/fmt/os.h +427 -0
  33. data/vendor/simpleble/dependencies/internal/fmt/ostream.h +166 -0
  34. data/vendor/simpleble/dependencies/internal/fmt/printf.h +633 -0
  35. data/vendor/simpleble/dependencies/internal/fmt/ranges.h +850 -0
  36. data/vendor/simpleble/dependencies/internal/fmt/std.h +726 -0
  37. data/vendor/simpleble/dependencies/internal/fmt/xchar.h +373 -0
  38. data/vendor/simpleble/dependencies/internal/simplejni/Common.hpp +579 -0
  39. data/vendor/simpleble/dependencies/internal/simplejni/References.hpp +151 -0
  40. data/vendor/simpleble/dependencies/internal/simplejni/Registry.hpp +183 -0
  41. data/vendor/simpleble/dependencies/internal/simplejni/VM.hpp +88 -0
  42. data/vendor/simpleble/examples/simpleble/src/connect.cpp +67 -0
  43. data/vendor/simpleble/examples/simpleble/src/connect_safe.cpp +91 -0
  44. data/vendor/simpleble/examples/simpleble/src/list_adapters.cpp +22 -0
  45. data/vendor/simpleble/examples/simpleble/src/list_adapters_safe.cpp +33 -0
  46. data/vendor/simpleble/examples/simpleble/src/list_paired.cpp +27 -0
  47. data/vendor/simpleble/examples/simpleble/src/multiconnect.cpp +60 -0
  48. data/vendor/simpleble/examples/simpleble/src/notify.cpp +85 -0
  49. data/vendor/simpleble/examples/simpleble/src/notify_multi.cpp +101 -0
  50. data/vendor/simpleble/examples/simpleble/src/power_cycle.cpp +43 -0
  51. data/vendor/simpleble/examples/simpleble/src/read.cpp +82 -0
  52. data/vendor/simpleble/examples/simpleble/src/scan.cpp +62 -0
  53. data/vendor/simpleble/examples/simpleble/src/utils.cpp +59 -0
  54. data/vendor/simpleble/examples/simpleble/src/utils.hpp +27 -0
  55. data/vendor/simpleble/examples/simpleble/src/write.cpp +81 -0
  56. data/vendor/simpleble/examples/simplebluez/ble_nus/ble_nus.cpp +138 -0
  57. data/vendor/simpleble/examples/simplebluez/connect/connect.cpp +119 -0
  58. data/vendor/simpleble/examples/simplebluez/list_adapters/list_adapters.cpp +44 -0
  59. data/vendor/simpleble/examples/simplebluez/list_paired/list_paired.cpp +48 -0
  60. data/vendor/simpleble/examples/simplebluez/notify/notify.cpp +145 -0
  61. data/vendor/simpleble/examples/simplebluez/pair/pair.cpp +181 -0
  62. data/vendor/simpleble/examples/simplebluez/read/read.cpp +141 -0
  63. data/vendor/simpleble/examples/simplebluez/scan/scan.cpp +85 -0
  64. data/vendor/simpleble/examples/simplecble/c/connect.c +163 -0
  65. data/vendor/simpleble/examples/simplecble/c/notify.c +217 -0
  66. data/vendor/simpleble/examples/simplecble/c/scan.c +164 -0
  67. data/vendor/simpleble/examples/simpledbus/notification.cpp +24 -0
  68. data/vendor/simpleble/hitl/src/test_sanity.cpp +48 -0
  69. data/vendor/simpleble/install_simplecble/include/simpleble/Adapter.h +102 -0
  70. data/vendor/simpleble/install_simplecble/include/simpleble/AdapterSafe.h +58 -0
  71. data/vendor/simpleble/install_simplecble/include/simpleble/Advanced.h +50 -0
  72. data/vendor/simpleble/install_simplecble/include/simpleble/Characteristic.h +39 -0
  73. data/vendor/simpleble/install_simplecble/include/simpleble/Config.h +55 -0
  74. data/vendor/simpleble/install_simplecble/include/simpleble/Descriptor.h +30 -0
  75. data/vendor/simpleble/install_simplecble/include/simpleble/Exceptions.h +72 -0
  76. data/vendor/simpleble/install_simplecble/include/simpleble/Logging.h +73 -0
  77. data/vendor/simpleble/install_simplecble/include/simpleble/Peripheral.h +82 -0
  78. data/vendor/simpleble/install_simplecble/include/simpleble/PeripheralSafe.h +64 -0
  79. data/vendor/simpleble/install_simplecble/include/simpleble/Service.h +34 -0
  80. data/vendor/simpleble/install_simplecble/include/simpleble/SimpleBLE.h +8 -0
  81. data/vendor/simpleble/install_simplecble/include/simpleble/Types.h +49 -0
  82. data/vendor/simpleble/install_simplecble/include/simpleble/Utils.h +13 -0
  83. data/vendor/simpleble/install_simplecble/include/simpleble/export.h +43 -0
  84. data/vendor/simpleble/install_simplecble/include/simpleble/kvn/kvn_bytearray.h +222 -0
  85. data/vendor/simpleble/install_simplecble/include/simplecble/adapter.h +188 -0
  86. data/vendor/simpleble/install_simplecble/include/simplecble/logging.h +37 -0
  87. data/vendor/simpleble/install_simplecble/include/simplecble/peripheral.h +304 -0
  88. data/vendor/simpleble/install_simplecble/include/simplecble/simpleble.h +21 -0
  89. data/vendor/simpleble/install_simplecble/include/simplecble/types.h +73 -0
  90. data/vendor/simpleble/install_simplecble/include/simplecble/utils.h +27 -0
  91. data/vendor/simpleble/simpleble/include/simpleble/Adapter.h +102 -0
  92. data/vendor/simpleble/simpleble/include/simpleble/AdapterSafe.h +58 -0
  93. data/vendor/simpleble/simpleble/include/simpleble/Characteristic.h +39 -0
  94. data/vendor/simpleble/simpleble/include/simpleble/Config.h +55 -0
  95. data/vendor/simpleble/simpleble/include/simpleble/Descriptor.h +30 -0
  96. data/vendor/simpleble/simpleble/include/simpleble/Exceptions.h +72 -0
  97. data/vendor/simpleble/simpleble/include/simpleble/Logging.h +73 -0
  98. data/vendor/simpleble/simpleble/include/simpleble/Peripheral.h +82 -0
  99. data/vendor/simpleble/simpleble/include/simpleble/PeripheralSafe.h +64 -0
  100. data/vendor/simpleble/simpleble/include/simpleble/Service.h +34 -0
  101. data/vendor/simpleble/simpleble/include/simpleble/SimpleBLE.h +8 -0
  102. data/vendor/simpleble/simpleble/include/simpleble/Types.h +49 -0
  103. data/vendor/simpleble/simpleble/include/simpleble/Utils.h +13 -0
  104. data/vendor/simpleble/simpleble/include/simpleble_c/adapter.h +188 -0
  105. data/vendor/simpleble/simpleble/include/simpleble_c/logging.h +37 -0
  106. data/vendor/simpleble/simpleble/include/simpleble_c/peripheral.h +304 -0
  107. data/vendor/simpleble/simpleble/include/simpleble_c/simpleble.h +21 -0
  108. data/vendor/simpleble/simpleble/include/simpleble_c/types.h +73 -0
  109. data/vendor/simpleble/simpleble/include/simpleble_c/utils.h +27 -0
  110. data/vendor/simpleble/simpleble/src/CommonUtils.h +63 -0
  111. data/vendor/simpleble/simpleble/src/Exceptions.cpp +31 -0
  112. data/vendor/simpleble/simpleble/src/Logging.cpp +136 -0
  113. data/vendor/simpleble/simpleble/src/LoggingInternal.h +85 -0
  114. data/vendor/simpleble/simpleble/src/Utils.cpp +24 -0
  115. data/vendor/simpleble/simpleble/src/backends/android/AdapterAndroid.cpp +101 -0
  116. data/vendor/simpleble/simpleble/src/backends/android/AdapterAndroid.h +70 -0
  117. data/vendor/simpleble/simpleble/src/backends/android/BackendAndroid.cpp +40 -0
  118. data/vendor/simpleble/simpleble/src/backends/android/BackendAndroid.h +20 -0
  119. data/vendor/simpleble/simpleble/src/backends/android/PeripheralAndroid.cpp +365 -0
  120. data/vendor/simpleble/simpleble/src/backends/android/PeripheralAndroid.h +90 -0
  121. data/vendor/simpleble/simpleble/src/backends/android/bridge/BluetoothGattCallback.cpp +432 -0
  122. data/vendor/simpleble/simpleble/src/backends/android/bridge/BluetoothGattCallback.h +102 -0
  123. data/vendor/simpleble/simpleble/src/backends/android/bridge/ScanCallback.cpp +142 -0
  124. data/vendor/simpleble/simpleble/src/backends/android/bridge/ScanCallback.h +55 -0
  125. data/vendor/simpleble/simpleble/src/backends/android/types/android/bluetooth/BluetoothAdapter.cpp +107 -0
  126. data/vendor/simpleble/simpleble/src/backends/android/types/android/bluetooth/BluetoothAdapter.h +55 -0
  127. data/vendor/simpleble/simpleble/src/backends/android/types/android/bluetooth/BluetoothDevice.cpp +68 -0
  128. data/vendor/simpleble/simpleble/src/backends/android/types/android/bluetooth/BluetoothDevice.h +54 -0
  129. data/vendor/simpleble/simpleble/src/backends/android/types/android/bluetooth/BluetoothGatt.cpp +115 -0
  130. data/vendor/simpleble/simpleble/src/backends/android/types/android/bluetooth/BluetoothGatt.h +75 -0
  131. data/vendor/simpleble/simpleble/src/backends/android/types/android/bluetooth/BluetoothGattCharacteristic.cpp +142 -0
  132. data/vendor/simpleble/simpleble/src/backends/android/types/android/bluetooth/BluetoothGattCharacteristic.h +66 -0
  133. data/vendor/simpleble/simpleble/src/backends/android/types/android/bluetooth/BluetoothGattDescriptor.cpp +67 -0
  134. data/vendor/simpleble/simpleble/src/backends/android/types/android/bluetooth/BluetoothGattDescriptor.h +46 -0
  135. data/vendor/simpleble/simpleble/src/backends/android/types/android/bluetooth/BluetoothGattService.cpp +106 -0
  136. data/vendor/simpleble/simpleble/src/backends/android/types/android/bluetooth/BluetoothGattService.h +47 -0
  137. data/vendor/simpleble/simpleble/src/backends/android/types/android/bluetooth/le/BluetoothScanner.cpp +47 -0
  138. data/vendor/simpleble/simpleble/src/backends/android/types/android/bluetooth/le/BluetoothScanner.h +37 -0
  139. data/vendor/simpleble/simpleble/src/backends/android/types/android/bluetooth/le/ScanRecord.cpp +69 -0
  140. data/vendor/simpleble/simpleble/src/backends/android/types/android/bluetooth/le/ScanRecord.h +41 -0
  141. data/vendor/simpleble/simpleble/src/backends/android/types/android/bluetooth/le/ScanResult.cpp +63 -0
  142. data/vendor/simpleble/simpleble/src/backends/android/types/android/bluetooth/le/ScanResult.h +42 -0
  143. data/vendor/simpleble/simpleble/src/backends/android/types/android/os/ParcelUUID.cpp +32 -0
  144. data/vendor/simpleble/simpleble/src/backends/android/types/android/os/ParcelUUID.h +30 -0
  145. data/vendor/simpleble/simpleble/src/backends/android/types/android/util/SparseArray.cpp +54 -0
  146. data/vendor/simpleble/simpleble/src/backends/android/types/android/util/SparseArray.h +37 -0
  147. data/vendor/simpleble/simpleble/src/backends/android/types/java/util/Iterator.cpp +36 -0
  148. data/vendor/simpleble/simpleble/src/backends/android/types/java/util/Iterator.h +28 -0
  149. data/vendor/simpleble/simpleble/src/backends/android/types/java/util/List.cpp +29 -0
  150. data/vendor/simpleble/simpleble/src/backends/android/types/java/util/List.h +27 -0
  151. data/vendor/simpleble/simpleble/src/backends/android/types/java/util/Set.cpp +33 -0
  152. data/vendor/simpleble/simpleble/src/backends/android/types/java/util/Set.h +28 -0
  153. data/vendor/simpleble/simpleble/src/backends/android/types/java/util/UUID.cpp +26 -0
  154. data/vendor/simpleble/simpleble/src/backends/android/types/java/util/UUID.h +29 -0
  155. data/vendor/simpleble/simpleble/src/backends/common/AdapterBase.cpp +53 -0
  156. data/vendor/simpleble/simpleble/src/backends/common/AdapterBase.h +81 -0
  157. data/vendor/simpleble/simpleble/src/backends/common/AdapterBaseTypes.h +22 -0
  158. data/vendor/simpleble/simpleble/src/backends/common/BackendBase.h +20 -0
  159. data/vendor/simpleble/simpleble/src/backends/common/BackendUtils.h +33 -0
  160. data/vendor/simpleble/simpleble/src/backends/common/CharacteristicBase.cpp +28 -0
  161. data/vendor/simpleble/simpleble/src/backends/common/CharacteristicBase.h +38 -0
  162. data/vendor/simpleble/simpleble/src/backends/common/DescriptorBase.cpp +7 -0
  163. data/vendor/simpleble/simpleble/src/backends/common/DescriptorBase.h +19 -0
  164. data/vendor/simpleble/simpleble/src/backends/common/PeripheralBase.h +82 -0
  165. data/vendor/simpleble/simpleble/src/backends/common/ServiceBase.cpp +18 -0
  166. data/vendor/simpleble/simpleble/src/backends/common/ServiceBase.h +28 -0
  167. data/vendor/simpleble/simpleble/src/backends/linux/AdapterLinux.cpp +102 -0
  168. data/vendor/simpleble/simpleble/src/backends/linux/AdapterLinux.h +55 -0
  169. data/vendor/simpleble/simpleble/src/backends/linux/BackendBluez.cpp +87 -0
  170. data/vendor/simpleble/simpleble/src/backends/linux/PeripheralLinux.cpp +376 -0
  171. data/vendor/simpleble/simpleble/src/backends/linux/PeripheralLinux.h +90 -0
  172. data/vendor/simpleble/simpleble/src/backends/macos/AdapterBaseMacOS.h +29 -0
  173. data/vendor/simpleble/simpleble/src/backends/macos/AdapterMac.h +78 -0
  174. data/vendor/simpleble/simpleble/src/backends/macos/PeripheralBaseMacOS.h +49 -0
  175. data/vendor/simpleble/simpleble/src/backends/macos/PeripheralMac.h +81 -0
  176. data/vendor/simpleble/simpleble/src/backends/macos/Utils.h +9 -0
  177. data/vendor/simpleble/simpleble/src/backends/plain/AdapterPlain.cpp +65 -0
  178. data/vendor/simpleble/simpleble/src/backends/plain/AdapterPlain.h +49 -0
  179. data/vendor/simpleble/simpleble/src/backends/plain/BackendPlain.cpp +30 -0
  180. data/vendor/simpleble/simpleble/src/backends/plain/PeripheralPlain.cpp +159 -0
  181. data/vendor/simpleble/simpleble/src/backends/plain/PeripheralPlain.h +72 -0
  182. data/vendor/simpleble/simpleble/src/backends/windows/AdapterWindows.cpp +330 -0
  183. data/vendor/simpleble/simpleble/src/backends/windows/AdapterWindows.h +89 -0
  184. data/vendor/simpleble/simpleble/src/backends/windows/BackendWinRT.cpp +67 -0
  185. data/vendor/simpleble/simpleble/src/backends/windows/BackendWinRT.h +18 -0
  186. data/vendor/simpleble/simpleble/src/backends/windows/MtaManager.cpp +49 -0
  187. data/vendor/simpleble/simpleble/src/backends/windows/MtaManager.h +90 -0
  188. data/vendor/simpleble/simpleble/src/backends/windows/PeripheralWindows.cpp +487 -0
  189. data/vendor/simpleble/simpleble/src/backends/windows/PeripheralWindows.h +129 -0
  190. data/vendor/simpleble/simpleble/src/backends/windows/Utils.cpp +146 -0
  191. data/vendor/simpleble/simpleble/src/backends/windows/Utils.h +47 -0
  192. data/vendor/simpleble/simpleble/src/builders/BuildVec.h +32 -0
  193. data/vendor/simpleble/simpleble/src/builders/BuilderBase.h +87 -0
  194. data/vendor/simpleble/simpleble/src/external/TaskRunner.hpp +99 -0
  195. data/vendor/simpleble/simpleble/src/external/ThreadRunner.h +52 -0
  196. data/vendor/simpleble/simpleble/src/external/kvn_safe_callback.hpp +66 -0
  197. data/vendor/simpleble/simpleble/src/external/kvn_safe_map.hpp +94 -0
  198. data/vendor/simpleble/simpleble/src/external/kvn_threadrunner.hpp +70 -0
  199. data/vendor/simpleble/simpleble/src/external/logfwd.hpp +35 -0
  200. data/vendor/simpleble/simpleble/src/frontends/base/Adapter.cpp +111 -0
  201. data/vendor/simpleble/simpleble/src/frontends/base/Backend.cpp +83 -0
  202. data/vendor/simpleble/simpleble/src/frontends/base/Backend.h +76 -0
  203. data/vendor/simpleble/simpleble/src/frontends/base/Characteristic.cpp +56 -0
  204. data/vendor/simpleble/simpleble/src/frontends/base/Descriptor.cpp +21 -0
  205. data/vendor/simpleble/simpleble/src/frontends/base/Peripheral.cpp +113 -0
  206. data/vendor/simpleble/simpleble/src/frontends/base/Service.cpp +26 -0
  207. data/vendor/simpleble/simpleble/src/frontends/safe/AdapterSafe.cpp +158 -0
  208. data/vendor/simpleble/simpleble/src/frontends/safe/PeripheralSafe.cpp +219 -0
  209. data/vendor/simpleble/simpleble/src_c/adapter.cpp +204 -0
  210. data/vendor/simpleble/simpleble/src_c/logging.cpp +19 -0
  211. data/vendor/simpleble/simpleble/src_c/peripheral.cpp +444 -0
  212. data/vendor/simpleble/simpleble/src_c/simpleble.cpp +5 -0
  213. data/vendor/simpleble/simpleble/src_c/utils.cpp +15 -0
  214. data/vendor/simpleble/simpleble/test/src/main.cpp +8 -0
  215. data/vendor/simpleble/simpleble/test/src/test_bytearray.cpp +246 -0
  216. data/vendor/simpleble/simpleble/test/src/test_utils.cpp +24 -0
  217. data/vendor/simpleble/simplebluez/include/simplebluez/Adapter.h +46 -0
  218. data/vendor/simpleble/simplebluez/include/simplebluez/Agent.h +52 -0
  219. data/vendor/simpleble/simplebluez/include/simplebluez/Bluez.h +37 -0
  220. data/vendor/simpleble/simplebluez/include/simplebluez/BluezOrg.h +22 -0
  221. data/vendor/simpleble/simplebluez/include/simplebluez/BluezOrgBluez.h +26 -0
  222. data/vendor/simpleble/simplebluez/include/simplebluez/BluezRoot.h +32 -0
  223. data/vendor/simpleble/simplebluez/include/simplebluez/Characteristic.h +46 -0
  224. data/vendor/simpleble/simplebluez/include/simplebluez/Descriptor.h +33 -0
  225. data/vendor/simpleble/simplebluez/include/simplebluez/Device.h +64 -0
  226. data/vendor/simpleble/simplebluez/include/simplebluez/Exceptions.h +43 -0
  227. data/vendor/simpleble/simplebluez/include/simplebluez/Service.h +27 -0
  228. data/vendor/simpleble/simplebluez/include/simplebluez/Types.h +9 -0
  229. data/vendor/simpleble/simplebluez/include/simplebluez/interfaces/Adapter1.h +49 -0
  230. data/vendor/simpleble/simplebluez/include/simplebluez/interfaces/Agent1.h +100 -0
  231. data/vendor/simpleble/simplebluez/include/simplebluez/interfaces/AgentManager1.h +24 -0
  232. data/vendor/simpleble/simplebluez/include/simplebluez/interfaces/Battery1.h +32 -0
  233. data/vendor/simpleble/simplebluez/include/simplebluez/interfaces/Device1.h +62 -0
  234. data/vendor/simpleble/simplebluez/include/simplebluez/interfaces/GattCharacteristic1.h +48 -0
  235. data/vendor/simpleble/simplebluez/include/simplebluez/interfaces/GattDescriptor1.h +41 -0
  236. data/vendor/simpleble/simplebluez/include/simplebluez/interfaces/GattService1.h +28 -0
  237. data/vendor/simpleble/simplebluez/src/Adapter.cpp +78 -0
  238. data/vendor/simpleble/simplebluez/src/Agent.cpp +72 -0
  239. data/vendor/simpleble/simplebluez/src/Bluez.cpp +45 -0
  240. data/vendor/simpleble/simplebluez/src/BluezOrg.cpp +20 -0
  241. data/vendor/simpleble/simplebluez/src/BluezOrgBluez.cpp +23 -0
  242. data/vendor/simpleble/simplebluez/src/BluezRoot.cpp +44 -0
  243. data/vendor/simpleble/simplebluez/src/Characteristic.cpp +64 -0
  244. data/vendor/simpleble/simplebluez/src/Descriptor.cpp +27 -0
  245. data/vendor/simpleble/simplebluez/src/Device.cpp +104 -0
  246. data/vendor/simpleble/simplebluez/src/Exceptions.cpp +29 -0
  247. data/vendor/simpleble/simplebluez/src/Logging.cpp +52 -0
  248. data/vendor/simpleble/simplebluez/src/Logging.h +57 -0
  249. data/vendor/simpleble/simplebluez/src/Service.cpp +33 -0
  250. data/vendor/simpleble/simplebluez/src/interfaces/Adapter1.cpp +123 -0
  251. data/vendor/simpleble/simplebluez/src/interfaces/Agent1.cpp +143 -0
  252. data/vendor/simpleble/simplebluez/src/interfaces/AgentManager1.cpp +34 -0
  253. data/vendor/simpleble/simplebluez/src/interfaces/Battery1.cpp +30 -0
  254. data/vendor/simpleble/simplebluez/src/interfaces/Device1.cpp +170 -0
  255. data/vendor/simpleble/simplebluez/src/interfaces/GattCharacteristic1.cpp +118 -0
  256. data/vendor/simpleble/simplebluez/src/interfaces/GattDescriptor1.cpp +78 -0
  257. data/vendor/simpleble/simplebluez/src/interfaces/GattService1.cpp +28 -0
  258. data/vendor/simpleble/simplebluez/test/src/helpers/PythonRunner.cpp +53 -0
  259. data/vendor/simpleble/simplebluez/test/src/helpers/PythonRunner.h +24 -0
  260. data/vendor/simpleble/simplebluez/test/src/main.cpp +16 -0
  261. data/vendor/simpleble/simplecble/include/simplecble/adapter.h +188 -0
  262. data/vendor/simpleble/simplecble/include/simplecble/logging.h +37 -0
  263. data/vendor/simpleble/simplecble/include/simplecble/peripheral.h +304 -0
  264. data/vendor/simpleble/simplecble/include/simplecble/simpleble.h +21 -0
  265. data/vendor/simpleble/simplecble/include/simplecble/types.h +73 -0
  266. data/vendor/simpleble/simplecble/include/simplecble/utils.h +27 -0
  267. data/vendor/simpleble/simplecble/src/adapter.cpp +204 -0
  268. data/vendor/simpleble/simplecble/src/logging.cpp +19 -0
  269. data/vendor/simpleble/simplecble/src/peripheral.cpp +444 -0
  270. data/vendor/simpleble/simplecble/src/simpleble.cpp +5 -0
  271. data/vendor/simpleble/simplecble/src/utils.cpp +15 -0
  272. data/vendor/simpleble/simpledbus/include/simpledbus/advanced/Interface.h +67 -0
  273. data/vendor/simpleble/simpledbus/include/simpledbus/advanced/InterfaceRegistry.h +64 -0
  274. data/vendor/simpleble/simpledbus/include/simpledbus/advanced/Proxy.h +117 -0
  275. data/vendor/simpleble/simpledbus/include/simpledbus/base/Connection.h +50 -0
  276. data/vendor/simpleble/simpledbus/include/simpledbus/base/Exceptions.h +56 -0
  277. data/vendor/simpleble/simpledbus/include/simpledbus/base/Holder.h +147 -0
  278. data/vendor/simpleble/simpledbus/include/simpledbus/base/Logging.h +57 -0
  279. data/vendor/simpleble/simpledbus/include/simpledbus/base/Message.h +89 -0
  280. data/vendor/simpleble/simpledbus/include/simpledbus/base/Path.h +24 -0
  281. data/vendor/simpleble/simpledbus/include/simpledbus/interfaces/ObjectManager.h +26 -0
  282. data/vendor/simpleble/simpledbus/src/advanced/Interface.cpp +155 -0
  283. data/vendor/simpleble/simpledbus/src/advanced/Proxy.cpp +375 -0
  284. data/vendor/simpleble/simpledbus/src/base/Connection.cpp +222 -0
  285. data/vendor/simpleble/simpledbus/src/base/Exceptions.cpp +39 -0
  286. data/vendor/simpleble/simpledbus/src/base/Holder.cpp +739 -0
  287. data/vendor/simpleble/simpledbus/src/base/Logging.cpp +52 -0
  288. data/vendor/simpleble/simpledbus/src/base/Message.cpp +622 -0
  289. data/vendor/simpleble/simpledbus/src/base/Path.cpp +129 -0
  290. data/vendor/simpleble/simpledbus/src/interfaces/ObjectManager.cpp +58 -0
  291. data/vendor/simpleble/simpledbus/test/src/helpers/PythonRunner.cpp +53 -0
  292. data/vendor/simpleble/simpledbus/test/src/helpers/PythonRunner.h +24 -0
  293. data/vendor/simpleble/simpledbus/test/src/main.cpp +16 -0
  294. data/vendor/simpleble/simpledbus/test/src/test_holder.cpp +184 -0
  295. data/vendor/simpleble/simpledbus/test/src/test_message.cpp +397 -0
  296. data/vendor/simpleble/simpledbus/test/src/test_path.cpp +76 -0
  297. data/vendor/simpleble/simpledbus/test/src/test_proxy_children.cpp +109 -0
  298. data/vendor/simpleble/simpledbus/test/src/test_proxy_interfaces.cpp +102 -0
  299. data/vendor/simpleble/simpledbus/test/src/test_proxy_lifetime.cpp +18 -0
  300. data/vendor/simpleble/simpledroidble/simpledroidble/src/main/cpp/ThreadRunner.h +89 -0
  301. data/vendor/simpleble/simpledroidble/simpledroidble/src/main/cpp/android_utils.cpp +55 -0
  302. data/vendor/simpleble/simpledroidble/simpledroidble/src/main/cpp/android_utils.h +18 -0
  303. data/vendor/simpleble/simpledroidble/simpledroidble/src/main/cpp/simpleble_android.cpp +813 -0
  304. data/vendor/simpleble/simplejavable/cpp/src/core/AdapterWrapper.cpp +37 -0
  305. data/vendor/simpleble/simplejavable/cpp/src/core/AdapterWrapper.h +23 -0
  306. data/vendor/simpleble/simplejavable/cpp/src/core/Cache.cpp +58 -0
  307. data/vendor/simpleble/simplejavable/cpp/src/core/Cache.h +34 -0
  308. data/vendor/simpleble/simplejavable/cpp/src/core/PeripheralWrapper.cpp +17 -0
  309. data/vendor/simpleble/simplejavable/cpp/src/core/PeripheralWrapper.h +19 -0
  310. data/vendor/simpleble/simplejavable/cpp/src/java/lang/ArrayList.cpp +257 -0
  311. data/vendor/simpleble/simplejavable/cpp/src/java/lang/ArrayList.h +78 -0
  312. data/vendor/simpleble/simplejavable/cpp/src/java/lang/HashMap.cpp +96 -0
  313. data/vendor/simpleble/simplejavable/cpp/src/java/lang/HashMap.h +54 -0
  314. data/vendor/simpleble/simplejavable/cpp/src/java/lang/Integer.cpp +93 -0
  315. data/vendor/simpleble/simplejavable/cpp/src/java/lang/Integer.h +49 -0
  316. data/vendor/simpleble/simplejavable/cpp/src/java/lang/Iterator.cpp +85 -0
  317. data/vendor/simpleble/simplejavable/cpp/src/java/lang/Iterator.h +48 -0
  318. data/vendor/simpleble/simplejavable/cpp/src/org/simplejavable/AdapterCallback.cpp +91 -0
  319. data/vendor/simpleble/simplejavable/cpp/src/org/simplejavable/AdapterCallback.h +90 -0
  320. data/vendor/simpleble/simplejavable/cpp/src/org/simplejavable/Characteristic.cpp +35 -0
  321. data/vendor/simpleble/simplejavable/cpp/src/org/simplejavable/Characteristic.h +60 -0
  322. data/vendor/simpleble/simplejavable/cpp/src/org/simplejavable/DataCallback.cpp +33 -0
  323. data/vendor/simpleble/simplejavable/cpp/src/org/simplejavable/DataCallback.h +45 -0
  324. data/vendor/simpleble/simplejavable/cpp/src/org/simplejavable/Descriptor.cpp +30 -0
  325. data/vendor/simpleble/simplejavable/cpp/src/org/simplejavable/Descriptor.h +49 -0
  326. data/vendor/simpleble/simplejavable/cpp/src/org/simplejavable/PeripheralCallback.cpp +41 -0
  327. data/vendor/simpleble/simplejavable/cpp/src/org/simplejavable/PeripheralCallback.h +51 -0
  328. data/vendor/simpleble/simplejavable/cpp/src/org/simplejavable/Service.cpp +33 -0
  329. data/vendor/simpleble/simplejavable/cpp/src/org/simplejavable/Service.h +54 -0
  330. data/vendor/simpleble/simplejavable/cpp/src/simplejavable.cpp +361 -0
  331. data/vendor/simpleble/simplepyble/src/main.cpp +55 -0
  332. data/vendor/simpleble/simplepyble/src/wrap_adapter.cpp +106 -0
  333. data/vendor/simpleble/simplepyble/src/wrap_characteristic.cpp +56 -0
  334. data/vendor/simpleble/simplepyble/src/wrap_config.cpp +136 -0
  335. data/vendor/simpleble/simplepyble/src/wrap_descriptor.cpp +21 -0
  336. data/vendor/simpleble/simplepyble/src/wrap_peripheral.cpp +217 -0
  337. data/vendor/simpleble/simplepyble/src/wrap_service.cpp +32 -0
  338. data/vendor/simpleble/simplepyble/src/wrap_types.cpp +21 -0
  339. data/vendor/simpleble/simplersble/src/bindings/Bindings.cpp +338 -0
  340. data/vendor/simpleble/simplersble/src/bindings/Bindings.hpp +178 -0
  341. metadata +430 -0
@@ -0,0 +1,2962 @@
1
+ // Formatting library for C++ - the base API for char/UTF-8
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_BASE_H_
9
+ #define FMT_BASE_H_
10
+
11
+ #if defined(FMT_IMPORT_STD) && !defined(FMT_MODULE)
12
+ # define FMT_MODULE
13
+ #endif
14
+
15
+ #ifndef FMT_MODULE
16
+ # include <limits.h> // CHAR_BIT
17
+ # include <stdio.h> // FILE
18
+ # include <string.h> // memcmp
19
+
20
+ # include <type_traits> // std::enable_if
21
+ #endif
22
+
23
+ // The fmt library version in the form major * 10000 + minor * 100 + patch.
24
+ #define FMT_VERSION 110104
25
+
26
+ // Detect compiler versions.
27
+ #if defined(__clang__) && !defined(__ibmxl__)
28
+ # define FMT_CLANG_VERSION (__clang_major__ * 100 + __clang_minor__)
29
+ #else
30
+ # define FMT_CLANG_VERSION 0
31
+ #endif
32
+ #if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER)
33
+ # define FMT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
34
+ #else
35
+ # define FMT_GCC_VERSION 0
36
+ #endif
37
+ #if defined(__ICL)
38
+ # define FMT_ICC_VERSION __ICL
39
+ #elif defined(__INTEL_COMPILER)
40
+ # define FMT_ICC_VERSION __INTEL_COMPILER
41
+ #else
42
+ # define FMT_ICC_VERSION 0
43
+ #endif
44
+ #if defined(_MSC_VER)
45
+ # define FMT_MSC_VERSION _MSC_VER
46
+ #else
47
+ # define FMT_MSC_VERSION 0
48
+ #endif
49
+
50
+ // Detect standard library versions.
51
+ #ifdef _GLIBCXX_RELEASE
52
+ # define FMT_GLIBCXX_RELEASE _GLIBCXX_RELEASE
53
+ #else
54
+ # define FMT_GLIBCXX_RELEASE 0
55
+ #endif
56
+ #ifdef _LIBCPP_VERSION
57
+ # define FMT_LIBCPP_VERSION _LIBCPP_VERSION
58
+ #else
59
+ # define FMT_LIBCPP_VERSION 0
60
+ #endif
61
+
62
+ #ifdef _MSVC_LANG
63
+ # define FMT_CPLUSPLUS _MSVC_LANG
64
+ #else
65
+ # define FMT_CPLUSPLUS __cplusplus
66
+ #endif
67
+
68
+ // Detect __has_*.
69
+ #ifdef __has_feature
70
+ # define FMT_HAS_FEATURE(x) __has_feature(x)
71
+ #else
72
+ # define FMT_HAS_FEATURE(x) 0
73
+ #endif
74
+ #ifdef __has_include
75
+ # define FMT_HAS_INCLUDE(x) __has_include(x)
76
+ #else
77
+ # define FMT_HAS_INCLUDE(x) 0
78
+ #endif
79
+ #ifdef __has_builtin
80
+ # define FMT_HAS_BUILTIN(x) __has_builtin(x)
81
+ #else
82
+ # define FMT_HAS_BUILTIN(x) 0
83
+ #endif
84
+ #ifdef __has_cpp_attribute
85
+ # define FMT_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
86
+ #else
87
+ # define FMT_HAS_CPP_ATTRIBUTE(x) 0
88
+ #endif
89
+
90
+ #define FMT_HAS_CPP14_ATTRIBUTE(attribute) \
91
+ (FMT_CPLUSPLUS >= 201402L && FMT_HAS_CPP_ATTRIBUTE(attribute))
92
+
93
+ #define FMT_HAS_CPP17_ATTRIBUTE(attribute) \
94
+ (FMT_CPLUSPLUS >= 201703L && FMT_HAS_CPP_ATTRIBUTE(attribute))
95
+
96
+ // Detect C++14 relaxed constexpr.
97
+ #ifdef FMT_USE_CONSTEXPR
98
+ // Use the provided definition.
99
+ #elif FMT_GCC_VERSION >= 702 && FMT_CPLUSPLUS >= 201402L
100
+ // GCC only allows constexpr member functions in non-literal types since 7.2:
101
+ // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66297.
102
+ # define FMT_USE_CONSTEXPR 1
103
+ #elif FMT_ICC_VERSION
104
+ # define FMT_USE_CONSTEXPR 0 // https://github.com/fmtlib/fmt/issues/1628
105
+ #elif FMT_HAS_FEATURE(cxx_relaxed_constexpr) || FMT_MSC_VERSION >= 1912
106
+ # define FMT_USE_CONSTEXPR 1
107
+ #else
108
+ # define FMT_USE_CONSTEXPR 0
109
+ #endif
110
+ #if FMT_USE_CONSTEXPR
111
+ # define FMT_CONSTEXPR constexpr
112
+ #else
113
+ # define FMT_CONSTEXPR
114
+ #endif
115
+
116
+ // Detect consteval, C++20 constexpr extensions and std::is_constant_evaluated.
117
+ #if !defined(__cpp_lib_is_constant_evaluated)
118
+ # define FMT_USE_CONSTEVAL 0
119
+ #elif FMT_CPLUSPLUS < 201709L
120
+ # define FMT_USE_CONSTEVAL 0
121
+ #elif FMT_GLIBCXX_RELEASE && FMT_GLIBCXX_RELEASE < 10
122
+ # define FMT_USE_CONSTEVAL 0
123
+ #elif FMT_LIBCPP_VERSION && FMT_LIBCPP_VERSION < 10000
124
+ # define FMT_USE_CONSTEVAL 0
125
+ #elif defined(__apple_build_version__) && __apple_build_version__ < 14000029L
126
+ # define FMT_USE_CONSTEVAL 0 // consteval is broken in Apple clang < 14.
127
+ #elif FMT_MSC_VERSION && FMT_MSC_VERSION < 1929
128
+ # define FMT_USE_CONSTEVAL 0 // consteval is broken in MSVC VS2019 < 16.10.
129
+ #elif defined(__cpp_consteval)
130
+ # define FMT_USE_CONSTEVAL 1
131
+ #elif FMT_GCC_VERSION >= 1002 || FMT_CLANG_VERSION >= 1101
132
+ # define FMT_USE_CONSTEVAL 1
133
+ #else
134
+ # define FMT_USE_CONSTEVAL 0
135
+ #endif
136
+ #if FMT_USE_CONSTEVAL
137
+ # define FMT_CONSTEVAL consteval
138
+ # define FMT_CONSTEXPR20 constexpr
139
+ #else
140
+ # define FMT_CONSTEVAL
141
+ # define FMT_CONSTEXPR20
142
+ #endif
143
+
144
+ // Check if exceptions are disabled.
145
+ #ifdef FMT_USE_EXCEPTIONS
146
+ // Use the provided definition.
147
+ #elif defined(__GNUC__) && !defined(__EXCEPTIONS)
148
+ # define FMT_USE_EXCEPTIONS 0
149
+ #elif defined(__clang__) && !defined(__cpp_exceptions)
150
+ # define FMT_USE_EXCEPTIONS 0
151
+ #elif FMT_MSC_VERSION && !_HAS_EXCEPTIONS
152
+ # define FMT_USE_EXCEPTIONS 0
153
+ #else
154
+ # define FMT_USE_EXCEPTIONS 1
155
+ #endif
156
+ #if FMT_USE_EXCEPTIONS
157
+ # define FMT_TRY try
158
+ # define FMT_CATCH(x) catch (x)
159
+ #else
160
+ # define FMT_TRY if (true)
161
+ # define FMT_CATCH(x) if (false)
162
+ #endif
163
+
164
+ #ifdef FMT_NO_UNIQUE_ADDRESS
165
+ // Use the provided definition.
166
+ #elif FMT_CPLUSPLUS < 202002L
167
+ // Not supported.
168
+ #elif FMT_HAS_CPP_ATTRIBUTE(no_unique_address)
169
+ # define FMT_NO_UNIQUE_ADDRESS [[no_unique_address]]
170
+ // VS2019 v16.10 and later except clang-cl (https://reviews.llvm.org/D110485).
171
+ #elif FMT_MSC_VERSION >= 1929 && !FMT_CLANG_VERSION
172
+ # define FMT_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]]
173
+ #endif
174
+ #ifndef FMT_NO_UNIQUE_ADDRESS
175
+ # define FMT_NO_UNIQUE_ADDRESS
176
+ #endif
177
+
178
+ #if FMT_HAS_CPP17_ATTRIBUTE(fallthrough)
179
+ # define FMT_FALLTHROUGH [[fallthrough]]
180
+ #elif defined(__clang__)
181
+ # define FMT_FALLTHROUGH [[clang::fallthrough]]
182
+ #elif FMT_GCC_VERSION >= 700 && \
183
+ (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= 520)
184
+ # define FMT_FALLTHROUGH [[gnu::fallthrough]]
185
+ #else
186
+ # define FMT_FALLTHROUGH
187
+ #endif
188
+
189
+ // Disable [[noreturn]] on MSVC/NVCC because of bogus unreachable code warnings.
190
+ #if FMT_HAS_CPP_ATTRIBUTE(noreturn) && !FMT_MSC_VERSION && !defined(__NVCC__)
191
+ # define FMT_NORETURN [[noreturn]]
192
+ #else
193
+ # define FMT_NORETURN
194
+ #endif
195
+
196
+ #ifdef FMT_NODISCARD
197
+ // Use the provided definition.
198
+ #elif FMT_HAS_CPP17_ATTRIBUTE(nodiscard)
199
+ # define FMT_NODISCARD [[nodiscard]]
200
+ #else
201
+ # define FMT_NODISCARD
202
+ #endif
203
+
204
+ #ifdef FMT_DEPRECATED
205
+ // Use the provided definition.
206
+ #elif FMT_HAS_CPP14_ATTRIBUTE(deprecated)
207
+ # define FMT_DEPRECATED [[deprecated]]
208
+ #else
209
+ # define FMT_DEPRECATED /* deprecated */
210
+ #endif
211
+
212
+ #ifdef FMT_ALWAYS_INLINE
213
+ // Use the provided definition.
214
+ #elif FMT_GCC_VERSION || FMT_CLANG_VERSION
215
+ # define FMT_ALWAYS_INLINE inline __attribute__((always_inline))
216
+ #else
217
+ # define FMT_ALWAYS_INLINE inline
218
+ #endif
219
+ // A version of FMT_ALWAYS_INLINE to prevent code bloat in debug mode.
220
+ #ifdef NDEBUG
221
+ # define FMT_INLINE FMT_ALWAYS_INLINE
222
+ #else
223
+ # define FMT_INLINE inline
224
+ #endif
225
+
226
+ #if FMT_GCC_VERSION || FMT_CLANG_VERSION
227
+ # define FMT_VISIBILITY(value) __attribute__((visibility(value)))
228
+ #else
229
+ # define FMT_VISIBILITY(value)
230
+ #endif
231
+
232
+ // Detect pragmas.
233
+ #define FMT_PRAGMA_IMPL(x) _Pragma(#x)
234
+ #if FMT_GCC_VERSION >= 504 && !defined(__NVCOMPILER)
235
+ // Workaround a _Pragma bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59884
236
+ // and an nvhpc warning: https://github.com/fmtlib/fmt/pull/2582.
237
+ # define FMT_PRAGMA_GCC(x) FMT_PRAGMA_IMPL(GCC x)
238
+ #else
239
+ # define FMT_PRAGMA_GCC(x)
240
+ #endif
241
+ #if FMT_CLANG_VERSION
242
+ # define FMT_PRAGMA_CLANG(x) FMT_PRAGMA_IMPL(clang x)
243
+ #else
244
+ # define FMT_PRAGMA_CLANG(x)
245
+ #endif
246
+ #if FMT_MSC_VERSION
247
+ # define FMT_MSC_WARNING(...) __pragma(warning(__VA_ARGS__))
248
+ #else
249
+ # define FMT_MSC_WARNING(...)
250
+ #endif
251
+
252
+ #ifndef FMT_BEGIN_NAMESPACE
253
+ # define FMT_BEGIN_NAMESPACE \
254
+ namespace fmt { \
255
+ inline namespace v11 {
256
+ # define FMT_END_NAMESPACE \
257
+ } \
258
+ }
259
+ #endif
260
+
261
+ #ifndef FMT_EXPORT
262
+ # define FMT_EXPORT
263
+ # define FMT_BEGIN_EXPORT
264
+ # define FMT_END_EXPORT
265
+ #endif
266
+
267
+ #ifdef _WIN32
268
+ # define FMT_WIN32 1
269
+ #else
270
+ # define FMT_WIN32 0
271
+ #endif
272
+
273
+ #if !defined(FMT_HEADER_ONLY) && FMT_WIN32
274
+ # if defined(FMT_LIB_EXPORT)
275
+ # define FMT_API __declspec(dllexport)
276
+ # elif defined(FMT_SHARED)
277
+ # define FMT_API __declspec(dllimport)
278
+ # endif
279
+ #elif defined(FMT_LIB_EXPORT) || defined(FMT_SHARED)
280
+ # define FMT_API FMT_VISIBILITY("default")
281
+ #endif
282
+ #ifndef FMT_API
283
+ # define FMT_API
284
+ #endif
285
+
286
+ #ifndef FMT_OPTIMIZE_SIZE
287
+ # define FMT_OPTIMIZE_SIZE 0
288
+ #endif
289
+
290
+ // FMT_BUILTIN_TYPE=0 may result in smaller library size at the cost of higher
291
+ // per-call binary size by passing built-in types through the extension API.
292
+ #ifndef FMT_BUILTIN_TYPES
293
+ # define FMT_BUILTIN_TYPES 1
294
+ #endif
295
+
296
+ #define FMT_APPLY_VARIADIC(expr) \
297
+ using unused = int[]; \
298
+ (void)unused { 0, (expr, 0)... }
299
+
300
+ // Enable minimal optimizations for more compact code in debug mode.
301
+ FMT_PRAGMA_GCC(push_options)
302
+ #if !defined(__OPTIMIZE__) && !defined(__CUDACC__) && !defined(FMT_MODULE)
303
+ FMT_PRAGMA_GCC(optimize("Og"))
304
+ #endif
305
+ FMT_PRAGMA_CLANG(diagnostic push)
306
+
307
+ FMT_BEGIN_NAMESPACE
308
+
309
+ // Implementations of enable_if_t and other metafunctions for older systems.
310
+ template <bool B, typename T = void>
311
+ using enable_if_t = typename std::enable_if<B, T>::type;
312
+ template <bool B, typename T, typename F>
313
+ using conditional_t = typename std::conditional<B, T, F>::type;
314
+ template <bool B> using bool_constant = std::integral_constant<bool, B>;
315
+ template <typename T>
316
+ using remove_reference_t = typename std::remove_reference<T>::type;
317
+ template <typename T>
318
+ using remove_const_t = typename std::remove_const<T>::type;
319
+ template <typename T>
320
+ using remove_cvref_t = typename std::remove_cv<remove_reference_t<T>>::type;
321
+ template <typename T>
322
+ using make_unsigned_t = typename std::make_unsigned<T>::type;
323
+ template <typename T>
324
+ using underlying_t = typename std::underlying_type<T>::type;
325
+ template <typename T> using decay_t = typename std::decay<T>::type;
326
+ using nullptr_t = decltype(nullptr);
327
+
328
+ #if FMT_GCC_VERSION && FMT_GCC_VERSION < 500
329
+ // A workaround for gcc 4.9 to make void_t work in a SFINAE context.
330
+ template <typename...> struct void_t_impl {
331
+ using type = void;
332
+ };
333
+ template <typename... T> using void_t = typename void_t_impl<T...>::type;
334
+ #else
335
+ template <typename...> using void_t = void;
336
+ #endif
337
+
338
+ struct monostate {
339
+ constexpr monostate() {}
340
+ };
341
+
342
+ // An enable_if helper to be used in template parameters which results in much
343
+ // shorter symbols: https://godbolt.org/z/sWw4vP. Extra parentheses are needed
344
+ // to workaround a bug in MSVC 2019 (see #1140 and #1186).
345
+ #ifdef FMT_DOC
346
+ # define FMT_ENABLE_IF(...)
347
+ #else
348
+ # define FMT_ENABLE_IF(...) fmt::enable_if_t<(__VA_ARGS__), int> = 0
349
+ #endif
350
+
351
+ template <typename T> constexpr auto min_of(T a, T b) -> T {
352
+ return a < b ? a : b;
353
+ }
354
+ template <typename T> constexpr auto max_of(T a, T b) -> T {
355
+ return a > b ? a : b;
356
+ }
357
+
358
+ namespace detail {
359
+ // Suppresses "unused variable" warnings with the method described in
360
+ // https://herbsutter.com/2009/10/18/mailbag-shutting-up-compiler-warnings/.
361
+ // (void)var does not work on many Intel compilers.
362
+ template <typename... T> FMT_CONSTEXPR void ignore_unused(const T&...) {}
363
+
364
+ constexpr auto is_constant_evaluated(bool default_value = false) noexcept
365
+ -> bool {
366
+ // Workaround for incompatibility between clang 14 and libstdc++ consteval-based
367
+ // std::is_constant_evaluated: https://github.com/fmtlib/fmt/issues/3247.
368
+ #if FMT_CPLUSPLUS >= 202002L && FMT_GLIBCXX_RELEASE >= 12 && \
369
+ (FMT_CLANG_VERSION >= 1400 && FMT_CLANG_VERSION < 1500)
370
+ ignore_unused(default_value);
371
+ return __builtin_is_constant_evaluated();
372
+ #elif defined(__cpp_lib_is_constant_evaluated)
373
+ ignore_unused(default_value);
374
+ return std::is_constant_evaluated();
375
+ #else
376
+ return default_value;
377
+ #endif
378
+ }
379
+
380
+ // Suppresses "conditional expression is constant" warnings.
381
+ template <typename T> FMT_ALWAYS_INLINE constexpr auto const_check(T val) -> T {
382
+ return val;
383
+ }
384
+
385
+ FMT_NORETURN FMT_API void assert_fail(const char* file, int line,
386
+ const char* message);
387
+
388
+ #if defined(FMT_ASSERT)
389
+ // Use the provided definition.
390
+ #elif defined(NDEBUG)
391
+ // FMT_ASSERT is not empty to avoid -Wempty-body.
392
+ # define FMT_ASSERT(condition, message) \
393
+ fmt::detail::ignore_unused((condition), (message))
394
+ #else
395
+ # define FMT_ASSERT(condition, message) \
396
+ ((condition) /* void() fails with -Winvalid-constexpr on clang 4.0.1 */ \
397
+ ? (void)0 \
398
+ : fmt::detail::assert_fail(__FILE__, __LINE__, (message)))
399
+ #endif
400
+
401
+ #ifdef FMT_USE_INT128
402
+ // Use the provided definition.
403
+ #elif defined(__SIZEOF_INT128__) && !defined(__NVCC__) && \
404
+ !(FMT_CLANG_VERSION && FMT_MSC_VERSION)
405
+ # define FMT_USE_INT128 1
406
+ using int128_opt = __int128_t; // An optional native 128-bit integer.
407
+ using uint128_opt = __uint128_t;
408
+ inline auto map(int128_opt x) -> int128_opt { return x; }
409
+ inline auto map(uint128_opt x) -> uint128_opt { return x; }
410
+ #else
411
+ # define FMT_USE_INT128 0
412
+ #endif
413
+ #if !FMT_USE_INT128
414
+ enum class int128_opt {};
415
+ enum class uint128_opt {};
416
+ // Reduce template instantiations.
417
+ inline auto map(int128_opt) -> monostate { return {}; }
418
+ inline auto map(uint128_opt) -> monostate { return {}; }
419
+ #endif
420
+
421
+ #ifndef FMT_USE_BITINT
422
+ # define FMT_USE_BITINT (FMT_CLANG_VERSION >= 1500)
423
+ #endif
424
+
425
+ #if FMT_USE_BITINT
426
+ FMT_PRAGMA_CLANG(diagnostic ignored "-Wbit-int-extension")
427
+ template <int N> using bitint = _BitInt(N);
428
+ template <int N> using ubitint = unsigned _BitInt(N);
429
+ #else
430
+ template <int N> struct bitint {};
431
+ template <int N> struct ubitint {};
432
+ #endif // FMT_USE_BITINT
433
+
434
+ // Casts a nonnegative integer to unsigned.
435
+ template <typename Int>
436
+ FMT_CONSTEXPR auto to_unsigned(Int value) -> make_unsigned_t<Int> {
437
+ FMT_ASSERT(std::is_unsigned<Int>::value || value >= 0, "negative value");
438
+ return static_cast<make_unsigned_t<Int>>(value);
439
+ }
440
+
441
+ template <typename Char>
442
+ using unsigned_char = conditional_t<sizeof(Char) == 1, unsigned char, unsigned>;
443
+
444
+ // A heuristic to detect std::string and std::[experimental::]string_view.
445
+ // It is mainly used to avoid dependency on <[experimental/]string_view>.
446
+ template <typename T, typename Enable = void>
447
+ struct is_std_string_like : std::false_type {};
448
+ template <typename T>
449
+ struct is_std_string_like<T, void_t<decltype(std::declval<T>().find_first_of(
450
+ typename T::value_type(), 0))>>
451
+ : std::is_convertible<decltype(std::declval<T>().data()),
452
+ const typename T::value_type*> {};
453
+
454
+ // Check if the literal encoding is UTF-8.
455
+ enum { is_utf8_enabled = "\u00A7"[1] == '\xA7' };
456
+ enum { use_utf8 = !FMT_WIN32 || is_utf8_enabled };
457
+
458
+ #ifndef FMT_UNICODE
459
+ # define FMT_UNICODE 1
460
+ #endif
461
+
462
+ static_assert(!FMT_UNICODE || use_utf8,
463
+ "Unicode support requires compiling with /utf-8");
464
+
465
+ template <typename T> constexpr const char* narrow(const T*) { return nullptr; }
466
+ constexpr FMT_ALWAYS_INLINE const char* narrow(const char* s) { return s; }
467
+
468
+ template <typename Char>
469
+ FMT_CONSTEXPR auto compare(const Char* s1, const Char* s2, std::size_t n)
470
+ -> int {
471
+ if (!is_constant_evaluated() && sizeof(Char) == 1) return memcmp(s1, s2, n);
472
+ for (; n != 0; ++s1, ++s2, --n) {
473
+ if (*s1 < *s2) return -1;
474
+ if (*s1 > *s2) return 1;
475
+ }
476
+ return 0;
477
+ }
478
+
479
+ namespace adl {
480
+ using namespace std;
481
+
482
+ template <typename Container>
483
+ auto invoke_back_inserter()
484
+ -> decltype(back_inserter(std::declval<Container&>()));
485
+ } // namespace adl
486
+
487
+ template <typename It, typename Enable = std::true_type>
488
+ struct is_back_insert_iterator : std::false_type {};
489
+
490
+ template <typename It>
491
+ struct is_back_insert_iterator<
492
+ It, bool_constant<std::is_same<
493
+ decltype(adl::invoke_back_inserter<typename It::container_type>()),
494
+ It>::value>> : std::true_type {};
495
+
496
+ // Extracts a reference to the container from *insert_iterator.
497
+ template <typename OutputIt>
498
+ inline FMT_CONSTEXPR20 auto get_container(OutputIt it) ->
499
+ typename OutputIt::container_type& {
500
+ struct accessor : OutputIt {
501
+ FMT_CONSTEXPR20 accessor(OutputIt base) : OutputIt(base) {}
502
+ using OutputIt::container;
503
+ };
504
+ return *accessor(it).container;
505
+ }
506
+ } // namespace detail
507
+
508
+ // Parsing-related public API and forward declarations.
509
+ FMT_BEGIN_EXPORT
510
+
511
+ /**
512
+ * An implementation of `std::basic_string_view` for pre-C++17. It provides a
513
+ * subset of the API. `fmt::basic_string_view` is used for format strings even
514
+ * if `std::basic_string_view` is available to prevent issues when a library is
515
+ * compiled with a different `-std` option than the client code (which is not
516
+ * recommended).
517
+ */
518
+ template <typename Char> class basic_string_view {
519
+ private:
520
+ const Char* data_;
521
+ size_t size_;
522
+
523
+ public:
524
+ using value_type = Char;
525
+ using iterator = const Char*;
526
+
527
+ constexpr basic_string_view() noexcept : data_(nullptr), size_(0) {}
528
+
529
+ /// Constructs a string reference object from a C string and a size.
530
+ constexpr basic_string_view(const Char* s, size_t count) noexcept
531
+ : data_(s), size_(count) {}
532
+
533
+ constexpr basic_string_view(nullptr_t) = delete;
534
+
535
+ /// Constructs a string reference object from a C string.
536
+ #if FMT_GCC_VERSION
537
+ FMT_ALWAYS_INLINE
538
+ #endif
539
+ FMT_CONSTEXPR20 basic_string_view(const Char* s) : data_(s) {
540
+ #if FMT_HAS_BUILTIN(__builtin_strlen) || FMT_GCC_VERSION || FMT_CLANG_VERSION
541
+ if (std::is_same<Char, char>::value) {
542
+ size_ = __builtin_strlen(detail::narrow(s));
543
+ return;
544
+ }
545
+ #endif
546
+ size_t len = 0;
547
+ while (*s++) ++len;
548
+ size_ = len;
549
+ }
550
+
551
+ /// Constructs a string reference from a `std::basic_string` or a
552
+ /// `std::basic_string_view` object.
553
+ template <typename S,
554
+ FMT_ENABLE_IF(detail::is_std_string_like<S>::value&& std::is_same<
555
+ typename S::value_type, Char>::value)>
556
+ FMT_CONSTEXPR basic_string_view(const S& s) noexcept
557
+ : data_(s.data()), size_(s.size()) {}
558
+
559
+ /// Returns a pointer to the string data.
560
+ constexpr auto data() const noexcept -> const Char* { return data_; }
561
+
562
+ /// Returns the string size.
563
+ constexpr auto size() const noexcept -> size_t { return size_; }
564
+
565
+ constexpr auto begin() const noexcept -> iterator { return data_; }
566
+ constexpr auto end() const noexcept -> iterator { return data_ + size_; }
567
+
568
+ constexpr auto operator[](size_t pos) const noexcept -> const Char& {
569
+ return data_[pos];
570
+ }
571
+
572
+ FMT_CONSTEXPR void remove_prefix(size_t n) noexcept {
573
+ data_ += n;
574
+ size_ -= n;
575
+ }
576
+
577
+ FMT_CONSTEXPR auto starts_with(basic_string_view<Char> sv) const noexcept
578
+ -> bool {
579
+ return size_ >= sv.size_ && detail::compare(data_, sv.data_, sv.size_) == 0;
580
+ }
581
+ FMT_CONSTEXPR auto starts_with(Char c) const noexcept -> bool {
582
+ return size_ >= 1 && *data_ == c;
583
+ }
584
+ FMT_CONSTEXPR auto starts_with(const Char* s) const -> bool {
585
+ return starts_with(basic_string_view<Char>(s));
586
+ }
587
+
588
+ // Lexicographically compare this string reference to other.
589
+ FMT_CONSTEXPR auto compare(basic_string_view other) const -> int {
590
+ int result =
591
+ detail::compare(data_, other.data_, min_of(size_, other.size_));
592
+ if (result != 0) return result;
593
+ return size_ == other.size_ ? 0 : (size_ < other.size_ ? -1 : 1);
594
+ }
595
+
596
+ FMT_CONSTEXPR friend auto operator==(basic_string_view lhs,
597
+ basic_string_view rhs) -> bool {
598
+ return lhs.compare(rhs) == 0;
599
+ }
600
+ friend auto operator!=(basic_string_view lhs, basic_string_view rhs) -> bool {
601
+ return lhs.compare(rhs) != 0;
602
+ }
603
+ friend auto operator<(basic_string_view lhs, basic_string_view rhs) -> bool {
604
+ return lhs.compare(rhs) < 0;
605
+ }
606
+ friend auto operator<=(basic_string_view lhs, basic_string_view rhs) -> bool {
607
+ return lhs.compare(rhs) <= 0;
608
+ }
609
+ friend auto operator>(basic_string_view lhs, basic_string_view rhs) -> bool {
610
+ return lhs.compare(rhs) > 0;
611
+ }
612
+ friend auto operator>=(basic_string_view lhs, basic_string_view rhs) -> bool {
613
+ return lhs.compare(rhs) >= 0;
614
+ }
615
+ };
616
+
617
+ using string_view = basic_string_view<char>;
618
+
619
+ /// Specifies if `T` is an extended character type. Can be specialized by users.
620
+ template <typename T> struct is_xchar : std::false_type {};
621
+ template <> struct is_xchar<wchar_t> : std::true_type {};
622
+ template <> struct is_xchar<char16_t> : std::true_type {};
623
+ template <> struct is_xchar<char32_t> : std::true_type {};
624
+ #ifdef __cpp_char8_t
625
+ template <> struct is_xchar<char8_t> : std::true_type {};
626
+ #endif
627
+
628
+ // DEPRECATED! Will be replaced with an alias to prevent specializations.
629
+ template <typename T> struct is_char : is_xchar<T> {};
630
+ template <> struct is_char<char> : std::true_type {};
631
+
632
+ template <typename T> class basic_appender;
633
+ using appender = basic_appender<char>;
634
+
635
+ // Checks whether T is a container with contiguous storage.
636
+ template <typename T> struct is_contiguous : std::false_type {};
637
+
638
+ class context;
639
+ template <typename OutputIt, typename Char> class generic_context;
640
+ template <typename Char> class parse_context;
641
+
642
+ // Longer aliases for C++20 compatibility.
643
+ template <typename Char> using basic_format_parse_context = parse_context<Char>;
644
+ using format_parse_context = parse_context<char>;
645
+ template <typename OutputIt, typename Char>
646
+ using basic_format_context =
647
+ conditional_t<std::is_same<OutputIt, appender>::value, context,
648
+ generic_context<OutputIt, Char>>;
649
+ using format_context = context;
650
+
651
+ template <typename Char>
652
+ using buffered_context =
653
+ conditional_t<std::is_same<Char, char>::value, context,
654
+ generic_context<basic_appender<Char>, Char>>;
655
+
656
+ template <typename Context> class basic_format_arg;
657
+ template <typename Context> class basic_format_args;
658
+
659
+ // A separate type would result in shorter symbols but break ABI compatibility
660
+ // between clang and gcc on ARM (#1919).
661
+ using format_args = basic_format_args<context>;
662
+
663
+ // A formatter for objects of type T.
664
+ template <typename T, typename Char = char, typename Enable = void>
665
+ struct formatter {
666
+ // A deleted default constructor indicates a disabled formatter.
667
+ formatter() = delete;
668
+ };
669
+
670
+ /// Reports a format error at compile time or, via a `format_error` exception,
671
+ /// at runtime.
672
+ // This function is intentionally not constexpr to give a compile-time error.
673
+ FMT_NORETURN FMT_API void report_error(const char* message);
674
+
675
+ enum class presentation_type : unsigned char {
676
+ // Common specifiers:
677
+ none = 0,
678
+ debug = 1, // '?'
679
+ string = 2, // 's' (string, bool)
680
+
681
+ // Integral, bool and character specifiers:
682
+ dec = 3, // 'd'
683
+ hex, // 'x' or 'X'
684
+ oct, // 'o'
685
+ bin, // 'b' or 'B'
686
+ chr, // 'c'
687
+
688
+ // String and pointer specifiers:
689
+ pointer = 3, // 'p'
690
+
691
+ // Floating-point specifiers:
692
+ exp = 1, // 'e' or 'E' (1 since there is no FP debug presentation)
693
+ fixed, // 'f' or 'F'
694
+ general, // 'g' or 'G'
695
+ hexfloat // 'a' or 'A'
696
+ };
697
+
698
+ enum class align { none, left, right, center, numeric };
699
+ enum class sign { none, minus, plus, space };
700
+ enum class arg_id_kind { none, index, name };
701
+
702
+ // Basic format specifiers for built-in and string types.
703
+ class basic_specs {
704
+ private:
705
+ // Data is arranged as follows:
706
+ //
707
+ // 0 1 2 3
708
+ // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
709
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
710
+ // |type |align| w | p | s |u|#|L| f | unused |
711
+ // +-----+-----+---+---+---+-+-+-+-----+---------------------------+
712
+ //
713
+ // w - dynamic width info
714
+ // p - dynamic precision info
715
+ // s - sign
716
+ // u - uppercase (e.g. 'X' for 'x')
717
+ // # - alternate form ('#')
718
+ // L - localized
719
+ // f - fill size
720
+ //
721
+ // Bitfields are not used because of compiler bugs such as gcc bug 61414.
722
+ enum : unsigned {
723
+ type_mask = 0x00007,
724
+ align_mask = 0x00038,
725
+ width_mask = 0x000C0,
726
+ precision_mask = 0x00300,
727
+ sign_mask = 0x00C00,
728
+ uppercase_mask = 0x01000,
729
+ alternate_mask = 0x02000,
730
+ localized_mask = 0x04000,
731
+ fill_size_mask = 0x38000,
732
+
733
+ align_shift = 3,
734
+ width_shift = 6,
735
+ precision_shift = 8,
736
+ sign_shift = 10,
737
+ fill_size_shift = 15,
738
+
739
+ max_fill_size = 4
740
+ };
741
+
742
+ unsigned data_ = 1 << fill_size_shift;
743
+ static_assert(sizeof(basic_specs::data_) * CHAR_BIT >= 18, "");
744
+
745
+ // Character (code unit) type is erased to prevent template bloat.
746
+ char fill_data_[max_fill_size] = {' '};
747
+
748
+ FMT_CONSTEXPR void set_fill_size(size_t size) {
749
+ data_ = (data_ & ~fill_size_mask) |
750
+ (static_cast<unsigned>(size) << fill_size_shift);
751
+ }
752
+
753
+ public:
754
+ constexpr auto type() const -> presentation_type {
755
+ return static_cast<presentation_type>(data_ & type_mask);
756
+ }
757
+ FMT_CONSTEXPR void set_type(presentation_type t) {
758
+ data_ = (data_ & ~type_mask) | static_cast<unsigned>(t);
759
+ }
760
+
761
+ constexpr auto align() const -> align {
762
+ return static_cast<fmt::align>((data_ & align_mask) >> align_shift);
763
+ }
764
+ FMT_CONSTEXPR void set_align(fmt::align a) {
765
+ data_ = (data_ & ~align_mask) | (static_cast<unsigned>(a) << align_shift);
766
+ }
767
+
768
+ constexpr auto dynamic_width() const -> arg_id_kind {
769
+ return static_cast<arg_id_kind>((data_ & width_mask) >> width_shift);
770
+ }
771
+ FMT_CONSTEXPR void set_dynamic_width(arg_id_kind w) {
772
+ data_ = (data_ & ~width_mask) | (static_cast<unsigned>(w) << width_shift);
773
+ }
774
+
775
+ FMT_CONSTEXPR auto dynamic_precision() const -> arg_id_kind {
776
+ return static_cast<arg_id_kind>((data_ & precision_mask) >>
777
+ precision_shift);
778
+ }
779
+ FMT_CONSTEXPR void set_dynamic_precision(arg_id_kind p) {
780
+ data_ = (data_ & ~precision_mask) |
781
+ (static_cast<unsigned>(p) << precision_shift);
782
+ }
783
+
784
+ constexpr bool dynamic() const {
785
+ return (data_ & (width_mask | precision_mask)) != 0;
786
+ }
787
+
788
+ constexpr auto sign() const -> sign {
789
+ return static_cast<fmt::sign>((data_ & sign_mask) >> sign_shift);
790
+ }
791
+ FMT_CONSTEXPR void set_sign(fmt::sign s) {
792
+ data_ = (data_ & ~sign_mask) | (static_cast<unsigned>(s) << sign_shift);
793
+ }
794
+
795
+ constexpr auto upper() const -> bool { return (data_ & uppercase_mask) != 0; }
796
+ FMT_CONSTEXPR void set_upper() { data_ |= uppercase_mask; }
797
+
798
+ constexpr auto alt() const -> bool { return (data_ & alternate_mask) != 0; }
799
+ FMT_CONSTEXPR void set_alt() { data_ |= alternate_mask; }
800
+ FMT_CONSTEXPR void clear_alt() { data_ &= ~alternate_mask; }
801
+
802
+ constexpr auto localized() const -> bool {
803
+ return (data_ & localized_mask) != 0;
804
+ }
805
+ FMT_CONSTEXPR void set_localized() { data_ |= localized_mask; }
806
+
807
+ constexpr auto fill_size() const -> size_t {
808
+ return (data_ & fill_size_mask) >> fill_size_shift;
809
+ }
810
+
811
+ template <typename Char, FMT_ENABLE_IF(std::is_same<Char, char>::value)>
812
+ constexpr auto fill() const -> const Char* {
813
+ return fill_data_;
814
+ }
815
+ template <typename Char, FMT_ENABLE_IF(!std::is_same<Char, char>::value)>
816
+ constexpr auto fill() const -> const Char* {
817
+ return nullptr;
818
+ }
819
+
820
+ template <typename Char> constexpr auto fill_unit() const -> Char {
821
+ using uchar = unsigned char;
822
+ return static_cast<Char>(static_cast<uchar>(fill_data_[0]) |
823
+ (static_cast<uchar>(fill_data_[1]) << 8) |
824
+ (static_cast<uchar>(fill_data_[2]) << 16));
825
+ }
826
+
827
+ FMT_CONSTEXPR void set_fill(char c) {
828
+ fill_data_[0] = c;
829
+ set_fill_size(1);
830
+ }
831
+
832
+ template <typename Char>
833
+ FMT_CONSTEXPR void set_fill(basic_string_view<Char> s) {
834
+ auto size = s.size();
835
+ set_fill_size(size);
836
+ if (size == 1) {
837
+ unsigned uchar = static_cast<detail::unsigned_char<Char>>(s[0]);
838
+ fill_data_[0] = static_cast<char>(uchar);
839
+ fill_data_[1] = static_cast<char>(uchar >> 8);
840
+ fill_data_[2] = static_cast<char>(uchar >> 16);
841
+ return;
842
+ }
843
+ FMT_ASSERT(size <= max_fill_size, "invalid fill");
844
+ for (size_t i = 0; i < size; ++i)
845
+ fill_data_[i & 3] = static_cast<char>(s[i]);
846
+ }
847
+
848
+ FMT_CONSTEXPR void copy_fill_from(const basic_specs& specs) {
849
+ set_fill_size(specs.fill_size());
850
+ for (size_t i = 0; i < max_fill_size; ++i)
851
+ fill_data_[i] = specs.fill_data_[i];
852
+ }
853
+ };
854
+
855
+ // Format specifiers for built-in and string types.
856
+ struct format_specs : basic_specs {
857
+ int width;
858
+ int precision;
859
+
860
+ constexpr format_specs() : width(0), precision(-1) {}
861
+ };
862
+
863
+ /**
864
+ * Parsing context consisting of a format string range being parsed and an
865
+ * argument counter for automatic indexing.
866
+ */
867
+ template <typename Char = char> class parse_context {
868
+ private:
869
+ basic_string_view<Char> fmt_;
870
+ int next_arg_id_;
871
+
872
+ enum { use_constexpr_cast = !FMT_GCC_VERSION || FMT_GCC_VERSION >= 1200 };
873
+
874
+ FMT_CONSTEXPR void do_check_arg_id(int arg_id);
875
+
876
+ public:
877
+ using char_type = Char;
878
+ using iterator = const Char*;
879
+
880
+ constexpr explicit parse_context(basic_string_view<Char> fmt,
881
+ int next_arg_id = 0)
882
+ : fmt_(fmt), next_arg_id_(next_arg_id) {}
883
+
884
+ /// Returns an iterator to the beginning of the format string range being
885
+ /// parsed.
886
+ constexpr auto begin() const noexcept -> iterator { return fmt_.begin(); }
887
+
888
+ /// Returns an iterator past the end of the format string range being parsed.
889
+ constexpr auto end() const noexcept -> iterator { return fmt_.end(); }
890
+
891
+ /// Advances the begin iterator to `it`.
892
+ FMT_CONSTEXPR void advance_to(iterator it) {
893
+ fmt_.remove_prefix(detail::to_unsigned(it - begin()));
894
+ }
895
+
896
+ /// Reports an error if using the manual argument indexing; otherwise returns
897
+ /// the next argument index and switches to the automatic indexing.
898
+ FMT_CONSTEXPR auto next_arg_id() -> int {
899
+ if (next_arg_id_ < 0) {
900
+ report_error("cannot switch from manual to automatic argument indexing");
901
+ return 0;
902
+ }
903
+ int id = next_arg_id_++;
904
+ do_check_arg_id(id);
905
+ return id;
906
+ }
907
+
908
+ /// Reports an error if using the automatic argument indexing; otherwise
909
+ /// switches to the manual indexing.
910
+ FMT_CONSTEXPR void check_arg_id(int id) {
911
+ if (next_arg_id_ > 0) {
912
+ report_error("cannot switch from automatic to manual argument indexing");
913
+ return;
914
+ }
915
+ next_arg_id_ = -1;
916
+ do_check_arg_id(id);
917
+ }
918
+ FMT_CONSTEXPR void check_arg_id(basic_string_view<Char>) {
919
+ next_arg_id_ = -1;
920
+ }
921
+ FMT_CONSTEXPR void check_dynamic_spec(int arg_id);
922
+ };
923
+
924
+ FMT_END_EXPORT
925
+
926
+ namespace detail {
927
+
928
+ // Constructs fmt::basic_string_view<Char> from types implicitly convertible
929
+ // to it, deducing Char. Explicitly convertible types such as the ones returned
930
+ // from FMT_STRING are intentionally excluded.
931
+ template <typename Char, FMT_ENABLE_IF(is_char<Char>::value)>
932
+ constexpr auto to_string_view(const Char* s) -> basic_string_view<Char> {
933
+ return s;
934
+ }
935
+ template <typename T, FMT_ENABLE_IF(is_std_string_like<T>::value)>
936
+ constexpr auto to_string_view(const T& s)
937
+ -> basic_string_view<typename T::value_type> {
938
+ return s;
939
+ }
940
+ template <typename Char>
941
+ constexpr auto to_string_view(basic_string_view<Char> s)
942
+ -> basic_string_view<Char> {
943
+ return s;
944
+ }
945
+
946
+ template <typename T, typename Enable = void>
947
+ struct has_to_string_view : std::false_type {};
948
+ // detail:: is intentional since to_string_view is not an extension point.
949
+ template <typename T>
950
+ struct has_to_string_view<
951
+ T, void_t<decltype(detail::to_string_view(std::declval<T>()))>>
952
+ : std::true_type {};
953
+
954
+ /// String's character (code unit) type. detail:: is intentional to prevent ADL.
955
+ template <typename S,
956
+ typename V = decltype(detail::to_string_view(std::declval<S>()))>
957
+ using char_t = typename V::value_type;
958
+
959
+ enum class type {
960
+ none_type,
961
+ // Integer types should go first,
962
+ int_type,
963
+ uint_type,
964
+ long_long_type,
965
+ ulong_long_type,
966
+ int128_type,
967
+ uint128_type,
968
+ bool_type,
969
+ char_type,
970
+ last_integer_type = char_type,
971
+ // followed by floating-point types.
972
+ float_type,
973
+ double_type,
974
+ long_double_type,
975
+ last_numeric_type = long_double_type,
976
+ cstring_type,
977
+ string_type,
978
+ pointer_type,
979
+ custom_type
980
+ };
981
+
982
+ // Maps core type T to the corresponding type enum constant.
983
+ template <typename T, typename Char>
984
+ struct type_constant : std::integral_constant<type, type::custom_type> {};
985
+
986
+ #define FMT_TYPE_CONSTANT(Type, constant) \
987
+ template <typename Char> \
988
+ struct type_constant<Type, Char> \
989
+ : std::integral_constant<type, type::constant> {}
990
+
991
+ FMT_TYPE_CONSTANT(int, int_type);
992
+ FMT_TYPE_CONSTANT(unsigned, uint_type);
993
+ FMT_TYPE_CONSTANT(long long, long_long_type);
994
+ FMT_TYPE_CONSTANT(unsigned long long, ulong_long_type);
995
+ FMT_TYPE_CONSTANT(int128_opt, int128_type);
996
+ FMT_TYPE_CONSTANT(uint128_opt, uint128_type);
997
+ FMT_TYPE_CONSTANT(bool, bool_type);
998
+ FMT_TYPE_CONSTANT(Char, char_type);
999
+ FMT_TYPE_CONSTANT(float, float_type);
1000
+ FMT_TYPE_CONSTANT(double, double_type);
1001
+ FMT_TYPE_CONSTANT(long double, long_double_type);
1002
+ FMT_TYPE_CONSTANT(const Char*, cstring_type);
1003
+ FMT_TYPE_CONSTANT(basic_string_view<Char>, string_type);
1004
+ FMT_TYPE_CONSTANT(const void*, pointer_type);
1005
+
1006
+ constexpr auto is_integral_type(type t) -> bool {
1007
+ return t > type::none_type && t <= type::last_integer_type;
1008
+ }
1009
+ constexpr auto is_arithmetic_type(type t) -> bool {
1010
+ return t > type::none_type && t <= type::last_numeric_type;
1011
+ }
1012
+
1013
+ constexpr auto set(type rhs) -> int { return 1 << static_cast<int>(rhs); }
1014
+ constexpr auto in(type t, int set) -> bool {
1015
+ return ((set >> static_cast<int>(t)) & 1) != 0;
1016
+ }
1017
+
1018
+ // Bitsets of types.
1019
+ enum {
1020
+ sint_set =
1021
+ set(type::int_type) | set(type::long_long_type) | set(type::int128_type),
1022
+ uint_set = set(type::uint_type) | set(type::ulong_long_type) |
1023
+ set(type::uint128_type),
1024
+ bool_set = set(type::bool_type),
1025
+ char_set = set(type::char_type),
1026
+ float_set = set(type::float_type) | set(type::double_type) |
1027
+ set(type::long_double_type),
1028
+ string_set = set(type::string_type),
1029
+ cstring_set = set(type::cstring_type),
1030
+ pointer_set = set(type::pointer_type)
1031
+ };
1032
+
1033
+ struct view {};
1034
+
1035
+ template <typename Char, typename T> struct named_arg;
1036
+ template <typename T> struct is_named_arg : std::false_type {};
1037
+ template <typename T> struct is_static_named_arg : std::false_type {};
1038
+
1039
+ template <typename Char, typename T>
1040
+ struct is_named_arg<named_arg<Char, T>> : std::true_type {};
1041
+
1042
+ template <typename Char, typename T> struct named_arg : view {
1043
+ const Char* name;
1044
+ const T& value;
1045
+
1046
+ named_arg(const Char* n, const T& v) : name(n), value(v) {}
1047
+ static_assert(!is_named_arg<T>::value, "nested named arguments");
1048
+ };
1049
+
1050
+ template <bool B = false> constexpr auto count() -> int { return B ? 1 : 0; }
1051
+ template <bool B1, bool B2, bool... Tail> constexpr auto count() -> int {
1052
+ return (B1 ? 1 : 0) + count<B2, Tail...>();
1053
+ }
1054
+
1055
+ template <typename... Args> constexpr auto count_named_args() -> int {
1056
+ return count<is_named_arg<Args>::value...>();
1057
+ }
1058
+ template <typename... Args> constexpr auto count_static_named_args() -> int {
1059
+ return count<is_static_named_arg<Args>::value...>();
1060
+ }
1061
+
1062
+ template <typename Char> struct named_arg_info {
1063
+ const Char* name;
1064
+ int id;
1065
+ };
1066
+
1067
+ template <typename Char, typename T, FMT_ENABLE_IF(!is_named_arg<T>::value)>
1068
+ void init_named_arg(named_arg_info<Char>*, int& arg_index, int&, const T&) {
1069
+ ++arg_index;
1070
+ }
1071
+ template <typename Char, typename T, FMT_ENABLE_IF(is_named_arg<T>::value)>
1072
+ void init_named_arg(named_arg_info<Char>* named_args, int& arg_index,
1073
+ int& named_arg_index, const T& arg) {
1074
+ named_args[named_arg_index++] = {arg.name, arg_index++};
1075
+ }
1076
+
1077
+ template <typename T, typename Char,
1078
+ FMT_ENABLE_IF(!is_static_named_arg<T>::value)>
1079
+ FMT_CONSTEXPR void init_static_named_arg(named_arg_info<Char>*, int& arg_index,
1080
+ int&) {
1081
+ ++arg_index;
1082
+ }
1083
+ template <typename T, typename Char,
1084
+ FMT_ENABLE_IF(is_static_named_arg<T>::value)>
1085
+ FMT_CONSTEXPR void init_static_named_arg(named_arg_info<Char>* named_args,
1086
+ int& arg_index, int& named_arg_index) {
1087
+ named_args[named_arg_index++] = {T::name, arg_index++};
1088
+ }
1089
+
1090
+ // To minimize the number of types we need to deal with, long is translated
1091
+ // either to int or to long long depending on its size.
1092
+ enum { long_short = sizeof(long) == sizeof(int) };
1093
+ using long_type = conditional_t<long_short, int, long long>;
1094
+ using ulong_type = conditional_t<long_short, unsigned, unsigned long long>;
1095
+
1096
+ template <typename T>
1097
+ using format_as_result =
1098
+ remove_cvref_t<decltype(format_as(std::declval<const T&>()))>;
1099
+ template <typename T>
1100
+ using format_as_member_result =
1101
+ remove_cvref_t<decltype(formatter<T>::format_as(std::declval<const T&>()))>;
1102
+
1103
+ template <typename T, typename Enable = std::true_type>
1104
+ struct use_format_as : std::false_type {};
1105
+ // format_as member is only used to avoid injection into the std namespace.
1106
+ template <typename T, typename Enable = std::true_type>
1107
+ struct use_format_as_member : std::false_type {};
1108
+
1109
+ // Only map owning types because mapping views can be unsafe.
1110
+ template <typename T>
1111
+ struct use_format_as<
1112
+ T, bool_constant<std::is_arithmetic<format_as_result<T>>::value>>
1113
+ : std::true_type {};
1114
+ template <typename T>
1115
+ struct use_format_as_member<
1116
+ T, bool_constant<std::is_arithmetic<format_as_member_result<T>>::value>>
1117
+ : std::true_type {};
1118
+
1119
+ template <typename T, typename U = remove_const_t<T>>
1120
+ using use_formatter =
1121
+ bool_constant<(std::is_class<T>::value || std::is_enum<T>::value ||
1122
+ std::is_union<T>::value || std::is_array<T>::value) &&
1123
+ !has_to_string_view<T>::value && !is_named_arg<T>::value &&
1124
+ !use_format_as<T>::value && !use_format_as_member<U>::value>;
1125
+
1126
+ template <typename Char, typename T, typename U = remove_const_t<T>>
1127
+ auto has_formatter_impl(T* p, buffered_context<Char>* ctx = nullptr)
1128
+ -> decltype(formatter<U, Char>().format(*p, *ctx), std::true_type());
1129
+ template <typename Char> auto has_formatter_impl(...) -> std::false_type;
1130
+
1131
+ // T can be const-qualified to check if it is const-formattable.
1132
+ template <typename T, typename Char> constexpr auto has_formatter() -> bool {
1133
+ return decltype(has_formatter_impl<Char>(static_cast<T*>(nullptr)))::value;
1134
+ }
1135
+
1136
+ // Maps formatting argument types to natively supported types or user-defined
1137
+ // types with formatters. Returns void on errors to be SFINAE-friendly.
1138
+ template <typename Char> struct type_mapper {
1139
+ static auto map(signed char) -> int;
1140
+ static auto map(unsigned char) -> unsigned;
1141
+ static auto map(short) -> int;
1142
+ static auto map(unsigned short) -> unsigned;
1143
+ static auto map(int) -> int;
1144
+ static auto map(unsigned) -> unsigned;
1145
+ static auto map(long) -> long_type;
1146
+ static auto map(unsigned long) -> ulong_type;
1147
+ static auto map(long long) -> long long;
1148
+ static auto map(unsigned long long) -> unsigned long long;
1149
+ static auto map(int128_opt) -> int128_opt;
1150
+ static auto map(uint128_opt) -> uint128_opt;
1151
+ static auto map(bool) -> bool;
1152
+
1153
+ template <int N>
1154
+ static auto map(bitint<N>) -> conditional_t<N <= 64, long long, void>;
1155
+ template <int N>
1156
+ static auto map(ubitint<N>)
1157
+ -> conditional_t<N <= 64, unsigned long long, void>;
1158
+
1159
+ template <typename T, FMT_ENABLE_IF(is_char<T>::value)>
1160
+ static auto map(T) -> conditional_t<
1161
+ std::is_same<T, char>::value || std::is_same<T, Char>::value, Char, void>;
1162
+
1163
+ static auto map(float) -> float;
1164
+ static auto map(double) -> double;
1165
+ static auto map(long double) -> long double;
1166
+
1167
+ static auto map(Char*) -> const Char*;
1168
+ static auto map(const Char*) -> const Char*;
1169
+ template <typename T, typename C = char_t<T>,
1170
+ FMT_ENABLE_IF(!std::is_pointer<T>::value)>
1171
+ static auto map(const T&) -> conditional_t<std::is_same<C, Char>::value,
1172
+ basic_string_view<C>, void>;
1173
+
1174
+ static auto map(void*) -> const void*;
1175
+ static auto map(const void*) -> const void*;
1176
+ static auto map(volatile void*) -> const void*;
1177
+ static auto map(const volatile void*) -> const void*;
1178
+ static auto map(nullptr_t) -> const void*;
1179
+ template <typename T, FMT_ENABLE_IF(std::is_pointer<T>::value ||
1180
+ std::is_member_pointer<T>::value)>
1181
+ static auto map(const T&) -> void;
1182
+
1183
+ template <typename T, FMT_ENABLE_IF(use_format_as<T>::value)>
1184
+ static auto map(const T& x) -> decltype(map(format_as(x)));
1185
+ template <typename T, FMT_ENABLE_IF(use_format_as_member<T>::value)>
1186
+ static auto map(const T& x) -> decltype(map(formatter<T>::format_as(x)));
1187
+
1188
+ template <typename T, FMT_ENABLE_IF(use_formatter<T>::value)>
1189
+ static auto map(T&) -> conditional_t<has_formatter<T, Char>(), T&, void>;
1190
+
1191
+ template <typename T, FMT_ENABLE_IF(is_named_arg<T>::value)>
1192
+ static auto map(const T& named_arg) -> decltype(map(named_arg.value));
1193
+ };
1194
+
1195
+ // detail:: is used to workaround a bug in MSVC 2017.
1196
+ template <typename T, typename Char>
1197
+ using mapped_t = decltype(detail::type_mapper<Char>::map(std::declval<T&>()));
1198
+
1199
+ // A type constant after applying type_mapper.
1200
+ template <typename T, typename Char = char>
1201
+ using mapped_type_constant = type_constant<mapped_t<T, Char>, Char>;
1202
+
1203
+ template <typename T, typename Context,
1204
+ type TYPE =
1205
+ mapped_type_constant<T, typename Context::char_type>::value>
1206
+ using stored_type_constant = std::integral_constant<
1207
+ type, Context::builtin_types || TYPE == type::int_type ? TYPE
1208
+ : type::custom_type>;
1209
+ // A parse context with extra data used only in compile-time checks.
1210
+ template <typename Char>
1211
+ class compile_parse_context : public parse_context<Char> {
1212
+ private:
1213
+ int num_args_;
1214
+ const type* types_;
1215
+ using base = parse_context<Char>;
1216
+
1217
+ public:
1218
+ FMT_CONSTEXPR explicit compile_parse_context(basic_string_view<Char> fmt,
1219
+ int num_args, const type* types,
1220
+ int next_arg_id = 0)
1221
+ : base(fmt, next_arg_id), num_args_(num_args), types_(types) {}
1222
+
1223
+ constexpr auto num_args() const -> int { return num_args_; }
1224
+ constexpr auto arg_type(int id) const -> type { return types_[id]; }
1225
+
1226
+ FMT_CONSTEXPR auto next_arg_id() -> int {
1227
+ int id = base::next_arg_id();
1228
+ if (id >= num_args_) report_error("argument not found");
1229
+ return id;
1230
+ }
1231
+
1232
+ FMT_CONSTEXPR void check_arg_id(int id) {
1233
+ base::check_arg_id(id);
1234
+ if (id >= num_args_) report_error("argument not found");
1235
+ }
1236
+ using base::check_arg_id;
1237
+
1238
+ FMT_CONSTEXPR void check_dynamic_spec(int arg_id) {
1239
+ ignore_unused(arg_id);
1240
+ if (arg_id < num_args_ && types_ && !is_integral_type(types_[arg_id]))
1241
+ report_error("width/precision is not integer");
1242
+ }
1243
+ };
1244
+
1245
+ // An argument reference.
1246
+ template <typename Char> union arg_ref {
1247
+ FMT_CONSTEXPR arg_ref(int idx = 0) : index(idx) {}
1248
+ FMT_CONSTEXPR arg_ref(basic_string_view<Char> n) : name(n) {}
1249
+
1250
+ int index;
1251
+ basic_string_view<Char> name;
1252
+ };
1253
+
1254
+ // Format specifiers with width and precision resolved at formatting rather
1255
+ // than parsing time to allow reusing the same parsed specifiers with
1256
+ // different sets of arguments (precompilation of format strings).
1257
+ template <typename Char = char> struct dynamic_format_specs : format_specs {
1258
+ arg_ref<Char> width_ref;
1259
+ arg_ref<Char> precision_ref;
1260
+ };
1261
+
1262
+ // Converts a character to ASCII. Returns '\0' on conversion failure.
1263
+ template <typename Char, FMT_ENABLE_IF(std::is_integral<Char>::value)>
1264
+ constexpr auto to_ascii(Char c) -> char {
1265
+ return c <= 0xff ? static_cast<char>(c) : '\0';
1266
+ }
1267
+
1268
+ // Returns the number of code units in a code point or 1 on error.
1269
+ template <typename Char>
1270
+ FMT_CONSTEXPR auto code_point_length(const Char* begin) -> int {
1271
+ if (const_check(sizeof(Char) != 1)) return 1;
1272
+ auto c = static_cast<unsigned char>(*begin);
1273
+ return static_cast<int>((0x3a55000000000000ull >> (2 * (c >> 3))) & 3) + 1;
1274
+ }
1275
+
1276
+ // Parses the range [begin, end) as an unsigned integer. This function assumes
1277
+ // that the range is non-empty and the first character is a digit.
1278
+ template <typename Char>
1279
+ FMT_CONSTEXPR auto parse_nonnegative_int(const Char*& begin, const Char* end,
1280
+ int error_value) noexcept -> int {
1281
+ FMT_ASSERT(begin != end && '0' <= *begin && *begin <= '9', "");
1282
+ unsigned value = 0, prev = 0;
1283
+ auto p = begin;
1284
+ do {
1285
+ prev = value;
1286
+ value = value * 10 + unsigned(*p - '0');
1287
+ ++p;
1288
+ } while (p != end && '0' <= *p && *p <= '9');
1289
+ auto num_digits = p - begin;
1290
+ begin = p;
1291
+ int digits10 = static_cast<int>(sizeof(int) * CHAR_BIT * 3 / 10);
1292
+ if (num_digits <= digits10) return static_cast<int>(value);
1293
+ // Check for overflow.
1294
+ unsigned max = INT_MAX;
1295
+ return num_digits == digits10 + 1 &&
1296
+ prev * 10ull + unsigned(p[-1] - '0') <= max
1297
+ ? static_cast<int>(value)
1298
+ : error_value;
1299
+ }
1300
+
1301
+ FMT_CONSTEXPR inline auto parse_align(char c) -> align {
1302
+ switch (c) {
1303
+ case '<': return align::left;
1304
+ case '>': return align::right;
1305
+ case '^': return align::center;
1306
+ }
1307
+ return align::none;
1308
+ }
1309
+
1310
+ template <typename Char> constexpr auto is_name_start(Char c) -> bool {
1311
+ return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '_';
1312
+ }
1313
+
1314
+ template <typename Char, typename Handler>
1315
+ FMT_CONSTEXPR auto parse_arg_id(const Char* begin, const Char* end,
1316
+ Handler&& handler) -> const Char* {
1317
+ Char c = *begin;
1318
+ if (c >= '0' && c <= '9') {
1319
+ int index = 0;
1320
+ if (c != '0')
1321
+ index = parse_nonnegative_int(begin, end, INT_MAX);
1322
+ else
1323
+ ++begin;
1324
+ if (begin == end || (*begin != '}' && *begin != ':'))
1325
+ report_error("invalid format string");
1326
+ else
1327
+ handler.on_index(index);
1328
+ return begin;
1329
+ }
1330
+ if (FMT_OPTIMIZE_SIZE > 1 || !is_name_start(c)) {
1331
+ report_error("invalid format string");
1332
+ return begin;
1333
+ }
1334
+ auto it = begin;
1335
+ do {
1336
+ ++it;
1337
+ } while (it != end && (is_name_start(*it) || ('0' <= *it && *it <= '9')));
1338
+ handler.on_name({begin, to_unsigned(it - begin)});
1339
+ return it;
1340
+ }
1341
+
1342
+ template <typename Char> struct dynamic_spec_handler {
1343
+ parse_context<Char>& ctx;
1344
+ arg_ref<Char>& ref;
1345
+ arg_id_kind& kind;
1346
+
1347
+ FMT_CONSTEXPR void on_index(int id) {
1348
+ ref = id;
1349
+ kind = arg_id_kind::index;
1350
+ ctx.check_arg_id(id);
1351
+ ctx.check_dynamic_spec(id);
1352
+ }
1353
+ FMT_CONSTEXPR void on_name(basic_string_view<Char> id) {
1354
+ ref = id;
1355
+ kind = arg_id_kind::name;
1356
+ ctx.check_arg_id(id);
1357
+ }
1358
+ };
1359
+
1360
+ template <typename Char> struct parse_dynamic_spec_result {
1361
+ const Char* end;
1362
+ arg_id_kind kind;
1363
+ };
1364
+
1365
+ // Parses integer | "{" [arg_id] "}".
1366
+ template <typename Char>
1367
+ FMT_CONSTEXPR auto parse_dynamic_spec(const Char* begin, const Char* end,
1368
+ int& value, arg_ref<Char>& ref,
1369
+ parse_context<Char>& ctx)
1370
+ -> parse_dynamic_spec_result<Char> {
1371
+ FMT_ASSERT(begin != end, "");
1372
+ auto kind = arg_id_kind::none;
1373
+ if ('0' <= *begin && *begin <= '9') {
1374
+ int val = parse_nonnegative_int(begin, end, -1);
1375
+ if (val == -1) report_error("number is too big");
1376
+ value = val;
1377
+ } else {
1378
+ if (*begin == '{') {
1379
+ ++begin;
1380
+ if (begin != end) {
1381
+ Char c = *begin;
1382
+ if (c == '}' || c == ':') {
1383
+ int id = ctx.next_arg_id();
1384
+ ref = id;
1385
+ kind = arg_id_kind::index;
1386
+ ctx.check_dynamic_spec(id);
1387
+ } else {
1388
+ begin = parse_arg_id(begin, end,
1389
+ dynamic_spec_handler<Char>{ctx, ref, kind});
1390
+ }
1391
+ }
1392
+ if (begin != end && *begin == '}') return {++begin, kind};
1393
+ }
1394
+ report_error("invalid format string");
1395
+ }
1396
+ return {begin, kind};
1397
+ }
1398
+
1399
+ template <typename Char>
1400
+ FMT_CONSTEXPR auto parse_width(const Char* begin, const Char* end,
1401
+ format_specs& specs, arg_ref<Char>& width_ref,
1402
+ parse_context<Char>& ctx) -> const Char* {
1403
+ auto result = parse_dynamic_spec(begin, end, specs.width, width_ref, ctx);
1404
+ specs.set_dynamic_width(result.kind);
1405
+ return result.end;
1406
+ }
1407
+
1408
+ template <typename Char>
1409
+ FMT_CONSTEXPR auto parse_precision(const Char* begin, const Char* end,
1410
+ format_specs& specs,
1411
+ arg_ref<Char>& precision_ref,
1412
+ parse_context<Char>& ctx) -> const Char* {
1413
+ ++begin;
1414
+ if (begin == end) {
1415
+ report_error("invalid precision");
1416
+ return begin;
1417
+ }
1418
+ auto result =
1419
+ parse_dynamic_spec(begin, end, specs.precision, precision_ref, ctx);
1420
+ specs.set_dynamic_precision(result.kind);
1421
+ return result.end;
1422
+ }
1423
+
1424
+ enum class state { start, align, sign, hash, zero, width, precision, locale };
1425
+
1426
+ // Parses standard format specifiers.
1427
+ template <typename Char>
1428
+ FMT_CONSTEXPR auto parse_format_specs(const Char* begin, const Char* end,
1429
+ dynamic_format_specs<Char>& specs,
1430
+ parse_context<Char>& ctx, type arg_type)
1431
+ -> const Char* {
1432
+ auto c = '\0';
1433
+ if (end - begin > 1) {
1434
+ auto next = to_ascii(begin[1]);
1435
+ c = parse_align(next) == align::none ? to_ascii(*begin) : '\0';
1436
+ } else {
1437
+ if (begin == end) return begin;
1438
+ c = to_ascii(*begin);
1439
+ }
1440
+
1441
+ struct {
1442
+ state current_state = state::start;
1443
+ FMT_CONSTEXPR void operator()(state s, bool valid = true) {
1444
+ if (current_state >= s || !valid)
1445
+ report_error("invalid format specifier");
1446
+ current_state = s;
1447
+ }
1448
+ } enter_state;
1449
+
1450
+ using pres = presentation_type;
1451
+ constexpr auto integral_set = sint_set | uint_set | bool_set | char_set;
1452
+ struct {
1453
+ const Char*& begin;
1454
+ format_specs& specs;
1455
+ type arg_type;
1456
+
1457
+ FMT_CONSTEXPR auto operator()(pres pres_type, int set) -> const Char* {
1458
+ if (!in(arg_type, set)) report_error("invalid format specifier");
1459
+ specs.set_type(pres_type);
1460
+ return begin + 1;
1461
+ }
1462
+ } parse_presentation_type{begin, specs, arg_type};
1463
+
1464
+ for (;;) {
1465
+ switch (c) {
1466
+ case '<':
1467
+ case '>':
1468
+ case '^':
1469
+ enter_state(state::align);
1470
+ specs.set_align(parse_align(c));
1471
+ ++begin;
1472
+ break;
1473
+ case '+':
1474
+ case ' ':
1475
+ specs.set_sign(c == ' ' ? sign::space : sign::plus);
1476
+ FMT_FALLTHROUGH;
1477
+ case '-':
1478
+ enter_state(state::sign, in(arg_type, sint_set | float_set));
1479
+ ++begin;
1480
+ break;
1481
+ case '#':
1482
+ enter_state(state::hash, is_arithmetic_type(arg_type));
1483
+ specs.set_alt();
1484
+ ++begin;
1485
+ break;
1486
+ case '0':
1487
+ enter_state(state::zero);
1488
+ if (!is_arithmetic_type(arg_type))
1489
+ report_error("format specifier requires numeric argument");
1490
+ if (specs.align() == align::none) {
1491
+ // Ignore 0 if align is specified for compatibility with std::format.
1492
+ specs.set_align(align::numeric);
1493
+ specs.set_fill('0');
1494
+ }
1495
+ ++begin;
1496
+ break;
1497
+ // clang-format off
1498
+ case '1': case '2': case '3': case '4': case '5':
1499
+ case '6': case '7': case '8': case '9': case '{':
1500
+ // clang-format on
1501
+ enter_state(state::width);
1502
+ begin = parse_width(begin, end, specs, specs.width_ref, ctx);
1503
+ break;
1504
+ case '.':
1505
+ enter_state(state::precision,
1506
+ in(arg_type, float_set | string_set | cstring_set));
1507
+ begin = parse_precision(begin, end, specs, specs.precision_ref, ctx);
1508
+ break;
1509
+ case 'L':
1510
+ enter_state(state::locale, is_arithmetic_type(arg_type));
1511
+ specs.set_localized();
1512
+ ++begin;
1513
+ break;
1514
+ case 'd': return parse_presentation_type(pres::dec, integral_set);
1515
+ case 'X': specs.set_upper(); FMT_FALLTHROUGH;
1516
+ case 'x': return parse_presentation_type(pres::hex, integral_set);
1517
+ case 'o': return parse_presentation_type(pres::oct, integral_set);
1518
+ case 'B': specs.set_upper(); FMT_FALLTHROUGH;
1519
+ case 'b': return parse_presentation_type(pres::bin, integral_set);
1520
+ case 'E': specs.set_upper(); FMT_FALLTHROUGH;
1521
+ case 'e': return parse_presentation_type(pres::exp, float_set);
1522
+ case 'F': specs.set_upper(); FMT_FALLTHROUGH;
1523
+ case 'f': return parse_presentation_type(pres::fixed, float_set);
1524
+ case 'G': specs.set_upper(); FMT_FALLTHROUGH;
1525
+ case 'g': return parse_presentation_type(pres::general, float_set);
1526
+ case 'A': specs.set_upper(); FMT_FALLTHROUGH;
1527
+ case 'a': return parse_presentation_type(pres::hexfloat, float_set);
1528
+ case 'c':
1529
+ if (arg_type == type::bool_type) report_error("invalid format specifier");
1530
+ return parse_presentation_type(pres::chr, integral_set);
1531
+ case 's':
1532
+ return parse_presentation_type(pres::string,
1533
+ bool_set | string_set | cstring_set);
1534
+ case 'p':
1535
+ return parse_presentation_type(pres::pointer, pointer_set | cstring_set);
1536
+ case '?':
1537
+ return parse_presentation_type(pres::debug,
1538
+ char_set | string_set | cstring_set);
1539
+ case '}': return begin;
1540
+ default: {
1541
+ if (*begin == '}') return begin;
1542
+ // Parse fill and alignment.
1543
+ auto fill_end = begin + code_point_length(begin);
1544
+ if (end - fill_end <= 0) {
1545
+ report_error("invalid format specifier");
1546
+ return begin;
1547
+ }
1548
+ if (*begin == '{') {
1549
+ report_error("invalid fill character '{'");
1550
+ return begin;
1551
+ }
1552
+ auto alignment = parse_align(to_ascii(*fill_end));
1553
+ enter_state(state::align, alignment != align::none);
1554
+ specs.set_fill(
1555
+ basic_string_view<Char>(begin, to_unsigned(fill_end - begin)));
1556
+ specs.set_align(alignment);
1557
+ begin = fill_end + 1;
1558
+ }
1559
+ }
1560
+ if (begin == end) return begin;
1561
+ c = to_ascii(*begin);
1562
+ }
1563
+ }
1564
+
1565
+ template <typename Char, typename Handler>
1566
+ FMT_CONSTEXPR FMT_INLINE auto parse_replacement_field(const Char* begin,
1567
+ const Char* end,
1568
+ Handler&& handler)
1569
+ -> const Char* {
1570
+ ++begin;
1571
+ if (begin == end) {
1572
+ handler.on_error("invalid format string");
1573
+ return end;
1574
+ }
1575
+ int arg_id = 0;
1576
+ switch (*begin) {
1577
+ case '}':
1578
+ handler.on_replacement_field(handler.on_arg_id(), begin);
1579
+ return begin + 1;
1580
+ case '{': handler.on_text(begin, begin + 1); return begin + 1;
1581
+ case ':': arg_id = handler.on_arg_id(); break;
1582
+ default: {
1583
+ struct id_adapter {
1584
+ Handler& handler;
1585
+ int arg_id;
1586
+
1587
+ FMT_CONSTEXPR void on_index(int id) { arg_id = handler.on_arg_id(id); }
1588
+ FMT_CONSTEXPR void on_name(basic_string_view<Char> id) {
1589
+ arg_id = handler.on_arg_id(id);
1590
+ }
1591
+ } adapter = {handler, 0};
1592
+ begin = parse_arg_id(begin, end, adapter);
1593
+ arg_id = adapter.arg_id;
1594
+ Char c = begin != end ? *begin : Char();
1595
+ if (c == '}') {
1596
+ handler.on_replacement_field(arg_id, begin);
1597
+ return begin + 1;
1598
+ }
1599
+ if (c != ':') {
1600
+ handler.on_error("missing '}' in format string");
1601
+ return end;
1602
+ }
1603
+ break;
1604
+ }
1605
+ }
1606
+ begin = handler.on_format_specs(arg_id, begin + 1, end);
1607
+ if (begin == end || *begin != '}')
1608
+ return handler.on_error("unknown format specifier"), end;
1609
+ return begin + 1;
1610
+ }
1611
+
1612
+ template <typename Char, typename Handler>
1613
+ FMT_CONSTEXPR void parse_format_string(basic_string_view<Char> fmt,
1614
+ Handler&& handler) {
1615
+ auto begin = fmt.data(), end = begin + fmt.size();
1616
+ auto p = begin;
1617
+ while (p != end) {
1618
+ auto c = *p++;
1619
+ if (c == '{') {
1620
+ handler.on_text(begin, p - 1);
1621
+ begin = p = parse_replacement_field(p - 1, end, handler);
1622
+ } else if (c == '}') {
1623
+ if (p == end || *p != '}')
1624
+ return handler.on_error("unmatched '}' in format string");
1625
+ handler.on_text(begin, p);
1626
+ begin = ++p;
1627
+ }
1628
+ }
1629
+ handler.on_text(begin, end);
1630
+ }
1631
+
1632
+ // Checks char specs and returns true iff the presentation type is char-like.
1633
+ FMT_CONSTEXPR inline auto check_char_specs(const format_specs& specs) -> bool {
1634
+ auto type = specs.type();
1635
+ if (type != presentation_type::none && type != presentation_type::chr &&
1636
+ type != presentation_type::debug) {
1637
+ return false;
1638
+ }
1639
+ if (specs.align() == align::numeric || specs.sign() != sign::none ||
1640
+ specs.alt()) {
1641
+ report_error("invalid format specifier for char");
1642
+ }
1643
+ return true;
1644
+ }
1645
+
1646
+ // A base class for compile-time strings.
1647
+ struct compile_string {};
1648
+
1649
+ template <typename T, typename Char>
1650
+ FMT_VISIBILITY("hidden") // Suppress an ld warning on macOS (#3769).
1651
+ FMT_CONSTEXPR auto invoke_parse(parse_context<Char>& ctx) -> const Char* {
1652
+ using mapped_type = remove_cvref_t<mapped_t<T, Char>>;
1653
+ constexpr bool formattable =
1654
+ std::is_constructible<formatter<mapped_type, Char>>::value;
1655
+ if (!formattable) return ctx.begin(); // Error is reported in the value ctor.
1656
+ using formatted_type = conditional_t<formattable, mapped_type, int>;
1657
+ return formatter<formatted_type, Char>().parse(ctx);
1658
+ }
1659
+
1660
+ template <typename... T> struct arg_pack {};
1661
+
1662
+ template <typename Char, int NUM_ARGS, int NUM_NAMED_ARGS, bool DYNAMIC_NAMES>
1663
+ class format_string_checker {
1664
+ private:
1665
+ type types_[max_of(1, NUM_ARGS)];
1666
+ named_arg_info<Char> named_args_[max_of(1, NUM_NAMED_ARGS)];
1667
+ compile_parse_context<Char> context_;
1668
+
1669
+ using parse_func = auto (*)(parse_context<Char>&) -> const Char*;
1670
+ parse_func parse_funcs_[max_of(1, NUM_ARGS)];
1671
+
1672
+ public:
1673
+ template <typename... T>
1674
+ FMT_CONSTEXPR explicit format_string_checker(basic_string_view<Char> fmt,
1675
+ arg_pack<T...>)
1676
+ : types_{mapped_type_constant<T, Char>::value...},
1677
+ named_args_{},
1678
+ context_(fmt, NUM_ARGS, types_),
1679
+ parse_funcs_{&invoke_parse<T, Char>...} {
1680
+ int arg_index = 0, named_arg_index = 0;
1681
+ FMT_APPLY_VARIADIC(
1682
+ init_static_named_arg<T>(named_args_, arg_index, named_arg_index));
1683
+ ignore_unused(arg_index, named_arg_index);
1684
+ }
1685
+
1686
+ FMT_CONSTEXPR void on_text(const Char*, const Char*) {}
1687
+
1688
+ FMT_CONSTEXPR auto on_arg_id() -> int { return context_.next_arg_id(); }
1689
+ FMT_CONSTEXPR auto on_arg_id(int id) -> int {
1690
+ context_.check_arg_id(id);
1691
+ return id;
1692
+ }
1693
+ FMT_CONSTEXPR auto on_arg_id(basic_string_view<Char> id) -> int {
1694
+ for (int i = 0; i < NUM_NAMED_ARGS; ++i) {
1695
+ if (named_args_[i].name == id) return named_args_[i].id;
1696
+ }
1697
+ if (!DYNAMIC_NAMES) on_error("argument not found");
1698
+ return -1;
1699
+ }
1700
+
1701
+ FMT_CONSTEXPR void on_replacement_field(int id, const Char* begin) {
1702
+ on_format_specs(id, begin, begin); // Call parse() on empty specs.
1703
+ }
1704
+
1705
+ FMT_CONSTEXPR auto on_format_specs(int id, const Char* begin, const Char* end)
1706
+ -> const Char* {
1707
+ context_.advance_to(begin);
1708
+ if (id >= 0 && id < NUM_ARGS) return parse_funcs_[id](context_);
1709
+ while (begin != end && *begin != '}') ++begin;
1710
+ return begin;
1711
+ }
1712
+
1713
+ FMT_NORETURN FMT_CONSTEXPR void on_error(const char* message) {
1714
+ report_error(message);
1715
+ }
1716
+ };
1717
+
1718
+ /// A contiguous memory buffer with an optional growing ability. It is an
1719
+ /// internal class and shouldn't be used directly, only via `memory_buffer`.
1720
+ template <typename T> class buffer {
1721
+ private:
1722
+ T* ptr_;
1723
+ size_t size_;
1724
+ size_t capacity_;
1725
+
1726
+ using grow_fun = void (*)(buffer& buf, size_t capacity);
1727
+ grow_fun grow_;
1728
+
1729
+ protected:
1730
+ // Don't initialize ptr_ since it is not accessed to save a few cycles.
1731
+ FMT_MSC_WARNING(suppress : 26495)
1732
+ FMT_CONSTEXPR buffer(grow_fun grow, size_t sz) noexcept
1733
+ : size_(sz), capacity_(sz), grow_(grow) {}
1734
+
1735
+ constexpr buffer(grow_fun grow, T* p = nullptr, size_t sz = 0,
1736
+ size_t cap = 0) noexcept
1737
+ : ptr_(p), size_(sz), capacity_(cap), grow_(grow) {}
1738
+
1739
+ FMT_CONSTEXPR20 ~buffer() = default;
1740
+ buffer(buffer&&) = default;
1741
+
1742
+ /// Sets the buffer data and capacity.
1743
+ FMT_CONSTEXPR void set(T* buf_data, size_t buf_capacity) noexcept {
1744
+ ptr_ = buf_data;
1745
+ capacity_ = buf_capacity;
1746
+ }
1747
+
1748
+ public:
1749
+ using value_type = T;
1750
+ using const_reference = const T&;
1751
+
1752
+ buffer(const buffer&) = delete;
1753
+ void operator=(const buffer&) = delete;
1754
+
1755
+ auto begin() noexcept -> T* { return ptr_; }
1756
+ auto end() noexcept -> T* { return ptr_ + size_; }
1757
+
1758
+ auto begin() const noexcept -> const T* { return ptr_; }
1759
+ auto end() const noexcept -> const T* { return ptr_ + size_; }
1760
+
1761
+ /// Returns the size of this buffer.
1762
+ constexpr auto size() const noexcept -> size_t { return size_; }
1763
+
1764
+ /// Returns the capacity of this buffer.
1765
+ constexpr auto capacity() const noexcept -> size_t { return capacity_; }
1766
+
1767
+ /// Returns a pointer to the buffer data (not null-terminated).
1768
+ FMT_CONSTEXPR auto data() noexcept -> T* { return ptr_; }
1769
+ FMT_CONSTEXPR auto data() const noexcept -> const T* { return ptr_; }
1770
+
1771
+ /// Clears this buffer.
1772
+ FMT_CONSTEXPR void clear() { size_ = 0; }
1773
+
1774
+ // Tries resizing the buffer to contain `count` elements. If T is a POD type
1775
+ // the new elements may not be initialized.
1776
+ FMT_CONSTEXPR void try_resize(size_t count) {
1777
+ try_reserve(count);
1778
+ size_ = min_of(count, capacity_);
1779
+ }
1780
+
1781
+ // Tries increasing the buffer capacity to `new_capacity`. It can increase the
1782
+ // capacity by a smaller amount than requested but guarantees there is space
1783
+ // for at least one additional element either by increasing the capacity or by
1784
+ // flushing the buffer if it is full.
1785
+ FMT_CONSTEXPR void try_reserve(size_t new_capacity) {
1786
+ if (new_capacity > capacity_) grow_(*this, new_capacity);
1787
+ }
1788
+
1789
+ FMT_CONSTEXPR void push_back(const T& value) {
1790
+ try_reserve(size_ + 1);
1791
+ ptr_[size_++] = value;
1792
+ }
1793
+
1794
+ /// Appends data to the end of the buffer.
1795
+ template <typename U>
1796
+ // Workaround for MSVC2019 to fix error C2893: Failed to specialize function
1797
+ // template 'void fmt::v11::detail::buffer<T>::append(const U *,const U *)'.
1798
+ #if !FMT_MSC_VERSION || FMT_MSC_VERSION >= 1940
1799
+ FMT_CONSTEXPR20
1800
+ #endif
1801
+ void
1802
+ append(const U* begin, const U* end) {
1803
+ while (begin != end) {
1804
+ auto count = to_unsigned(end - begin);
1805
+ try_reserve(size_ + count);
1806
+ auto free_cap = capacity_ - size_;
1807
+ if (free_cap < count) count = free_cap;
1808
+ // A loop is faster than memcpy on small sizes.
1809
+ T* out = ptr_ + size_;
1810
+ for (size_t i = 0; i < count; ++i) out[i] = begin[i];
1811
+ size_ += count;
1812
+ begin += count;
1813
+ }
1814
+ }
1815
+
1816
+ template <typename Idx> FMT_CONSTEXPR auto operator[](Idx index) -> T& {
1817
+ return ptr_[index];
1818
+ }
1819
+ template <typename Idx>
1820
+ FMT_CONSTEXPR auto operator[](Idx index) const -> const T& {
1821
+ return ptr_[index];
1822
+ }
1823
+ };
1824
+
1825
+ struct buffer_traits {
1826
+ constexpr explicit buffer_traits(size_t) {}
1827
+ constexpr auto count() const -> size_t { return 0; }
1828
+ constexpr auto limit(size_t size) const -> size_t { return size; }
1829
+ };
1830
+
1831
+ class fixed_buffer_traits {
1832
+ private:
1833
+ size_t count_ = 0;
1834
+ size_t limit_;
1835
+
1836
+ public:
1837
+ constexpr explicit fixed_buffer_traits(size_t limit) : limit_(limit) {}
1838
+ constexpr auto count() const -> size_t { return count_; }
1839
+ FMT_CONSTEXPR auto limit(size_t size) -> size_t {
1840
+ size_t n = limit_ > count_ ? limit_ - count_ : 0;
1841
+ count_ += size;
1842
+ return min_of(size, n);
1843
+ }
1844
+ };
1845
+
1846
+ // A buffer that writes to an output iterator when flushed.
1847
+ template <typename OutputIt, typename T, typename Traits = buffer_traits>
1848
+ class iterator_buffer : public Traits, public buffer<T> {
1849
+ private:
1850
+ OutputIt out_;
1851
+ enum { buffer_size = 256 };
1852
+ T data_[buffer_size];
1853
+
1854
+ static FMT_CONSTEXPR void grow(buffer<T>& buf, size_t) {
1855
+ if (buf.size() == buffer_size) static_cast<iterator_buffer&>(buf).flush();
1856
+ }
1857
+
1858
+ void flush() {
1859
+ auto size = this->size();
1860
+ this->clear();
1861
+ const T* begin = data_;
1862
+ const T* end = begin + this->limit(size);
1863
+ while (begin != end) *out_++ = *begin++;
1864
+ }
1865
+
1866
+ public:
1867
+ explicit iterator_buffer(OutputIt out, size_t n = buffer_size)
1868
+ : Traits(n), buffer<T>(grow, data_, 0, buffer_size), out_(out) {}
1869
+ iterator_buffer(iterator_buffer&& other) noexcept
1870
+ : Traits(other),
1871
+ buffer<T>(grow, data_, 0, buffer_size),
1872
+ out_(other.out_) {}
1873
+ ~iterator_buffer() {
1874
+ // Don't crash if flush fails during unwinding.
1875
+ FMT_TRY { flush(); }
1876
+ FMT_CATCH(...) {}
1877
+ }
1878
+
1879
+ auto out() -> OutputIt {
1880
+ flush();
1881
+ return out_;
1882
+ }
1883
+ auto count() const -> size_t { return Traits::count() + this->size(); }
1884
+ };
1885
+
1886
+ template <typename T>
1887
+ class iterator_buffer<T*, T, fixed_buffer_traits> : public fixed_buffer_traits,
1888
+ public buffer<T> {
1889
+ private:
1890
+ T* out_;
1891
+ enum { buffer_size = 256 };
1892
+ T data_[buffer_size];
1893
+
1894
+ static FMT_CONSTEXPR void grow(buffer<T>& buf, size_t) {
1895
+ if (buf.size() == buf.capacity())
1896
+ static_cast<iterator_buffer&>(buf).flush();
1897
+ }
1898
+
1899
+ void flush() {
1900
+ size_t n = this->limit(this->size());
1901
+ if (this->data() == out_) {
1902
+ out_ += n;
1903
+ this->set(data_, buffer_size);
1904
+ }
1905
+ this->clear();
1906
+ }
1907
+
1908
+ public:
1909
+ explicit iterator_buffer(T* out, size_t n = buffer_size)
1910
+ : fixed_buffer_traits(n), buffer<T>(grow, out, 0, n), out_(out) {}
1911
+ iterator_buffer(iterator_buffer&& other) noexcept
1912
+ : fixed_buffer_traits(other),
1913
+ buffer<T>(static_cast<iterator_buffer&&>(other)),
1914
+ out_(other.out_) {
1915
+ if (this->data() != out_) {
1916
+ this->set(data_, buffer_size);
1917
+ this->clear();
1918
+ }
1919
+ }
1920
+ ~iterator_buffer() { flush(); }
1921
+
1922
+ auto out() -> T* {
1923
+ flush();
1924
+ return out_;
1925
+ }
1926
+ auto count() const -> size_t {
1927
+ return fixed_buffer_traits::count() + this->size();
1928
+ }
1929
+ };
1930
+
1931
+ template <typename T> class iterator_buffer<T*, T> : public buffer<T> {
1932
+ public:
1933
+ explicit iterator_buffer(T* out, size_t = 0)
1934
+ : buffer<T>([](buffer<T>&, size_t) {}, out, 0, ~size_t()) {}
1935
+
1936
+ auto out() -> T* { return &*this->end(); }
1937
+ };
1938
+
1939
+ template <typename Container>
1940
+ class container_buffer : public buffer<typename Container::value_type> {
1941
+ private:
1942
+ using value_type = typename Container::value_type;
1943
+
1944
+ static FMT_CONSTEXPR void grow(buffer<value_type>& buf, size_t capacity) {
1945
+ auto& self = static_cast<container_buffer&>(buf);
1946
+ self.container.resize(capacity);
1947
+ self.set(&self.container[0], capacity);
1948
+ }
1949
+
1950
+ public:
1951
+ Container& container;
1952
+
1953
+ explicit container_buffer(Container& c)
1954
+ : buffer<value_type>(grow, c.size()), container(c) {}
1955
+ };
1956
+
1957
+ // A buffer that writes to a container with the contiguous storage.
1958
+ template <typename OutputIt>
1959
+ class iterator_buffer<
1960
+ OutputIt,
1961
+ enable_if_t<is_back_insert_iterator<OutputIt>::value &&
1962
+ is_contiguous<typename OutputIt::container_type>::value,
1963
+ typename OutputIt::container_type::value_type>>
1964
+ : public container_buffer<typename OutputIt::container_type> {
1965
+ private:
1966
+ using base = container_buffer<typename OutputIt::container_type>;
1967
+
1968
+ public:
1969
+ explicit iterator_buffer(typename OutputIt::container_type& c) : base(c) {}
1970
+ explicit iterator_buffer(OutputIt out, size_t = 0)
1971
+ : base(get_container(out)) {}
1972
+
1973
+ auto out() -> OutputIt { return OutputIt(this->container); }
1974
+ };
1975
+
1976
+ // A buffer that counts the number of code units written discarding the output.
1977
+ template <typename T = char> class counting_buffer : public buffer<T> {
1978
+ private:
1979
+ enum { buffer_size = 256 };
1980
+ T data_[buffer_size];
1981
+ size_t count_ = 0;
1982
+
1983
+ static FMT_CONSTEXPR void grow(buffer<T>& buf, size_t) {
1984
+ if (buf.size() != buffer_size) return;
1985
+ static_cast<counting_buffer&>(buf).count_ += buf.size();
1986
+ buf.clear();
1987
+ }
1988
+
1989
+ public:
1990
+ FMT_CONSTEXPR counting_buffer() : buffer<T>(grow, data_, 0, buffer_size) {}
1991
+
1992
+ constexpr auto count() const noexcept -> size_t {
1993
+ return count_ + this->size();
1994
+ }
1995
+ };
1996
+
1997
+ template <typename T>
1998
+ struct is_back_insert_iterator<basic_appender<T>> : std::true_type {};
1999
+
2000
+ template <typename OutputIt, typename InputIt, typename = void>
2001
+ struct has_back_insert_iterator_container_append : std::false_type {};
2002
+ template <typename OutputIt, typename InputIt>
2003
+ struct has_back_insert_iterator_container_append<
2004
+ OutputIt, InputIt,
2005
+ void_t<decltype(get_container(std::declval<OutputIt>())
2006
+ .append(std::declval<InputIt>(),
2007
+ std::declval<InputIt>()))>> : std::true_type {};
2008
+
2009
+ // An optimized version of std::copy with the output value type (T).
2010
+ template <typename T, typename InputIt, typename OutputIt,
2011
+ FMT_ENABLE_IF(is_back_insert_iterator<OutputIt>::value&&
2012
+ has_back_insert_iterator_container_append<
2013
+ OutputIt, InputIt>::value)>
2014
+ FMT_CONSTEXPR20 auto copy(InputIt begin, InputIt end, OutputIt out)
2015
+ -> OutputIt {
2016
+ get_container(out).append(begin, end);
2017
+ return out;
2018
+ }
2019
+
2020
+ template <typename T, typename InputIt, typename OutputIt,
2021
+ FMT_ENABLE_IF(is_back_insert_iterator<OutputIt>::value &&
2022
+ !has_back_insert_iterator_container_append<
2023
+ OutputIt, InputIt>::value)>
2024
+ FMT_CONSTEXPR20 auto copy(InputIt begin, InputIt end, OutputIt out)
2025
+ -> OutputIt {
2026
+ auto& c = get_container(out);
2027
+ c.insert(c.end(), begin, end);
2028
+ return out;
2029
+ }
2030
+
2031
+ template <typename T, typename InputIt, typename OutputIt,
2032
+ FMT_ENABLE_IF(!is_back_insert_iterator<OutputIt>::value)>
2033
+ FMT_CONSTEXPR auto copy(InputIt begin, InputIt end, OutputIt out) -> OutputIt {
2034
+ while (begin != end) *out++ = static_cast<T>(*begin++);
2035
+ return out;
2036
+ }
2037
+
2038
+ template <typename T, typename V, typename OutputIt>
2039
+ FMT_CONSTEXPR auto copy(basic_string_view<V> s, OutputIt out) -> OutputIt {
2040
+ return copy<T>(s.begin(), s.end(), out);
2041
+ }
2042
+
2043
+ template <typename It, typename Enable = std::true_type>
2044
+ struct is_buffer_appender : std::false_type {};
2045
+ template <typename It>
2046
+ struct is_buffer_appender<
2047
+ It, bool_constant<
2048
+ is_back_insert_iterator<It>::value &&
2049
+ std::is_base_of<buffer<typename It::container_type::value_type>,
2050
+ typename It::container_type>::value>>
2051
+ : std::true_type {};
2052
+
2053
+ // Maps an output iterator to a buffer.
2054
+ template <typename T, typename OutputIt,
2055
+ FMT_ENABLE_IF(!is_buffer_appender<OutputIt>::value)>
2056
+ auto get_buffer(OutputIt out) -> iterator_buffer<OutputIt, T> {
2057
+ return iterator_buffer<OutputIt, T>(out);
2058
+ }
2059
+ template <typename T, typename OutputIt,
2060
+ FMT_ENABLE_IF(is_buffer_appender<OutputIt>::value)>
2061
+ auto get_buffer(OutputIt out) -> buffer<T>& {
2062
+ return get_container(out);
2063
+ }
2064
+
2065
+ template <typename Buf, typename OutputIt>
2066
+ auto get_iterator(Buf& buf, OutputIt) -> decltype(buf.out()) {
2067
+ return buf.out();
2068
+ }
2069
+ template <typename T, typename OutputIt>
2070
+ auto get_iterator(buffer<T>&, OutputIt out) -> OutputIt {
2071
+ return out;
2072
+ }
2073
+
2074
+ // This type is intentionally undefined, only used for errors.
2075
+ template <typename T, typename Char> struct type_is_unformattable_for;
2076
+
2077
+ template <typename Char> struct string_value {
2078
+ const Char* data;
2079
+ size_t size;
2080
+ auto str() const -> basic_string_view<Char> { return {data, size}; }
2081
+ };
2082
+
2083
+ template <typename Context> struct custom_value {
2084
+ using char_type = typename Context::char_type;
2085
+ void* value;
2086
+ void (*format)(void* arg, parse_context<char_type>& parse_ctx, Context& ctx);
2087
+ };
2088
+
2089
+ template <typename Char> struct named_arg_value {
2090
+ const named_arg_info<Char>* data;
2091
+ size_t size;
2092
+ };
2093
+
2094
+ struct custom_tag {};
2095
+
2096
+ #if !FMT_BUILTIN_TYPES
2097
+ # define FMT_BUILTIN , monostate
2098
+ #else
2099
+ # define FMT_BUILTIN
2100
+ #endif
2101
+
2102
+ // A formatting argument value.
2103
+ template <typename Context> class value {
2104
+ public:
2105
+ using char_type = typename Context::char_type;
2106
+
2107
+ union {
2108
+ monostate no_value;
2109
+ int int_value;
2110
+ unsigned uint_value;
2111
+ long long long_long_value;
2112
+ unsigned long long ulong_long_value;
2113
+ int128_opt int128_value;
2114
+ uint128_opt uint128_value;
2115
+ bool bool_value;
2116
+ char_type char_value;
2117
+ float float_value;
2118
+ double double_value;
2119
+ long double long_double_value;
2120
+ const void* pointer;
2121
+ string_value<char_type> string;
2122
+ custom_value<Context> custom;
2123
+ named_arg_value<char_type> named_args;
2124
+ };
2125
+
2126
+ constexpr FMT_INLINE value() : no_value() {}
2127
+ constexpr FMT_INLINE value(signed char x) : int_value(x) {}
2128
+ constexpr FMT_INLINE value(unsigned char x FMT_BUILTIN) : uint_value(x) {}
2129
+ constexpr FMT_INLINE value(signed short x) : int_value(x) {}
2130
+ constexpr FMT_INLINE value(unsigned short x FMT_BUILTIN) : uint_value(x) {}
2131
+ constexpr FMT_INLINE value(int x) : int_value(x) {}
2132
+ constexpr FMT_INLINE value(unsigned x FMT_BUILTIN) : uint_value(x) {}
2133
+ FMT_CONSTEXPR FMT_INLINE value(long x FMT_BUILTIN) : value(long_type(x)) {}
2134
+ FMT_CONSTEXPR FMT_INLINE value(unsigned long x FMT_BUILTIN)
2135
+ : value(ulong_type(x)) {}
2136
+ constexpr FMT_INLINE value(long long x FMT_BUILTIN) : long_long_value(x) {}
2137
+ constexpr FMT_INLINE value(unsigned long long x FMT_BUILTIN)
2138
+ : ulong_long_value(x) {}
2139
+ FMT_INLINE value(int128_opt x FMT_BUILTIN) : int128_value(x) {}
2140
+ FMT_INLINE value(uint128_opt x FMT_BUILTIN) : uint128_value(x) {}
2141
+ constexpr FMT_INLINE value(bool x FMT_BUILTIN) : bool_value(x) {}
2142
+
2143
+ template <int N>
2144
+ constexpr FMT_INLINE value(bitint<N> x FMT_BUILTIN) : long_long_value(x) {
2145
+ static_assert(N <= 64, "unsupported _BitInt");
2146
+ }
2147
+ template <int N>
2148
+ constexpr FMT_INLINE value(ubitint<N> x FMT_BUILTIN) : ulong_long_value(x) {
2149
+ static_assert(N <= 64, "unsupported _BitInt");
2150
+ }
2151
+
2152
+ template <typename T, FMT_ENABLE_IF(is_char<T>::value)>
2153
+ constexpr FMT_INLINE value(T x FMT_BUILTIN) : char_value(x) {
2154
+ static_assert(
2155
+ std::is_same<T, char>::value || std::is_same<T, char_type>::value,
2156
+ "mixing character types is disallowed");
2157
+ }
2158
+
2159
+ constexpr FMT_INLINE value(float x FMT_BUILTIN) : float_value(x) {}
2160
+ constexpr FMT_INLINE value(double x FMT_BUILTIN) : double_value(x) {}
2161
+ FMT_INLINE value(long double x FMT_BUILTIN) : long_double_value(x) {}
2162
+
2163
+ FMT_CONSTEXPR FMT_INLINE value(char_type* x FMT_BUILTIN) {
2164
+ string.data = x;
2165
+ if (is_constant_evaluated()) string.size = 0;
2166
+ }
2167
+ FMT_CONSTEXPR FMT_INLINE value(const char_type* x FMT_BUILTIN) {
2168
+ string.data = x;
2169
+ if (is_constant_evaluated()) string.size = 0;
2170
+ }
2171
+ template <typename T, typename C = char_t<T>,
2172
+ FMT_ENABLE_IF(!std::is_pointer<T>::value)>
2173
+ FMT_CONSTEXPR value(const T& x FMT_BUILTIN) {
2174
+ static_assert(std::is_same<C, char_type>::value,
2175
+ "mixing character types is disallowed");
2176
+ auto sv = to_string_view(x);
2177
+ string.data = sv.data();
2178
+ string.size = sv.size();
2179
+ }
2180
+ FMT_INLINE value(void* x FMT_BUILTIN) : pointer(x) {}
2181
+ FMT_INLINE value(const void* x FMT_BUILTIN) : pointer(x) {}
2182
+ FMT_INLINE value(volatile void* x FMT_BUILTIN)
2183
+ : pointer(const_cast<const void*>(x)) {}
2184
+ FMT_INLINE value(const volatile void* x FMT_BUILTIN)
2185
+ : pointer(const_cast<const void*>(x)) {}
2186
+ FMT_INLINE value(nullptr_t) : pointer(nullptr) {}
2187
+
2188
+ template <typename T, FMT_ENABLE_IF(std::is_pointer<T>::value ||
2189
+ std::is_member_pointer<T>::value)>
2190
+ value(const T&) {
2191
+ // Formatting of arbitrary pointers is disallowed. If you want to format a
2192
+ // pointer cast it to `void*` or `const void*`. In particular, this forbids
2193
+ // formatting of `[const] volatile char*` printed as bool by iostreams.
2194
+ static_assert(sizeof(T) == 0,
2195
+ "formatting of non-void pointers is disallowed");
2196
+ }
2197
+
2198
+ template <typename T, FMT_ENABLE_IF(use_format_as<T>::value)>
2199
+ value(const T& x) : value(format_as(x)) {}
2200
+ template <typename T, FMT_ENABLE_IF(use_format_as_member<T>::value)>
2201
+ value(const T& x) : value(formatter<T>::format_as(x)) {}
2202
+
2203
+ template <typename T, FMT_ENABLE_IF(is_named_arg<T>::value)>
2204
+ value(const T& named_arg) : value(named_arg.value) {}
2205
+
2206
+ template <typename T,
2207
+ FMT_ENABLE_IF(use_formatter<T>::value || !FMT_BUILTIN_TYPES)>
2208
+ FMT_CONSTEXPR20 FMT_INLINE value(T& x) : value(x, custom_tag()) {}
2209
+
2210
+ FMT_ALWAYS_INLINE value(const named_arg_info<char_type>* args, size_t size)
2211
+ : named_args{args, size} {}
2212
+
2213
+ private:
2214
+ template <typename T, FMT_ENABLE_IF(has_formatter<T, char_type>())>
2215
+ FMT_CONSTEXPR value(T& x, custom_tag) {
2216
+ using value_type = remove_const_t<T>;
2217
+ // T may overload operator& e.g. std::vector<bool>::reference in libc++.
2218
+ if (!is_constant_evaluated()) {
2219
+ custom.value =
2220
+ const_cast<char*>(&reinterpret_cast<const volatile char&>(x));
2221
+ } else {
2222
+ custom.value = nullptr;
2223
+ #if defined(__cpp_if_constexpr)
2224
+ if constexpr (std::is_same<decltype(&x), remove_reference_t<T>*>::value)
2225
+ custom.value = const_cast<value_type*>(&x);
2226
+ #endif
2227
+ }
2228
+ custom.format = format_custom<value_type, formatter<value_type, char_type>>;
2229
+ }
2230
+
2231
+ template <typename T, FMT_ENABLE_IF(!has_formatter<T, char_type>())>
2232
+ FMT_CONSTEXPR value(const T&, custom_tag) {
2233
+ // Cannot format an argument; to make type T formattable provide a
2234
+ // formatter<T> specialization: https://fmt.dev/latest/api.html#udt.
2235
+ type_is_unformattable_for<T, char_type> _;
2236
+ }
2237
+
2238
+ // Formats an argument of a custom type, such as a user-defined class.
2239
+ template <typename T, typename Formatter>
2240
+ static void format_custom(void* arg, parse_context<char_type>& parse_ctx,
2241
+ Context& ctx) {
2242
+ auto f = Formatter();
2243
+ parse_ctx.advance_to(f.parse(parse_ctx));
2244
+ using qualified_type =
2245
+ conditional_t<has_formatter<const T, char_type>(), const T, T>;
2246
+ // format must be const for compatibility with std::format and compilation.
2247
+ const auto& cf = f;
2248
+ ctx.advance_to(cf.format(*static_cast<qualified_type*>(arg), ctx));
2249
+ }
2250
+ };
2251
+
2252
+ enum { packed_arg_bits = 4 };
2253
+ // Maximum number of arguments with packed types.
2254
+ enum { max_packed_args = 62 / packed_arg_bits };
2255
+ enum : unsigned long long { is_unpacked_bit = 1ULL << 63 };
2256
+ enum : unsigned long long { has_named_args_bit = 1ULL << 62 };
2257
+
2258
+ template <typename It, typename T, typename Enable = void>
2259
+ struct is_output_iterator : std::false_type {};
2260
+
2261
+ template <> struct is_output_iterator<appender, char> : std::true_type {};
2262
+
2263
+ template <typename It, typename T>
2264
+ struct is_output_iterator<
2265
+ It, T,
2266
+ enable_if_t<std::is_assignable<decltype(*std::declval<decay_t<It>&>()++),
2267
+ T>::value>> : std::true_type {};
2268
+
2269
+ #ifndef FMT_USE_LOCALE
2270
+ # define FMT_USE_LOCALE (FMT_OPTIMIZE_SIZE <= 1)
2271
+ #endif
2272
+
2273
+ // A type-erased reference to an std::locale to avoid a heavy <locale> include.
2274
+ class locale_ref {
2275
+ #if FMT_USE_LOCALE
2276
+ private:
2277
+ const void* locale_; // A type-erased pointer to std::locale.
2278
+
2279
+ public:
2280
+ constexpr locale_ref() : locale_(nullptr) {}
2281
+ template <typename Locale> locale_ref(const Locale& loc);
2282
+
2283
+ inline explicit operator bool() const noexcept { return locale_ != nullptr; }
2284
+ #endif // FMT_USE_LOCALE
2285
+
2286
+ public:
2287
+ template <typename Locale> auto get() const -> Locale;
2288
+ };
2289
+
2290
+ template <typename> constexpr auto encode_types() -> unsigned long long {
2291
+ return 0;
2292
+ }
2293
+
2294
+ template <typename Context, typename Arg, typename... Args>
2295
+ constexpr auto encode_types() -> unsigned long long {
2296
+ return static_cast<unsigned>(stored_type_constant<Arg, Context>::value) |
2297
+ (encode_types<Context, Args...>() << packed_arg_bits);
2298
+ }
2299
+
2300
+ template <typename Context, typename... T, size_t NUM_ARGS = sizeof...(T)>
2301
+ constexpr auto make_descriptor() -> unsigned long long {
2302
+ return NUM_ARGS <= max_packed_args ? encode_types<Context, T...>()
2303
+ : is_unpacked_bit | NUM_ARGS;
2304
+ }
2305
+
2306
+ template <typename Context, int NUM_ARGS>
2307
+ using arg_t = conditional_t<NUM_ARGS <= max_packed_args, value<Context>,
2308
+ basic_format_arg<Context>>;
2309
+
2310
+ template <typename Context, int NUM_ARGS, int NUM_NAMED_ARGS,
2311
+ unsigned long long DESC>
2312
+ struct named_arg_store {
2313
+ // args_[0].named_args points to named_args to avoid bloating format_args.
2314
+ arg_t<Context, NUM_ARGS> args[1 + NUM_ARGS];
2315
+ named_arg_info<typename Context::char_type> named_args[NUM_NAMED_ARGS];
2316
+
2317
+ template <typename... T>
2318
+ FMT_CONSTEXPR FMT_ALWAYS_INLINE named_arg_store(T&... values)
2319
+ : args{{named_args, NUM_NAMED_ARGS}, values...} {
2320
+ int arg_index = 0, named_arg_index = 0;
2321
+ FMT_APPLY_VARIADIC(
2322
+ init_named_arg(named_args, arg_index, named_arg_index, values));
2323
+ }
2324
+
2325
+ named_arg_store(named_arg_store&& rhs) {
2326
+ args[0] = {named_args, NUM_NAMED_ARGS};
2327
+ for (size_t i = 1; i < sizeof(args) / sizeof(*args); ++i)
2328
+ args[i] = rhs.args[i];
2329
+ for (size_t i = 0; i < NUM_NAMED_ARGS; ++i)
2330
+ named_args[i] = rhs.named_args[i];
2331
+ }
2332
+
2333
+ named_arg_store(const named_arg_store& rhs) = delete;
2334
+ named_arg_store& operator=(const named_arg_store& rhs) = delete;
2335
+ named_arg_store& operator=(named_arg_store&& rhs) = delete;
2336
+ operator const arg_t<Context, NUM_ARGS>*() const { return args + 1; }
2337
+ };
2338
+
2339
+ // An array of references to arguments. It can be implicitly converted to
2340
+ // `basic_format_args` for passing into type-erased formatting functions
2341
+ // such as `vformat`. It is a plain struct to reduce binary size in debug mode.
2342
+ template <typename Context, int NUM_ARGS, int NUM_NAMED_ARGS,
2343
+ unsigned long long DESC>
2344
+ struct format_arg_store {
2345
+ // +1 to workaround a bug in gcc 7.5 that causes duplicated-branches warning.
2346
+ using type =
2347
+ conditional_t<NUM_NAMED_ARGS == 0,
2348
+ arg_t<Context, NUM_ARGS>[max_of(1, NUM_ARGS)],
2349
+ named_arg_store<Context, NUM_ARGS, NUM_NAMED_ARGS, DESC>>;
2350
+ type args;
2351
+ };
2352
+
2353
+ // TYPE can be different from type_constant<T>, e.g. for __float128.
2354
+ template <typename T, typename Char, type TYPE> struct native_formatter {
2355
+ private:
2356
+ dynamic_format_specs<Char> specs_;
2357
+
2358
+ public:
2359
+ using nonlocking = void;
2360
+
2361
+ FMT_CONSTEXPR auto parse(parse_context<Char>& ctx) -> const Char* {
2362
+ if (ctx.begin() == ctx.end() || *ctx.begin() == '}') return ctx.begin();
2363
+ auto end = parse_format_specs(ctx.begin(), ctx.end(), specs_, ctx, TYPE);
2364
+ if (const_check(TYPE == type::char_type)) check_char_specs(specs_);
2365
+ return end;
2366
+ }
2367
+
2368
+ template <type U = TYPE,
2369
+ FMT_ENABLE_IF(U == type::string_type || U == type::cstring_type ||
2370
+ U == type::char_type)>
2371
+ FMT_CONSTEXPR void set_debug_format(bool set = true) {
2372
+ specs_.set_type(set ? presentation_type::debug : presentation_type::none);
2373
+ }
2374
+
2375
+ FMT_PRAGMA_CLANG(diagnostic ignored "-Wundefined-inline")
2376
+ template <typename FormatContext>
2377
+ FMT_CONSTEXPR auto format(const T& val, FormatContext& ctx) const
2378
+ -> decltype(ctx.out());
2379
+ };
2380
+
2381
+ template <typename T, typename Enable = void>
2382
+ struct locking
2383
+ : bool_constant<mapped_type_constant<T>::value == type::custom_type> {};
2384
+ template <typename T>
2385
+ struct locking<T, void_t<typename formatter<remove_cvref_t<T>>::nonlocking>>
2386
+ : std::false_type {};
2387
+
2388
+ template <typename T = int> FMT_CONSTEXPR inline auto is_locking() -> bool {
2389
+ return locking<T>::value;
2390
+ }
2391
+ template <typename T1, typename T2, typename... Tail>
2392
+ FMT_CONSTEXPR inline auto is_locking() -> bool {
2393
+ return locking<T1>::value || is_locking<T2, Tail...>();
2394
+ }
2395
+
2396
+ FMT_API void vformat_to(buffer<char>& buf, string_view fmt, format_args args,
2397
+ locale_ref loc = {});
2398
+
2399
+ #if FMT_WIN32
2400
+ FMT_API void vprint_mojibake(FILE*, string_view, format_args, bool);
2401
+ #else // format_args is passed by reference since it is defined later.
2402
+ inline void vprint_mojibake(FILE*, string_view, const format_args&, bool) {}
2403
+ #endif
2404
+ } // namespace detail
2405
+
2406
+ // The main public API.
2407
+
2408
+ template <typename Char>
2409
+ FMT_CONSTEXPR void parse_context<Char>::do_check_arg_id(int arg_id) {
2410
+ // Argument id is only checked at compile time during parsing because
2411
+ // formatting has its own validation.
2412
+ if (detail::is_constant_evaluated() && use_constexpr_cast) {
2413
+ auto ctx = static_cast<detail::compile_parse_context<Char>*>(this);
2414
+ if (arg_id >= ctx->num_args()) report_error("argument not found");
2415
+ }
2416
+ }
2417
+
2418
+ template <typename Char>
2419
+ FMT_CONSTEXPR void parse_context<Char>::check_dynamic_spec(int arg_id) {
2420
+ using detail::compile_parse_context;
2421
+ if (detail::is_constant_evaluated() && use_constexpr_cast)
2422
+ static_cast<compile_parse_context<Char>*>(this)->check_dynamic_spec(arg_id);
2423
+ }
2424
+
2425
+ FMT_BEGIN_EXPORT
2426
+
2427
+ // An output iterator that appends to a buffer. It is used instead of
2428
+ // back_insert_iterator to reduce symbol sizes and avoid <iterator> dependency.
2429
+ template <typename T> class basic_appender {
2430
+ protected:
2431
+ detail::buffer<T>* container;
2432
+
2433
+ public:
2434
+ using container_type = detail::buffer<T>;
2435
+
2436
+ FMT_CONSTEXPR basic_appender(detail::buffer<T>& buf) : container(&buf) {}
2437
+
2438
+ FMT_CONSTEXPR20 auto operator=(T c) -> basic_appender& {
2439
+ container->push_back(c);
2440
+ return *this;
2441
+ }
2442
+ FMT_CONSTEXPR20 auto operator*() -> basic_appender& { return *this; }
2443
+ FMT_CONSTEXPR20 auto operator++() -> basic_appender& { return *this; }
2444
+ FMT_CONSTEXPR20 auto operator++(int) -> basic_appender { return *this; }
2445
+ };
2446
+
2447
+ // A formatting argument. Context is a template parameter for the compiled API
2448
+ // where output can be unbuffered.
2449
+ template <typename Context> class basic_format_arg {
2450
+ private:
2451
+ detail::value<Context> value_;
2452
+ detail::type type_;
2453
+
2454
+ friend class basic_format_args<Context>;
2455
+
2456
+ using char_type = typename Context::char_type;
2457
+
2458
+ public:
2459
+ class handle {
2460
+ private:
2461
+ detail::custom_value<Context> custom_;
2462
+
2463
+ public:
2464
+ explicit handle(detail::custom_value<Context> custom) : custom_(custom) {}
2465
+
2466
+ void format(parse_context<char_type>& parse_ctx, Context& ctx) const {
2467
+ custom_.format(custom_.value, parse_ctx, ctx);
2468
+ }
2469
+ };
2470
+
2471
+ constexpr basic_format_arg() : type_(detail::type::none_type) {}
2472
+ basic_format_arg(const detail::named_arg_info<char_type>* args, size_t size)
2473
+ : value_(args, size) {}
2474
+ template <typename T>
2475
+ basic_format_arg(T&& val)
2476
+ : value_(val), type_(detail::stored_type_constant<T, Context>::value) {}
2477
+
2478
+ constexpr explicit operator bool() const noexcept {
2479
+ return type_ != detail::type::none_type;
2480
+ }
2481
+ auto type() const -> detail::type { return type_; }
2482
+
2483
+ /**
2484
+ * Visits an argument dispatching to the appropriate visit method based on
2485
+ * the argument type. For example, if the argument type is `double` then
2486
+ * `vis(value)` will be called with the value of type `double`.
2487
+ */
2488
+ template <typename Visitor>
2489
+ FMT_CONSTEXPR FMT_INLINE auto visit(Visitor&& vis) const -> decltype(vis(0)) {
2490
+ using detail::map;
2491
+ switch (type_) {
2492
+ case detail::type::none_type: break;
2493
+ case detail::type::int_type: return vis(value_.int_value);
2494
+ case detail::type::uint_type: return vis(value_.uint_value);
2495
+ case detail::type::long_long_type: return vis(value_.long_long_value);
2496
+ case detail::type::ulong_long_type: return vis(value_.ulong_long_value);
2497
+ case detail::type::int128_type: return vis(map(value_.int128_value));
2498
+ case detail::type::uint128_type: return vis(map(value_.uint128_value));
2499
+ case detail::type::bool_type: return vis(value_.bool_value);
2500
+ case detail::type::char_type: return vis(value_.char_value);
2501
+ case detail::type::float_type: return vis(value_.float_value);
2502
+ case detail::type::double_type: return vis(value_.double_value);
2503
+ case detail::type::long_double_type: return vis(value_.long_double_value);
2504
+ case detail::type::cstring_type: return vis(value_.string.data);
2505
+ case detail::type::string_type: return vis(value_.string.str());
2506
+ case detail::type::pointer_type: return vis(value_.pointer);
2507
+ case detail::type::custom_type: return vis(handle(value_.custom));
2508
+ }
2509
+ return vis(monostate());
2510
+ }
2511
+
2512
+ auto format_custom(const char_type* parse_begin,
2513
+ parse_context<char_type>& parse_ctx, Context& ctx)
2514
+ -> bool {
2515
+ if (type_ != detail::type::custom_type) return false;
2516
+ parse_ctx.advance_to(parse_begin);
2517
+ value_.custom.format(value_.custom.value, parse_ctx, ctx);
2518
+ return true;
2519
+ }
2520
+ };
2521
+
2522
+ /**
2523
+ * A view of a collection of formatting arguments. To avoid lifetime issues it
2524
+ * should only be used as a parameter type in type-erased functions such as
2525
+ * `vformat`:
2526
+ *
2527
+ * void vlog(fmt::string_view fmt, fmt::format_args args); // OK
2528
+ * fmt::format_args args = fmt::make_format_args(); // Dangling reference
2529
+ */
2530
+ template <typename Context> class basic_format_args {
2531
+ private:
2532
+ // A descriptor that contains information about formatting arguments.
2533
+ // If the number of arguments is less or equal to max_packed_args then
2534
+ // argument types are passed in the descriptor. This reduces binary code size
2535
+ // per formatting function call.
2536
+ unsigned long long desc_;
2537
+ union {
2538
+ // If is_packed() returns true then argument values are stored in values_;
2539
+ // otherwise they are stored in args_. This is done to improve cache
2540
+ // locality and reduce compiled code size since storing larger objects
2541
+ // may require more code (at least on x86-64) even if the same amount of
2542
+ // data is actually copied to stack. It saves ~10% on the bloat test.
2543
+ const detail::value<Context>* values_;
2544
+ const basic_format_arg<Context>* args_;
2545
+ };
2546
+
2547
+ constexpr auto is_packed() const -> bool {
2548
+ return (desc_ & detail::is_unpacked_bit) == 0;
2549
+ }
2550
+ constexpr auto has_named_args() const -> bool {
2551
+ return (desc_ & detail::has_named_args_bit) != 0;
2552
+ }
2553
+
2554
+ FMT_CONSTEXPR auto type(int index) const -> detail::type {
2555
+ int shift = index * detail::packed_arg_bits;
2556
+ unsigned mask = (1 << detail::packed_arg_bits) - 1;
2557
+ return static_cast<detail::type>((desc_ >> shift) & mask);
2558
+ }
2559
+
2560
+ template <int NUM_ARGS, int NUM_NAMED_ARGS, unsigned long long DESC>
2561
+ using store =
2562
+ detail::format_arg_store<Context, NUM_ARGS, NUM_NAMED_ARGS, DESC>;
2563
+
2564
+ public:
2565
+ using format_arg = basic_format_arg<Context>;
2566
+
2567
+ constexpr basic_format_args() : desc_(0), args_(nullptr) {}
2568
+
2569
+ /// Constructs a `basic_format_args` object from `format_arg_store`.
2570
+ template <int NUM_ARGS, int NUM_NAMED_ARGS, unsigned long long DESC,
2571
+ FMT_ENABLE_IF(NUM_ARGS <= detail::max_packed_args)>
2572
+ constexpr FMT_ALWAYS_INLINE basic_format_args(
2573
+ const store<NUM_ARGS, NUM_NAMED_ARGS, DESC>& s)
2574
+ : desc_(DESC | (NUM_NAMED_ARGS != 0 ? +detail::has_named_args_bit : 0)),
2575
+ values_(s.args) {}
2576
+
2577
+ template <int NUM_ARGS, int NUM_NAMED_ARGS, unsigned long long DESC,
2578
+ FMT_ENABLE_IF(NUM_ARGS > detail::max_packed_args)>
2579
+ constexpr basic_format_args(const store<NUM_ARGS, NUM_NAMED_ARGS, DESC>& s)
2580
+ : desc_(DESC | (NUM_NAMED_ARGS != 0 ? +detail::has_named_args_bit : 0)),
2581
+ args_(s.args) {}
2582
+
2583
+ /// Constructs a `basic_format_args` object from a dynamic list of arguments.
2584
+ constexpr basic_format_args(const format_arg* args, int count,
2585
+ bool has_named = false)
2586
+ : desc_(detail::is_unpacked_bit | detail::to_unsigned(count) |
2587
+ (has_named ? +detail::has_named_args_bit : 0)),
2588
+ args_(args) {}
2589
+
2590
+ /// Returns the argument with the specified id.
2591
+ FMT_CONSTEXPR auto get(int id) const -> format_arg {
2592
+ auto arg = format_arg();
2593
+ if (!is_packed()) {
2594
+ if (id < max_size()) arg = args_[id];
2595
+ return arg;
2596
+ }
2597
+ if (static_cast<unsigned>(id) >= detail::max_packed_args) return arg;
2598
+ arg.type_ = type(id);
2599
+ if (arg.type_ != detail::type::none_type) arg.value_ = values_[id];
2600
+ return arg;
2601
+ }
2602
+
2603
+ template <typename Char>
2604
+ auto get(basic_string_view<Char> name) const -> format_arg {
2605
+ int id = get_id(name);
2606
+ return id >= 0 ? get(id) : format_arg();
2607
+ }
2608
+
2609
+ template <typename Char>
2610
+ FMT_CONSTEXPR auto get_id(basic_string_view<Char> name) const -> int {
2611
+ if (!has_named_args()) return -1;
2612
+ const auto& named_args =
2613
+ (is_packed() ? values_[-1] : args_[-1].value_).named_args;
2614
+ for (size_t i = 0; i < named_args.size; ++i) {
2615
+ if (named_args.data[i].name == name) return named_args.data[i].id;
2616
+ }
2617
+ return -1;
2618
+ }
2619
+
2620
+ auto max_size() const -> int {
2621
+ unsigned long long max_packed = detail::max_packed_args;
2622
+ return static_cast<int>(is_packed() ? max_packed
2623
+ : desc_ & ~detail::is_unpacked_bit);
2624
+ }
2625
+ };
2626
+
2627
+ // A formatting context.
2628
+ class context {
2629
+ private:
2630
+ appender out_;
2631
+ format_args args_;
2632
+ FMT_NO_UNIQUE_ADDRESS detail::locale_ref loc_;
2633
+
2634
+ public:
2635
+ /// The character type for the output.
2636
+ using char_type = char;
2637
+
2638
+ using iterator = appender;
2639
+ using format_arg = basic_format_arg<context>;
2640
+ using parse_context_type FMT_DEPRECATED = parse_context<>;
2641
+ template <typename T> using formatter_type FMT_DEPRECATED = formatter<T>;
2642
+ enum { builtin_types = FMT_BUILTIN_TYPES };
2643
+
2644
+ /// Constructs a `context` object. References to the arguments are stored
2645
+ /// in the object so make sure they have appropriate lifetimes.
2646
+ FMT_CONSTEXPR context(iterator out, format_args args,
2647
+ detail::locale_ref loc = {})
2648
+ : out_(out), args_(args), loc_(loc) {}
2649
+ context(context&&) = default;
2650
+ context(const context&) = delete;
2651
+ void operator=(const context&) = delete;
2652
+
2653
+ FMT_CONSTEXPR auto arg(int id) const -> format_arg { return args_.get(id); }
2654
+ inline auto arg(string_view name) const -> format_arg {
2655
+ return args_.get(name);
2656
+ }
2657
+ FMT_CONSTEXPR auto arg_id(string_view name) const -> int {
2658
+ return args_.get_id(name);
2659
+ }
2660
+ auto args() const -> const format_args& { return args_; }
2661
+
2662
+ // Returns an iterator to the beginning of the output range.
2663
+ FMT_CONSTEXPR auto out() const -> iterator { return out_; }
2664
+
2665
+ // Advances the begin iterator to `it`.
2666
+ FMT_CONSTEXPR void advance_to(iterator) {}
2667
+
2668
+ FMT_CONSTEXPR auto locale() const -> detail::locale_ref { return loc_; }
2669
+ };
2670
+
2671
+ template <typename Char = char> struct runtime_format_string {
2672
+ basic_string_view<Char> str;
2673
+ };
2674
+
2675
+ /**
2676
+ * Creates a runtime format string.
2677
+ *
2678
+ * **Example**:
2679
+ *
2680
+ * // Check format string at runtime instead of compile-time.
2681
+ * fmt::print(fmt::runtime("{:d}"), "I am not a number");
2682
+ */
2683
+ inline auto runtime(string_view s) -> runtime_format_string<> { return {{s}}; }
2684
+
2685
+ /// A compile-time format string. Use `format_string` in the public API to
2686
+ /// prevent type deduction.
2687
+ template <typename... T> struct fstring {
2688
+ private:
2689
+ static constexpr int num_static_named_args =
2690
+ detail::count_static_named_args<T...>();
2691
+
2692
+ using checker = detail::format_string_checker<
2693
+ char, static_cast<int>(sizeof...(T)), num_static_named_args,
2694
+ num_static_named_args != detail::count_named_args<T...>()>;
2695
+
2696
+ using arg_pack = detail::arg_pack<T...>;
2697
+
2698
+ public:
2699
+ string_view str;
2700
+ using t = fstring;
2701
+
2702
+ // Reports a compile-time error if S is not a valid format string for T.
2703
+ template <size_t N>
2704
+ FMT_CONSTEVAL FMT_ALWAYS_INLINE fstring(const char (&s)[N]) : str(s, N - 1) {
2705
+ using namespace detail;
2706
+ static_assert(count<(std::is_base_of<view, remove_reference_t<T>>::value &&
2707
+ std::is_reference<T>::value)...>() == 0,
2708
+ "passing views as lvalues is disallowed");
2709
+ if (FMT_USE_CONSTEVAL) parse_format_string<char>(s, checker(s, arg_pack()));
2710
+ #ifdef FMT_ENFORCE_COMPILE_STRING
2711
+ static_assert(
2712
+ FMT_USE_CONSTEVAL && sizeof(s) != 0,
2713
+ "FMT_ENFORCE_COMPILE_STRING requires format strings to use FMT_STRING");
2714
+ #endif
2715
+ }
2716
+ template <typename S,
2717
+ FMT_ENABLE_IF(std::is_convertible<const S&, string_view>::value)>
2718
+ FMT_CONSTEVAL FMT_ALWAYS_INLINE fstring(const S& s) : str(s) {
2719
+ auto sv = string_view(str);
2720
+ if (FMT_USE_CONSTEVAL)
2721
+ detail::parse_format_string<char>(sv, checker(sv, arg_pack()));
2722
+ #ifdef FMT_ENFORCE_COMPILE_STRING
2723
+ static_assert(
2724
+ FMT_USE_CONSTEVAL && sizeof(s) != 0,
2725
+ "FMT_ENFORCE_COMPILE_STRING requires format strings to use FMT_STRING");
2726
+ #endif
2727
+ }
2728
+ template <typename S,
2729
+ FMT_ENABLE_IF(std::is_base_of<detail::compile_string, S>::value&&
2730
+ std::is_same<typename S::char_type, char>::value)>
2731
+ FMT_ALWAYS_INLINE fstring(const S&) : str(S()) {
2732
+ FMT_CONSTEXPR auto sv = string_view(S());
2733
+ FMT_CONSTEXPR int unused =
2734
+ (parse_format_string(sv, checker(sv, arg_pack())), 0);
2735
+ detail::ignore_unused(unused);
2736
+ }
2737
+ fstring(runtime_format_string<> fmt) : str(fmt.str) {}
2738
+
2739
+ // Returning by reference generates better code in debug mode.
2740
+ FMT_ALWAYS_INLINE operator const string_view&() const { return str; }
2741
+ auto get() const -> string_view { return str; }
2742
+ };
2743
+
2744
+ template <typename... T> using format_string = typename fstring<T...>::t;
2745
+
2746
+ template <typename T, typename Char = char>
2747
+ using is_formattable = bool_constant<!std::is_same<
2748
+ detail::mapped_t<conditional_t<std::is_void<T>::value, int*, T>, Char>,
2749
+ void>::value>;
2750
+ #ifdef __cpp_concepts
2751
+ template <typename T, typename Char = char>
2752
+ concept formattable = is_formattable<remove_reference_t<T>, Char>::value;
2753
+ #endif
2754
+
2755
+ template <typename T, typename Char>
2756
+ using has_formatter FMT_DEPRECATED = std::is_constructible<formatter<T, Char>>;
2757
+
2758
+ // A formatter specialization for natively supported types.
2759
+ template <typename T, typename Char>
2760
+ struct formatter<T, Char,
2761
+ enable_if_t<detail::type_constant<T, Char>::value !=
2762
+ detail::type::custom_type>>
2763
+ : detail::native_formatter<T, Char, detail::type_constant<T, Char>::value> {
2764
+ };
2765
+
2766
+ /**
2767
+ * Constructs an object that stores references to arguments and can be
2768
+ * implicitly converted to `format_args`. `Context` can be omitted in which case
2769
+ * it defaults to `context`. See `arg` for lifetime considerations.
2770
+ */
2771
+ // Take arguments by lvalue references to avoid some lifetime issues, e.g.
2772
+ // auto args = make_format_args(std::string());
2773
+ template <typename Context = context, typename... T,
2774
+ int NUM_ARGS = sizeof...(T),
2775
+ int NUM_NAMED_ARGS = detail::count_named_args<T...>(),
2776
+ unsigned long long DESC = detail::make_descriptor<Context, T...>()>
2777
+ constexpr FMT_ALWAYS_INLINE auto make_format_args(T&... args)
2778
+ -> detail::format_arg_store<Context, NUM_ARGS, NUM_NAMED_ARGS, DESC> {
2779
+ // Suppress warnings for pathological types convertible to detail::value.
2780
+ FMT_PRAGMA_GCC(diagnostic ignored "-Wconversion")
2781
+ return {{args...}};
2782
+ }
2783
+
2784
+ template <typename... T>
2785
+ using vargs =
2786
+ detail::format_arg_store<context, sizeof...(T),
2787
+ detail::count_named_args<T...>(),
2788
+ detail::make_descriptor<context, T...>()>;
2789
+
2790
+ /**
2791
+ * Returns a named argument to be used in a formatting function.
2792
+ * It should only be used in a call to a formatting function.
2793
+ *
2794
+ * **Example**:
2795
+ *
2796
+ * fmt::print("The answer is {answer}.", fmt::arg("answer", 42));
2797
+ */
2798
+ template <typename Char, typename T>
2799
+ inline auto arg(const Char* name, const T& arg) -> detail::named_arg<Char, T> {
2800
+ return {name, arg};
2801
+ }
2802
+
2803
+ /// Formats a string and writes the output to `out`.
2804
+ template <typename OutputIt,
2805
+ FMT_ENABLE_IF(detail::is_output_iterator<remove_cvref_t<OutputIt>,
2806
+ char>::value)>
2807
+ auto vformat_to(OutputIt&& out, string_view fmt, format_args args)
2808
+ -> remove_cvref_t<OutputIt> {
2809
+ auto&& buf = detail::get_buffer<char>(out);
2810
+ detail::vformat_to(buf, fmt, args, {});
2811
+ return detail::get_iterator(buf, out);
2812
+ }
2813
+
2814
+ /**
2815
+ * Formats `args` according to specifications in `fmt`, writes the result to
2816
+ * the output iterator `out` and returns the iterator past the end of the output
2817
+ * range. `format_to` does not append a terminating null character.
2818
+ *
2819
+ * **Example**:
2820
+ *
2821
+ * auto out = std::vector<char>();
2822
+ * fmt::format_to(std::back_inserter(out), "{}", 42);
2823
+ */
2824
+ template <typename OutputIt, typename... T,
2825
+ FMT_ENABLE_IF(detail::is_output_iterator<remove_cvref_t<OutputIt>,
2826
+ char>::value)>
2827
+ FMT_INLINE auto format_to(OutputIt&& out, format_string<T...> fmt, T&&... args)
2828
+ -> remove_cvref_t<OutputIt> {
2829
+ return vformat_to(out, fmt.str, vargs<T...>{{args...}});
2830
+ }
2831
+
2832
+ template <typename OutputIt> struct format_to_n_result {
2833
+ /// Iterator past the end of the output range.
2834
+ OutputIt out;
2835
+ /// Total (not truncated) output size.
2836
+ size_t size;
2837
+ };
2838
+
2839
+ template <typename OutputIt, typename... T,
2840
+ FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value)>
2841
+ auto vformat_to_n(OutputIt out, size_t n, string_view fmt, format_args args)
2842
+ -> format_to_n_result<OutputIt> {
2843
+ using traits = detail::fixed_buffer_traits;
2844
+ auto buf = detail::iterator_buffer<OutputIt, char, traits>(out, n);
2845
+ detail::vformat_to(buf, fmt, args, {});
2846
+ return {buf.out(), buf.count()};
2847
+ }
2848
+
2849
+ /**
2850
+ * Formats `args` according to specifications in `fmt`, writes up to `n`
2851
+ * characters of the result to the output iterator `out` and returns the total
2852
+ * (not truncated) output size and the iterator past the end of the output
2853
+ * range. `format_to_n` does not append a terminating null character.
2854
+ */
2855
+ template <typename OutputIt, typename... T,
2856
+ FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value)>
2857
+ FMT_INLINE auto format_to_n(OutputIt out, size_t n, format_string<T...> fmt,
2858
+ T&&... args) -> format_to_n_result<OutputIt> {
2859
+ return vformat_to_n(out, n, fmt.str, vargs<T...>{{args...}});
2860
+ }
2861
+
2862
+ struct format_to_result {
2863
+ /// Pointer to just after the last successful write in the array.
2864
+ char* out;
2865
+ /// Specifies if the output was truncated.
2866
+ bool truncated;
2867
+
2868
+ FMT_CONSTEXPR operator char*() const {
2869
+ // Report truncation to prevent silent data loss.
2870
+ if (truncated) report_error("output is truncated");
2871
+ return out;
2872
+ }
2873
+ };
2874
+
2875
+ template <size_t N>
2876
+ auto vformat_to(char (&out)[N], string_view fmt, format_args args)
2877
+ -> format_to_result {
2878
+ auto result = vformat_to_n(out, N, fmt, args);
2879
+ return {result.out, result.size > N};
2880
+ }
2881
+
2882
+ template <size_t N, typename... T>
2883
+ FMT_INLINE auto format_to(char (&out)[N], format_string<T...> fmt, T&&... args)
2884
+ -> format_to_result {
2885
+ auto result = vformat_to_n(out, N, fmt.str, vargs<T...>{{args...}});
2886
+ return {result.out, result.size > N};
2887
+ }
2888
+
2889
+ /// Returns the number of chars in the output of `format(fmt, args...)`.
2890
+ template <typename... T>
2891
+ FMT_NODISCARD FMT_INLINE auto formatted_size(format_string<T...> fmt,
2892
+ T&&... args) -> size_t {
2893
+ auto buf = detail::counting_buffer<>();
2894
+ detail::vformat_to(buf, fmt.str, vargs<T...>{{args...}}, {});
2895
+ return buf.count();
2896
+ }
2897
+
2898
+ FMT_API void vprint(string_view fmt, format_args args);
2899
+ FMT_API void vprint(FILE* f, string_view fmt, format_args args);
2900
+ FMT_API void vprintln(FILE* f, string_view fmt, format_args args);
2901
+ FMT_API void vprint_buffered(FILE* f, string_view fmt, format_args args);
2902
+
2903
+ /**
2904
+ * Formats `args` according to specifications in `fmt` and writes the output
2905
+ * to `stdout`.
2906
+ *
2907
+ * **Example**:
2908
+ *
2909
+ * fmt::print("The answer is {}.", 42);
2910
+ */
2911
+ template <typename... T>
2912
+ FMT_INLINE void print(format_string<T...> fmt, T&&... args) {
2913
+ vargs<T...> va = {{args...}};
2914
+ if (detail::const_check(!detail::use_utf8))
2915
+ return detail::vprint_mojibake(stdout, fmt.str, va, false);
2916
+ return detail::is_locking<T...>() ? vprint_buffered(stdout, fmt.str, va)
2917
+ : vprint(fmt.str, va);
2918
+ }
2919
+
2920
+ /**
2921
+ * Formats `args` according to specifications in `fmt` and writes the
2922
+ * output to the file `f`.
2923
+ *
2924
+ * **Example**:
2925
+ *
2926
+ * fmt::print(stderr, "Don't {}!", "panic");
2927
+ */
2928
+ template <typename... T>
2929
+ FMT_INLINE void print(FILE* f, format_string<T...> fmt, T&&... args) {
2930
+ vargs<T...> va = {{args...}};
2931
+ if (detail::const_check(!detail::use_utf8))
2932
+ return detail::vprint_mojibake(f, fmt.str, va, false);
2933
+ return detail::is_locking<T...>() ? vprint_buffered(f, fmt.str, va)
2934
+ : vprint(f, fmt.str, va);
2935
+ }
2936
+
2937
+ /// Formats `args` according to specifications in `fmt` and writes the output
2938
+ /// to the file `f` followed by a newline.
2939
+ template <typename... T>
2940
+ FMT_INLINE void println(FILE* f, format_string<T...> fmt, T&&... args) {
2941
+ vargs<T...> va = {{args...}};
2942
+ return detail::const_check(detail::use_utf8)
2943
+ ? vprintln(f, fmt.str, va)
2944
+ : detail::vprint_mojibake(f, fmt.str, va, true);
2945
+ }
2946
+
2947
+ /// Formats `args` according to specifications in `fmt` and writes the output
2948
+ /// to `stdout` followed by a newline.
2949
+ template <typename... T>
2950
+ FMT_INLINE void println(format_string<T...> fmt, T&&... args) {
2951
+ return fmt::println(stdout, fmt, static_cast<T&&>(args)...);
2952
+ }
2953
+
2954
+ FMT_END_EXPORT
2955
+ FMT_PRAGMA_CLANG(diagnostic pop)
2956
+ FMT_PRAGMA_GCC(pop_options)
2957
+ FMT_END_NAMESPACE
2958
+
2959
+ #ifdef FMT_HEADER_ONLY
2960
+ # include "format.h"
2961
+ #endif
2962
+ #endif // FMT_BASE_H_