couchbase 3.0.0-universal-darwin-19 → 3.0.1-universal-darwin-19

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 (902) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/ext/CMakeLists.txt +86 -169
  4. data/ext/build_version.hxx.in +3 -2
  5. data/ext/cmake/Backtrace.cmake +35 -0
  6. data/ext/cmake/BuildTracing.cmake +6 -0
  7. data/ext/cmake/Cache.cmake +29 -0
  8. data/ext/cmake/CompilerWarnings.cmake +78 -0
  9. data/ext/cmake/PreventInSourceBuilds.cmake +18 -0
  10. data/ext/cmake/Sanitizers.cmake +66 -0
  11. data/ext/cmake/StandardProjectSettings.cmake +40 -0
  12. data/ext/cmake/StaticAnalyzers.cmake +37 -0
  13. data/ext/cmake/Testing.cmake +52 -0
  14. data/ext/cmake/ThirdPartyDependencies.cmake +20 -0
  15. data/ext/cmake/VersionInfo.cmake +37 -0
  16. data/ext/couchbase/bucket.hxx +37 -12
  17. data/ext/couchbase/capabilities.hxx +117 -0
  18. data/ext/couchbase/cbcrypto/cbcrypto.cc +15 -15
  19. data/ext/couchbase/cluster.hxx +34 -2
  20. data/ext/couchbase/cluster_options.hxx +1 -0
  21. data/ext/couchbase/configuration.hxx +228 -52
  22. data/ext/couchbase/couchbase.cxx +914 -35
  23. data/ext/couchbase/diagnostics.hxx +251 -0
  24. data/ext/couchbase/document_id.hxx +3 -1
  25. data/ext/couchbase/errors.hxx +10 -1
  26. data/ext/couchbase/io/http_command.hxx +11 -7
  27. data/ext/couchbase/io/http_context.hxx +37 -0
  28. data/ext/couchbase/io/http_message.hxx +9 -0
  29. data/ext/couchbase/io/http_parser.hxx +2 -0
  30. data/ext/couchbase/io/http_session.hxx +100 -14
  31. data/ext/couchbase/io/http_session_manager.hxx +65 -5
  32. data/ext/couchbase/io/mcbp_command.hxx +16 -7
  33. data/ext/couchbase/io/mcbp_session.hxx +193 -51
  34. data/ext/couchbase/io/query_cache.hxx +61 -0
  35. data/ext/couchbase/io/retry_context.hxx +1 -2
  36. data/ext/couchbase/io/retry_orchestrator.hxx +16 -0
  37. data/ext/couchbase/io/retry_strategy.hxx +1 -1
  38. data/ext/couchbase/io/streams.hxx +61 -10
  39. data/ext/couchbase/operations.hxx +13 -0
  40. data/ext/couchbase/operations/analytics_dataset_create.hxx +1 -1
  41. data/ext/couchbase/operations/analytics_dataset_drop.hxx +1 -1
  42. data/ext/couchbase/operations/analytics_dataset_get_all.hxx +1 -1
  43. data/ext/couchbase/operations/analytics_dataverse_create.hxx +1 -1
  44. data/ext/couchbase/operations/analytics_dataverse_drop.hxx +1 -1
  45. data/ext/couchbase/operations/analytics_get_pending_mutations.hxx +1 -1
  46. data/ext/couchbase/operations/analytics_index_create.hxx +1 -1
  47. data/ext/couchbase/operations/analytics_index_drop.hxx +1 -1
  48. data/ext/couchbase/operations/analytics_index_get_all.hxx +1 -1
  49. data/ext/couchbase/operations/analytics_link_connect.hxx +1 -1
  50. data/ext/couchbase/operations/analytics_link_disconnect.hxx +1 -1
  51. data/ext/couchbase/operations/bucket_create.hxx +11 -5
  52. data/ext/couchbase/operations/bucket_drop.hxx +1 -1
  53. data/ext/couchbase/operations/bucket_flush.hxx +1 -1
  54. data/ext/couchbase/operations/bucket_get.hxx +1 -1
  55. data/ext/couchbase/operations/bucket_get_all.hxx +1 -1
  56. data/ext/couchbase/operations/bucket_settings.hxx +43 -4
  57. data/ext/couchbase/operations/bucket_update.hxx +11 -5
  58. data/ext/couchbase/operations/cluster_developer_preview_enable.hxx +1 -1
  59. data/ext/couchbase/operations/collection_create.hxx +3 -1
  60. data/ext/couchbase/operations/collection_drop.hxx +1 -1
  61. data/ext/couchbase/operations/collections_manifest_get.hxx +70 -0
  62. data/ext/couchbase/operations/document_analytics.hxx +6 -1
  63. data/ext/couchbase/operations/document_get_projected.hxx +1 -1
  64. data/ext/couchbase/operations/document_query.hxx +85 -8
  65. data/ext/couchbase/operations/document_search.hxx +14 -4
  66. data/ext/couchbase/operations/document_view.hxx +1 -1
  67. data/ext/couchbase/operations/group_drop.hxx +71 -0
  68. data/ext/couchbase/operations/group_get.hxx +75 -0
  69. data/ext/couchbase/operations/group_get_all.hxx +70 -0
  70. data/ext/couchbase/operations/group_upsert.hxx +118 -0
  71. data/ext/couchbase/operations/query_index_build_deferred.hxx +1 -1
  72. data/ext/couchbase/operations/query_index_create.hxx +1 -1
  73. data/ext/couchbase/operations/query_index_drop.hxx +1 -1
  74. data/ext/couchbase/operations/query_index_get_all.hxx +3 -2
  75. data/ext/couchbase/operations/rbac.hxx +276 -0
  76. data/ext/couchbase/operations/role_get_all.hxx +70 -0
  77. data/ext/couchbase/operations/scope_create.hxx +6 -2
  78. data/ext/couchbase/operations/scope_drop.hxx +1 -1
  79. data/ext/couchbase/operations/scope_get_all.hxx +1 -1
  80. data/ext/couchbase/operations/search_get_stats.hxx +59 -0
  81. data/ext/couchbase/operations/search_index_analyze_document.hxx +1 -1
  82. data/ext/couchbase/operations/search_index_control_ingest.hxx +1 -1
  83. data/ext/couchbase/operations/search_index_control_plan_freeze.hxx +1 -1
  84. data/ext/couchbase/operations/search_index_control_query.hxx +1 -1
  85. data/ext/couchbase/operations/search_index_drop.hxx +1 -1
  86. data/ext/couchbase/operations/search_index_get.hxx +1 -1
  87. data/ext/couchbase/operations/search_index_get_all.hxx +1 -1
  88. data/ext/couchbase/operations/search_index_get_documents_count.hxx +24 -16
  89. data/ext/couchbase/operations/search_index_get_stats.hxx +81 -0
  90. data/ext/couchbase/operations/search_index_upsert.hxx +1 -1
  91. data/ext/couchbase/operations/user_drop.hxx +72 -0
  92. data/ext/couchbase/operations/user_get.hxx +76 -0
  93. data/ext/couchbase/operations/user_get_all.hxx +71 -0
  94. data/ext/couchbase/operations/user_upsert.hxx +125 -0
  95. data/ext/couchbase/operations/view_index_drop.hxx +1 -1
  96. data/ext/couchbase/operations/view_index_get.hxx +1 -1
  97. data/ext/couchbase/operations/view_index_get_all.hxx +1 -1
  98. data/ext/couchbase/operations/view_index_upsert.hxx +1 -1
  99. data/ext/couchbase/origin.hxx +4 -4
  100. data/ext/couchbase/platform/terminate_handler.cc +5 -4
  101. data/ext/couchbase/protocol/client_opcode.hxx +38 -38
  102. data/ext/couchbase/protocol/client_response.hxx +2 -2
  103. data/ext/couchbase/protocol/cmd_cluster_map_change_notification.hxx +6 -3
  104. data/ext/couchbase/protocol/cmd_get_cluster_config.hxx +3 -1
  105. data/ext/couchbase/protocol/magic.hxx +6 -6
  106. data/ext/couchbase/protocol/server_opcode.hxx +2 -2
  107. data/ext/couchbase/protocol/status.hxx +57 -57
  108. data/ext/couchbase/service_type.hxx +1 -1
  109. data/ext/couchbase/utils/connection_string.hxx +12 -3
  110. data/ext/couchbase/version.hxx +1 -1
  111. data/ext/extconf.rb +21 -9
  112. data/ext/test/test_helper.hxx +141 -0
  113. data/ext/test/test_helper_native.hxx +59 -0
  114. data/ext/test/test_helper_ruby.hxx +72 -0
  115. data/ext/test/test_native_diagnostics.cxx +385 -0
  116. data/ext/test/test_native_trivial_crud.cxx +83 -0
  117. data/ext/test/test_ruby_trivial_crud.cxx +35 -0
  118. data/ext/test/test_ruby_trivial_query.cxx +34 -0
  119. data/ext/third_party/asio/asio/include/asio.hpp +35 -0
  120. data/ext/third_party/asio/asio/include/asio/any_io_executor.hpp +71 -0
  121. data/ext/third_party/asio/asio/include/asio/associated_allocator.hpp +1 -7
  122. data/ext/third_party/asio/asio/include/asio/associated_executor.hpp +36 -19
  123. data/ext/third_party/asio/asio/include/asio/async_result.hpp +1 -8
  124. data/ext/third_party/asio/asio/include/asio/awaitable.hpp +14 -4
  125. data/ext/third_party/asio/asio/include/asio/basic_datagram_socket.hpp +12 -7
  126. data/ext/third_party/asio/asio/include/asio/basic_deadline_timer.hpp +4 -4
  127. data/ext/third_party/asio/asio/include/asio/basic_raw_socket.hpp +11 -7
  128. data/ext/third_party/asio/asio/include/asio/basic_seq_packet_socket.hpp +9 -4
  129. data/ext/third_party/asio/asio/include/asio/basic_serial_port.hpp +6 -6
  130. data/ext/third_party/asio/asio/include/asio/basic_signal_set.hpp +4 -4
  131. data/ext/third_party/asio/asio/include/asio/basic_socket.hpp +5 -5
  132. data/ext/third_party/asio/asio/include/asio/basic_socket_acceptor.hpp +13 -7
  133. data/ext/third_party/asio/asio/include/asio/basic_stream_socket.hpp +7 -3
  134. data/ext/third_party/asio/asio/include/asio/basic_waitable_timer.hpp +52 -4
  135. data/ext/third_party/asio/asio/include/asio/bind_executor.hpp +10 -15
  136. data/ext/third_party/asio/asio/include/asio/buffer.hpp +6 -4
  137. data/ext/third_party/asio/asio/include/asio/co_spawn.hpp +380 -9
  138. data/ext/third_party/asio/asio/include/asio/defer.hpp +4 -1
  139. data/ext/third_party/asio/asio/include/asio/detached.hpp +50 -0
  140. data/ext/third_party/asio/asio/include/asio/detail/atomic_count.hpp +19 -0
  141. data/ext/third_party/asio/asio/include/asio/detail/bind_handler.hpp +144 -26
  142. data/ext/third_party/asio/asio/include/asio/detail/blocking_executor_op.hpp +107 -0
  143. data/ext/third_party/asio/asio/include/asio/detail/buffer_sequence_adapter.hpp +106 -0
  144. data/ext/third_party/asio/asio/include/asio/detail/bulk_executor_op.hpp +88 -0
  145. data/ext/third_party/asio/asio/include/asio/detail/completion_handler.hpp +10 -5
  146. data/ext/third_party/asio/asio/include/asio/detail/conditionally_enabled_event.hpp +8 -0
  147. data/ext/third_party/asio/asio/include/asio/detail/config.hpp +360 -37
  148. data/ext/third_party/asio/asio/include/asio/detail/deadline_timer_service.hpp +17 -2
  149. data/ext/third_party/asio/asio/include/asio/detail/descriptor_ops.hpp +24 -6
  150. data/ext/third_party/asio/asio/include/asio/detail/descriptor_read_op.hpp +32 -14
  151. data/ext/third_party/asio/asio/include/asio/detail/descriptor_write_op.hpp +32 -14
  152. data/ext/third_party/asio/asio/include/asio/detail/executor_function.hpp +133 -34
  153. data/ext/third_party/asio/asio/include/asio/detail/handler_alloc_helpers.hpp +42 -0
  154. data/ext/third_party/asio/asio/include/asio/detail/handler_invoke_helpers.hpp +23 -0
  155. data/ext/third_party/asio/asio/include/asio/detail/handler_tracking.hpp +26 -0
  156. data/ext/third_party/asio/asio/include/asio/detail/handler_work.hpp +370 -45
  157. data/ext/third_party/asio/asio/include/asio/detail/impl/descriptor_ops.ipp +208 -74
  158. data/ext/third_party/asio/asio/include/asio/detail/impl/handler_tracking.ipp +39 -1
  159. data/ext/third_party/asio/asio/include/asio/detail/impl/reactive_serial_port_service.ipp +12 -15
  160. data/ext/third_party/asio/asio/include/asio/detail/impl/scheduler.ipp +37 -0
  161. data/ext/third_party/asio/asio/include/asio/detail/impl/signal_set_service.ipp +2 -1
  162. data/ext/third_party/asio/asio/include/asio/detail/impl/socket_ops.ipp +661 -274
  163. data/ext/third_party/asio/asio/include/asio/detail/impl/strand_executor_service.hpp +210 -4
  164. data/ext/third_party/asio/asio/include/asio/detail/impl/strand_service.hpp +8 -9
  165. data/ext/third_party/asio/asio/include/asio/detail/impl/strand_service.ipp +5 -4
  166. data/ext/third_party/asio/asio/include/asio/detail/impl/win_iocp_io_context.ipp +15 -6
  167. data/ext/third_party/asio/asio/include/asio/detail/io_object_impl.hpp +32 -50
  168. data/ext/third_party/asio/asio/include/asio/detail/memory.hpp +3 -0
  169. data/ext/third_party/asio/asio/include/asio/detail/null_event.hpp +6 -0
  170. data/ext/third_party/asio/asio/include/asio/detail/pop_options.hpp +1 -1
  171. data/ext/third_party/asio/asio/include/asio/detail/posix_event.hpp +13 -0
  172. data/ext/third_party/asio/asio/include/asio/detail/push_options.hpp +1 -1
  173. data/ext/third_party/asio/asio/include/asio/detail/reactive_descriptor_service.hpp +38 -13
  174. data/ext/third_party/asio/asio/include/asio/detail/reactive_null_buffers_op.hpp +12 -6
  175. data/ext/third_party/asio/asio/include/asio/detail/reactive_serial_port_service.hpp +2 -3
  176. data/ext/third_party/asio/asio/include/asio/detail/reactive_socket_accept_op.hpp +36 -24
  177. data/ext/third_party/asio/asio/include/asio/detail/reactive_socket_connect_op.hpp +17 -10
  178. data/ext/third_party/asio/asio/include/asio/detail/reactive_socket_recv_op.hpp +38 -16
  179. data/ext/third_party/asio/asio/include/asio/detail/reactive_socket_recvfrom_op.hpp +36 -14
  180. data/ext/third_party/asio/asio/include/asio/detail/reactive_socket_recvmsg_op.hpp +21 -11
  181. data/ext/third_party/asio/asio/include/asio/detail/reactive_socket_send_op.hpp +43 -17
  182. data/ext/third_party/asio/asio/include/asio/detail/reactive_socket_sendto_op.hpp +39 -17
  183. data/ext/third_party/asio/asio/include/asio/detail/reactive_socket_service.hpp +44 -21
  184. data/ext/third_party/asio/asio/include/asio/detail/reactive_socket_service_base.hpp +41 -18
  185. data/ext/third_party/asio/asio/include/asio/detail/reactive_wait_op.hpp +12 -6
  186. data/ext/third_party/asio/asio/include/asio/detail/reactor_op.hpp +3 -1
  187. data/ext/third_party/asio/asio/include/asio/detail/resolve_endpoint_op.hpp +10 -8
  188. data/ext/third_party/asio/asio/include/asio/detail/resolve_query_op.hpp +11 -9
  189. data/ext/third_party/asio/asio/include/asio/detail/scheduler.hpp +8 -0
  190. data/ext/third_party/asio/asio/include/asio/detail/signal_handler.hpp +7 -5
  191. data/ext/third_party/asio/asio/include/asio/detail/socket_ops.hpp +46 -0
  192. data/ext/third_party/asio/asio/include/asio/detail/source_location.hpp +45 -0
  193. data/ext/third_party/asio/asio/include/asio/detail/std_event.hpp +12 -0
  194. data/ext/third_party/asio/asio/include/asio/detail/strand_executor_service.hpp +25 -1
  195. data/ext/third_party/asio/asio/include/asio/detail/strand_service.hpp +4 -1
  196. data/ext/third_party/asio/asio/include/asio/detail/thread_info_base.hpp +58 -0
  197. data/ext/third_party/asio/asio/include/asio/detail/type_traits.hpp +59 -0
  198. data/ext/third_party/asio/asio/include/asio/detail/variadic_templates.hpp +144 -1
  199. data/ext/third_party/asio/asio/include/asio/detail/wait_handler.hpp +9 -6
  200. data/ext/third_party/asio/asio/include/asio/detail/win_event.hpp +13 -0
  201. data/ext/third_party/asio/asio/include/asio/detail/win_iocp_handle_read_op.hpp +9 -5
  202. data/ext/third_party/asio/asio/include/asio/detail/win_iocp_handle_write_op.hpp +9 -5
  203. data/ext/third_party/asio/asio/include/asio/detail/win_iocp_io_context.hpp +5 -1
  204. data/ext/third_party/asio/asio/include/asio/detail/win_iocp_null_buffers_op.hpp +10 -6
  205. data/ext/third_party/asio/asio/include/asio/detail/win_iocp_overlapped_op.hpp +9 -5
  206. data/ext/third_party/asio/asio/include/asio/detail/win_iocp_overlapped_ptr.hpp +18 -6
  207. data/ext/third_party/asio/asio/include/asio/detail/win_iocp_socket_accept_op.hpp +15 -11
  208. data/ext/third_party/asio/asio/include/asio/detail/win_iocp_socket_connect_op.hpp +10 -5
  209. data/ext/third_party/asio/asio/include/asio/detail/win_iocp_socket_recv_op.hpp +8 -4
  210. data/ext/third_party/asio/asio/include/asio/detail/win_iocp_socket_recvfrom_op.hpp +8 -4
  211. data/ext/third_party/asio/asio/include/asio/detail/win_iocp_socket_recvmsg_op.hpp +8 -4
  212. data/ext/third_party/asio/asio/include/asio/detail/win_iocp_socket_send_op.hpp +8 -4
  213. data/ext/third_party/asio/asio/include/asio/detail/win_iocp_wait_op.hpp +10 -5
  214. data/ext/third_party/asio/asio/include/asio/detail/winrt_resolve_op.hpp +8 -4
  215. data/ext/third_party/asio/asio/include/asio/detail/winrt_socket_connect_op.hpp +8 -4
  216. data/ext/third_party/asio/asio/include/asio/detail/winrt_socket_recv_op.hpp +8 -4
  217. data/ext/third_party/asio/asio/include/asio/detail/winrt_socket_send_op.hpp +8 -4
  218. data/ext/third_party/asio/asio/include/asio/detail/work_dispatcher.hpp +81 -6
  219. data/ext/third_party/asio/asio/include/asio/detail/wrapped_handler.hpp +45 -9
  220. data/ext/third_party/asio/asio/include/asio/dispatch.hpp +4 -1
  221. data/ext/third_party/asio/asio/include/asio/execution.hpp +48 -0
  222. data/ext/third_party/asio/asio/include/asio/execution/allocator.hpp +249 -0
  223. data/ext/third_party/asio/asio/include/asio/execution/any_executor.hpp +2264 -0
  224. data/ext/third_party/asio/asio/include/asio/execution/bad_executor.hpp +47 -0
  225. data/ext/third_party/asio/asio/include/asio/execution/blocking.hpp +1351 -0
  226. data/ext/third_party/asio/asio/include/asio/execution/blocking_adaptation.hpp +1064 -0
  227. data/ext/third_party/asio/asio/include/asio/execution/bulk_execute.hpp +390 -0
  228. data/ext/third_party/asio/asio/include/asio/execution/bulk_guarantee.hpp +1018 -0
  229. data/ext/third_party/asio/asio/include/asio/execution/connect.hpp +486 -0
  230. data/ext/third_party/asio/asio/include/asio/execution/context.hpp +185 -0
  231. data/ext/third_party/asio/asio/include/asio/execution/context_as.hpp +201 -0
  232. data/ext/third_party/asio/asio/include/asio/execution/detail/as_invocable.hpp +152 -0
  233. data/ext/third_party/asio/asio/include/asio/execution/detail/as_operation.hpp +105 -0
  234. data/ext/third_party/asio/asio/include/asio/execution/detail/as_receiver.hpp +128 -0
  235. data/ext/third_party/asio/asio/include/asio/execution/detail/bulk_sender.hpp +261 -0
  236. data/ext/third_party/asio/asio/include/asio/execution/detail/submit_receiver.hpp +233 -0
  237. data/ext/third_party/asio/asio/include/asio/execution/detail/void_receiver.hpp +90 -0
  238. data/ext/third_party/asio/asio/include/asio/execution/execute.hpp +264 -0
  239. data/ext/third_party/asio/asio/include/asio/execution/executor.hpp +238 -0
  240. data/ext/third_party/asio/asio/include/asio/execution/impl/bad_executor.ipp +40 -0
  241. data/ext/third_party/asio/asio/include/asio/execution/impl/receiver_invocation_error.ipp +36 -0
  242. data/ext/third_party/asio/asio/include/asio/execution/invocable_archetype.hpp +71 -0
  243. data/ext/third_party/asio/asio/include/asio/execution/mapping.hpp +917 -0
  244. data/ext/third_party/asio/asio/include/asio/execution/occupancy.hpp +178 -0
  245. data/ext/third_party/asio/asio/include/asio/execution/operation_state.hpp +94 -0
  246. data/ext/third_party/asio/asio/include/asio/execution/outstanding_work.hpp +721 -0
  247. data/ext/third_party/asio/asio/include/asio/execution/prefer_only.hpp +327 -0
  248. data/ext/third_party/asio/asio/include/asio/execution/receiver.hpp +280 -0
  249. data/ext/third_party/asio/asio/include/asio/execution/receiver_invocation_error.hpp +48 -0
  250. data/ext/third_party/asio/asio/include/asio/execution/relationship.hpp +720 -0
  251. data/ext/third_party/asio/asio/include/asio/execution/schedule.hpp +290 -0
  252. data/ext/third_party/asio/asio/include/asio/execution/scheduler.hpp +86 -0
  253. data/ext/third_party/asio/asio/include/asio/execution/sender.hpp +311 -0
  254. data/ext/third_party/asio/asio/include/asio/execution/set_done.hpp +253 -0
  255. data/ext/third_party/asio/asio/include/asio/execution/set_error.hpp +253 -0
  256. data/ext/third_party/asio/asio/include/asio/execution/set_value.hpp +486 -0
  257. data/ext/third_party/asio/asio/include/asio/execution/start.hpp +250 -0
  258. data/ext/third_party/asio/asio/include/asio/execution/submit.hpp +450 -0
  259. data/ext/third_party/asio/asio/include/asio/executor.hpp +7 -1
  260. data/ext/third_party/asio/asio/include/asio/executor_work_guard.hpp +126 -9
  261. data/ext/third_party/asio/asio/include/asio/handler_alloc_hook.hpp +28 -5
  262. data/ext/third_party/asio/asio/include/asio/handler_invoke_hook.hpp +29 -3
  263. data/ext/third_party/asio/asio/include/asio/impl/awaitable.hpp +14 -0
  264. data/ext/third_party/asio/asio/include/asio/impl/buffered_read_stream.hpp +44 -8
  265. data/ext/third_party/asio/asio/include/asio/impl/buffered_write_stream.hpp +44 -8
  266. data/ext/third_party/asio/asio/include/asio/impl/co_spawn.hpp +145 -7
  267. data/ext/third_party/asio/asio/include/asio/impl/compose.hpp +124 -22
  268. data/ext/third_party/asio/asio/include/asio/impl/connect.hpp +52 -8
  269. data/ext/third_party/asio/asio/include/asio/impl/defer.hpp +147 -12
  270. data/ext/third_party/asio/asio/include/asio/impl/dispatch.hpp +142 -12
  271. data/ext/third_party/asio/asio/include/asio/impl/executor.hpp +15 -101
  272. data/ext/third_party/asio/asio/include/asio/impl/executor.ipp +5 -0
  273. data/ext/third_party/asio/asio/include/asio/impl/handler_alloc_hook.ipp +13 -4
  274. data/ext/third_party/asio/asio/include/asio/impl/io_context.hpp +144 -57
  275. data/ext/third_party/asio/asio/include/asio/impl/multiple_exceptions.ipp +49 -0
  276. data/ext/third_party/asio/asio/include/asio/impl/post.hpp +147 -12
  277. data/ext/third_party/asio/asio/include/asio/impl/read.hpp +85 -18
  278. data/ext/third_party/asio/asio/include/asio/impl/read_at.hpp +59 -14
  279. data/ext/third_party/asio/asio/include/asio/impl/read_until.hpp +241 -56
  280. data/ext/third_party/asio/asio/include/asio/impl/redirect_error.hpp +22 -4
  281. data/ext/third_party/asio/asio/include/asio/impl/spawn.hpp +58 -22
  282. data/ext/third_party/asio/asio/include/asio/impl/src.hpp +3 -0
  283. data/ext/third_party/asio/asio/include/asio/impl/system_context.ipp +16 -4
  284. data/ext/third_party/asio/asio/include/asio/impl/system_executor.hpp +113 -12
  285. data/ext/third_party/asio/asio/include/asio/impl/thread_pool.hpp +260 -37
  286. data/ext/third_party/asio/asio/include/asio/impl/thread_pool.ipp +61 -7
  287. data/ext/third_party/asio/asio/include/asio/impl/use_awaitable.hpp +5 -2
  288. data/ext/third_party/asio/asio/include/asio/impl/use_future.hpp +147 -6
  289. data/ext/third_party/asio/asio/include/asio/impl/write.hpp +75 -14
  290. data/ext/third_party/asio/asio/include/asio/impl/write_at.hpp +53 -11
  291. data/ext/third_party/asio/asio/include/asio/io_context.hpp +706 -48
  292. data/ext/third_party/asio/asio/include/asio/io_context_strand.hpp +3 -1
  293. data/ext/third_party/asio/asio/include/asio/ip/basic_resolver.hpp +4 -4
  294. data/ext/third_party/asio/asio/include/asio/is_applicable_property.hpp +61 -0
  295. data/ext/third_party/asio/asio/include/asio/multiple_exceptions.hpp +58 -0
  296. data/ext/third_party/asio/asio/include/asio/posix/basic_descriptor.hpp +4 -4
  297. data/ext/third_party/asio/asio/include/asio/posix/basic_stream_descriptor.hpp +5 -5
  298. data/ext/third_party/asio/asio/include/asio/post.hpp +4 -1
  299. data/ext/third_party/asio/asio/include/asio/prefer.hpp +656 -0
  300. data/ext/third_party/asio/asio/include/asio/query.hpp +296 -0
  301. data/ext/third_party/asio/asio/include/asio/read_until.hpp +6 -6
  302. data/ext/third_party/asio/asio/include/asio/require.hpp +524 -0
  303. data/ext/third_party/asio/asio/include/asio/require_concept.hpp +310 -0
  304. data/ext/third_party/asio/asio/include/asio/spawn.hpp +12 -4
  305. data/ext/third_party/asio/asio/include/asio/ssl/detail/buffered_handshake_op.hpp +5 -0
  306. data/ext/third_party/asio/asio/include/asio/ssl/detail/engine.hpp +5 -0
  307. data/ext/third_party/asio/asio/include/asio/ssl/detail/handshake_op.hpp +5 -0
  308. data/ext/third_party/asio/asio/include/asio/ssl/detail/impl/engine.ipp +16 -3
  309. data/ext/third_party/asio/asio/include/asio/ssl/detail/io.hpp +38 -4
  310. data/ext/third_party/asio/asio/include/asio/ssl/detail/read_op.hpp +5 -0
  311. data/ext/third_party/asio/asio/include/asio/ssl/detail/shutdown_op.hpp +5 -0
  312. data/ext/third_party/asio/asio/include/asio/ssl/detail/stream_core.hpp +36 -2
  313. data/ext/third_party/asio/asio/include/asio/ssl/detail/write_op.hpp +10 -1
  314. data/ext/third_party/asio/asio/include/asio/ssl/stream.hpp +15 -0
  315. data/ext/third_party/asio/asio/include/asio/static_thread_pool.hpp +31 -0
  316. data/ext/third_party/asio/asio/include/asio/strand.hpp +232 -9
  317. data/ext/third_party/asio/asio/include/asio/system_context.hpp +12 -3
  318. data/ext/third_party/asio/asio/include/asio/system_executor.hpp +557 -24
  319. data/ext/third_party/asio/asio/include/asio/thread_pool.hpp +913 -37
  320. data/ext/third_party/asio/asio/include/asio/traits/bulk_execute_free.hpp +114 -0
  321. data/ext/third_party/asio/asio/include/asio/traits/bulk_execute_member.hpp +114 -0
  322. data/ext/third_party/asio/asio/include/asio/traits/connect_free.hpp +112 -0
  323. data/ext/third_party/asio/asio/include/asio/traits/connect_member.hpp +112 -0
  324. data/ext/third_party/asio/asio/include/asio/traits/equality_comparable.hpp +100 -0
  325. data/ext/third_party/asio/asio/include/asio/traits/execute_free.hpp +108 -0
  326. data/ext/third_party/asio/asio/include/asio/traits/execute_member.hpp +108 -0
  327. data/ext/third_party/asio/asio/include/asio/traits/prefer_free.hpp +108 -0
  328. data/ext/third_party/asio/asio/include/asio/traits/prefer_member.hpp +108 -0
  329. data/ext/third_party/asio/asio/include/asio/traits/query_free.hpp +108 -0
  330. data/ext/third_party/asio/asio/include/asio/traits/query_member.hpp +108 -0
  331. data/ext/third_party/asio/asio/include/asio/traits/query_static_constexpr_member.hpp +108 -0
  332. data/ext/third_party/asio/asio/include/asio/traits/require_concept_free.hpp +108 -0
  333. data/ext/third_party/asio/asio/include/asio/traits/require_concept_member.hpp +108 -0
  334. data/ext/third_party/asio/asio/include/asio/traits/require_free.hpp +108 -0
  335. data/ext/third_party/asio/asio/include/asio/traits/require_member.hpp +108 -0
  336. data/ext/third_party/asio/asio/include/asio/traits/schedule_free.hpp +108 -0
  337. data/ext/third_party/asio/asio/include/asio/traits/schedule_member.hpp +108 -0
  338. data/ext/third_party/asio/asio/include/asio/traits/set_done_free.hpp +108 -0
  339. data/ext/third_party/asio/asio/include/asio/traits/set_done_member.hpp +108 -0
  340. data/ext/third_party/asio/asio/include/asio/traits/set_error_free.hpp +112 -0
  341. data/ext/third_party/asio/asio/include/asio/traits/set_error_member.hpp +112 -0
  342. data/ext/third_party/asio/asio/include/asio/traits/set_value_free.hpp +234 -0
  343. data/ext/third_party/asio/asio/include/asio/traits/set_value_member.hpp +234 -0
  344. data/ext/third_party/asio/asio/include/asio/traits/start_free.hpp +108 -0
  345. data/ext/third_party/asio/asio/include/asio/traits/start_member.hpp +108 -0
  346. data/ext/third_party/asio/asio/include/asio/traits/static_query.hpp +108 -0
  347. data/ext/third_party/asio/asio/include/asio/traits/static_require.hpp +123 -0
  348. data/ext/third_party/asio/asio/include/asio/traits/static_require_concept.hpp +123 -0
  349. data/ext/third_party/asio/asio/include/asio/traits/submit_free.hpp +112 -0
  350. data/ext/third_party/asio/asio/include/asio/traits/submit_member.hpp +112 -0
  351. data/ext/third_party/asio/asio/include/asio/ts/executor.hpp +1 -0
  352. data/ext/third_party/asio/asio/include/asio/ts/netfwd.hpp +67 -8
  353. data/ext/third_party/asio/asio/include/asio/use_awaitable.hpp +63 -4
  354. data/ext/third_party/asio/asio/include/asio/version.hpp +1 -1
  355. data/ext/third_party/asio/asio/include/asio/windows/basic_object_handle.hpp +4 -4
  356. data/ext/third_party/asio/asio/include/asio/windows/basic_overlapped_handle.hpp +2 -2
  357. data/ext/third_party/asio/asio/include/asio/windows/basic_random_access_handle.hpp +5 -5
  358. data/ext/third_party/asio/asio/include/asio/windows/basic_stream_handle.hpp +5 -5
  359. data/ext/third_party/asio/asio/include/asio/windows/overlapped_ptr.hpp +4 -2
  360. data/ext/third_party/gsl/CMakeLists.txt +13 -5
  361. data/ext/third_party/gsl/include/gsl/gsl_assert +1 -1
  362. data/ext/third_party/gsl/include/gsl/gsl_byte +3 -3
  363. data/ext/third_party/gsl/include/gsl/gsl_narrow +52 -0
  364. data/ext/third_party/gsl/include/gsl/gsl_util +8 -50
  365. data/ext/third_party/gsl/include/gsl/multi_span +0 -10
  366. data/ext/third_party/gsl/include/gsl/pointers +14 -28
  367. data/ext/third_party/gsl/include/gsl/span +98 -46
  368. data/ext/third_party/gsl/include/gsl/string_span +37 -47
  369. data/ext/third_party/http_parser/http_parser.c +17 -10
  370. data/ext/third_party/http_parser/http_parser.h +4 -2
  371. data/ext/third_party/json/include/tao/json/basic_value.hpp +3 -2
  372. data/ext/third_party/json/include/tao/json/binary.hpp +4 -4
  373. data/ext/third_party/json/include/tao/json/binary_view.hpp +2 -2
  374. data/ext/third_party/json/include/tao/json/binding.hpp +2 -2
  375. data/ext/third_party/json/include/tao/json/binding/factory.hpp +8 -7
  376. data/ext/third_party/json/include/tao/json/binding/internal/array.hpp +2 -1
  377. data/ext/third_party/json/include/tao/json/binding/internal/object.hpp +6 -5
  378. data/ext/third_party/json/include/tao/json/binding/versions.hpp +3 -1
  379. data/ext/third_party/json/include/tao/json/cbor.hpp +1 -0
  380. data/ext/third_party/json/include/tao/json/cbor/consume_file.hpp +7 -7
  381. data/ext/third_party/json/include/tao/json/cbor/events/from_binary.hpp +43 -0
  382. data/ext/third_party/json/include/tao/json/cbor/events/from_file.hpp +4 -4
  383. data/ext/third_party/json/include/tao/json/cbor/events/from_string.hpp +3 -3
  384. data/ext/third_party/json/include/tao/json/cbor/from_binary.hpp +32 -0
  385. data/ext/third_party/json/include/tao/json/cbor/from_file.hpp +5 -5
  386. data/ext/third_party/json/include/tao/json/cbor/internal/grammar.hpp +2 -1
  387. data/ext/third_party/json/include/tao/json/consume_file.hpp +7 -7
  388. data/ext/third_party/json/include/tao/json/contrib/internal/indirect_traits.hpp +13 -6
  389. data/ext/third_party/json/include/tao/json/contrib/position.hpp +15 -15
  390. data/ext/third_party/json/include/tao/json/contrib/reference.hpp +5 -7
  391. data/ext/third_party/json/include/tao/json/contrib/schema.hpp +58 -35
  392. data/ext/third_party/json/include/tao/json/contrib/shared_ptr_traits.hpp +12 -4
  393. data/ext/third_party/json/include/tao/json/contrib/unique_ptr_traits.hpp +12 -4
  394. data/ext/third_party/json/include/tao/json/contrib/unordered_map_traits.hpp +1 -1
  395. data/ext/third_party/json/include/tao/json/contrib/unordered_set_traits.hpp +2 -2
  396. data/ext/third_party/json/include/tao/json/events/compare.hpp +2 -12
  397. data/ext/third_party/json/include/tao/json/events/from_file.hpp +4 -4
  398. data/ext/third_party/json/include/tao/json/events/from_string.hpp +2 -2
  399. data/ext/third_party/json/include/tao/json/events/invalid_string_to_binary.hpp +1 -1
  400. data/ext/third_party/json/include/tao/json/events/key_camel_case_to_snake_case.hpp +3 -3
  401. data/ext/third_party/json/include/tao/json/events/key_snake_case_to_camel_case.hpp +1 -1
  402. data/ext/third_party/json/include/tao/json/events/tee.hpp +2 -2
  403. data/ext/third_party/json/include/tao/json/events/to_pretty_stream.hpp +1 -1
  404. data/ext/third_party/json/include/tao/json/events/to_stream.hpp +1 -1
  405. data/ext/third_party/json/include/tao/json/events/transformer.hpp +3 -3
  406. data/ext/third_party/json/include/tao/json/events/validate_event_order.hpp +3 -3
  407. data/ext/third_party/json/include/tao/json/events/virtual_ref.hpp +6 -0
  408. data/ext/third_party/json/include/tao/json/external/pegtl.hpp +4 -13
  409. data/ext/third_party/json/include/tao/json/external/pegtl/argv_input.hpp +3 -5
  410. data/ext/third_party/json/include/tao/json/external/pegtl/ascii.hpp +5 -18
  411. data/ext/third_party/json/include/tao/json/external/pegtl/buffer_input.hpp +3 -3
  412. data/ext/third_party/json/include/tao/json/external/pegtl/change_action.hpp +2 -2
  413. data/ext/third_party/json/include/tao/json/external/pegtl/change_action_and_state.hpp +6 -6
  414. data/ext/third_party/json/include/tao/json/external/pegtl/change_action_and_states.hpp +5 -5
  415. data/ext/third_party/json/include/tao/json/external/pegtl/change_control.hpp +2 -2
  416. data/ext/third_party/json/include/tao/json/external/pegtl/change_state.hpp +6 -6
  417. data/ext/third_party/json/include/tao/json/external/pegtl/change_states.hpp +5 -5
  418. data/ext/third_party/json/include/tao/json/external/pegtl/contrib/alphabet.hpp +52 -52
  419. data/ext/third_party/json/include/tao/json/external/pegtl/contrib/analyze.hpp +176 -0
  420. data/ext/third_party/json/include/tao/json/external/pegtl/contrib/analyze_traits.hpp +275 -0
  421. data/ext/third_party/json/include/tao/json/external/pegtl/contrib/control_action.hpp +77 -0
  422. data/ext/third_party/json/include/tao/json/external/pegtl/contrib/coverage.hpp +151 -0
  423. data/ext/third_party/json/include/tao/json/external/pegtl/contrib/forward.hpp +16 -0
  424. data/ext/third_party/json/include/tao/json/external/pegtl/contrib/http.hpp +37 -18
  425. data/ext/third_party/json/include/tao/json/external/pegtl/contrib/icu/internal.hpp +20 -22
  426. data/ext/third_party/json/include/tao/json/external/pegtl/contrib/icu/utf16.hpp +6 -10
  427. data/ext/third_party/json/include/tao/json/external/pegtl/contrib/icu/utf32.hpp +6 -10
  428. data/ext/third_party/json/include/tao/json/external/pegtl/contrib/icu/utf8.hpp +2 -4
  429. data/ext/third_party/json/include/tao/json/external/pegtl/contrib/if_then.hpp +11 -10
  430. data/ext/third_party/json/include/tao/json/external/pegtl/contrib/integer.hpp +116 -131
  431. data/ext/third_party/json/include/tao/json/external/pegtl/{internal → contrib/internal}/endian.hpp +4 -4
  432. data/ext/third_party/json/include/tao/json/external/pegtl/{internal → contrib/internal}/endian_gcc.hpp +2 -2
  433. data/ext/third_party/json/include/tao/json/external/pegtl/{internal → contrib/internal}/endian_win.hpp +2 -2
  434. data/ext/third_party/json/include/tao/json/external/pegtl/{internal → contrib/internal}/peek_mask_uint.hpp +9 -9
  435. data/ext/third_party/json/include/tao/json/external/pegtl/{internal → contrib/internal}/peek_mask_uint8.hpp +9 -10
  436. data/ext/third_party/json/include/tao/json/external/pegtl/{internal → contrib/internal}/peek_uint.hpp +9 -9
  437. data/ext/third_party/json/include/tao/json/external/pegtl/{internal → contrib/internal}/peek_uint8.hpp +9 -10
  438. data/ext/third_party/json/include/tao/json/external/pegtl/{internal → contrib/internal}/peek_utf16.hpp +10 -10
  439. data/ext/third_party/json/include/tao/json/external/pegtl/{internal → contrib/internal}/peek_utf32.hpp +9 -9
  440. data/ext/third_party/json/include/tao/json/external/pegtl/{internal → contrib/internal}/read_uint.hpp +3 -3
  441. data/ext/third_party/json/include/tao/json/external/pegtl/contrib/internal/set_stack_guard.hpp +52 -0
  442. data/ext/third_party/json/include/tao/json/external/pegtl/contrib/parse_tree.hpp +80 -201
  443. data/ext/third_party/json/include/tao/json/external/pegtl/contrib/parse_tree_to_dot.hpp +11 -10
  444. data/ext/third_party/json/include/tao/json/external/pegtl/contrib/print.hpp +75 -0
  445. data/ext/third_party/json/include/tao/json/external/pegtl/contrib/print_coverage.hpp +53 -0
  446. data/ext/third_party/json/include/tao/json/external/pegtl/contrib/raw_string.hpp +45 -36
  447. data/ext/third_party/json/include/tao/json/external/pegtl/contrib/remove_first_state.hpp +33 -50
  448. data/ext/third_party/json/include/tao/json/external/pegtl/contrib/remove_last_states.hpp +117 -0
  449. data/ext/third_party/json/include/tao/json/external/pegtl/contrib/rep_one_min_max.hpp +43 -11
  450. data/ext/third_party/json/include/tao/json/external/pegtl/contrib/rep_string.hpp +1 -2
  451. data/ext/third_party/json/include/tao/json/external/pegtl/contrib/shuffle_states.hpp +193 -0
  452. data/ext/third_party/json/include/tao/json/external/pegtl/contrib/state_control.hpp +118 -0
  453. data/ext/third_party/json/include/tao/json/external/pegtl/contrib/trace.hpp +227 -0
  454. data/ext/third_party/json/include/tao/json/external/pegtl/{uint16.hpp → contrib/uint16.hpp} +5 -5
  455. data/ext/third_party/json/include/tao/json/external/pegtl/{uint32.hpp → contrib/uint32.hpp} +5 -5
  456. data/ext/third_party/json/include/tao/json/external/pegtl/{uint64.hpp → contrib/uint64.hpp} +5 -5
  457. data/ext/third_party/json/include/tao/json/external/pegtl/{uint8.hpp → contrib/uint8.hpp} +5 -5
  458. data/ext/third_party/json/include/tao/json/external/pegtl/contrib/unescape.hpp +14 -14
  459. data/ext/third_party/json/include/tao/json/external/pegtl/contrib/uri.hpp +1 -1
  460. data/ext/third_party/json/include/tao/json/external/pegtl/{utf16.hpp → contrib/utf16.hpp} +5 -5
  461. data/ext/third_party/json/include/tao/json/external/pegtl/{utf32.hpp → contrib/utf32.hpp} +5 -5
  462. data/ext/third_party/json/include/tao/json/external/pegtl/cstream_input.hpp +2 -3
  463. data/ext/third_party/json/include/tao/json/external/pegtl/{internal/demangle.hpp → demangle.hpp} +12 -14
  464. data/ext/third_party/json/include/tao/json/external/pegtl/disable_action.hpp +2 -2
  465. data/ext/third_party/json/include/tao/json/external/pegtl/discard_input.hpp +2 -2
  466. data/ext/third_party/json/include/tao/json/external/pegtl/discard_input_on_failure.hpp +2 -2
  467. data/ext/third_party/json/include/tao/json/external/pegtl/discard_input_on_success.hpp +2 -2
  468. data/ext/third_party/json/include/tao/json/external/pegtl/enable_action.hpp +2 -2
  469. data/ext/third_party/json/include/tao/json/external/pegtl/file_input.hpp +1 -1
  470. data/ext/third_party/json/include/tao/json/external/pegtl/internal/action.hpp +19 -9
  471. data/ext/third_party/json/include/tao/json/external/pegtl/internal/action_input.hpp +7 -8
  472. data/ext/third_party/json/include/tao/json/external/pegtl/internal/any.hpp +14 -14
  473. data/ext/third_party/json/include/tao/json/external/pegtl/internal/apply.hpp +9 -9
  474. data/ext/third_party/json/include/tao/json/external/pegtl/internal/apply0.hpp +8 -7
  475. data/ext/third_party/json/include/tao/json/external/pegtl/internal/apply_single.hpp +4 -4
  476. data/ext/third_party/json/include/tao/json/external/pegtl/internal/at.hpp +17 -15
  477. data/ext/third_party/json/include/tao/json/external/pegtl/internal/bof.hpp +7 -6
  478. data/ext/third_party/json/include/tao/json/external/pegtl/internal/bol.hpp +8 -8
  479. data/ext/third_party/json/include/tao/json/external/pegtl/internal/bump.hpp +4 -4
  480. data/ext/third_party/json/include/tao/json/external/pegtl/internal/bump_help.hpp +3 -3
  481. data/ext/third_party/json/include/tao/json/external/pegtl/internal/bytes.hpp +17 -10
  482. data/ext/third_party/json/include/tao/json/external/pegtl/internal/control.hpp +19 -9
  483. data/ext/third_party/json/include/tao/json/external/pegtl/internal/cr_crlf_eol.hpp +2 -2
  484. data/ext/third_party/json/include/tao/json/external/pegtl/internal/cr_eol.hpp +2 -2
  485. data/ext/third_party/json/include/tao/json/external/pegtl/internal/crlf_eol.hpp +2 -2
  486. data/ext/third_party/json/include/tao/json/external/pegtl/internal/cstream_reader.hpp +1 -1
  487. data/ext/third_party/json/include/tao/json/external/pegtl/internal/{always_false.hpp → dependent_false.hpp} +3 -8
  488. data/ext/third_party/json/include/tao/json/external/pegtl/internal/disable.hpp +19 -9
  489. data/ext/third_party/json/include/tao/json/external/pegtl/internal/discard.hpp +7 -6
  490. data/ext/third_party/json/include/tao/json/external/pegtl/internal/enable.hpp +19 -9
  491. data/ext/third_party/json/include/tao/json/external/pegtl/internal/{skip_control.hpp → enable_control.hpp} +5 -5
  492. data/ext/third_party/json/include/tao/json/external/pegtl/internal/eof.hpp +7 -6
  493. data/ext/third_party/json/include/tao/json/external/pegtl/internal/eol.hpp +8 -7
  494. data/ext/third_party/json/include/tao/json/external/pegtl/internal/eolf.hpp +8 -7
  495. data/ext/third_party/json/include/tao/json/external/pegtl/internal/failure.hpp +32 -0
  496. data/ext/third_party/json/include/tao/json/external/pegtl/internal/file_mapper_posix.hpp +61 -10
  497. data/ext/third_party/json/include/tao/json/external/pegtl/internal/file_mapper_win32.hpp +27 -33
  498. data/ext/third_party/json/include/tao/json/external/pegtl/internal/file_reader.hpp +29 -26
  499. data/ext/third_party/json/include/tao/json/external/pegtl/internal/has_apply.hpp +3 -7
  500. data/ext/third_party/json/include/tao/json/external/pegtl/internal/has_apply0.hpp +3 -7
  501. data/ext/third_party/json/include/tao/json/external/pegtl/internal/has_match.hpp +4 -20
  502. data/ext/third_party/json/include/tao/json/external/pegtl/internal/has_unwind.hpp +21 -0
  503. data/ext/third_party/json/include/tao/json/external/pegtl/internal/if_apply.hpp +8 -7
  504. data/ext/third_party/json/include/tao/json/external/pegtl/internal/if_must.hpp +8 -9
  505. data/ext/third_party/json/include/tao/json/external/pegtl/internal/if_must_else.hpp +2 -0
  506. data/ext/third_party/json/include/tao/json/external/pegtl/internal/if_then_else.hpp +7 -7
  507. data/ext/third_party/json/include/tao/json/external/pegtl/internal/istream_reader.hpp +1 -2
  508. data/ext/third_party/json/include/tao/json/external/pegtl/internal/istring.hpp +11 -11
  509. data/ext/third_party/json/include/tao/json/external/pegtl/internal/iterator.hpp +7 -10
  510. data/ext/third_party/json/include/tao/json/external/pegtl/internal/lf_crlf_eol.hpp +2 -2
  511. data/ext/third_party/json/include/tao/json/external/pegtl/internal/lf_eol.hpp +2 -2
  512. data/ext/third_party/json/include/tao/json/external/pegtl/internal/list_tail.hpp +4 -2
  513. data/ext/third_party/json/include/tao/json/external/pegtl/internal/list_tail_pad.hpp +1 -1
  514. data/ext/third_party/json/include/tao/json/external/pegtl/internal/marker.hpp +3 -5
  515. data/ext/third_party/json/include/tao/json/external/pegtl/internal/minus.hpp +21 -0
  516. data/ext/third_party/json/include/tao/json/external/pegtl/internal/missing_apply.hpp +5 -2
  517. data/ext/third_party/json/include/tao/json/external/pegtl/internal/missing_apply0.hpp +5 -2
  518. data/ext/third_party/json/include/tao/json/external/pegtl/internal/must.hpp +16 -24
  519. data/ext/third_party/json/include/tao/json/external/pegtl/internal/not_at.hpp +17 -15
  520. data/ext/third_party/json/include/tao/json/external/pegtl/internal/one.hpp +23 -12
  521. data/ext/third_party/json/include/tao/json/external/pegtl/internal/opt.hpp +16 -16
  522. data/ext/third_party/json/include/tao/json/external/pegtl/internal/path_to_string.hpp +26 -0
  523. data/ext/third_party/json/include/tao/json/external/pegtl/internal/peek_char.hpp +5 -5
  524. data/ext/third_party/json/include/tao/json/external/pegtl/internal/peek_utf8.hpp +12 -13
  525. data/ext/third_party/json/include/tao/json/external/pegtl/internal/plus.hpp +18 -11
  526. data/ext/third_party/json/include/tao/json/external/pegtl/internal/raise.hpp +8 -17
  527. data/ext/third_party/json/include/tao/json/external/pegtl/internal/range.hpp +22 -17
  528. data/ext/third_party/json/include/tao/json/external/pegtl/internal/ranges.hpp +28 -18
  529. data/ext/third_party/json/include/tao/json/external/pegtl/internal/rematch.hpp +12 -9
  530. data/ext/third_party/json/include/tao/json/external/pegtl/internal/rep.hpp +26 -25
  531. data/ext/third_party/json/include/tao/json/external/pegtl/internal/rep_min_max.hpp +23 -21
  532. data/ext/third_party/json/include/tao/json/external/pegtl/internal/rep_opt.hpp +24 -9
  533. data/ext/third_party/json/include/tao/json/external/pegtl/internal/require.hpp +10 -10
  534. data/ext/third_party/json/include/tao/json/external/pegtl/internal/rules.hpp +4 -4
  535. data/ext/third_party/json/include/tao/json/external/pegtl/internal/seq.hpp +18 -33
  536. data/ext/third_party/json/include/tao/json/external/pegtl/internal/sor.hpp +24 -17
  537. data/ext/third_party/json/include/tao/json/external/pegtl/internal/star.hpp +13 -8
  538. data/ext/third_party/json/include/tao/json/external/pegtl/internal/state.hpp +21 -11
  539. data/ext/third_party/json/include/tao/json/external/pegtl/internal/string.hpp +11 -11
  540. data/ext/third_party/json/include/tao/json/external/pegtl/internal/success.hpp +32 -0
  541. data/ext/third_party/json/include/tao/json/external/pegtl/internal/try_catch_type.hpp +16 -16
  542. data/ext/third_party/json/include/tao/json/external/pegtl/internal/until.hpp +18 -14
  543. data/ext/third_party/json/include/tao/json/external/pegtl/istream_input.hpp +2 -3
  544. data/ext/third_party/json/include/tao/json/external/pegtl/match.hpp +125 -29
  545. data/ext/third_party/json/include/tao/json/external/pegtl/memory_input.hpp +32 -48
  546. data/ext/third_party/json/include/tao/json/external/pegtl/mmap_input.hpp +16 -16
  547. data/ext/third_party/json/include/tao/json/external/pegtl/must_if.hpp +64 -0
  548. data/ext/third_party/json/include/tao/json/external/pegtl/normal.hpp +25 -25
  549. data/ext/third_party/json/include/tao/json/external/pegtl/nothing.hpp +1 -2
  550. data/ext/third_party/json/include/tao/json/external/pegtl/parse.hpp +6 -8
  551. data/ext/third_party/json/include/tao/json/external/pegtl/parse_error.hpp +80 -35
  552. data/ext/third_party/json/include/tao/json/external/pegtl/position.hpp +18 -10
  553. data/ext/third_party/json/include/tao/json/external/pegtl/read_input.hpp +18 -38
  554. data/ext/third_party/json/include/tao/json/external/pegtl/rules.hpp +6 -5
  555. data/ext/third_party/json/include/tao/json/external/pegtl/string_input.hpp +3 -5
  556. data/ext/third_party/json/include/tao/json/external/pegtl/type_list.hpp +46 -0
  557. data/ext/third_party/json/include/tao/json/external/pegtl/visit.hpp +66 -0
  558. data/ext/third_party/json/include/tao/json/from_file.hpp +5 -5
  559. data/ext/third_party/json/include/tao/json/internal/action.hpp +3 -3
  560. data/ext/third_party/json/include/tao/json/internal/dependent_false.hpp +14 -0
  561. data/ext/third_party/json/include/tao/json/internal/errors.hpp +17 -17
  562. data/ext/third_party/json/include/tao/json/internal/format.hpp +0 -2
  563. data/ext/third_party/json/include/tao/json/internal/grammar.hpp +17 -17
  564. data/ext/third_party/json/include/tao/json/internal/pair.hpp +1 -1
  565. data/ext/third_party/json/include/tao/json/internal/sha256.hpp +8 -8
  566. data/ext/third_party/json/include/tao/json/internal/single.hpp +1 -1
  567. data/ext/third_party/json/include/tao/json/internal/type_traits.hpp +12 -29
  568. data/ext/third_party/json/include/tao/json/jaxn/consume_file.hpp +7 -7
  569. data/ext/third_party/json/include/tao/json/jaxn/events/from_file.hpp +4 -4
  570. data/ext/third_party/json/include/tao/json/jaxn/events/from_string.hpp +2 -2
  571. data/ext/third_party/json/include/tao/json/jaxn/from_file.hpp +5 -5
  572. data/ext/third_party/json/include/tao/json/jaxn/internal/action.hpp +6 -6
  573. data/ext/third_party/json/include/tao/json/jaxn/internal/bunescape_action.hpp +2 -2
  574. data/ext/third_party/json/include/tao/json/jaxn/internal/errors.hpp +43 -43
  575. data/ext/third_party/json/include/tao/json/jaxn/internal/grammar.hpp +36 -36
  576. data/ext/third_party/json/include/tao/json/jaxn/internal/integer.hpp +10 -11
  577. data/ext/third_party/json/include/tao/json/jaxn/is_identifier.hpp +2 -2
  578. data/ext/third_party/json/include/tao/json/jaxn/parts_parser.hpp +1 -3
  579. data/ext/third_party/json/include/tao/json/message_extension.hpp +2 -2
  580. data/ext/third_party/json/include/tao/json/msgpack.hpp +1 -0
  581. data/ext/third_party/json/include/tao/json/msgpack/consume_file.hpp +7 -7
  582. data/ext/third_party/json/include/tao/json/msgpack/events/from_binary.hpp +43 -0
  583. data/ext/third_party/json/include/tao/json/msgpack/events/from_file.hpp +4 -4
  584. data/ext/third_party/json/include/tao/json/msgpack/events/from_string.hpp +4 -4
  585. data/ext/third_party/json/include/tao/json/msgpack/events/to_stream.hpp +4 -4
  586. data/ext/third_party/json/include/tao/json/msgpack/from_binary.hpp +32 -0
  587. data/ext/third_party/json/include/tao/json/msgpack/from_file.hpp +5 -5
  588. data/ext/third_party/json/include/tao/json/msgpack/internal/grammar.hpp +2 -1
  589. data/ext/third_party/json/include/tao/json/operators.hpp +0 -4
  590. data/ext/third_party/json/include/tao/json/parts_parser.hpp +3 -7
  591. data/ext/third_party/json/include/tao/json/self_contained.hpp +6 -18
  592. data/ext/third_party/json/include/tao/json/span.hpp +94 -166
  593. data/ext/third_party/json/include/tao/json/ubjson.hpp +1 -0
  594. data/ext/third_party/json/include/tao/json/ubjson/consume_file.hpp +7 -7
  595. data/ext/third_party/json/include/tao/json/ubjson/events/from_binary.hpp +43 -0
  596. data/ext/third_party/json/include/tao/json/ubjson/events/from_file.hpp +4 -4
  597. data/ext/third_party/json/include/tao/json/ubjson/events/from_string.hpp +3 -3
  598. data/ext/third_party/json/include/tao/json/ubjson/from_binary.hpp +32 -0
  599. data/ext/third_party/json/include/tao/json/ubjson/from_file.hpp +5 -5
  600. data/ext/third_party/json/include/tao/json/ubjson/internal/grammar.hpp +5 -3
  601. data/ext/third_party/json/include/tao/json/utf8.hpp +1 -1
  602. data/ext/third_party/snappy/snappy.cc +6 -2
  603. data/ext/third_party/spdlog/CMakeLists.txt +24 -57
  604. data/ext/third_party/spdlog/cmake/version.rc.in +1 -1
  605. data/ext/third_party/spdlog/include/spdlog/async.h +3 -3
  606. data/ext/third_party/spdlog/include/spdlog/cfg/argv.h +3 -4
  607. data/ext/third_party/spdlog/include/spdlog/cfg/env.h +6 -4
  608. data/ext/third_party/spdlog/include/spdlog/cfg/helpers-inl.h +22 -6
  609. data/ext/third_party/spdlog/include/spdlog/cfg/helpers.h +3 -2
  610. data/ext/third_party/spdlog/include/spdlog/common.h +1 -2
  611. data/ext/third_party/spdlog/include/spdlog/details/fmt_helper.h +9 -1
  612. data/ext/third_party/spdlog/include/spdlog/details/os.h +1 -1
  613. data/ext/third_party/spdlog/include/spdlog/details/registry-inl.h +21 -7
  614. data/ext/third_party/spdlog/include/spdlog/details/registry.h +6 -3
  615. data/ext/third_party/spdlog/include/spdlog/details/synchronous_factory.h +1 -1
  616. data/ext/third_party/spdlog/include/spdlog/details/tcp_client-windows.h +1 -1
  617. data/ext/third_party/spdlog/include/spdlog/details/tcp_client.h +8 -7
  618. data/ext/third_party/spdlog/include/spdlog/fmt/bin_to_hex.h +2 -2
  619. data/ext/third_party/spdlog/include/spdlog/fmt/bundled/chrono.h +66 -62
  620. data/ext/third_party/spdlog/include/spdlog/fmt/bundled/color.h +35 -37
  621. data/ext/third_party/spdlog/include/spdlog/fmt/bundled/compile.h +173 -103
  622. data/ext/third_party/spdlog/include/spdlog/fmt/bundled/core.h +538 -445
  623. data/ext/third_party/spdlog/include/spdlog/fmt/bundled/format-inl.h +114 -64
  624. data/ext/third_party/spdlog/include/spdlog/fmt/bundled/format.h +1152 -1071
  625. data/ext/third_party/spdlog/include/spdlog/fmt/bundled/locale.h +16 -16
  626. data/ext/third_party/spdlog/include/spdlog/fmt/bundled/os.h +450 -0
  627. data/ext/third_party/spdlog/include/spdlog/fmt/bundled/ostream.h +37 -13
  628. data/ext/third_party/spdlog/include/spdlog/fmt/bundled/posix.h +1 -1
  629. data/ext/third_party/spdlog/include/spdlog/fmt/bundled/printf.h +93 -63
  630. data/ext/third_party/spdlog/include/spdlog/fmt/bundled/ranges.h +35 -36
  631. data/ext/third_party/spdlog/include/spdlog/fmt/chrono.h +20 -0
  632. data/ext/third_party/spdlog/include/spdlog/fmt/fmt.h +2 -0
  633. data/ext/third_party/spdlog/include/spdlog/logger-inl.h +5 -1
  634. data/ext/third_party/spdlog/include/spdlog/logger.h +50 -76
  635. data/ext/third_party/spdlog/include/spdlog/pattern_formatter-inl.h +23 -8
  636. data/ext/third_party/spdlog/include/spdlog/pattern_formatter.h +3 -3
  637. data/ext/third_party/spdlog/include/spdlog/sinks/daily_file_sink.h +1 -1
  638. data/ext/third_party/spdlog/include/spdlog/sinks/msvc_sink.h +5 -5
  639. data/ext/third_party/spdlog/include/spdlog/sinks/ringbuffer_sink.h +6 -4
  640. data/ext/third_party/spdlog/include/spdlog/sinks/stdout_sinks-inl.h +32 -3
  641. data/ext/third_party/spdlog/include/spdlog/sinks/stdout_sinks.h +7 -0
  642. data/ext/third_party/spdlog/include/spdlog/sinks/wincolor_sink-inl.h +4 -14
  643. data/ext/third_party/spdlog/include/spdlog/spdlog-inl.h +11 -1
  644. data/ext/third_party/spdlog/include/spdlog/spdlog.h +23 -68
  645. data/ext/third_party/spdlog/include/spdlog/stopwatch.h +61 -0
  646. data/ext/third_party/spdlog/include/spdlog/version.h +2 -2
  647. data/ext/third_party/spdlog/src/fmt.cpp +21 -147
  648. data/lib/couchbase/cluster.rb +111 -1
  649. data/lib/couchbase/collection_options.rb +18 -1
  650. data/lib/couchbase/errors.rb +3 -0
  651. data/lib/couchbase/libcouchbase.bundle +0 -0
  652. data/lib/couchbase/management/bucket_manager.rb +36 -3
  653. data/lib/couchbase/management/search_index_manager.rb +42 -1
  654. data/lib/couchbase/management/user_manager.rb +155 -48
  655. data/lib/couchbase/query_options.rb +7 -0
  656. data/lib/couchbase/scope.rb +1 -0
  657. data/lib/couchbase/search_options.rb +69 -1
  658. data/lib/couchbase/version.rb +1 -1
  659. metadata +171 -267
  660. data/.rubocop.yml +0 -227
  661. data/.rubocop_todo.yml +0 -47
  662. data/.yardopts +0 -1
  663. data/CONTRIBUTING.md +0 -110
  664. data/Gemfile +0 -37
  665. data/Rakefile +0 -51
  666. data/couchbase.gemspec +0 -79
  667. data/examples/analytics.rb +0 -236
  668. data/examples/auth.rb +0 -33
  669. data/examples/crud.rb +0 -34
  670. data/examples/managing_analytics_indexes.rb +0 -86
  671. data/examples/managing_buckets.rb +0 -61
  672. data/examples/managing_collections.rb +0 -71
  673. data/examples/managing_query_indexes.rb +0 -83
  674. data/examples/managing_search_indexes.rb +0 -77
  675. data/examples/managing_view_indexes.rb +0 -68
  676. data/examples/query.rb +0 -32
  677. data/examples/query_with_consistency.rb +0 -86
  678. data/examples/search.rb +0 -202
  679. data/examples/search_with_consistency.rb +0 -97
  680. data/examples/subdocument.rb +0 -63
  681. data/examples/view.rb +0 -59
  682. data/ext/.clang-format +0 -15
  683. data/ext/.clang-tidy +0 -22
  684. data/ext/.cmake-format.yaml +0 -8
  685. data/ext/.gitignore +0 -2
  686. data/ext/.idea/.name +0 -1
  687. data/ext/.idea/dictionaries/couchbase_terms.xml +0 -14
  688. data/ext/.idea/ext.iml +0 -2
  689. data/ext/.idea/misc.xml +0 -16
  690. data/ext/.idea/modules.xml +0 -8
  691. data/ext/.idea/vcs.xml +0 -12
  692. data/ext/test/main.cxx +0 -184
  693. data/ext/third_party/asio/.appveyor.yml +0 -107
  694. data/ext/third_party/asio/.cirrus.yml +0 -16
  695. data/ext/third_party/asio/.gitignore +0 -3
  696. data/ext/third_party/asio/.travis.yml +0 -323
  697. data/ext/third_party/asio/asio/.gitignore +0 -23
  698. data/ext/third_party/asio/asio/COPYING +0 -4
  699. data/ext/third_party/asio/asio/INSTALL +0 -5
  700. data/ext/third_party/asio/asio/LICENSE_1_0.txt +0 -23
  701. data/ext/third_party/asio/asio/Makefile.am +0 -19
  702. data/ext/third_party/asio/asio/README +0 -4
  703. data/ext/third_party/asio/asio/asio.manifest +0 -4865
  704. data/ext/third_party/asio/asio/autogen.sh +0 -55
  705. data/ext/third_party/asio/asio/boost_asio.manifest +0 -5193
  706. data/ext/third_party/asio/asio/boostify.pl +0 -603
  707. data/ext/third_party/asio/asio/configure.ac +0 -182
  708. data/ext/third_party/asio/asio/include/.gitignore +0 -2
  709. data/ext/third_party/asio/asio/include/Makefile.am +0 -484
  710. data/ext/third_party/asio/asio/include/asio/detail/io_object_executor.hpp +0 -167
  711. data/ext/third_party/asio/asio/include/asio/impl/src.cpp +0 -25
  712. data/ext/third_party/asio/asio/release.pl +0 -440
  713. data/ext/third_party/asio/asio/src/.gitignore +0 -11
  714. data/ext/third_party/asio/asio/src/Makefile.am +0 -23
  715. data/ext/third_party/asio/asio/src/Makefile.mgw +0 -204
  716. data/ext/third_party/asio/asio/src/Makefile.msc +0 -497
  717. data/ext/third_party/asio/asio/src/asio.cpp +0 -11
  718. data/ext/third_party/asio/asio/src/asio_ssl.cpp +0 -11
  719. data/ext/third_party/asio/asio/src/doc/.gitignore +0 -5
  720. data/ext/third_party/asio/asio/src/doc/Jamfile.v2 +0 -62
  721. data/ext/third_party/asio/asio/src/doc/asio.png +0 -0
  722. data/ext/third_party/asio/asio/src/doc/asio.qbk +0 -127
  723. data/ext/third_party/asio/asio/src/doc/asioref.sty +0 -90
  724. data/ext/third_party/asio/asio/src/doc/asioref.xsl +0 -94
  725. data/ext/third_party/asio/asio/src/doc/boost_bind_dox.txt +0 -5
  726. data/ext/third_party/asio/asio/src/doc/doxy2qbk.pl +0 -22
  727. data/ext/third_party/asio/asio/src/doc/examples.qbk +0 -564
  728. data/ext/third_party/asio/asio/src/doc/history.qbk +0 -1794
  729. data/ext/third_party/asio/asio/src/doc/index.xml +0 -13
  730. data/ext/third_party/asio/asio/src/doc/makepdf.pl +0 -26
  731. data/ext/third_party/asio/asio/src/doc/net_ts.qbk +0 -479
  732. data/ext/third_party/asio/asio/src/doc/noncopyable_dox.txt +0 -3
  733. data/ext/third_party/asio/asio/src/doc/overview.qbk +0 -103
  734. data/ext/third_party/asio/asio/src/doc/overview/allocation.qbk +0 -89
  735. data/ext/third_party/asio/asio/src/doc/overview/async.qbk +0 -185
  736. data/ext/third_party/asio/asio/src/doc/overview/async_op1.dot +0 -78
  737. data/ext/third_party/asio/asio/src/doc/overview/async_op1.png +0 -0
  738. data/ext/third_party/asio/asio/src/doc/overview/async_op2.dot +0 -78
  739. data/ext/third_party/asio/asio/src/doc/overview/async_op2.png +0 -0
  740. data/ext/third_party/asio/asio/src/doc/overview/basics.qbk +0 -106
  741. data/ext/third_party/asio/asio/src/doc/overview/bsd_sockets.qbk +0 -270
  742. data/ext/third_party/asio/asio/src/doc/overview/buffers.qbk +0 -163
  743. data/ext/third_party/asio/asio/src/doc/overview/concurrency_hint.qbk +0 -88
  744. data/ext/third_party/asio/asio/src/doc/overview/coroutine.qbk +0 -51
  745. data/ext/third_party/asio/asio/src/doc/overview/coroutines_ts.qbk +0 -97
  746. data/ext/third_party/asio/asio/src/doc/overview/cpp2011.qbk +0 -271
  747. data/ext/third_party/asio/asio/src/doc/overview/handler_tracking.qbk +0 -220
  748. data/ext/third_party/asio/asio/src/doc/overview/implementation.qbk +0 -305
  749. data/ext/third_party/asio/asio/src/doc/overview/iostreams.qbk +0 -72
  750. data/ext/third_party/asio/asio/src/doc/overview/line_based.qbk +0 -118
  751. data/ext/third_party/asio/asio/src/doc/overview/other_protocols.qbk +0 -94
  752. data/ext/third_party/asio/asio/src/doc/overview/posix.qbk +0 -152
  753. data/ext/third_party/asio/asio/src/doc/overview/proactor.dot +0 -100
  754. data/ext/third_party/asio/asio/src/doc/overview/proactor.png +0 -0
  755. data/ext/third_party/asio/asio/src/doc/overview/protocols.qbk +0 -149
  756. data/ext/third_party/asio/asio/src/doc/overview/rationale.qbk +0 -54
  757. data/ext/third_party/asio/asio/src/doc/overview/reactor.qbk +0 -44
  758. data/ext/third_party/asio/asio/src/doc/overview/serial_ports.qbk +0 -45
  759. data/ext/third_party/asio/asio/src/doc/overview/signals.qbk +0 -44
  760. data/ext/third_party/asio/asio/src/doc/overview/spawn.qbk +0 -102
  761. data/ext/third_party/asio/asio/src/doc/overview/ssl.qbk +0 -124
  762. data/ext/third_party/asio/asio/src/doc/overview/strands.qbk +0 -114
  763. data/ext/third_party/asio/asio/src/doc/overview/streams.qbk +0 -62
  764. data/ext/third_party/asio/asio/src/doc/overview/sync_op.dot +0 -67
  765. data/ext/third_party/asio/asio/src/doc/overview/sync_op.png +0 -0
  766. data/ext/third_party/asio/asio/src/doc/overview/threads.qbk +0 -67
  767. data/ext/third_party/asio/asio/src/doc/overview/timers.qbk +0 -52
  768. data/ext/third_party/asio/asio/src/doc/overview/windows.qbk +0 -126
  769. data/ext/third_party/asio/asio/src/doc/project-root.jam +0 -1
  770. data/ext/third_party/asio/asio/src/doc/quickref.xml +0 -561
  771. data/ext/third_party/asio/asio/src/doc/reference.dox +0 -264
  772. data/ext/third_party/asio/asio/src/doc/reference.qbk +0 -125973
  773. data/ext/third_party/asio/asio/src/doc/reference.xsl +0 -1831
  774. data/ext/third_party/asio/asio/src/doc/release_checklist.htm +0 -68
  775. data/ext/third_party/asio/asio/src/doc/requirements/AcceptHandler.qbk +0 -72
  776. data/ext/third_party/asio/asio/src/doc/requirements/AcceptableProtocol.qbk +0 -25
  777. data/ext/third_party/asio/asio/src/doc/requirements/AsyncRandomAccessReadDevice.qbk +0 -56
  778. data/ext/third_party/asio/asio/src/doc/requirements/AsyncRandomAccessWriteDevice.qbk +0 -57
  779. data/ext/third_party/asio/asio/src/doc/requirements/AsyncReadStream.qbk +0 -50
  780. data/ext/third_party/asio/asio/src/doc/requirements/AsyncWriteStream.qbk +0 -48
  781. data/ext/third_party/asio/asio/src/doc/requirements/BufferedHandshakeHandler.qbk +0 -55
  782. data/ext/third_party/asio/asio/src/doc/requirements/CompletionCondition.qbk +0 -42
  783. data/ext/third_party/asio/asio/src/doc/requirements/CompletionHandler.qbk +0 -63
  784. data/ext/third_party/asio/asio/src/doc/requirements/ConnectCondition.qbk +0 -34
  785. data/ext/third_party/asio/asio/src/doc/requirements/ConnectHandler.qbk +0 -72
  786. data/ext/third_party/asio/asio/src/doc/requirements/ConstBufferSequence.qbk +0 -53
  787. data/ext/third_party/asio/asio/src/doc/requirements/DynamicBuffer.qbk +0 -16
  788. data/ext/third_party/asio/asio/src/doc/requirements/DynamicBuffer_v1.qbk +0 -93
  789. data/ext/third_party/asio/asio/src/doc/requirements/DynamicBuffer_v2.qbk +0 -94
  790. data/ext/third_party/asio/asio/src/doc/requirements/Endpoint.qbk +0 -97
  791. data/ext/third_party/asio/asio/src/doc/requirements/EndpointSequence.qbk +0 -30
  792. data/ext/third_party/asio/asio/src/doc/requirements/ExecutionContext.qbk +0 -36
  793. data/ext/third_party/asio/asio/src/doc/requirements/Executor.qbk +0 -141
  794. data/ext/third_party/asio/asio/src/doc/requirements/GettableSerialPortOption.qbk +0 -33
  795. data/ext/third_party/asio/asio/src/doc/requirements/GettableSocketOption.qbk +0 -67
  796. data/ext/third_party/asio/asio/src/doc/requirements/Handler.qbk +0 -64
  797. data/ext/third_party/asio/asio/src/doc/requirements/HandshakeHandler.qbk +0 -72
  798. data/ext/third_party/asio/asio/src/doc/requirements/InternetProtocol.qbk +0 -47
  799. data/ext/third_party/asio/asio/src/doc/requirements/IoControlCommand.qbk +0 -34
  800. data/ext/third_party/asio/asio/src/doc/requirements/IoObjectService.qbk +0 -62
  801. data/ext/third_party/asio/asio/src/doc/requirements/IteratorConnectHandler.qbk +0 -81
  802. data/ext/third_party/asio/asio/src/doc/requirements/LegacyCompletionHandler.qbk +0 -65
  803. data/ext/third_party/asio/asio/src/doc/requirements/MoveAcceptHandler.qbk +0 -61
  804. data/ext/third_party/asio/asio/src/doc/requirements/MutableBufferSequence.qbk +0 -54
  805. data/ext/third_party/asio/asio/src/doc/requirements/ProtoAllocator.qbk +0 -19
  806. data/ext/third_party/asio/asio/src/doc/requirements/Protocol.qbk +0 -56
  807. data/ext/third_party/asio/asio/src/doc/requirements/RangeConnectHandler.qbk +0 -82
  808. data/ext/third_party/asio/asio/src/doc/requirements/ReadHandler.qbk +0 -79
  809. data/ext/third_party/asio/asio/src/doc/requirements/ResolveHandler.qbk +0 -82
  810. data/ext/third_party/asio/asio/src/doc/requirements/Service.qbk +0 -40
  811. data/ext/third_party/asio/asio/src/doc/requirements/SettableSerialPortOption.qbk +0 -33
  812. data/ext/third_party/asio/asio/src/doc/requirements/SettableSocketOption.qbk +0 -54
  813. data/ext/third_party/asio/asio/src/doc/requirements/ShutdownHandler.qbk +0 -72
  814. data/ext/third_party/asio/asio/src/doc/requirements/SignalHandler.qbk +0 -79
  815. data/ext/third_party/asio/asio/src/doc/requirements/SyncRandomAccessReadDevice.qbk +0 -49
  816. data/ext/third_party/asio/asio/src/doc/requirements/SyncRandomAccessWriteDevice.qbk +0 -49
  817. data/ext/third_party/asio/asio/src/doc/requirements/SyncReadStream.qbk +0 -41
  818. data/ext/third_party/asio/asio/src/doc/requirements/SyncWriteStream.qbk +0 -39
  819. data/ext/third_party/asio/asio/src/doc/requirements/TimeTraits.qbk +0 -72
  820. data/ext/third_party/asio/asio/src/doc/requirements/WaitHandler.qbk +0 -72
  821. data/ext/third_party/asio/asio/src/doc/requirements/WaitTraits.qbk +0 -52
  822. data/ext/third_party/asio/asio/src/doc/requirements/WriteHandler.qbk +0 -79
  823. data/ext/third_party/asio/asio/src/doc/requirements/asynchronous_operations.qbk +0 -300
  824. data/ext/third_party/asio/asio/src/doc/requirements/asynchronous_socket_operations.qbk +0 -39
  825. data/ext/third_party/asio/asio/src/doc/requirements/read_write_operations.qbk +0 -34
  826. data/ext/third_party/asio/asio/src/doc/requirements/synchronous_socket_operations.qbk +0 -37
  827. data/ext/third_party/asio/asio/src/doc/std_exception_dox.txt +0 -7
  828. data/ext/third_party/asio/asio/src/doc/tutorial.dox +0 -226
  829. data/ext/third_party/asio/asio/src/doc/tutorial.qbk +0 -2387
  830. data/ext/third_party/asio/asio/src/doc/tutorial.xsl +0 -437
  831. data/ext/third_party/asio/asio/src/doc/using.qbk +0 -309
  832. data/ext/third_party/asio/asio/tsify.pl +0 -574
  833. data/ext/third_party/gsl/.clang-format +0 -34
  834. data/ext/third_party/gsl/.github/workflows/main.yml +0 -94
  835. data/ext/third_party/gsl/.gitignore +0 -16
  836. data/ext/third_party/gsl/.travis.yml +0 -551
  837. data/ext/third_party/gsl/CMakeSettings.json +0 -18
  838. data/ext/third_party/gsl/CONTRIBUTING.md +0 -29
  839. data/ext/third_party/gsl/GSL.natvis +0 -98
  840. data/ext/third_party/gsl/README.md +0 -124
  841. data/ext/third_party/gsl/appveyor.yml +0 -128
  842. data/ext/third_party/http_parser/.gitignore +0 -30
  843. data/ext/third_party/http_parser/.mailmap +0 -8
  844. data/ext/third_party/http_parser/.travis.yml +0 -13
  845. data/ext/third_party/http_parser/AUTHORS +0 -68
  846. data/ext/third_party/http_parser/Makefile +0 -160
  847. data/ext/third_party/http_parser/README.md +0 -246
  848. data/ext/third_party/http_parser/bench.c +0 -128
  849. data/ext/third_party/http_parser/http_parser.gyp +0 -111
  850. data/ext/third_party/http_parser/test.c +0 -4600
  851. data/ext/third_party/json/.appveyor.yml +0 -44
  852. data/ext/third_party/json/.clang-format +0 -84
  853. data/ext/third_party/json/.conan/build.py +0 -80
  854. data/ext/third_party/json/.conan/test_package/CMakeLists.txt +0 -12
  855. data/ext/third_party/json/.conan/test_package/conanfile.py +0 -24
  856. data/ext/third_party/json/.conan/test_package/test_package.cpp +0 -16
  857. data/ext/third_party/json/.gitignore +0 -3
  858. data/ext/third_party/json/.travis.yml +0 -173
  859. data/ext/third_party/json/Makefile +0 -77
  860. data/ext/third_party/json/README.md +0 -149
  861. data/ext/third_party/json/conanfile.py +0 -28
  862. data/ext/third_party/json/include/tao/json/external/pegtl/analysis/analyze_cycles.hpp +0 -127
  863. data/ext/third_party/json/include/tao/json/external/pegtl/analysis/counted.hpp +0 -23
  864. data/ext/third_party/json/include/tao/json/external/pegtl/analysis/generic.hpp +0 -31
  865. data/ext/third_party/json/include/tao/json/external/pegtl/analysis/grammar_info.hpp +0 -32
  866. data/ext/third_party/json/include/tao/json/external/pegtl/analysis/insert_guard.hpp +0 -51
  867. data/ext/third_party/json/include/tao/json/external/pegtl/analysis/insert_rules.hpp +0 -25
  868. data/ext/third_party/json/include/tao/json/external/pegtl/analysis/rule_info.hpp +0 -29
  869. data/ext/third_party/json/include/tao/json/external/pegtl/analysis/rule_type.hpp +0 -21
  870. data/ext/third_party/json/include/tao/json/external/pegtl/analyze.hpp +0 -21
  871. data/ext/third_party/json/include/tao/json/external/pegtl/contrib/counter.hpp +0 -54
  872. data/ext/third_party/json/include/tao/json/external/pegtl/contrib/tracer.hpp +0 -158
  873. data/ext/third_party/json/include/tao/json/external/pegtl/internal/alnum.hpp +0 -18
  874. data/ext/third_party/json/include/tao/json/external/pegtl/internal/alpha.hpp +0 -18
  875. data/ext/third_party/json/include/tao/json/external/pegtl/internal/dusel_mode.hpp +0 -23
  876. data/ext/third_party/json/include/tao/json/external/pegtl/internal/duseltronik.hpp +0 -187
  877. data/ext/third_party/json/include/tao/json/external/pegtl/internal/file_opener.hpp +0 -72
  878. data/ext/third_party/json/include/tao/json/external/pegtl/internal/trivial.hpp +0 -32
  879. data/ext/third_party/snappy/.appveyor.yml +0 -36
  880. data/ext/third_party/snappy/.gitignore +0 -8
  881. data/ext/third_party/snappy/.travis.yml +0 -98
  882. data/ext/third_party/snappy/AUTHORS +0 -1
  883. data/ext/third_party/snappy/CONTRIBUTING.md +0 -26
  884. data/ext/third_party/snappy/NEWS +0 -188
  885. data/ext/third_party/snappy/README.md +0 -148
  886. data/ext/third_party/snappy/docs/README.md +0 -72
  887. data/ext/third_party/snappy/format_description.txt +0 -110
  888. data/ext/third_party/snappy/framing_format.txt +0 -135
  889. data/ext/third_party/snappy/snappy-test.cc +0 -613
  890. data/ext/third_party/snappy/snappy-test.h +0 -526
  891. data/ext/third_party/snappy/snappy_compress_fuzzer.cc +0 -60
  892. data/ext/third_party/snappy/snappy_uncompress_fuzzer.cc +0 -58
  893. data/ext/third_party/snappy/snappy_unittest.cc +0 -1512
  894. data/ext/third_party/spdlog/.clang-format +0 -108
  895. data/ext/third_party/spdlog/.clang-tidy +0 -54
  896. data/ext/third_party/spdlog/.gitattributes +0 -1
  897. data/ext/third_party/spdlog/.gitignore +0 -83
  898. data/ext/third_party/spdlog/.travis.yml +0 -112
  899. data/ext/third_party/spdlog/INSTALL +0 -24
  900. data/ext/third_party/spdlog/README.md +0 -423
  901. data/ext/third_party/spdlog/appveyor.yml +0 -51
  902. data/ext/third_party/spdlog/include/spdlog/cfg/log_levels.h +0 -47
@@ -15,6 +15,7 @@
15
15
  #include <cstdarg>
16
16
  #include <cstring> // for std::memmove
17
17
  #include <cwchar>
18
+ #include <exception>
18
19
 
19
20
  #include "format.h"
20
21
  #if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
@@ -22,8 +23,16 @@
22
23
  #endif
23
24
 
24
25
  #ifdef _WIN32
26
+ # if !defined(NOMINMAX) && !defined(WIN32_LEAN_AND_MEAN)
27
+ # define NOMINMAX
28
+ # define WIN32_LEAN_AND_MEAN
29
+ # include <windows.h>
30
+ # undef WIN32_LEAN_AND_MEAN
31
+ # undef NOMINMAX
32
+ # else
33
+ # include <windows.h>
34
+ # endif
25
35
  # include <io.h>
26
- # include <windows.h>
27
36
  #endif
28
37
 
29
38
  #ifdef _MSC_VER
@@ -33,15 +42,19 @@
33
42
 
34
43
  // Dummy implementations of strerror_r and strerror_s called if corresponding
35
44
  // system functions are not available.
36
- inline fmt::internal::null<> strerror_r(int, char*, ...) { return {}; }
37
- inline fmt::internal::null<> strerror_s(char*, std::size_t, ...) { return {}; }
45
+ inline fmt::detail::null<> strerror_r(int, char*, ...) { return {}; }
46
+ inline fmt::detail::null<> strerror_s(char*, size_t, ...) { return {}; }
38
47
 
39
48
  FMT_BEGIN_NAMESPACE
40
- namespace internal {
49
+ namespace detail {
41
50
 
42
51
  FMT_FUNC void assert_fail(const char* file, int line, const char* message) {
43
- print(stderr, "{}:{}: assertion failed: {}", file, line, message);
44
- std::abort();
52
+ // Use unchecked std::fprintf to avoid triggering another assertion when
53
+ // writing to stderr fails
54
+ std::fprintf(stderr, "%s:%d: assertion failed: %s", file, line, message);
55
+ // Chosen instead of std::abort to satisfy Clang in CUDA mode during device
56
+ // code pass.
57
+ std::terminate();
45
58
  }
46
59
 
47
60
  #ifndef _MSC_VER
@@ -67,14 +80,14 @@ inline int fmt_snprintf(char* buffer, size_t size, const char* format, ...) {
67
80
  // other - failure
68
81
  // Buffer should be at least of size 1.
69
82
  FMT_FUNC int safe_strerror(int error_code, char*& buffer,
70
- std::size_t buffer_size) FMT_NOEXCEPT {
83
+ size_t buffer_size) FMT_NOEXCEPT {
71
84
  FMT_ASSERT(buffer != nullptr && buffer_size != 0, "invalid buffer");
72
85
 
73
86
  class dispatcher {
74
87
  private:
75
88
  int error_code_;
76
89
  char*& buffer_;
77
- std::size_t buffer_size_;
90
+ size_t buffer_size_;
78
91
 
79
92
  // A noop assignment operator to avoid bogus warnings.
80
93
  void operator=(const dispatcher&) {}
@@ -97,7 +110,7 @@ FMT_FUNC int safe_strerror(int error_code, char*& buffer,
97
110
 
98
111
  // Handle the case when strerror_r is not available.
99
112
  FMT_MAYBE_UNUSED
100
- int handle(internal::null<>) {
113
+ int handle(detail::null<>) {
101
114
  return fallback(strerror_s(buffer_, buffer_size_, error_code_));
102
115
  }
103
116
 
@@ -111,7 +124,7 @@ FMT_FUNC int safe_strerror(int error_code, char*& buffer,
111
124
 
112
125
  #if !FMT_MSC_VER
113
126
  // Fallback to strerror if strerror_r and strerror_s are not available.
114
- int fallback(internal::null<>) {
127
+ int fallback(detail::null<>) {
115
128
  errno = 0;
116
129
  buffer_ = strerror(error_code_);
117
130
  return errno;
@@ -119,7 +132,7 @@ FMT_FUNC int safe_strerror(int error_code, char*& buffer,
119
132
  #endif
120
133
 
121
134
  public:
122
- dispatcher(int err_code, char*& buf, std::size_t buf_size)
135
+ dispatcher(int err_code, char*& buf, size_t buf_size)
123
136
  : error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {}
124
137
 
125
138
  int run() { return handle(strerror_r(error_code_, buffer_, buffer_size_)); }
@@ -127,7 +140,7 @@ FMT_FUNC int safe_strerror(int error_code, char*& buffer,
127
140
  return dispatcher(error_code, buffer, buffer_size).run();
128
141
  }
129
142
 
130
- FMT_FUNC void format_error_code(internal::buffer<char>& out, int error_code,
143
+ FMT_FUNC void format_error_code(detail::buffer<char>& out, int error_code,
131
144
  string_view message) FMT_NOEXCEPT {
132
145
  // Report error code making sure that the output fits into
133
146
  // inline_buffer_size to avoid dynamic memory allocation and potential
@@ -136,20 +149,17 @@ FMT_FUNC void format_error_code(internal::buffer<char>& out, int error_code,
136
149
  static const char SEP[] = ": ";
137
150
  static const char ERROR_STR[] = "error ";
138
151
  // Subtract 2 to account for terminating null characters in SEP and ERROR_STR.
139
- std::size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2;
152
+ size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2;
140
153
  auto abs_value = static_cast<uint32_or_64_or_128_t<int>>(error_code);
141
- if (internal::is_negative(error_code)) {
154
+ if (detail::is_negative(error_code)) {
142
155
  abs_value = 0 - abs_value;
143
156
  ++error_code_size;
144
157
  }
145
- error_code_size += internal::to_unsigned(internal::count_digits(abs_value));
146
- internal::writer w(out);
147
- if (message.size() <= inline_buffer_size - error_code_size) {
148
- w.write(message);
149
- w.write(SEP);
150
- }
151
- w.write(ERROR_STR);
152
- w.write(error_code);
158
+ error_code_size += detail::to_unsigned(detail::count_digits(abs_value));
159
+ auto it = std::back_inserter(out);
160
+ if (message.size() <= inline_buffer_size - error_code_size)
161
+ format_to(it, "{}{}", message, SEP);
162
+ format_to(it, "{}{}", ERROR_STR, error_code);
153
163
  assert(out.size() <= inline_buffer_size);
154
164
  }
155
165
 
@@ -168,10 +178,10 @@ FMT_FUNC void fwrite_fully(const void* ptr, size_t size, size_t count,
168
178
  size_t written = std::fwrite(ptr, size, count, stream);
169
179
  if (written < count) FMT_THROW(system_error(errno, "cannot write to file"));
170
180
  }
171
- } // namespace internal
181
+ } // namespace detail
172
182
 
173
183
  #if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
174
- namespace internal {
184
+ namespace detail {
175
185
 
176
186
  template <typename Locale>
177
187
  locale_ref::locale_ref(const Locale& loc) : locale_(&loc) {
@@ -194,18 +204,16 @@ template <typename Char> FMT_FUNC Char decimal_point_impl(locale_ref loc) {
194
204
  return std::use_facet<std::numpunct<Char>>(loc.get<std::locale>())
195
205
  .decimal_point();
196
206
  }
197
- } // namespace internal
207
+ } // namespace detail
198
208
  #else
199
209
  template <typename Char>
200
- FMT_FUNC std::string internal::grouping_impl(locale_ref) {
210
+ FMT_FUNC std::string detail::grouping_impl(locale_ref) {
201
211
  return "\03";
202
212
  }
203
- template <typename Char>
204
- FMT_FUNC Char internal::thousands_sep_impl(locale_ref) {
213
+ template <typename Char> FMT_FUNC Char detail::thousands_sep_impl(locale_ref) {
205
214
  return FMT_STATIC_THOUSANDS_SEPARATOR;
206
215
  }
207
- template <typename Char>
208
- FMT_FUNC Char internal::decimal_point_impl(locale_ref) {
216
+ template <typename Char> FMT_FUNC Char detail::decimal_point_impl(locale_ref) {
209
217
  return '.';
210
218
  }
211
219
  #endif
@@ -222,9 +230,9 @@ FMT_FUNC void system_error::init(int err_code, string_view format_str,
222
230
  base = std::runtime_error(to_string(buffer));
223
231
  }
224
232
 
225
- namespace internal {
233
+ namespace detail {
226
234
 
227
- template <> FMT_FUNC int count_digits<4>(internal::fallback_uintptr n) {
235
+ template <> FMT_FUNC int count_digits<4>(detail::fallback_uintptr n) {
228
236
  // fallback_uintptr is always stored in little endian.
229
237
  int i = static_cast<int>(sizeof(void*)) - 1;
230
238
  while (i > 0 && n.value[i] == 0) --i;
@@ -233,12 +241,27 @@ template <> FMT_FUNC int count_digits<4>(internal::fallback_uintptr n) {
233
241
  }
234
242
 
235
243
  template <typename T>
236
- const char basic_data<T>::digits[] =
237
- "0001020304050607080910111213141516171819"
238
- "2021222324252627282930313233343536373839"
239
- "4041424344454647484950515253545556575859"
240
- "6061626364656667686970717273747576777879"
241
- "8081828384858687888990919293949596979899";
244
+ const typename basic_data<T>::digit_pair basic_data<T>::digits[] = {
245
+ {'0', '0'}, {'0', '1'}, {'0', '2'}, {'0', '3'}, {'0', '4'},
246
+ {'0', '5'}, {'0', '6'}, {'0', '7'}, {'0', '8'}, {'0', '9'},
247
+ {'1', '0'}, {'1', '1'}, {'1', '2'}, {'1', '3'}, {'1', '4'},
248
+ {'1', '5'}, {'1', '6'}, {'1', '7'}, {'1', '8'}, {'1', '9'},
249
+ {'2', '0'}, {'2', '1'}, {'2', '2'}, {'2', '3'}, {'2', '4'},
250
+ {'2', '5'}, {'2', '6'}, {'2', '7'}, {'2', '8'}, {'2', '9'},
251
+ {'3', '0'}, {'3', '1'}, {'3', '2'}, {'3', '3'}, {'3', '4'},
252
+ {'3', '5'}, {'3', '6'}, {'3', '7'}, {'3', '8'}, {'3', '9'},
253
+ {'4', '0'}, {'4', '1'}, {'4', '2'}, {'4', '3'}, {'4', '4'},
254
+ {'4', '5'}, {'4', '6'}, {'4', '7'}, {'4', '8'}, {'4', '9'},
255
+ {'5', '0'}, {'5', '1'}, {'5', '2'}, {'5', '3'}, {'5', '4'},
256
+ {'5', '5'}, {'5', '6'}, {'5', '7'}, {'5', '8'}, {'5', '9'},
257
+ {'6', '0'}, {'6', '1'}, {'6', '2'}, {'6', '3'}, {'6', '4'},
258
+ {'6', '5'}, {'6', '6'}, {'6', '7'}, {'6', '8'}, {'6', '9'},
259
+ {'7', '0'}, {'7', '1'}, {'7', '2'}, {'7', '3'}, {'7', '4'},
260
+ {'7', '5'}, {'7', '6'}, {'7', '7'}, {'7', '8'}, {'7', '9'},
261
+ {'8', '0'}, {'8', '1'}, {'8', '2'}, {'8', '3'}, {'8', '4'},
262
+ {'8', '5'}, {'8', '6'}, {'8', '7'}, {'8', '8'}, {'8', '9'},
263
+ {'9', '0'}, {'9', '1'}, {'9', '2'}, {'9', '3'}, {'9', '4'},
264
+ {'9', '5'}, {'9', '6'}, {'9', '7'}, {'9', '8'}, {'9', '9'}};
242
265
 
243
266
  template <typename T>
244
267
  const char basic_data<T>::hex_digits[] = "0123456789abcdef";
@@ -317,6 +340,10 @@ const char basic_data<T>::background_color[] = "\x1b[48;2;";
317
340
  template <typename T> const char basic_data<T>::reset_color[] = "\x1b[0m";
318
341
  template <typename T> const wchar_t basic_data<T>::wreset_color[] = L"\x1b[0m";
319
342
  template <typename T> const char basic_data<T>::signs[] = {0, '-', '+', ' '};
343
+ template <typename T>
344
+ const char basic_data<T>::left_padding_shifts[] = {31, 31, 0, 1, 0};
345
+ template <typename T>
346
+ const char basic_data<T>::right_padding_shifts[] = {0, 31, 0, 1, 0};
320
347
 
321
348
  template <typename T> struct bits {
322
349
  static FMT_CONSTEXPR_DECL const int value =
@@ -576,9 +603,10 @@ class bigint {
576
603
  void operator=(const bigint&) = delete;
577
604
 
578
605
  void assign(const bigint& other) {
579
- bigits_.resize(other.bigits_.size());
606
+ auto size = other.bigits_.size();
607
+ bigits_.resize(size);
580
608
  auto data = other.bigits_.data();
581
- std::copy(data, data + other.bigits_.size(), bigits_.data());
609
+ std::copy(data, data + size, make_checked(bigits_.data(), size));
582
610
  exp_ = other.exp_;
583
611
  }
584
612
 
@@ -594,7 +622,7 @@ class bigint {
594
622
 
595
623
  int num_bigits() const { return static_cast<int>(bigits_.size()) + exp_; }
596
624
 
597
- bigint& operator<<=(int shift) {
625
+ FMT_NOINLINE bigint& operator<<=(int shift) {
598
626
  assert(shift >= 0);
599
627
  exp_ += shift / bigit_bits;
600
628
  shift %= bigit_bits;
@@ -1125,7 +1153,7 @@ int snprintf_float(T value, int precision, float_specs specs,
1125
1153
  precision = (precision >= 0 ? precision : 6) - 1;
1126
1154
 
1127
1155
  // Build the format string.
1128
- enum { max_format_size = 7 }; // Ths longest format is "%#.*Le".
1156
+ enum { max_format_size = 7 }; // The longest format is "%#.*Le".
1129
1157
  char format[max_format_size];
1130
1158
  char* format_ptr = format;
1131
1159
  *format_ptr++ = '%';
@@ -1145,13 +1173,13 @@ int snprintf_float(T value, int precision, float_specs specs,
1145
1173
  for (;;) {
1146
1174
  auto begin = buf.data() + offset;
1147
1175
  auto capacity = buf.capacity() - offset;
1148
- #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1176
+ #ifdef FMT_FUZZ
1149
1177
  if (precision > 100000)
1150
1178
  throw std::runtime_error(
1151
1179
  "fuzz mode - avoid large allocation inside snprintf");
1152
1180
  #endif
1153
1181
  // Suppress the warning about a nonliteral format string.
1154
- // Cannot use auto becase of a bug in MinGW (#1532).
1182
+ // Cannot use auto because of a bug in MinGW (#1532).
1155
1183
  int (*snprintf_ptr)(char*, size_t, const char*, ...) = FMT_SNPRINTF;
1156
1184
  int result = precision >= 0
1157
1185
  ? snprintf_ptr(begin, capacity, format, precision, value)
@@ -1268,14 +1296,14 @@ FMT_FUNC const char* utf8_decode(const char* buf, uint32_t* c, int* e) {
1268
1296
 
1269
1297
  return next;
1270
1298
  }
1271
- } // namespace internal
1299
+ } // namespace detail
1272
1300
 
1273
- template <> struct formatter<internal::bigint> {
1301
+ template <> struct formatter<detail::bigint> {
1274
1302
  format_parse_context::iterator parse(format_parse_context& ctx) {
1275
1303
  return ctx.begin();
1276
1304
  }
1277
1305
 
1278
- format_context::iterator format(const internal::bigint& n,
1306
+ format_context::iterator format(const detail::bigint& n,
1279
1307
  format_context& ctx) {
1280
1308
  auto out = ctx.out();
1281
1309
  bool first = true;
@@ -1289,12 +1317,12 @@ template <> struct formatter<internal::bigint> {
1289
1317
  out = format_to(out, "{:08x}", value);
1290
1318
  }
1291
1319
  if (n.exp_ > 0)
1292
- out = format_to(out, "p{}", n.exp_ * internal::bigint::bigit_bits);
1320
+ out = format_to(out, "p{}", n.exp_ * detail::bigint::bigit_bits);
1293
1321
  return out;
1294
1322
  }
1295
1323
  };
1296
1324
 
1297
- FMT_FUNC internal::utf8_to_utf16::utf8_to_utf16(string_view s) {
1325
+ FMT_FUNC detail::utf8_to_utf16::utf8_to_utf16(string_view s) {
1298
1326
  auto transcode = [this](const char* p) {
1299
1327
  auto cp = uint32_t();
1300
1328
  auto error = 0;
@@ -1325,7 +1353,7 @@ FMT_FUNC internal::utf8_to_utf16::utf8_to_utf16(string_view s) {
1325
1353
  buffer_.push_back(0);
1326
1354
  }
1327
1355
 
1328
- FMT_FUNC void format_system_error(internal::buffer<char>& out, int error_code,
1356
+ FMT_FUNC void format_system_error(detail::buffer<char>& out, int error_code,
1329
1357
  string_view message) FMT_NOEXCEPT {
1330
1358
  FMT_TRY {
1331
1359
  memory_buffer buf;
@@ -1333,12 +1361,9 @@ FMT_FUNC void format_system_error(internal::buffer<char>& out, int error_code,
1333
1361
  for (;;) {
1334
1362
  char* system_message = &buf[0];
1335
1363
  int result =
1336
- internal::safe_strerror(error_code, system_message, buf.size());
1364
+ detail::safe_strerror(error_code, system_message, buf.size());
1337
1365
  if (result == 0) {
1338
- internal::writer w(out);
1339
- w.write(message);
1340
- w.write(": ");
1341
- w.write(system_message);
1366
+ format_to(std::back_inserter(out), "{}: {}", message, system_message);
1342
1367
  return;
1343
1368
  }
1344
1369
  if (result != ERANGE)
@@ -1350,7 +1375,7 @@ FMT_FUNC void format_system_error(internal::buffer<char>& out, int error_code,
1350
1375
  format_error_code(out, error_code, message);
1351
1376
  }
1352
1377
 
1353
- FMT_FUNC void internal::error_handler::on_error(const char* message) {
1378
+ FMT_FUNC void detail::error_handler::on_error(const char* message) {
1354
1379
  FMT_THROW(format_error(message));
1355
1380
  }
1356
1381
 
@@ -1359,14 +1384,39 @@ FMT_FUNC void report_system_error(int error_code,
1359
1384
  report_error(format_system_error, error_code, message);
1360
1385
  }
1361
1386
 
1387
+ struct stringifier {
1388
+ template <typename T> FMT_INLINE std::string operator()(T value) const {
1389
+ return to_string(value);
1390
+ }
1391
+ std::string operator()(basic_format_arg<format_context>::handle h) const {
1392
+ memory_buffer buf;
1393
+ detail::buffer<char>& base = buf;
1394
+ format_parse_context parse_ctx({});
1395
+ format_context format_ctx(std::back_inserter(base), {}, {});
1396
+ h.format(parse_ctx, format_ctx);
1397
+ return to_string(buf);
1398
+ }
1399
+ };
1400
+
1401
+ FMT_FUNC std::string detail::vformat(string_view format_str, format_args args) {
1402
+ if (format_str.size() == 2 && equal2(format_str.data(), "{}")) {
1403
+ auto arg = args.get(0);
1404
+ if (!arg) error_handler().on_error("argument not found");
1405
+ return visit_format_arg(stringifier(), arg);
1406
+ }
1407
+ memory_buffer buffer;
1408
+ detail::vformat_to(buffer, format_str, args);
1409
+ return to_string(buffer);
1410
+ }
1411
+
1362
1412
  FMT_FUNC void vprint(std::FILE* f, string_view format_str, format_args args) {
1363
1413
  memory_buffer buffer;
1364
- internal::vformat_to(buffer, format_str,
1365
- basic_format_args<buffer_context<char>>(args));
1414
+ detail::vformat_to(buffer, format_str,
1415
+ basic_format_args<buffer_context<char>>(args));
1366
1416
  #ifdef _WIN32
1367
1417
  auto fd = _fileno(f);
1368
1418
  if (_isatty(fd)) {
1369
- internal::utf8_to_utf16 u16(string_view(buffer.data(), buffer.size()));
1419
+ detail::utf8_to_utf16 u16(string_view(buffer.data(), buffer.size()));
1370
1420
  auto written = DWORD();
1371
1421
  if (!WriteConsoleW(reinterpret_cast<HANDLE>(_get_osfhandle(fd)),
1372
1422
  u16.c_str(), static_cast<DWORD>(u16.size()), &written,
@@ -1376,16 +1426,16 @@ FMT_FUNC void vprint(std::FILE* f, string_view format_str, format_args args) {
1376
1426
  return;
1377
1427
  }
1378
1428
  #endif
1379
- internal::fwrite_fully(buffer.data(), 1, buffer.size(), f);
1429
+ detail::fwrite_fully(buffer.data(), 1, buffer.size(), f);
1380
1430
  }
1381
1431
 
1382
1432
  #ifdef _WIN32
1383
1433
  // Print assuming legacy (non-Unicode) encoding.
1384
- FMT_FUNC void internal::vprint_mojibake(std::FILE* f, string_view format_str,
1385
- format_args args) {
1434
+ FMT_FUNC void detail::vprint_mojibake(std::FILE* f, string_view format_str,
1435
+ format_args args) {
1386
1436
  memory_buffer buffer;
1387
- internal::vformat_to(buffer, format_str,
1388
- basic_format_args<buffer_context<char>>(args));
1437
+ detail::vformat_to(buffer, format_str,
1438
+ basic_format_args<buffer_context<char>>(args));
1389
1439
  fwrite_fully(buffer.data(), 1, buffer.size(), f);
1390
1440
  }
1391
1441
  #endif
@@ -43,10 +43,6 @@
43
43
 
44
44
  #include "core.h"
45
45
 
46
- #ifdef FMT_DEPRECATED_INCLUDE_OS
47
- # include "os.h"
48
- #endif
49
-
50
46
  #ifdef __INTEL_COMPILER
51
47
  # define FMT_ICC_VERSION __INTEL_COMPILER
52
48
  #elif defined(__ICL)
@@ -76,7 +72,8 @@
76
72
  #if __cplusplus == 201103L || __cplusplus == 201402L
77
73
  # if defined(__clang__)
78
74
  # define FMT_FALLTHROUGH [[clang::fallthrough]]
79
- # elif FMT_GCC_VERSION >= 700 && !defined(__PGI)
75
+ # elif FMT_GCC_VERSION >= 700 && !defined(__PGI) && \
76
+ (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= 520)
80
77
  # define FMT_FALLTHROUGH [[gnu::fallthrough]]
81
78
  # else
82
79
  # define FMT_FALLTHROUGH
@@ -88,20 +85,28 @@
88
85
  # define FMT_FALLTHROUGH
89
86
  #endif
90
87
 
88
+ #ifndef FMT_MAYBE_UNUSED
89
+ # if FMT_HAS_CPP17_ATTRIBUTE(maybe_unused)
90
+ # define FMT_MAYBE_UNUSED [[maybe_unused]]
91
+ # else
92
+ # define FMT_MAYBE_UNUSED
93
+ # endif
94
+ #endif
95
+
91
96
  #ifndef FMT_THROW
92
97
  # if FMT_EXCEPTIONS
93
98
  # if FMT_MSC_VER || FMT_NVCC
94
99
  FMT_BEGIN_NAMESPACE
95
- namespace internal {
100
+ namespace detail {
96
101
  template <typename Exception> inline void do_throw(const Exception& x) {
97
102
  // Silence unreachable code warnings in MSVC and NVCC because these
98
103
  // are nearly impossible to fix in a generic code.
99
104
  volatile bool b = true;
100
105
  if (b) throw x;
101
106
  }
102
- } // namespace internal
107
+ } // namespace detail
103
108
  FMT_END_NAMESPACE
104
- # define FMT_THROW(x) internal::do_throw(x)
109
+ # define FMT_THROW(x) detail::do_throw(x)
105
110
  # else
106
111
  # define FMT_THROW(x) throw x
107
112
  # endif
@@ -123,11 +128,10 @@ FMT_END_NAMESPACE
123
128
  #endif
124
129
 
125
130
  #ifndef FMT_USE_USER_DEFINED_LITERALS
126
- // For Intel and NVIDIA compilers both they and the system gcc/msc support UDLs.
127
- # if (FMT_HAS_FEATURE(cxx_user_literals) || FMT_GCC_VERSION >= 407 || \
128
- FMT_MSC_VER >= 1900) && \
129
- (!(FMT_ICC_VERSION || FMT_CUDA_VERSION) || FMT_ICC_VERSION >= 1500 || \
130
- FMT_CUDA_VERSION >= 700)
131
+ // EDG based compilers (Intel, NVIDIA, Elbrus, etc), GCC and MSVC support UDLs.
132
+ # if (FMT_HAS_FEATURE(cxx_user_literals) || FMT_GCC_VERSION >= 407 || \
133
+ FMT_MSC_VER >= 1900) && \
134
+ (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= /* UDL feature */ 480)
131
135
  # define FMT_USE_USER_DEFINED_LITERALS 1
132
136
  # else
133
137
  # define FMT_USE_USER_DEFINED_LITERALS 0
@@ -135,12 +139,11 @@ FMT_END_NAMESPACE
135
139
  #endif
136
140
 
137
141
  #ifndef FMT_USE_UDL_TEMPLATE
138
- // EDG front end based compilers (icc, nvcc) and GCC < 6.4 do not propertly
142
+ // EDG frontend based compilers (icc, nvcc, etc) and GCC < 6.4 do not properly
139
143
  // support UDL templates and GCC >= 9 warns about them.
140
- # if FMT_USE_USER_DEFINED_LITERALS && FMT_ICC_VERSION == 0 && \
141
- FMT_CUDA_VERSION == 0 && \
142
- ((FMT_GCC_VERSION >= 604 && FMT_GCC_VERSION <= 900 && \
143
- __cplusplus >= 201402L) || \
144
+ # if FMT_USE_USER_DEFINED_LITERALS && \
145
+ (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= 501) && \
146
+ ((FMT_GCC_VERSION >= 604 && __cplusplus >= 201402L) || \
144
147
  FMT_CLANG_VERSION >= 304)
145
148
  # define FMT_USE_UDL_TEMPLATE 1
146
149
  # else
@@ -176,7 +179,7 @@ FMT_END_NAMESPACE
176
179
  # include <intrin.h> // _BitScanReverse, _BitScanReverse64
177
180
 
178
181
  FMT_BEGIN_NAMESPACE
179
- namespace internal {
182
+ namespace detail {
180
183
  // Avoid Clang with Microsoft CodeGen's -Wunknown-pragmas warning.
181
184
  # ifndef __clang__
182
185
  # pragma intrinsic(_BitScanReverse)
@@ -189,10 +192,10 @@ inline uint32_t clz(uint32_t x) {
189
192
  // Static analysis complains about using uninitialized data
190
193
  // "r", but the only way that can happen is if "x" is 0,
191
194
  // which the callers guarantee to not happen.
192
- # pragma warning(suppress : 6102)
195
+ FMT_SUPPRESS_MSC_WARNING(6102)
193
196
  return 31 - r;
194
197
  }
195
- # define FMT_BUILTIN_CLZ(n) internal::clz(n)
198
+ # define FMT_BUILTIN_CLZ(n) detail::clz(n)
196
199
 
197
200
  # if defined(_WIN64) && !defined(__clang__)
198
201
  # pragma intrinsic(_BitScanReverse64)
@@ -214,26 +217,21 @@ inline uint32_t clzll(uint64_t x) {
214
217
  // Static analysis complains about using uninitialized data
215
218
  // "r", but the only way that can happen is if "x" is 0,
216
219
  // which the callers guarantee to not happen.
217
- # pragma warning(suppress : 6102)
220
+ FMT_SUPPRESS_MSC_WARNING(6102)
218
221
  return 63 - r;
219
222
  }
220
- # define FMT_BUILTIN_CLZLL(n) internal::clzll(n)
221
- } // namespace internal
223
+ # define FMT_BUILTIN_CLZLL(n) detail::clzll(n)
224
+ } // namespace detail
222
225
  FMT_END_NAMESPACE
223
226
  #endif
224
227
 
225
228
  // Enable the deprecated numeric alignment.
226
- #ifndef FMT_NUMERIC_ALIGN
227
- # define FMT_NUMERIC_ALIGN 1
228
- #endif
229
-
230
- // Enable the deprecated percent specifier.
231
- #ifndef FMT_DEPRECATED_PERCENT
232
- # define FMT_DEPRECATED_PERCENT 0
229
+ #ifndef FMT_DEPRECATED_NUMERIC_ALIGN
230
+ # define FMT_DEPRECATED_NUMERIC_ALIGN 0
233
231
  #endif
234
232
 
235
233
  FMT_BEGIN_NAMESPACE
236
- namespace internal {
234
+ namespace detail {
237
235
 
238
236
  // An equivalent of `*reinterpret_cast<Dest*>(&source)` that doesn't have
239
237
  // undefined behavior (e.g. due to type aliasing).
@@ -285,14 +283,31 @@ template <typename T> constexpr T max_value() {
285
283
  template <typename T> constexpr int num_bits() {
286
284
  return std::numeric_limits<T>::digits;
287
285
  }
286
+ // std::numeric_limits<T>::digits may return 0 for 128-bit ints.
287
+ template <> constexpr int num_bits<int128_t>() { return 128; }
288
+ template <> constexpr int num_bits<uint128_t>() { return 128; }
288
289
  template <> constexpr int num_bits<fallback_uintptr>() {
289
290
  return static_cast<int>(sizeof(void*) *
290
291
  std::numeric_limits<unsigned char>::digits);
291
292
  }
292
293
 
294
+ FMT_INLINE void assume(bool condition) {
295
+ (void)condition;
296
+ #if FMT_HAS_BUILTIN(__builtin_assume)
297
+ __builtin_assume(condition);
298
+ #endif
299
+ }
300
+
301
+ // A workaround for gcc 4.8 to make void_t work in a SFINAE context.
302
+ template <typename... Ts> struct void_t_impl { using type = void; };
303
+
304
+ template <typename... Ts>
305
+ using void_t = typename detail::void_t_impl<Ts...>::type;
306
+
293
307
  // An approximation of iterator_t for pre-C++20 systems.
294
308
  template <typename T>
295
309
  using iterator_t = decltype(std::begin(std::declval<T&>()));
310
+ template <typename T> using sentinel_t = decltype(std::end(std::declval<T&>()));
296
311
 
297
312
  // Detect the iterator category of *any* given type in a SFINAE-friendly way.
298
313
  // Unfortunately, older implementations of std::iterator_traits are not safe
@@ -339,25 +354,39 @@ inline typename Container::value_type* get_data(Container& c) {
339
354
  #if defined(_SECURE_SCL) && _SECURE_SCL
340
355
  // Make a checked iterator to avoid MSVC warnings.
341
356
  template <typename T> using checked_ptr = stdext::checked_array_iterator<T*>;
342
- template <typename T> checked_ptr<T> make_checked(T* p, std::size_t size) {
357
+ template <typename T> checked_ptr<T> make_checked(T* p, size_t size) {
343
358
  return {p, size};
344
359
  }
345
360
  #else
346
361
  template <typename T> using checked_ptr = T*;
347
- template <typename T> inline T* make_checked(T* p, std::size_t) { return p; }
362
+ template <typename T> inline T* make_checked(T* p, size_t) { return p; }
348
363
  #endif
349
364
 
350
365
  template <typename Container, FMT_ENABLE_IF(is_contiguous<Container>::value)>
351
- inline checked_ptr<typename Container::value_type> reserve(
352
- std::back_insert_iterator<Container>& it, std::size_t n) {
366
+ #if FMT_CLANG_VERSION
367
+ __attribute__((no_sanitize("undefined")))
368
+ #endif
369
+ inline checked_ptr<typename Container::value_type>
370
+ reserve(std::back_insert_iterator<Container> it, size_t n) {
353
371
  Container& c = get_container(it);
354
- std::size_t size = c.size();
372
+ size_t size = c.size();
355
373
  c.resize(size + n);
356
374
  return make_checked(get_data(c) + size, n);
357
375
  }
358
376
 
377
+ template <typename Iterator> inline Iterator& reserve(Iterator& it, size_t) {
378
+ return it;
379
+ }
380
+
381
+ template <typename Container, FMT_ENABLE_IF(is_contiguous<Container>::value)>
382
+ inline std::back_insert_iterator<Container> base_iterator(
383
+ std::back_insert_iterator<Container>& it,
384
+ checked_ptr<typename Container::value_type>) {
385
+ return it;
386
+ }
387
+
359
388
  template <typename Iterator>
360
- inline Iterator& reserve(Iterator& it, std::size_t) {
389
+ inline Iterator base_iterator(Iterator, Iterator it) {
361
390
  return it;
362
391
  }
363
392
 
@@ -365,7 +394,7 @@ inline Iterator& reserve(Iterator& it, std::size_t) {
365
394
  // discards them.
366
395
  class counting_iterator {
367
396
  private:
368
- std::size_t count_;
397
+ size_t count_;
369
398
 
370
399
  public:
371
400
  using iterator_category = std::output_iterator_tag;
@@ -380,7 +409,7 @@ class counting_iterator {
380
409
 
381
410
  counting_iterator() : count_(0) {}
382
411
 
383
- std::size_t count() const { return count_; }
412
+ size_t count() const { return count_; }
384
413
 
385
414
  counting_iterator& operator++() {
386
415
  ++count_;
@@ -399,10 +428,10 @@ class counting_iterator {
399
428
  template <typename OutputIt> class truncating_iterator_base {
400
429
  protected:
401
430
  OutputIt out_;
402
- std::size_t limit_;
403
- std::size_t count_;
431
+ size_t limit_;
432
+ size_t count_;
404
433
 
405
- truncating_iterator_base(OutputIt out, std::size_t limit)
434
+ truncating_iterator_base(OutputIt out, size_t limit)
406
435
  : out_(out), limit_(limit), count_(0) {}
407
436
 
408
437
  public:
@@ -415,7 +444,7 @@ template <typename OutputIt> class truncating_iterator_base {
415
444
  truncating_iterator_base; // Mark iterator as checked.
416
445
 
417
446
  OutputIt base() const { return out_; }
418
- std::size_t count() const { return count_; }
447
+ size_t count() const { return count_; }
419
448
  };
420
449
 
421
450
  // An output iterator that truncates the output and counts the number of objects
@@ -433,7 +462,7 @@ class truncating_iterator<OutputIt, std::false_type>
433
462
  public:
434
463
  using value_type = typename truncating_iterator_base<OutputIt>::value_type;
435
464
 
436
- truncating_iterator(OutputIt out, std::size_t limit)
465
+ truncating_iterator(OutputIt out, size_t limit)
437
466
  : truncating_iterator_base<OutputIt>(out, limit) {}
438
467
 
439
468
  truncating_iterator& operator++() {
@@ -456,7 +485,7 @@ template <typename OutputIt>
456
485
  class truncating_iterator<OutputIt, std::true_type>
457
486
  : public truncating_iterator_base<OutputIt> {
458
487
  public:
459
- truncating_iterator(OutputIt out, std::size_t limit)
488
+ truncating_iterator(OutputIt out, size_t limit)
460
489
  : truncating_iterator_base<OutputIt>(out, limit) {}
461
490
 
462
491
  template <typename T> truncating_iterator& operator=(T val) {
@@ -469,22 +498,6 @@ class truncating_iterator<OutputIt, std::true_type>
469
498
  truncating_iterator& operator*() { return *this; }
470
499
  };
471
500
 
472
- // A range with the specified output iterator and value type.
473
- template <typename OutputIt, typename T = typename OutputIt::value_type>
474
- class output_range {
475
- private:
476
- OutputIt it_;
477
-
478
- public:
479
- using value_type = T;
480
- using iterator = OutputIt;
481
- struct sentinel {};
482
-
483
- explicit output_range(OutputIt it) : it_(it) {}
484
- OutputIt begin() const { return it_; }
485
- sentinel end() const { return {}; } // Sentinel is not used yet.
486
- };
487
-
488
501
  template <typename Char>
489
502
  inline size_t count_code_points(basic_string_view<Char> s) {
490
503
  return s.size();
@@ -523,8 +536,6 @@ inline size_t code_point_index(basic_string_view<char8_type> s, size_t n) {
523
536
  return s.size();
524
537
  }
525
538
 
526
- inline char8_type to_char8_t(char c) { return static_cast<char8_type>(c); }
527
-
528
539
  template <typename InputIt, typename OutChar>
529
540
  using needs_conversion = bool_constant<
530
541
  std::is_same<typename std::iterator_traits<InputIt>::value_type,
@@ -540,7 +551,8 @@ OutputIt copy_str(InputIt begin, InputIt end, OutputIt it) {
540
551
  template <typename OutChar, typename InputIt, typename OutputIt,
541
552
  FMT_ENABLE_IF(needs_conversion<InputIt, OutChar>::value)>
542
553
  OutputIt copy_str(InputIt begin, InputIt end, OutputIt it) {
543
- return std::transform(begin, end, it, to_char8_t);
554
+ return std::transform(begin, end, it,
555
+ [](char c) { return static_cast<char8_type>(c); });
544
556
  }
545
557
 
546
558
  #ifndef FMT_USE_GRISU
@@ -555,43 +567,13 @@ template <typename T> constexpr bool use_grisu() {
555
567
  template <typename T>
556
568
  template <typename U>
557
569
  void buffer<T>::append(const U* begin, const U* end) {
558
- std::size_t new_size = size_ + to_unsigned(end - begin);
570
+ size_t new_size = size_ + to_unsigned(end - begin);
559
571
  reserve(new_size);
560
- std::uninitialized_copy(begin, end, make_checked(ptr_, capacity_) + size_);
572
+ std::uninitialized_copy(begin, end,
573
+ make_checked(ptr_ + size_, capacity_ - size_));
561
574
  size_ = new_size;
562
575
  }
563
- } // namespace internal
564
-
565
- // A range with an iterator appending to a buffer.
566
- template <typename T>
567
- class buffer_range : public internal::output_range<
568
- std::back_insert_iterator<internal::buffer<T>>, T> {
569
- public:
570
- using iterator = std::back_insert_iterator<internal::buffer<T>>;
571
- using internal::output_range<iterator, T>::output_range;
572
- buffer_range(internal::buffer<T>& buf)
573
- : internal::output_range<iterator, T>(std::back_inserter(buf)) {}
574
- };
575
-
576
- class FMT_DEPRECATED u8string_view
577
- : public basic_string_view<internal::char8_type> {
578
- public:
579
- u8string_view(const char* s)
580
- : basic_string_view<internal::char8_type>(
581
- reinterpret_cast<const internal::char8_type*>(s)) {}
582
- u8string_view(const char* s, size_t count) FMT_NOEXCEPT
583
- : basic_string_view<internal::char8_type>(
584
- reinterpret_cast<const internal::char8_type*>(s), count) {}
585
- };
586
-
587
- #if FMT_USE_USER_DEFINED_LITERALS
588
- inline namespace literals {
589
- FMT_DEPRECATED inline basic_string_view<internal::char8_type> operator"" _u(
590
- const char* s, std::size_t n) {
591
- return {reinterpret_cast<const internal::char8_type*>(s), n};
592
- }
593
- } // namespace literals
594
- #endif
576
+ } // namespace detail
595
577
 
596
578
  // The number of characters to store in the basic_memory_buffer object itself
597
579
  // to avoid dynamic memory allocation.
@@ -626,27 +608,30 @@ enum { inline_buffer_size = 500 };
626
608
  The output can be converted to an ``std::string`` with ``to_string(out)``.
627
609
  \endrst
628
610
  */
629
- template <typename T, std::size_t SIZE = inline_buffer_size,
611
+ template <typename T, size_t SIZE = inline_buffer_size,
630
612
  typename Allocator = std::allocator<T>>
631
- class basic_memory_buffer : private Allocator, public internal::buffer<T> {
613
+ class basic_memory_buffer : public detail::buffer<T> {
632
614
  private:
633
615
  T store_[SIZE];
634
616
 
617
+ // Don't inherit from Allocator avoid generating type_info for it.
618
+ Allocator alloc_;
619
+
635
620
  // Deallocate memory allocated by the buffer.
636
621
  void deallocate() {
637
622
  T* data = this->data();
638
- if (data != store_) Allocator::deallocate(data, this->capacity());
623
+ if (data != store_) alloc_.deallocate(data, this->capacity());
639
624
  }
640
625
 
641
626
  protected:
642
- void grow(std::size_t size) FMT_OVERRIDE;
627
+ void grow(size_t size) FMT_OVERRIDE;
643
628
 
644
629
  public:
645
630
  using value_type = T;
646
631
  using const_reference = const T&;
647
632
 
648
633
  explicit basic_memory_buffer(const Allocator& alloc = Allocator())
649
- : Allocator(alloc) {
634
+ : alloc_(alloc) {
650
635
  this->set(store_, SIZE);
651
636
  }
652
637
  ~basic_memory_buffer() FMT_OVERRIDE { deallocate(); }
@@ -654,14 +639,13 @@ class basic_memory_buffer : private Allocator, public internal::buffer<T> {
654
639
  private:
655
640
  // Move data from other to this buffer.
656
641
  void move(basic_memory_buffer& other) {
657
- Allocator &this_alloc = *this, &other_alloc = other;
658
- this_alloc = std::move(other_alloc);
642
+ alloc_ = std::move(other.alloc_);
659
643
  T* data = other.data();
660
- std::size_t size = other.size(), capacity = other.capacity();
644
+ size_t size = other.size(), capacity = other.capacity();
661
645
  if (data == other.store_) {
662
646
  this->set(store_, capacity);
663
647
  std::uninitialized_copy(other.store_, other.store_ + size,
664
- internal::make_checked(store_, capacity));
648
+ detail::make_checked(store_, capacity));
665
649
  } else {
666
650
  this->set(data, capacity);
667
651
  // Set pointer to the inline array so that delete is not called
@@ -693,32 +677,37 @@ class basic_memory_buffer : private Allocator, public internal::buffer<T> {
693
677
  }
694
678
 
695
679
  // Returns a copy of the allocator associated with this buffer.
696
- Allocator get_allocator() const { return *this; }
680
+ Allocator get_allocator() const { return alloc_; }
697
681
  };
698
682
 
699
- template <typename T, std::size_t SIZE, typename Allocator>
700
- void basic_memory_buffer<T, SIZE, Allocator>::grow(std::size_t size) {
701
- #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
702
- if (size > 1000) throw std::runtime_error("fuzz mode - won't grow that much");
683
+ template <typename T, size_t SIZE, typename Allocator>
684
+ void basic_memory_buffer<T, SIZE, Allocator>::grow(size_t size) {
685
+ #ifdef FMT_FUZZ
686
+ if (size > 5000) throw std::runtime_error("fuzz mode - won't grow that much");
703
687
  #endif
704
- std::size_t old_capacity = this->capacity();
705
- std::size_t new_capacity = old_capacity + old_capacity / 2;
688
+ size_t old_capacity = this->capacity();
689
+ size_t new_capacity = old_capacity + old_capacity / 2;
706
690
  if (size > new_capacity) new_capacity = size;
707
691
  T* old_data = this->data();
708
- T* new_data = std::allocator_traits<Allocator>::allocate(*this, new_capacity);
692
+ T* new_data =
693
+ std::allocator_traits<Allocator>::allocate(alloc_, new_capacity);
709
694
  // The following code doesn't throw, so the raw pointer above doesn't leak.
710
695
  std::uninitialized_copy(old_data, old_data + this->size(),
711
- internal::make_checked(new_data, new_capacity));
696
+ detail::make_checked(new_data, new_capacity));
712
697
  this->set(new_data, new_capacity);
713
698
  // deallocate must not throw according to the standard, but even if it does,
714
699
  // the buffer already uses the new storage and will deallocate it in
715
700
  // destructor.
716
- if (old_data != store_) Allocator::deallocate(old_data, old_capacity);
701
+ if (old_data != store_) alloc_.deallocate(old_data, old_capacity);
717
702
  }
718
703
 
719
704
  using memory_buffer = basic_memory_buffer<char>;
720
705
  using wmemory_buffer = basic_memory_buffer<wchar_t>;
721
706
 
707
+ template <typename T, size_t SIZE, typename Allocator>
708
+ struct is_contiguous<basic_memory_buffer<T, SIZE, Allocator>> : std::true_type {
709
+ };
710
+
722
711
  /** A formatting error such as invalid format string. */
723
712
  FMT_CLASS_API
724
713
  class FMT_API format_error : public std::runtime_error {
@@ -733,15 +722,20 @@ class FMT_API format_error : public std::runtime_error {
733
722
  ~format_error() FMT_NOEXCEPT FMT_OVERRIDE;
734
723
  };
735
724
 
736
- namespace internal {
725
+ namespace detail {
726
+
727
+ template <typename T>
728
+ using is_signed =
729
+ std::integral_constant<bool, std::numeric_limits<T>::is_signed ||
730
+ std::is_same<T, int128_t>::value>;
737
731
 
738
732
  // Returns true if value is negative, false otherwise.
739
733
  // Same as `value < 0` but doesn't produce warnings if T is an unsigned type.
740
- template <typename T, FMT_ENABLE_IF(std::numeric_limits<T>::is_signed)>
734
+ template <typename T, FMT_ENABLE_IF(is_signed<T>::value)>
741
735
  FMT_CONSTEXPR bool is_negative(T value) {
742
736
  return value < 0;
743
737
  }
744
- template <typename T, FMT_ENABLE_IF(!std::numeric_limits<T>::is_signed)>
738
+ template <typename T, FMT_ENABLE_IF(!is_signed<T>::value)>
745
739
  FMT_CONSTEXPR bool is_negative(T) {
746
740
  return false;
747
741
  }
@@ -756,9 +750,9 @@ FMT_CONSTEXPR bool is_supported_floating_point(T) {
756
750
  // Smallest of uint32_t, uint64_t, uint128_t that is large enough to
757
751
  // represent all values of T.
758
752
  template <typename T>
759
- using uint32_or_64_or_128_t = conditional_t<
760
- std::numeric_limits<T>::digits <= 32, uint32_t,
761
- conditional_t<std::numeric_limits<T>::digits <= 64, uint64_t, uint128_t>>;
753
+ using uint32_or_64_or_128_t =
754
+ conditional_t<num_bits<T>() <= 32, uint32_t,
755
+ conditional_t<num_bits<T>() <= 64, uint64_t, uint128_t>>;
762
756
 
763
757
  // Static data is placed in this class template for the header-only config.
764
758
  template <typename T = void> struct FMT_EXTERN_TEMPLATE_API basic_data {
@@ -767,16 +761,22 @@ template <typename T = void> struct FMT_EXTERN_TEMPLATE_API basic_data {
767
761
  static const uint64_t zero_or_powers_of_10_64[];
768
762
  static const uint64_t pow10_significands[];
769
763
  static const int16_t pow10_exponents[];
770
- static const char digits[];
764
+ // GCC generates slightly better code for pairs than chars.
765
+ using digit_pair = char[2];
766
+ static const digit_pair digits[];
771
767
  static const char hex_digits[];
772
768
  static const char foreground_color[];
773
769
  static const char background_color[];
774
770
  static const char reset_color[5];
775
771
  static const wchar_t wreset_color[5];
776
772
  static const char signs[];
773
+ static const char left_padding_shifts[5];
774
+ static const char right_padding_shifts[5];
777
775
  };
778
776
 
777
+ #ifndef FMT_EXPORTED
779
778
  FMT_EXTERN template struct basic_data<void>;
779
+ #endif
780
780
 
781
781
  // This is a struct rather than an alias to avoid shadowing warnings in gcc.
782
782
  struct data : basic_data<> {};
@@ -834,7 +834,7 @@ template <unsigned BITS, typename UInt> inline int count_digits(UInt n) {
834
834
  return num_digits;
835
835
  }
836
836
 
837
- template <> int count_digits<4>(internal::fallback_uintptr n);
837
+ template <> int count_digits<4>(detail::fallback_uintptr n);
838
838
 
839
839
  #if FMT_GCC_VERSION || FMT_CLANG_VERSION
840
840
  # define FMT_ALWAYS_INLINE inline __attribute__((always_inline))
@@ -850,6 +850,12 @@ inline int count_digits(uint32_t n) {
850
850
  }
851
851
  #endif
852
852
 
853
+ template <typename Int> constexpr int digits10() FMT_NOEXCEPT {
854
+ return std::numeric_limits<Int>::digits10;
855
+ }
856
+ template <> constexpr int digits10<int128_t>() FMT_NOEXCEPT { return 38; }
857
+ template <> constexpr int digits10<uint128_t>() FMT_NOEXCEPT { return 38; }
858
+
853
859
  template <typename Char> FMT_API std::string grouping_impl(locale_ref loc);
854
860
  template <typename Char> inline std::string grouping(locale_ref loc) {
855
861
  return grouping_impl<char>(loc);
@@ -874,57 +880,61 @@ template <> inline wchar_t decimal_point(locale_ref loc) {
874
880
  return decimal_point_impl<wchar_t>(loc);
875
881
  }
876
882
 
877
- // Formats a decimal unsigned integer value writing into buffer.
878
- // add_thousands_sep is called after writing each char to add a thousands
879
- // separator if necessary.
880
- template <typename UInt, typename Char, typename F>
881
- inline Char* format_decimal(Char* buffer, UInt value, int num_digits,
882
- F add_thousands_sep) {
883
- FMT_ASSERT(num_digits >= 0, "invalid digit count");
884
- buffer += num_digits;
885
- Char* end = buffer;
883
+ // Compares two characters for equality.
884
+ template <typename Char> bool equal2(const Char* lhs, const char* rhs) {
885
+ return lhs[0] == rhs[0] && lhs[1] == rhs[1];
886
+ }
887
+ inline bool equal2(const char* lhs, const char* rhs) {
888
+ return memcmp(lhs, rhs, 2) == 0;
889
+ }
890
+
891
+ // Copies two characters from src to dst.
892
+ template <typename Char> void copy2(Char* dst, const char* src) {
893
+ *dst++ = static_cast<Char>(*src++);
894
+ *dst = static_cast<Char>(*src);
895
+ }
896
+ inline void copy2(char* dst, const char* src) { memcpy(dst, src, 2); }
897
+
898
+ template <typename Iterator> struct format_decimal_result {
899
+ Iterator begin;
900
+ Iterator end;
901
+ };
902
+
903
+ // Formats a decimal unsigned integer value writing into out pointing to a
904
+ // buffer of specified size. The caller must ensure that the buffer is large
905
+ // enough.
906
+ template <typename Char, typename UInt>
907
+ inline format_decimal_result<Char*> format_decimal(Char* out, UInt value,
908
+ int size) {
909
+ FMT_ASSERT(size >= count_digits(value), "invalid digit count");
910
+ out += size;
911
+ Char* end = out;
886
912
  while (value >= 100) {
887
913
  // Integer division is slow so do it for a group of two digits instead
888
914
  // of for every digit. The idea comes from the talk by Alexandrescu
889
915
  // "Three Optimization Tips for C++". See speed-test for a comparison.
890
- auto index = static_cast<unsigned>((value % 100) * 2);
916
+ out -= 2;
917
+ copy2(out, data::digits[value % 100]);
891
918
  value /= 100;
892
- *--buffer = static_cast<Char>(data::digits[index + 1]);
893
- add_thousands_sep(buffer);
894
- *--buffer = static_cast<Char>(data::digits[index]);
895
- add_thousands_sep(buffer);
896
919
  }
897
920
  if (value < 10) {
898
- *--buffer = static_cast<Char>('0' + value);
899
- return end;
921
+ *--out = static_cast<Char>('0' + value);
922
+ return {out, end};
900
923
  }
901
- auto index = static_cast<unsigned>(value * 2);
902
- *--buffer = static_cast<Char>(data::digits[index + 1]);
903
- add_thousands_sep(buffer);
904
- *--buffer = static_cast<Char>(data::digits[index]);
905
- return end;
924
+ out -= 2;
925
+ copy2(out, data::digits[value]);
926
+ return {out, end};
906
927
  }
907
928
 
908
- template <typename Int> constexpr int digits10() FMT_NOEXCEPT {
909
- return std::numeric_limits<Int>::digits10;
910
- }
911
- template <> constexpr int digits10<int128_t>() FMT_NOEXCEPT { return 38; }
912
- template <> constexpr int digits10<uint128_t>() FMT_NOEXCEPT { return 38; }
913
-
914
- template <typename Char, typename UInt, typename Iterator, typename F>
915
- inline Iterator format_decimal(Iterator out, UInt value, int num_digits,
916
- F add_thousands_sep) {
917
- FMT_ASSERT(num_digits >= 0, "invalid digit count");
929
+ template <typename Char, typename UInt, typename Iterator,
930
+ FMT_ENABLE_IF(!std::is_pointer<remove_cvref_t<Iterator>>::value)>
931
+ inline format_decimal_result<Iterator> format_decimal(Iterator out, UInt value,
932
+ int num_digits) {
918
933
  // Buffer should be large enough to hold all digits (<= digits10 + 1).
919
934
  enum { max_size = digits10<UInt>() + 1 };
920
935
  Char buffer[2 * max_size];
921
- auto end = format_decimal(buffer, value, num_digits, add_thousands_sep);
922
- return internal::copy_str<Char>(buffer, end, out);
923
- }
924
-
925
- template <typename Char, typename It, typename UInt>
926
- inline It format_decimal(It out, UInt value, int num_digits) {
927
- return format_decimal<Char>(out, value, num_digits, [](Char*) {});
936
+ auto end = format_decimal(buffer, value, num_digits).end;
937
+ return {out, detail::copy_str<Char>(buffer, end, out)};
928
938
  }
929
939
 
930
940
  template <unsigned BASE_BITS, typename Char, typename UInt>
@@ -942,7 +952,7 @@ inline Char* format_uint(Char* buffer, UInt value, int num_digits,
942
952
  }
943
953
 
944
954
  template <unsigned BASE_BITS, typename Char>
945
- Char* format_uint(Char* buffer, internal::fallback_uintptr n, int num_digits,
955
+ Char* format_uint(Char* buffer, detail::fallback_uintptr n, int num_digits,
946
956
  bool = false) {
947
957
  auto char_digits = std::numeric_limits<unsigned char>::digits / 4;
948
958
  int start = (num_digits + char_digits - 1) / char_digits - 1;
@@ -968,7 +978,7 @@ inline It format_uint(It out, UInt value, int num_digits, bool upper = false) {
968
978
  // Buffer should be large enough to hold all digits (digits / BASE_BITS + 1).
969
979
  char buffer[num_bits<UInt>() / BASE_BITS + 1];
970
980
  format_uint<BASE_BITS>(buffer, value, num_digits, upper);
971
- return internal::copy_str<Char>(buffer, buffer + num_digits, out);
981
+ return detail::copy_str<Char>(buffer, buffer + num_digits, out);
972
982
  }
973
983
 
974
984
  // A converter from UTF-8 to UTF-16.
@@ -1019,7 +1029,7 @@ template <typename Char> struct fill_t {
1019
1029
  return fill;
1020
1030
  }
1021
1031
  };
1022
- } // namespace internal
1032
+ } // namespace detail
1023
1033
 
1024
1034
  // We cannot use enum classes as bit fields because of a gcc bug
1025
1035
  // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61414.
@@ -1041,7 +1051,7 @@ template <typename Char> struct basic_format_specs {
1041
1051
  align_t align : 4;
1042
1052
  sign_t sign : 3;
1043
1053
  bool alt : 1; // Alternate form ('#').
1044
- internal::fill_t<Char> fill;
1054
+ detail::fill_t<Char> fill;
1045
1055
 
1046
1056
  constexpr basic_format_specs()
1047
1057
  : width(0),
@@ -1050,12 +1060,12 @@ template <typename Char> struct basic_format_specs {
1050
1060
  align(align::none),
1051
1061
  sign(sign::none),
1052
1062
  alt(false),
1053
- fill(internal::fill_t<Char>::make()) {}
1063
+ fill(detail::fill_t<Char>::make()) {}
1054
1064
  };
1055
1065
 
1056
1066
  using format_specs = basic_format_specs<char>;
1057
1067
 
1058
- namespace internal {
1068
+ namespace detail {
1059
1069
 
1060
1070
  // A floating-point presentation format.
1061
1071
  enum class float_format : unsigned char {
@@ -1071,7 +1081,6 @@ struct float_specs {
1071
1081
  sign_t sign : 8;
1072
1082
  bool upper : 1;
1073
1083
  bool locale : 1;
1074
- bool percent : 1;
1075
1084
  bool binary32 : 1;
1076
1085
  bool use_grisu : 1;
1077
1086
  bool showpoint : 1;
@@ -1087,12 +1096,12 @@ template <typename Char, typename It> It write_exponent(int exp, It it) {
1087
1096
  *it++ = static_cast<Char>('+');
1088
1097
  }
1089
1098
  if (exp >= 100) {
1090
- const char* top = data::digits + (exp / 100) * 2;
1099
+ const char* top = data::digits[exp / 100];
1091
1100
  if (exp >= 1000) *it++ = static_cast<Char>(top[0]);
1092
1101
  *it++ = static_cast<Char>(top[1]);
1093
1102
  exp %= 100;
1094
1103
  }
1095
- const char* d = data::digits + exp * 2;
1104
+ const char* d = data::digits[exp];
1096
1105
  *it++ = static_cast<Char>(d[0]);
1097
1106
  *it++ = static_cast<Char>(d[1]);
1098
1107
  return it;
@@ -1134,8 +1143,8 @@ template <typename Char> class float_writer {
1134
1143
  *it++ = static_cast<Char>('0');
1135
1144
  return it;
1136
1145
  }
1137
- #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1138
- if (num_zeros > 1000)
1146
+ #ifdef FMT_FUZZ
1147
+ if (num_zeros > 5000)
1139
1148
  throw std::runtime_error("fuzz mode - avoiding excessive cpu use");
1140
1149
  #endif
1141
1150
  it = std::fill_n(it, num_zeros, static_cast<Char>('0'));
@@ -1198,11 +1207,10 @@ template <typename Char> class float_writer {
1198
1207
  }
1199
1208
 
1200
1209
  size_t size() const { return size_; }
1201
- size_t width() const { return size(); }
1202
1210
 
1203
- template <typename It> void operator()(It&& it) {
1211
+ template <typename It> It operator()(It it) const {
1204
1212
  if (specs_.sign) *it++ = static_cast<Char>(data::signs[specs_.sign]);
1205
- it = prettify(it);
1213
+ return prettify(it);
1206
1214
  }
1207
1215
  };
1208
1216
 
@@ -1235,10 +1243,15 @@ FMT_CONSTEXPR void handle_int_type_spec(char spec, Handler&& handler) {
1235
1243
  case 'o':
1236
1244
  handler.on_oct();
1237
1245
  break;
1246
+ #ifdef FMT_DEPRECATED_N_SPECIFIER
1238
1247
  case 'n':
1248
+ #endif
1239
1249
  case 'L':
1240
1250
  handler.on_num();
1241
1251
  break;
1252
+ case 'c':
1253
+ handler.on_chr();
1254
+ break;
1242
1255
  default:
1243
1256
  handler.on_error();
1244
1257
  }
@@ -1274,19 +1287,16 @@ FMT_CONSTEXPR float_specs parse_float_type_spec(
1274
1287
  result.format = float_format::fixed;
1275
1288
  result.showpoint |= specs.precision != 0;
1276
1289
  break;
1277
- #if FMT_DEPRECATED_PERCENT
1278
- case '%':
1279
- result.format = float_format::fixed;
1280
- result.percent = true;
1281
- break;
1282
- #endif
1283
1290
  case 'A':
1284
1291
  result.upper = true;
1285
1292
  FMT_FALLTHROUGH;
1286
1293
  case 'a':
1287
1294
  result.format = float_format::hex;
1288
1295
  break;
1296
+ #ifdef FMT_DEPRECATED_N_SPECIFIER
1289
1297
  case 'n':
1298
+ #endif
1299
+ case 'L':
1290
1300
  result.locale = true;
1291
1301
  break;
1292
1302
  default:
@@ -1335,6 +1345,7 @@ template <typename ErrorHandler> class int_type_checker : private ErrorHandler {
1335
1345
  FMT_CONSTEXPR void on_bin() {}
1336
1346
  FMT_CONSTEXPR void on_oct() {}
1337
1347
  FMT_CONSTEXPR void on_num() {}
1348
+ FMT_CONSTEXPR void on_chr() {}
1338
1349
 
1339
1350
  FMT_CONSTEXPR void on_error() {
1340
1351
  ErrorHandler::on_error("invalid type specifier");
@@ -1366,38 +1377,6 @@ class cstring_type_checker : public ErrorHandler {
1366
1377
  FMT_CONSTEXPR void on_pointer() {}
1367
1378
  };
1368
1379
 
1369
- template <typename Context>
1370
- void arg_map<Context>::init(const basic_format_args<Context>& args) {
1371
- if (map_) return;
1372
- map_ = new entry[internal::to_unsigned(args.max_size())];
1373
- if (args.is_packed()) {
1374
- for (int i = 0;; ++i) {
1375
- internal::type arg_type = args.type(i);
1376
- if (arg_type == internal::type::none_type) return;
1377
- if (arg_type == internal::type::named_arg_type)
1378
- push_back(args.values_[i]);
1379
- }
1380
- }
1381
- for (int i = 0, n = args.max_size(); i < n; ++i) {
1382
- auto type = args.args_[i].type_;
1383
- if (type == internal::type::named_arg_type) push_back(args.args_[i].value_);
1384
- }
1385
- }
1386
-
1387
- template <typename Char> struct nonfinite_writer {
1388
- sign_t sign;
1389
- const char* str;
1390
- static constexpr size_t str_size = 3;
1391
-
1392
- size_t size() const { return str_size + (sign ? 1 : 0); }
1393
- size_t width() const { return size(); }
1394
-
1395
- template <typename It> void operator()(It&& it) const {
1396
- if (sign) *it++ = static_cast<Char>(data::signs[sign]);
1397
- it = copy_str<Char>(str, str + str_size, it);
1398
- }
1399
- };
1400
-
1401
1380
  template <typename OutputIt, typename Char>
1402
1381
  FMT_NOINLINE OutputIt fill(OutputIt it, size_t n, const fill_t<Char>& fill) {
1403
1382
  auto fill_size = fill.size();
@@ -1406,375 +1385,474 @@ FMT_NOINLINE OutputIt fill(OutputIt it, size_t n, const fill_t<Char>& fill) {
1406
1385
  return it;
1407
1386
  }
1408
1387
 
1409
- // This template provides operations for formatting and writing data into a
1410
- // character range.
1411
- template <typename Range> class basic_writer {
1412
- public:
1413
- using char_type = typename Range::value_type;
1414
- using iterator = typename Range::iterator;
1415
- using format_specs = basic_format_specs<char_type>;
1416
-
1417
- private:
1418
- iterator out_; // Output iterator.
1419
- locale_ref locale_;
1420
-
1421
- // Attempts to reserve space for n extra characters in the output range.
1422
- // Returns a pointer to the reserved range or a reference to out_.
1423
- auto reserve(std::size_t n) -> decltype(internal::reserve(out_, n)) {
1424
- return internal::reserve(out_, n);
1425
- }
1426
-
1427
- template <typename F> struct padded_int_writer {
1428
- size_t size_;
1429
- string_view prefix;
1430
- char_type fill;
1431
- std::size_t padding;
1432
- F f;
1433
-
1434
- size_t size() const { return size_; }
1435
- size_t width() const { return size_; }
1436
-
1437
- template <typename It> void operator()(It&& it) const {
1438
- if (prefix.size() != 0)
1439
- it = copy_str<char_type>(prefix.begin(), prefix.end(), it);
1440
- it = std::fill_n(it, padding, fill);
1441
- f(it);
1442
- }
1443
- };
1444
-
1445
- // Writes an integer in the format
1446
- // <left-padding><prefix><numeric-padding><digits><right-padding>
1447
- // where <digits> are written by f(it).
1448
- template <typename F>
1449
- void write_int(int num_digits, string_view prefix, format_specs specs, F f) {
1450
- std::size_t size = prefix.size() + to_unsigned(num_digits);
1451
- char_type fill = specs.fill[0];
1452
- std::size_t padding = 0;
1388
+ // Writes the output of f, padded according to format specifications in specs.
1389
+ // size: output size in code units.
1390
+ // width: output display width in (terminal) column positions.
1391
+ template <align::type align = align::left, typename OutputIt, typename Char,
1392
+ typename F>
1393
+ inline OutputIt write_padded(OutputIt out,
1394
+ const basic_format_specs<Char>& specs, size_t size,
1395
+ size_t width, const F& f) {
1396
+ static_assert(align == align::left || align == align::right, "");
1397
+ unsigned spec_width = to_unsigned(specs.width);
1398
+ size_t padding = spec_width > width ? spec_width - width : 0;
1399
+ auto* shifts = align == align::left ? data::left_padding_shifts
1400
+ : data::right_padding_shifts;
1401
+ size_t left_padding = padding >> shifts[specs.align];
1402
+ auto it = reserve(out, size + padding * specs.fill.size());
1403
+ it = fill(it, left_padding, specs.fill);
1404
+ it = f(it);
1405
+ it = fill(it, padding - left_padding, specs.fill);
1406
+ return base_iterator(out, it);
1407
+ }
1408
+
1409
+ template <align::type align = align::left, typename OutputIt, typename Char,
1410
+ typename F>
1411
+ inline OutputIt write_padded(OutputIt out,
1412
+ const basic_format_specs<Char>& specs, size_t size,
1413
+ const F& f) {
1414
+ return write_padded<align>(out, specs, size, size, f);
1415
+ }
1416
+
1417
+ template <typename Char, typename OutputIt>
1418
+ OutputIt write_bytes(OutputIt out, string_view bytes,
1419
+ const basic_format_specs<Char>& specs) {
1420
+ using iterator = remove_reference_t<decltype(reserve(out, 0))>;
1421
+ return write_padded(out, specs, bytes.size(), [bytes](iterator it) {
1422
+ const char* data = bytes.data();
1423
+ return copy_str<Char>(data, data + bytes.size(), it);
1424
+ });
1425
+ }
1426
+
1427
+ // Data for write_int that doesn't depend on output iterator type. It is used to
1428
+ // avoid template code bloat.
1429
+ template <typename Char> struct write_int_data {
1430
+ size_t size;
1431
+ size_t padding;
1432
+
1433
+ write_int_data(int num_digits, string_view prefix,
1434
+ const basic_format_specs<Char>& specs)
1435
+ : size(prefix.size() + to_unsigned(num_digits)), padding(0) {
1453
1436
  if (specs.align == align::numeric) {
1454
- auto unsiged_width = to_unsigned(specs.width);
1455
- if (unsiged_width > size) {
1456
- padding = unsiged_width - size;
1457
- size = unsiged_width;
1437
+ auto width = to_unsigned(specs.width);
1438
+ if (width > size) {
1439
+ padding = width - size;
1440
+ size = width;
1458
1441
  }
1459
1442
  } else if (specs.precision > num_digits) {
1460
1443
  size = prefix.size() + to_unsigned(specs.precision);
1461
1444
  padding = to_unsigned(specs.precision - num_digits);
1462
- fill = static_cast<char_type>('0');
1463
1445
  }
1464
- if (specs.align == align::none) specs.align = align::right;
1465
- write_padded(specs, padded_int_writer<F>{size, prefix, fill, padding, f});
1466
1446
  }
1447
+ };
1467
1448
 
1468
- // Writes a decimal integer.
1469
- template <typename Int> void write_decimal(Int value) {
1470
- auto abs_value = static_cast<uint32_or_64_or_128_t<Int>>(value);
1471
- bool negative = is_negative(value);
1472
- // Don't do -abs_value since it trips unsigned-integer-overflow sanitizer.
1473
- if (negative) abs_value = ~abs_value + 1;
1474
- int num_digits = count_digits(abs_value);
1475
- auto&& it = reserve((negative ? 1 : 0) + static_cast<size_t>(num_digits));
1476
- if (negative) *it++ = static_cast<char_type>('-');
1477
- it = format_decimal<char_type>(it, abs_value, num_digits);
1478
- }
1479
-
1480
- // The handle_int_type_spec handler that writes an integer.
1481
- template <typename Int, typename Specs> struct int_writer {
1482
- using unsigned_type = uint32_or_64_or_128_t<Int>;
1483
-
1484
- basic_writer<Range>& writer;
1485
- const Specs& specs;
1486
- unsigned_type abs_value;
1487
- char prefix[4];
1488
- unsigned prefix_size;
1489
-
1490
- string_view get_prefix() const { return string_view(prefix, prefix_size); }
1491
-
1492
- int_writer(basic_writer<Range>& w, Int value, const Specs& s)
1493
- : writer(w),
1494
- specs(s),
1495
- abs_value(static_cast<unsigned_type>(value)),
1496
- prefix_size(0) {
1497
- if (is_negative(value)) {
1498
- prefix[0] = '-';
1499
- ++prefix_size;
1500
- abs_value = 0 - abs_value;
1501
- } else if (specs.sign != sign::none && specs.sign != sign::minus) {
1502
- prefix[0] = specs.sign == sign::plus ? '+' : ' ';
1503
- ++prefix_size;
1504
- }
1449
+ // Writes an integer in the format
1450
+ // <left-padding><prefix><numeric-padding><digits><right-padding>
1451
+ // where <digits> are written by f(it).
1452
+ template <typename OutputIt, typename Char, typename F>
1453
+ OutputIt write_int(OutputIt out, int num_digits, string_view prefix,
1454
+ const basic_format_specs<Char>& specs, F f) {
1455
+ auto data = write_int_data<Char>(num_digits, prefix, specs);
1456
+ using iterator = remove_reference_t<decltype(reserve(out, 0))>;
1457
+ return write_padded<align::right>(out, specs, data.size, [=](iterator it) {
1458
+ if (prefix.size() != 0)
1459
+ it = copy_str<Char>(prefix.begin(), prefix.end(), it);
1460
+ it = std::fill_n(it, data.padding, static_cast<Char>('0'));
1461
+ return f(it);
1462
+ });
1463
+ }
1464
+
1465
+ template <typename StrChar, typename Char, typename OutputIt>
1466
+ OutputIt write(OutputIt out, basic_string_view<StrChar> s,
1467
+ const basic_format_specs<Char>& specs) {
1468
+ auto data = s.data();
1469
+ auto size = s.size();
1470
+ if (specs.precision >= 0 && to_unsigned(specs.precision) < size)
1471
+ size = code_point_index(s, to_unsigned(specs.precision));
1472
+ auto width = specs.width != 0
1473
+ ? count_code_points(basic_string_view<StrChar>(data, size))
1474
+ : 0;
1475
+ using iterator = remove_reference_t<decltype(reserve(out, 0))>;
1476
+ return write_padded(out, specs, size, width, [=](iterator it) {
1477
+ return copy_str<Char>(data, data + size, it);
1478
+ });
1479
+ }
1480
+
1481
+ // The handle_int_type_spec handler that writes an integer.
1482
+ template <typename OutputIt, typename Char, typename UInt> struct int_writer {
1483
+ OutputIt out;
1484
+ locale_ref locale;
1485
+ const basic_format_specs<Char>& specs;
1486
+ UInt abs_value;
1487
+ char prefix[4];
1488
+ unsigned prefix_size;
1489
+
1490
+ using iterator =
1491
+ remove_reference_t<decltype(reserve(std::declval<OutputIt&>(), 0))>;
1492
+
1493
+ string_view get_prefix() const { return string_view(prefix, prefix_size); }
1494
+
1495
+ template <typename Int>
1496
+ int_writer(OutputIt output, locale_ref loc, Int value,
1497
+ const basic_format_specs<Char>& s)
1498
+ : out(output),
1499
+ locale(loc),
1500
+ specs(s),
1501
+ abs_value(static_cast<UInt>(value)),
1502
+ prefix_size(0) {
1503
+ static_assert(std::is_same<uint32_or_64_or_128_t<Int>, UInt>::value, "");
1504
+ if (is_negative(value)) {
1505
+ prefix[0] = '-';
1506
+ ++prefix_size;
1507
+ abs_value = 0 - abs_value;
1508
+ } else if (specs.sign != sign::none && specs.sign != sign::minus) {
1509
+ prefix[0] = specs.sign == sign::plus ? '+' : ' ';
1510
+ ++prefix_size;
1505
1511
  }
1512
+ }
1506
1513
 
1507
- struct dec_writer {
1508
- unsigned_type abs_value;
1509
- int num_digits;
1510
-
1511
- template <typename It> void operator()(It&& it) const {
1512
- it = internal::format_decimal<char_type>(it, abs_value, num_digits);
1513
- }
1514
- };
1514
+ void on_dec() {
1515
+ auto num_digits = count_digits(abs_value);
1516
+ out = write_int(
1517
+ out, num_digits, get_prefix(), specs, [this, num_digits](iterator it) {
1518
+ return format_decimal<Char>(it, abs_value, num_digits).end;
1519
+ });
1520
+ }
1515
1521
 
1516
- void on_dec() {
1517
- int num_digits = count_digits(abs_value);
1518
- writer.write_int(num_digits, get_prefix(), specs,
1519
- dec_writer{abs_value, num_digits});
1522
+ void on_hex() {
1523
+ if (specs.alt) {
1524
+ prefix[prefix_size++] = '0';
1525
+ prefix[prefix_size++] = specs.type;
1520
1526
  }
1521
-
1522
- struct hex_writer {
1523
- int_writer& self;
1524
- int num_digits;
1525
-
1526
- template <typename It> void operator()(It&& it) const {
1527
- it = format_uint<4, char_type>(it, self.abs_value, num_digits,
1528
- self.specs.type != 'x');
1529
- }
1530
- };
1531
-
1532
- void on_hex() {
1533
- if (specs.alt) {
1534
- prefix[prefix_size++] = '0';
1535
- prefix[prefix_size++] = specs.type;
1536
- }
1537
- int num_digits = count_digits<4>(abs_value);
1538
- writer.write_int(num_digits, get_prefix(), specs,
1539
- hex_writer{*this, num_digits});
1527
+ int num_digits = count_digits<4>(abs_value);
1528
+ out = write_int(out, num_digits, get_prefix(), specs,
1529
+ [this, num_digits](iterator it) {
1530
+ return format_uint<4, Char>(it, abs_value, num_digits,
1531
+ specs.type != 'x');
1532
+ });
1533
+ }
1534
+
1535
+ void on_bin() {
1536
+ if (specs.alt) {
1537
+ prefix[prefix_size++] = '0';
1538
+ prefix[prefix_size++] = static_cast<char>(specs.type);
1540
1539
  }
1541
-
1542
- template <int BITS> struct bin_writer {
1543
- unsigned_type abs_value;
1544
- int num_digits;
1545
-
1546
- template <typename It> void operator()(It&& it) const {
1547
- it = format_uint<BITS, char_type>(it, abs_value, num_digits);
1548
- }
1549
- };
1550
-
1551
- void on_bin() {
1552
- if (specs.alt) {
1553
- prefix[prefix_size++] = '0';
1554
- prefix[prefix_size++] = static_cast<char>(specs.type);
1555
- }
1556
- int num_digits = count_digits<1>(abs_value);
1557
- writer.write_int(num_digits, get_prefix(), specs,
1558
- bin_writer<1>{abs_value, num_digits});
1540
+ int num_digits = count_digits<1>(abs_value);
1541
+ out = write_int(out, num_digits, get_prefix(), specs,
1542
+ [this, num_digits](iterator it) {
1543
+ return format_uint<1, Char>(it, abs_value, num_digits);
1544
+ });
1545
+ }
1546
+
1547
+ void on_oct() {
1548
+ int num_digits = count_digits<3>(abs_value);
1549
+ if (specs.alt && specs.precision <= num_digits && abs_value != 0) {
1550
+ // Octal prefix '0' is counted as a digit, so only add it if precision
1551
+ // is not greater than the number of digits.
1552
+ prefix[prefix_size++] = '0';
1559
1553
  }
1554
+ out = write_int(out, num_digits, get_prefix(), specs,
1555
+ [this, num_digits](iterator it) {
1556
+ return format_uint<3, Char>(it, abs_value, num_digits);
1557
+ });
1558
+ }
1560
1559
 
1561
- void on_oct() {
1562
- int num_digits = count_digits<3>(abs_value);
1563
- if (specs.alt && specs.precision <= num_digits && abs_value != 0) {
1564
- // Octal prefix '0' is counted as a digit, so only add it if precision
1565
- // is not greater than the number of digits.
1566
- prefix[prefix_size++] = '0';
1567
- }
1568
- writer.write_int(num_digits, get_prefix(), specs,
1569
- bin_writer<3>{abs_value, num_digits});
1570
- }
1560
+ enum { sep_size = 1 };
1571
1561
 
1572
- enum { sep_size = 1 };
1573
-
1574
- struct num_writer {
1575
- unsigned_type abs_value;
1576
- int size;
1577
- const std::string& groups;
1578
- char_type sep;
1579
-
1580
- template <typename It> void operator()(It&& it) const {
1581
- basic_string_view<char_type> s(&sep, sep_size);
1582
- // Index of a decimal digit with the least significant digit having
1583
- // index 0.
1584
- int digit_index = 0;
1585
- std::string::const_iterator group = groups.cbegin();
1586
- it = format_decimal<char_type>(
1587
- it, abs_value, size,
1588
- [this, s, &group, &digit_index](char_type*& buffer) {
1589
- if (*group <= 0 || ++digit_index % *group != 0 ||
1590
- *group == max_value<char>())
1591
- return;
1592
- if (group + 1 != groups.cend()) {
1593
- digit_index = 0;
1594
- ++group;
1595
- }
1596
- buffer -= s.size();
1597
- std::uninitialized_copy(s.data(), s.data() + s.size(),
1598
- make_checked(buffer, s.size()));
1599
- });
1600
- }
1601
- };
1602
-
1603
- void on_num() {
1604
- std::string groups = grouping<char_type>(writer.locale_);
1605
- if (groups.empty()) return on_dec();
1606
- auto sep = thousands_sep<char_type>(writer.locale_);
1607
- if (!sep) return on_dec();
1608
- int num_digits = count_digits(abs_value);
1609
- int size = num_digits;
1610
- std::string::const_iterator group = groups.cbegin();
1611
- while (group != groups.cend() && num_digits > *group && *group > 0 &&
1612
- *group != max_value<char>()) {
1613
- size += sep_size;
1614
- num_digits -= *group;
1562
+ void on_num() {
1563
+ std::string groups = grouping<Char>(locale);
1564
+ if (groups.empty()) return on_dec();
1565
+ auto sep = thousands_sep<Char>(locale);
1566
+ if (!sep) return on_dec();
1567
+ int num_digits = count_digits(abs_value);
1568
+ int size = num_digits, n = num_digits;
1569
+ std::string::const_iterator group = groups.cbegin();
1570
+ while (group != groups.cend() && n > *group && *group > 0 &&
1571
+ *group != max_value<char>()) {
1572
+ size += sep_size;
1573
+ n -= *group;
1574
+ ++group;
1575
+ }
1576
+ if (group == groups.cend()) size += sep_size * ((n - 1) / groups.back());
1577
+ char digits[40];
1578
+ format_decimal(digits, abs_value, num_digits);
1579
+ basic_memory_buffer<Char> buffer;
1580
+ size += prefix_size;
1581
+ buffer.resize(size);
1582
+ basic_string_view<Char> s(&sep, sep_size);
1583
+ // Index of a decimal digit with the least significant digit having index 0.
1584
+ int digit_index = 0;
1585
+ group = groups.cbegin();
1586
+ auto p = buffer.data() + size;
1587
+ for (int i = num_digits - 1; i >= 0; --i) {
1588
+ *--p = static_cast<Char>(digits[i]);
1589
+ if (*group <= 0 || ++digit_index % *group != 0 ||
1590
+ *group == max_value<char>())
1591
+ continue;
1592
+ if (group + 1 != groups.cend()) {
1593
+ digit_index = 0;
1615
1594
  ++group;
1616
1595
  }
1617
- if (group == groups.cend())
1618
- size += sep_size * ((num_digits - 1) / groups.back());
1619
- writer.write_int(size, get_prefix(), specs,
1620
- num_writer{abs_value, size, groups, sep});
1596
+ p -= s.size();
1597
+ std::uninitialized_copy(s.data(), s.data() + s.size(),
1598
+ make_checked(p, s.size()));
1621
1599
  }
1600
+ if (prefix_size != 0) p[-1] = static_cast<Char>('-');
1601
+ using iterator = remove_reference_t<decltype(reserve(out, 0))>;
1602
+ auto data = buffer.data();
1603
+ out = write_padded<align::right>(out, specs, size, size, [=](iterator it) {
1604
+ return copy_str<Char>(data, data + size, it);
1605
+ });
1606
+ }
1622
1607
 
1623
- FMT_NORETURN void on_error() {
1624
- FMT_THROW(format_error("invalid type specifier"));
1625
- }
1626
- };
1627
-
1628
- template <typename Char> struct str_writer {
1629
- const Char* s;
1630
- size_t size_;
1608
+ void on_chr() { *out++ = static_cast<Char>(abs_value); }
1631
1609
 
1632
- size_t size() const { return size_; }
1633
- size_t width() const {
1634
- return count_code_points(basic_string_view<Char>(s, size_));
1635
- }
1610
+ FMT_NORETURN void on_error() {
1611
+ FMT_THROW(format_error("invalid type specifier"));
1612
+ }
1613
+ };
1636
1614
 
1637
- template <typename It> void operator()(It&& it) const {
1638
- it = copy_str<char_type>(s, s + size_, it);
1639
- }
1615
+ template <typename Char, typename OutputIt>
1616
+ OutputIt write_nonfinite(OutputIt out, bool isinf,
1617
+ const basic_format_specs<Char>& specs,
1618
+ const float_specs& fspecs) {
1619
+ auto str =
1620
+ isinf ? (fspecs.upper ? "INF" : "inf") : (fspecs.upper ? "NAN" : "nan");
1621
+ constexpr size_t str_size = 3;
1622
+ auto sign = fspecs.sign;
1623
+ auto size = str_size + (sign ? 1 : 0);
1624
+ using iterator = remove_reference_t<decltype(reserve(out, 0))>;
1625
+ return write_padded(out, specs, size, [=](iterator it) {
1626
+ if (sign) *it++ = static_cast<Char>(data::signs[sign]);
1627
+ return copy_str<Char>(str, str + str_size, it);
1628
+ });
1629
+ }
1630
+
1631
+ template <typename Char, typename OutputIt, typename T,
1632
+ FMT_ENABLE_IF(std::is_floating_point<T>::value)>
1633
+ OutputIt write(OutputIt out, T value, basic_format_specs<Char> specs,
1634
+ locale_ref loc = {}) {
1635
+ if (const_check(!is_supported_floating_point(value))) return out;
1636
+ float_specs fspecs = parse_float_type_spec(specs);
1637
+ fspecs.sign = specs.sign;
1638
+ if (std::signbit(value)) { // value < 0 is false for NaN so use signbit.
1639
+ fspecs.sign = sign::minus;
1640
+ value = -value;
1641
+ } else if (fspecs.sign == sign::minus) {
1642
+ fspecs.sign = sign::none;
1643
+ }
1644
+
1645
+ if (!std::isfinite(value))
1646
+ return write_nonfinite(out, std::isinf(value), specs, fspecs);
1647
+
1648
+ if (specs.align == align::numeric && fspecs.sign) {
1649
+ auto it = reserve(out, 1);
1650
+ *it++ = static_cast<Char>(data::signs[fspecs.sign]);
1651
+ out = base_iterator(out, it);
1652
+ fspecs.sign = sign::none;
1653
+ if (specs.width != 0) --specs.width;
1654
+ }
1655
+
1656
+ memory_buffer buffer;
1657
+ if (fspecs.format == float_format::hex) {
1658
+ if (fspecs.sign) buffer.push_back(data::signs[fspecs.sign]);
1659
+ snprintf_float(promote_float(value), specs.precision, fspecs, buffer);
1660
+ return write_bytes(out, {buffer.data(), buffer.size()}, specs);
1661
+ }
1662
+ int precision = specs.precision >= 0 || !specs.type ? specs.precision : 6;
1663
+ if (fspecs.format == float_format::exp) {
1664
+ if (precision == max_value<int>())
1665
+ FMT_THROW(format_error("number is too big"));
1666
+ else
1667
+ ++precision;
1668
+ }
1669
+ if (const_check(std::is_same<T, float>())) fspecs.binary32 = true;
1670
+ fspecs.use_grisu = use_grisu<T>();
1671
+ int exp = format_float(promote_float(value), precision, fspecs, buffer);
1672
+ fspecs.precision = precision;
1673
+ Char point =
1674
+ fspecs.locale ? decimal_point<Char>(loc) : static_cast<Char>('.');
1675
+ float_writer<Char> w(buffer.data(), static_cast<int>(buffer.size()), exp,
1676
+ fspecs, point);
1677
+ return write_padded<align::right>(out, specs, w.size(), w);
1678
+ }
1679
+
1680
+ template <typename Char, typename OutputIt, typename T,
1681
+ FMT_ENABLE_IF(std::is_floating_point<T>::value)>
1682
+ OutputIt write(OutputIt out, T value) {
1683
+ if (const_check(!is_supported_floating_point(value))) return out;
1684
+ auto fspecs = float_specs();
1685
+ if (std::signbit(value)) { // value < 0 is false for NaN so use signbit.
1686
+ fspecs.sign = sign::minus;
1687
+ value = -value;
1688
+ }
1689
+
1690
+ auto specs = basic_format_specs<Char>();
1691
+ if (!std::isfinite(value))
1692
+ return write_nonfinite(out, std::isinf(value), specs, fspecs);
1693
+
1694
+ memory_buffer buffer;
1695
+ int precision = -1;
1696
+ if (const_check(std::is_same<T, float>())) fspecs.binary32 = true;
1697
+ fspecs.use_grisu = use_grisu<T>();
1698
+ int exp = format_float(promote_float(value), precision, fspecs, buffer);
1699
+ fspecs.precision = precision;
1700
+ float_writer<Char> w(buffer.data(), static_cast<int>(buffer.size()), exp,
1701
+ fspecs, static_cast<Char>('.'));
1702
+ return base_iterator(out, w(reserve(out, w.size())));
1703
+ }
1704
+
1705
+ template <typename Char, typename OutputIt>
1706
+ OutputIt write_char(OutputIt out, Char value,
1707
+ const basic_format_specs<Char>& specs) {
1708
+ using iterator = remove_reference_t<decltype(reserve(out, 0))>;
1709
+ return write_padded(out, specs, 1, [=](iterator it) {
1710
+ *it++ = value;
1711
+ return it;
1712
+ });
1713
+ }
1714
+
1715
+ template <typename Char, typename OutputIt, typename UIntPtr>
1716
+ OutputIt write_ptr(OutputIt out, UIntPtr value,
1717
+ const basic_format_specs<Char>* specs) {
1718
+ int num_digits = count_digits<4>(value);
1719
+ auto size = to_unsigned(num_digits) + size_t(2);
1720
+ using iterator = remove_reference_t<decltype(reserve(out, 0))>;
1721
+ auto write = [=](iterator it) {
1722
+ *it++ = static_cast<Char>('0');
1723
+ *it++ = static_cast<Char>('x');
1724
+ return format_uint<4, Char>(it, value, num_digits);
1640
1725
  };
1726
+ return specs ? write_padded<align::right>(out, *specs, size, write)
1727
+ : base_iterator(out, write(reserve(out, size)));
1728
+ }
1641
1729
 
1642
- struct bytes_writer {
1643
- string_view bytes;
1730
+ template <typename T> struct is_integral : std::is_integral<T> {};
1731
+ template <> struct is_integral<int128_t> : std::true_type {};
1732
+ template <> struct is_integral<uint128_t> : std::true_type {};
1644
1733
 
1645
- size_t size() const { return bytes.size(); }
1646
- size_t width() const { return bytes.size(); }
1734
+ template <typename Char, typename OutputIt>
1735
+ OutputIt write(OutputIt out, monostate) {
1736
+ FMT_ASSERT(false, "");
1737
+ return out;
1738
+ }
1647
1739
 
1648
- template <typename It> void operator()(It&& it) const {
1649
- const char* data = bytes.data();
1650
- it = copy_str<char>(data, data + size(), it);
1651
- }
1652
- };
1740
+ template <typename Char, typename OutputIt,
1741
+ FMT_ENABLE_IF(!std::is_same<Char, char>::value)>
1742
+ OutputIt write(OutputIt out, string_view value) {
1743
+ auto it = reserve(out, value.size());
1744
+ it = copy_str<Char>(value.begin(), value.end(), it);
1745
+ return base_iterator(out, it);
1746
+ }
1653
1747
 
1654
- template <typename UIntPtr> struct pointer_writer {
1655
- UIntPtr value;
1656
- int num_digits;
1748
+ template <typename Char, typename OutputIt>
1749
+ OutputIt write(OutputIt out, basic_string_view<Char> value) {
1750
+ auto it = reserve(out, value.size());
1751
+ it = std::copy(value.begin(), value.end(), it);
1752
+ return base_iterator(out, it);
1753
+ }
1657
1754
 
1658
- size_t size() const { return to_unsigned(num_digits) + 2; }
1659
- size_t width() const { return size(); }
1755
+ template <typename Char, typename OutputIt, typename T,
1756
+ FMT_ENABLE_IF(is_integral<T>::value &&
1757
+ !std::is_same<T, bool>::value &&
1758
+ !std::is_same<T, Char>::value)>
1759
+ OutputIt write(OutputIt out, T value) {
1760
+ auto abs_value = static_cast<uint32_or_64_or_128_t<T>>(value);
1761
+ bool negative = is_negative(value);
1762
+ // Don't do -abs_value since it trips unsigned-integer-overflow sanitizer.
1763
+ if (negative) abs_value = ~abs_value + 1;
1764
+ int num_digits = count_digits(abs_value);
1765
+ auto it = reserve(out, (negative ? 1 : 0) + static_cast<size_t>(num_digits));
1766
+ if (negative) *it++ = static_cast<Char>('-');
1767
+ it = format_decimal<Char>(it, abs_value, num_digits).end;
1768
+ return base_iterator(out, it);
1769
+ }
1660
1770
 
1661
- template <typename It> void operator()(It&& it) const {
1662
- *it++ = static_cast<char_type>('0');
1663
- *it++ = static_cast<char_type>('x');
1664
- it = format_uint<4, char_type>(it, value, num_digits);
1665
- }
1666
- };
1771
+ template <typename Char, typename OutputIt>
1772
+ OutputIt write(OutputIt out, bool value) {
1773
+ return write<Char>(out, string_view(value ? "true" : "false"));
1774
+ }
1667
1775
 
1668
- public:
1669
- explicit basic_writer(Range out, locale_ref loc = locale_ref())
1670
- : out_(out.begin()), locale_(loc) {}
1671
-
1672
- iterator out() const { return out_; }
1673
-
1674
- // Writes a value in the format
1675
- // <left-padding><value><right-padding>
1676
- // where <value> is written by f(it).
1677
- template <typename F> void write_padded(const format_specs& specs, F&& f) {
1678
- // User-perceived width (in code points).
1679
- unsigned width = to_unsigned(specs.width);
1680
- size_t size = f.size(); // The number of code units.
1681
- size_t num_code_points = width != 0 ? f.width() : size;
1682
- if (width <= num_code_points) return f(reserve(size));
1683
- size_t padding = width - num_code_points;
1684
- size_t fill_size = specs.fill.size();
1685
- auto&& it = reserve(size + padding * fill_size);
1686
- if (specs.align == align::right) {
1687
- it = fill(it, padding, specs.fill);
1688
- f(it);
1689
- } else if (specs.align == align::center) {
1690
- std::size_t left_padding = padding / 2;
1691
- it = fill(it, left_padding, specs.fill);
1692
- f(it);
1693
- it = fill(it, padding - left_padding, specs.fill);
1694
- } else {
1695
- f(it);
1696
- it = fill(it, padding, specs.fill);
1697
- }
1776
+ template <typename Char, typename OutputIt>
1777
+ OutputIt write(OutputIt out, Char value) {
1778
+ auto it = reserve(out, 1);
1779
+ *it++ = value;
1780
+ return base_iterator(out, it);
1781
+ }
1782
+
1783
+ template <typename Char, typename OutputIt>
1784
+ OutputIt write(OutputIt out, const Char* value) {
1785
+ if (!value) {
1786
+ FMT_THROW(format_error("string pointer is null"));
1787
+ } else {
1788
+ auto length = std::char_traits<Char>::length(value);
1789
+ out = write(out, basic_string_view<Char>(value, length));
1698
1790
  }
1791
+ return out;
1792
+ }
1699
1793
 
1700
- void write(int value) { write_decimal(value); }
1701
- void write(long value) { write_decimal(value); }
1702
- void write(long long value) { write_decimal(value); }
1794
+ template <typename Char, typename OutputIt>
1795
+ OutputIt write(OutputIt out, const void* value) {
1796
+ return write_ptr<Char>(out, to_uintptr(value), nullptr);
1797
+ }
1703
1798
 
1704
- void write(unsigned value) { write_decimal(value); }
1705
- void write(unsigned long value) { write_decimal(value); }
1706
- void write(unsigned long long value) { write_decimal(value); }
1799
+ template <typename Char, typename OutputIt, typename T>
1800
+ auto write(OutputIt out, const T& value) -> typename std::enable_if<
1801
+ mapped_type_constant<T, basic_format_context<OutputIt, Char>>::value ==
1802
+ type::custom_type,
1803
+ OutputIt>::type {
1804
+ basic_format_context<OutputIt, Char> ctx(out, {}, {});
1805
+ return formatter<T>().format(value, ctx);
1806
+ }
1707
1807
 
1708
- #if FMT_USE_INT128
1709
- void write(int128_t value) { write_decimal(value); }
1710
- void write(uint128_t value) { write_decimal(value); }
1711
- #endif
1808
+ // An argument visitor that formats the argument and writes it via the output
1809
+ // iterator. It's a class and not a generic lambda for compatibility with C++11.
1810
+ template <typename OutputIt, typename Char> struct default_arg_formatter {
1811
+ using context = basic_format_context<OutputIt, Char>;
1712
1812
 
1713
- template <typename T, typename Spec>
1714
- void write_int(T value, const Spec& spec) {
1715
- handle_int_type_spec(spec.type, int_writer<T, Spec>(*this, value, spec));
1813
+ OutputIt out;
1814
+ basic_format_args<context> args;
1815
+ locale_ref loc;
1816
+
1817
+ template <typename T> OutputIt operator()(T value) {
1818
+ return write<Char>(out, value);
1716
1819
  }
1717
1820
 
1718
- template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
1719
- void write(T value, format_specs specs = {}) {
1720
- if (const_check(!is_supported_floating_point(value))) {
1721
- return;
1722
- }
1723
- float_specs fspecs = parse_float_type_spec(specs);
1724
- fspecs.sign = specs.sign;
1725
- if (std::signbit(value)) { // value < 0 is false for NaN so use signbit.
1726
- fspecs.sign = sign::minus;
1727
- value = -value;
1728
- } else if (fspecs.sign == sign::minus) {
1729
- fspecs.sign = sign::none;
1730
- }
1821
+ OutputIt operator()(typename basic_format_arg<context>::handle handle) {
1822
+ basic_format_parse_context<Char> parse_ctx({});
1823
+ basic_format_context<OutputIt, Char> format_ctx(out, args, loc);
1824
+ handle.format(parse_ctx, format_ctx);
1825
+ return format_ctx.out();
1826
+ }
1827
+ };
1731
1828
 
1732
- if (!std::isfinite(value)) {
1733
- auto str = std::isinf(value) ? (fspecs.upper ? "INF" : "inf")
1734
- : (fspecs.upper ? "NAN" : "nan");
1735
- return write_padded(specs, nonfinite_writer<char_type>{fspecs.sign, str});
1736
- }
1829
+ template <typename OutputIt, typename Char,
1830
+ typename ErrorHandler = error_handler>
1831
+ class arg_formatter_base {
1832
+ public:
1833
+ using iterator = OutputIt;
1834
+ using char_type = Char;
1835
+ using format_specs = basic_format_specs<Char>;
1737
1836
 
1738
- if (specs.align == align::none) {
1739
- specs.align = align::right;
1740
- } else if (specs.align == align::numeric) {
1741
- if (fspecs.sign) {
1742
- auto&& it = reserve(1);
1743
- *it++ = static_cast<char_type>(data::signs[fspecs.sign]);
1744
- fspecs.sign = sign::none;
1745
- if (specs.width != 0) --specs.width;
1746
- }
1747
- specs.align = align::right;
1748
- }
1837
+ private:
1838
+ iterator out_;
1839
+ locale_ref locale_;
1840
+ format_specs* specs_;
1749
1841
 
1750
- memory_buffer buffer;
1751
- if (fspecs.format == float_format::hex) {
1752
- if (fspecs.sign) buffer.push_back(data::signs[fspecs.sign]);
1753
- snprintf_float(promote_float(value), specs.precision, fspecs, buffer);
1754
- write_padded(specs, str_writer<char>{buffer.data(), buffer.size()});
1755
- return;
1756
- }
1757
- int precision = specs.precision >= 0 || !specs.type ? specs.precision : 6;
1758
- if (fspecs.format == float_format::exp) {
1759
- if (precision == max_value<int>())
1760
- FMT_THROW(format_error("number is too big"));
1761
- else
1762
- ++precision;
1763
- }
1764
- if (const_check(std::is_same<T, float>())) fspecs.binary32 = true;
1765
- fspecs.use_grisu = use_grisu<T>();
1766
- if (const_check(FMT_DEPRECATED_PERCENT) && fspecs.percent) value *= 100;
1767
- int exp = format_float(promote_float(value), precision, fspecs, buffer);
1768
- if (const_check(FMT_DEPRECATED_PERCENT) && fspecs.percent) {
1769
- buffer.push_back('%');
1770
- --exp; // Adjust decimal place position.
1771
- }
1772
- fspecs.precision = precision;
1773
- char_type point = fspecs.locale ? decimal_point<char_type>(locale_)
1774
- : static_cast<char_type>('.');
1775
- write_padded(specs, float_writer<char_type>(buffer.data(),
1776
- static_cast<int>(buffer.size()),
1777
- exp, fspecs, point));
1842
+ // Attempts to reserve space for n extra characters in the output range.
1843
+ // Returns a pointer to the reserved range or a reference to out_.
1844
+ auto reserve(size_t n) -> decltype(detail::reserve(out_, n)) {
1845
+ return detail::reserve(out_, n);
1846
+ }
1847
+
1848
+ using reserve_iterator = remove_reference_t<decltype(
1849
+ detail::reserve(std::declval<iterator&>(), 0))>;
1850
+
1851
+ template <typename T> void write_int(T value, const format_specs& spec) {
1852
+ using uint_type = uint32_or_64_or_128_t<T>;
1853
+ int_writer<iterator, Char, uint_type> w(out_, locale_, value, spec);
1854
+ handle_int_type_spec(spec.type, w);
1855
+ out_ = w.out;
1778
1856
  }
1779
1857
 
1780
1858
  void write(char value) {
@@ -1782,198 +1860,151 @@ template <typename Range> class basic_writer {
1782
1860
  *it++ = value;
1783
1861
  }
1784
1862
 
1785
- template <typename Char, FMT_ENABLE_IF(std::is_same<Char, char_type>::value)>
1786
- void write(Char value) {
1787
- auto&& it = reserve(1);
1788
- *it++ = value;
1863
+ template <typename Ch, FMT_ENABLE_IF(std::is_same<Ch, Char>::value)>
1864
+ void write(Ch value) {
1865
+ out_ = detail::write<Char>(out_, value);
1789
1866
  }
1790
1867
 
1791
1868
  void write(string_view value) {
1792
1869
  auto&& it = reserve(value.size());
1793
- it = copy_str<char_type>(value.begin(), value.end(), it);
1870
+ it = copy_str<Char>(value.begin(), value.end(), it);
1794
1871
  }
1795
1872
  void write(wstring_view value) {
1796
- static_assert(std::is_same<char_type, wchar_t>::value, "");
1873
+ static_assert(std::is_same<Char, wchar_t>::value, "");
1797
1874
  auto&& it = reserve(value.size());
1798
1875
  it = std::copy(value.begin(), value.end(), it);
1799
1876
  }
1800
1877
 
1801
- template <typename Char>
1802
- void write(const Char* s, std::size_t size, const format_specs& specs) {
1803
- write_padded(specs, str_writer<Char>{s, size});
1804
- }
1805
-
1806
- template <typename Char>
1807
- void write(basic_string_view<Char> s, const format_specs& specs = {}) {
1808
- const Char* data = s.data();
1809
- std::size_t size = s.size();
1810
- if (specs.precision >= 0 && to_unsigned(specs.precision) < size)
1811
- size = code_point_index(s, to_unsigned(specs.precision));
1812
- write(data, size, specs);
1878
+ template <typename Ch>
1879
+ void write(const Ch* s, size_t size, const format_specs& specs) {
1880
+ auto width = specs.width != 0
1881
+ ? count_code_points(basic_string_view<Ch>(s, size))
1882
+ : 0;
1883
+ out_ = write_padded(out_, specs, size, width, [=](reserve_iterator it) {
1884
+ return copy_str<Char>(s, s + size, it);
1885
+ });
1813
1886
  }
1814
1887
 
1815
- void write_bytes(string_view bytes, const format_specs& specs) {
1816
- write_padded(specs, bytes_writer{bytes});
1888
+ template <typename Ch>
1889
+ void write(basic_string_view<Ch> s, const format_specs& specs = {}) {
1890
+ out_ = detail::write(out_, s, specs);
1817
1891
  }
1818
1892
 
1819
- template <typename UIntPtr>
1820
- void write_pointer(UIntPtr value, const format_specs* specs) {
1821
- int num_digits = count_digits<4>(value);
1822
- auto pw = pointer_writer<UIntPtr>{value, num_digits};
1823
- if (!specs) return pw(reserve(to_unsigned(num_digits) + 2));
1824
- format_specs specs_copy = *specs;
1825
- if (specs_copy.align == align::none) specs_copy.align = align::right;
1826
- write_padded(specs_copy, pw);
1893
+ void write_pointer(const void* p) {
1894
+ out_ = write_ptr<char_type>(out_, to_uintptr(p), specs_);
1827
1895
  }
1828
- };
1829
1896
 
1830
- using writer = basic_writer<buffer_range<char>>;
1831
-
1832
- template <typename T> struct is_integral : std::is_integral<T> {};
1833
- template <> struct is_integral<int128_t> : std::true_type {};
1834
- template <> struct is_integral<uint128_t> : std::true_type {};
1897
+ struct char_spec_handler : ErrorHandler {
1898
+ arg_formatter_base& formatter;
1899
+ Char value;
1835
1900
 
1836
- template <typename Range, typename ErrorHandler = internal::error_handler>
1837
- class arg_formatter_base {
1838
- public:
1839
- using char_type = typename Range::value_type;
1840
- using iterator = typename Range::iterator;
1841
- using format_specs = basic_format_specs<char_type>;
1901
+ char_spec_handler(arg_formatter_base& f, Char val)
1902
+ : formatter(f), value(val) {}
1842
1903
 
1843
- private:
1844
- using writer_type = basic_writer<Range>;
1845
- writer_type writer_;
1846
- format_specs* specs_;
1904
+ void on_int() {
1905
+ // char is only formatted as int if there are specs.
1906
+ formatter.write_int(static_cast<int>(value), *formatter.specs_);
1907
+ }
1908
+ void on_char() {
1909
+ if (formatter.specs_)
1910
+ formatter.out_ = write_char(formatter.out_, value, *formatter.specs_);
1911
+ else
1912
+ formatter.write(value);
1913
+ }
1914
+ };
1847
1915
 
1848
- struct char_writer {
1849
- char_type value;
1916
+ struct cstring_spec_handler : error_handler {
1917
+ arg_formatter_base& formatter;
1918
+ const Char* value;
1850
1919
 
1851
- size_t size() const { return 1; }
1852
- size_t width() const { return 1; }
1920
+ cstring_spec_handler(arg_formatter_base& f, const Char* val)
1921
+ : formatter(f), value(val) {}
1853
1922
 
1854
- template <typename It> void operator()(It&& it) const { *it++ = value; }
1923
+ void on_string() { formatter.write(value); }
1924
+ void on_pointer() { formatter.write_pointer(value); }
1855
1925
  };
1856
1926
 
1857
- void write_char(char_type value) {
1858
- if (specs_)
1859
- writer_.write_padded(*specs_, char_writer{value});
1860
- else
1861
- writer_.write(value);
1862
- }
1863
-
1864
- void write_pointer(const void* p) {
1865
- writer_.write_pointer(internal::to_uintptr(p), specs_);
1866
- }
1867
-
1868
1927
  protected:
1869
- writer_type& writer() { return writer_; }
1870
- FMT_DEPRECATED format_specs* spec() { return specs_; }
1928
+ iterator out() { return out_; }
1871
1929
  format_specs* specs() { return specs_; }
1872
- iterator out() { return writer_.out(); }
1873
1930
 
1874
1931
  void write(bool value) {
1875
- string_view sv(value ? "true" : "false");
1876
- specs_ ? writer_.write(sv, *specs_) : writer_.write(sv);
1932
+ if (specs_)
1933
+ write(string_view(value ? "true" : "false"), *specs_);
1934
+ else
1935
+ out_ = detail::write<Char>(out_, value);
1877
1936
  }
1878
1937
 
1879
- void write(const char_type* value) {
1938
+ void write(const Char* value) {
1880
1939
  if (!value) {
1881
1940
  FMT_THROW(format_error("string pointer is null"));
1882
1941
  } else {
1883
1942
  auto length = std::char_traits<char_type>::length(value);
1884
1943
  basic_string_view<char_type> sv(value, length);
1885
- specs_ ? writer_.write(sv, *specs_) : writer_.write(sv);
1944
+ specs_ ? write(sv, *specs_) : write(sv);
1886
1945
  }
1887
1946
  }
1888
1947
 
1889
1948
  public:
1890
- arg_formatter_base(Range r, format_specs* s, locale_ref loc)
1891
- : writer_(r, loc), specs_(s) {}
1949
+ arg_formatter_base(OutputIt out, format_specs* s, locale_ref loc)
1950
+ : out_(out), locale_(loc), specs_(s) {}
1892
1951
 
1893
1952
  iterator operator()(monostate) {
1894
1953
  FMT_ASSERT(false, "invalid argument type");
1895
- return out();
1954
+ return out_;
1896
1955
  }
1897
1956
 
1898
1957
  template <typename T, FMT_ENABLE_IF(is_integral<T>::value)>
1899
- iterator operator()(T value) {
1958
+ FMT_INLINE iterator operator()(T value) {
1900
1959
  if (specs_)
1901
- writer_.write_int(value, *specs_);
1960
+ write_int(value, *specs_);
1902
1961
  else
1903
- writer_.write(value);
1904
- return out();
1962
+ out_ = detail::write<Char>(out_, value);
1963
+ return out_;
1905
1964
  }
1906
1965
 
1907
- iterator operator()(char_type value) {
1908
- internal::handle_char_specs(
1909
- specs_, char_spec_handler(*this, static_cast<char_type>(value)));
1910
- return out();
1966
+ iterator operator()(Char value) {
1967
+ handle_char_specs(specs_,
1968
+ char_spec_handler(*this, static_cast<Char>(value)));
1969
+ return out_;
1911
1970
  }
1912
1971
 
1913
1972
  iterator operator()(bool value) {
1914
1973
  if (specs_ && specs_->type) return (*this)(value ? 1 : 0);
1915
1974
  write(value != 0);
1916
- return out();
1975
+ return out_;
1917
1976
  }
1918
1977
 
1919
1978
  template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
1920
1979
  iterator operator()(T value) {
1980
+ auto specs = specs_ ? *specs_ : format_specs();
1921
1981
  if (const_check(is_supported_floating_point(value)))
1922
- writer_.write(value, specs_ ? *specs_ : format_specs());
1982
+ out_ = detail::write(out_, value, specs, locale_);
1923
1983
  else
1924
1984
  FMT_ASSERT(false, "unsupported float argument type");
1925
- return out();
1985
+ return out_;
1926
1986
  }
1927
1987
 
1928
- struct char_spec_handler : ErrorHandler {
1929
- arg_formatter_base& formatter;
1930
- char_type value;
1931
-
1932
- char_spec_handler(arg_formatter_base& f, char_type val)
1933
- : formatter(f), value(val) {}
1934
-
1935
- void on_int() {
1936
- if (formatter.specs_)
1937
- formatter.writer_.write_int(value, *formatter.specs_);
1938
- else
1939
- formatter.writer_.write(value);
1940
- }
1941
- void on_char() { formatter.write_char(value); }
1942
- };
1943
-
1944
- struct cstring_spec_handler : internal::error_handler {
1945
- arg_formatter_base& formatter;
1946
- const char_type* value;
1947
-
1948
- cstring_spec_handler(arg_formatter_base& f, const char_type* val)
1949
- : formatter(f), value(val) {}
1950
-
1951
- void on_string() { formatter.write(value); }
1952
- void on_pointer() { formatter.write_pointer(value); }
1953
- };
1954
-
1955
- iterator operator()(const char_type* value) {
1956
- if (!specs_) return write(value), out();
1957
- internal::handle_cstring_type_spec(specs_->type,
1958
- cstring_spec_handler(*this, value));
1959
- return out();
1988
+ iterator operator()(const Char* value) {
1989
+ if (!specs_) return write(value), out_;
1990
+ handle_cstring_type_spec(specs_->type, cstring_spec_handler(*this, value));
1991
+ return out_;
1960
1992
  }
1961
1993
 
1962
- iterator operator()(basic_string_view<char_type> value) {
1994
+ iterator operator()(basic_string_view<Char> value) {
1963
1995
  if (specs_) {
1964
- internal::check_string_type_spec(specs_->type, internal::error_handler());
1965
- writer_.write(value, *specs_);
1996
+ check_string_type_spec(specs_->type, error_handler());
1997
+ write(value, *specs_);
1966
1998
  } else {
1967
- writer_.write(value);
1999
+ write(value);
1968
2000
  }
1969
- return out();
2001
+ return out_;
1970
2002
  }
1971
2003
 
1972
2004
  iterator operator()(const void* value) {
1973
- if (specs_)
1974
- check_pointer_type_spec(specs_->type, internal::error_handler());
2005
+ if (specs_) check_pointer_type_spec(specs_->type, error_handler());
1975
2006
  write_pointer(value);
1976
- return out();
2007
+ return out_;
1977
2008
  }
1978
2009
  };
1979
2010
 
@@ -2109,7 +2140,7 @@ template <typename Char> class specs_setter {
2109
2140
 
2110
2141
  template <typename ErrorHandler> class numeric_specs_checker {
2111
2142
  public:
2112
- FMT_CONSTEXPR numeric_specs_checker(ErrorHandler& eh, internal::type arg_type)
2143
+ FMT_CONSTEXPR numeric_specs_checker(ErrorHandler& eh, detail::type arg_type)
2113
2144
  : error_handler_(eh), arg_type_(arg_type) {}
2114
2145
 
2115
2146
  FMT_CONSTEXPR void require_numeric_argument() {
@@ -2132,18 +2163,24 @@ template <typename ErrorHandler> class numeric_specs_checker {
2132
2163
 
2133
2164
  private:
2134
2165
  ErrorHandler& error_handler_;
2135
- internal::type arg_type_;
2166
+ detail::type arg_type_;
2136
2167
  };
2137
2168
 
2138
2169
  // A format specifier handler that checks if specifiers are consistent with the
2139
2170
  // argument type.
2140
2171
  template <typename Handler> class specs_checker : public Handler {
2172
+ private:
2173
+ numeric_specs_checker<Handler> checker_;
2174
+
2175
+ // Suppress an MSVC warning about using this in initializer list.
2176
+ FMT_CONSTEXPR Handler& error_handler() { return *this; }
2177
+
2141
2178
  public:
2142
- FMT_CONSTEXPR specs_checker(const Handler& handler, internal::type arg_type)
2143
- : Handler(handler), checker_(*this, arg_type) {}
2179
+ FMT_CONSTEXPR specs_checker(const Handler& handler, detail::type arg_type)
2180
+ : Handler(handler), checker_(error_handler(), arg_type) {}
2144
2181
 
2145
2182
  FMT_CONSTEXPR specs_checker(const specs_checker& other)
2146
- : Handler(other), checker_(*this, other.arg_type_) {}
2183
+ : Handler(other), checker_(error_handler(), other.arg_type_) {}
2147
2184
 
2148
2185
  FMT_CONSTEXPR void on_align(align_t align) {
2149
2186
  if (align == align::numeric) checker_.require_numeric_argument();
@@ -2176,9 +2213,6 @@ template <typename Handler> class specs_checker : public Handler {
2176
2213
  }
2177
2214
 
2178
2215
  FMT_CONSTEXPR void end_precision() { checker_.check_precision(); }
2179
-
2180
- private:
2181
- numeric_specs_checker<Handler> checker_;
2182
2216
  };
2183
2217
 
2184
2218
  template <template <typename> class Handler, typename FormatArg,
@@ -2191,10 +2225,10 @@ FMT_CONSTEXPR int get_dynamic_spec(FormatArg arg, ErrorHandler eh) {
2191
2225
 
2192
2226
  struct auto_id {};
2193
2227
 
2194
- template <typename Context>
2195
- FMT_CONSTEXPR typename Context::format_arg get_arg(Context& ctx, int id) {
2228
+ template <typename Context, typename ID>
2229
+ FMT_CONSTEXPR typename Context::format_arg get_arg(Context& ctx, ID id) {
2196
2230
  auto arg = ctx.arg(id);
2197
- if (!arg) ctx.on_error("argument index out of range");
2231
+ if (!arg) ctx.on_error("argument not found");
2198
2232
  return arg;
2199
2233
  }
2200
2234
 
@@ -2227,17 +2261,17 @@ class specs_handler : public specs_setter<typename Context::char_type> {
2227
2261
  using format_arg = typename Context::format_arg;
2228
2262
 
2229
2263
  FMT_CONSTEXPR format_arg get_arg(auto_id) {
2230
- return internal::get_arg(context_, parse_context_.next_arg_id());
2264
+ return detail::get_arg(context_, parse_context_.next_arg_id());
2231
2265
  }
2232
2266
 
2233
2267
  FMT_CONSTEXPR format_arg get_arg(int arg_id) {
2234
2268
  parse_context_.check_arg_id(arg_id);
2235
- return internal::get_arg(context_, arg_id);
2269
+ return detail::get_arg(context_, arg_id);
2236
2270
  }
2237
2271
 
2238
2272
  FMT_CONSTEXPR format_arg get_arg(basic_string_view<char_type> arg_id) {
2239
2273
  parse_context_.check_arg_id(arg_id);
2240
- return context_.arg(arg_id);
2274
+ return detail::get_arg(context_, arg_id);
2241
2275
  }
2242
2276
 
2243
2277
  ParseContext& parse_context_;
@@ -2424,7 +2458,7 @@ FMT_CONSTEXPR const Char* parse_align(const Char* begin, const Char* end,
2424
2458
  case '>':
2425
2459
  align = align::right;
2426
2460
  break;
2427
- #if FMT_NUMERIC_ALIGN
2461
+ #if FMT_DEPRECATED_NUMERIC_ALIGN
2428
2462
  case '=':
2429
2463
  align = align::numeric;
2430
2464
  break;
@@ -2555,26 +2589,75 @@ template <>
2555
2589
  inline bool find<false, char>(const char* first, const char* last, char value,
2556
2590
  const char*& out) {
2557
2591
  out = static_cast<const char*>(
2558
- std::memchr(first, value, internal::to_unsigned(last - first)));
2592
+ std::memchr(first, value, detail::to_unsigned(last - first)));
2559
2593
  return out != nullptr;
2560
2594
  }
2561
2595
 
2562
2596
  template <typename Handler, typename Char> struct id_adapter {
2563
- FMT_CONSTEXPR void operator()() { handler.on_arg_id(); }
2564
- FMT_CONSTEXPR void operator()(int id) { handler.on_arg_id(id); }
2597
+ Handler& handler;
2598
+ int arg_id;
2599
+
2600
+ FMT_CONSTEXPR void operator()() { arg_id = handler.on_arg_id(); }
2601
+ FMT_CONSTEXPR void operator()(int id) { arg_id = handler.on_arg_id(id); }
2565
2602
  FMT_CONSTEXPR void operator()(basic_string_view<Char> id) {
2566
- handler.on_arg_id(id);
2603
+ arg_id = handler.on_arg_id(id);
2567
2604
  }
2568
2605
  FMT_CONSTEXPR void on_error(const char* message) {
2569
2606
  handler.on_error(message);
2570
2607
  }
2571
- Handler& handler;
2572
2608
  };
2573
2609
 
2610
+ template <typename Char, typename Handler>
2611
+ FMT_CONSTEXPR const Char* parse_replacement_field(const Char* begin,
2612
+ const Char* end,
2613
+ Handler&& handler) {
2614
+ ++begin;
2615
+ if (begin == end) return handler.on_error("invalid format string"), end;
2616
+ if (static_cast<char>(*begin) == '}') {
2617
+ handler.on_replacement_field(handler.on_arg_id(), begin);
2618
+ } else if (*begin == '{') {
2619
+ handler.on_text(begin, begin + 1);
2620
+ } else {
2621
+ auto adapter = id_adapter<Handler, Char>{handler, 0};
2622
+ begin = parse_arg_id(begin, end, adapter);
2623
+ Char c = begin != end ? *begin : Char();
2624
+ if (c == '}') {
2625
+ handler.on_replacement_field(adapter.arg_id, begin);
2626
+ } else if (c == ':') {
2627
+ begin = handler.on_format_specs(adapter.arg_id, begin + 1, end);
2628
+ if (begin == end || *begin != '}')
2629
+ return handler.on_error("unknown format specifier"), end;
2630
+ } else {
2631
+ return handler.on_error("missing '}' in format string"), end;
2632
+ }
2633
+ }
2634
+ return begin + 1;
2635
+ }
2636
+
2574
2637
  template <bool IS_CONSTEXPR, typename Char, typename Handler>
2575
- FMT_CONSTEXPR void parse_format_string(basic_string_view<Char> format_str,
2576
- Handler&& handler) {
2577
- struct pfs_writer {
2638
+ FMT_CONSTEXPR_DECL FMT_INLINE void parse_format_string(
2639
+ basic_string_view<Char> format_str, Handler&& handler) {
2640
+ auto begin = format_str.data();
2641
+ auto end = begin + format_str.size();
2642
+ if (end - begin < 32) {
2643
+ // Use a simple loop instead of memchr for small strings.
2644
+ const Char* p = begin;
2645
+ while (p != end) {
2646
+ auto c = *p++;
2647
+ if (c == '{') {
2648
+ handler.on_text(begin, p - 1);
2649
+ begin = p = parse_replacement_field(p - 1, end, handler);
2650
+ } else if (c == '}') {
2651
+ if (p == end || *p != '}')
2652
+ return handler.on_error("unmatched '}' in format string");
2653
+ handler.on_text(begin, p);
2654
+ begin = ++p;
2655
+ }
2656
+ }
2657
+ handler.on_text(begin, end);
2658
+ return;
2659
+ }
2660
+ struct writer {
2578
2661
  FMT_CONSTEXPR void operator()(const Char* begin, const Char* end) {
2579
2662
  if (begin == end) return;
2580
2663
  for (;;) {
@@ -2590,8 +2673,6 @@ FMT_CONSTEXPR void parse_format_string(basic_string_view<Char> format_str,
2590
2673
  }
2591
2674
  Handler& handler_;
2592
2675
  } write{handler};
2593
- auto begin = format_str.data();
2594
- auto end = begin + format_str.size();
2595
2676
  while (begin != end) {
2596
2677
  // Doing two passes with memchr (one for '{' and another for '}') is up to
2597
2678
  // 2.5x faster than the naive one-pass implementation on big format strings.
@@ -2599,27 +2680,7 @@ FMT_CONSTEXPR void parse_format_string(basic_string_view<Char> format_str,
2599
2680
  if (*begin != '{' && !find<IS_CONSTEXPR>(begin + 1, end, '{', p))
2600
2681
  return write(begin, end);
2601
2682
  write(begin, p);
2602
- ++p;
2603
- if (p == end) return handler.on_error("invalid format string");
2604
- if (static_cast<char>(*p) == '}') {
2605
- handler.on_arg_id();
2606
- handler.on_replacement_field(p);
2607
- } else if (*p == '{') {
2608
- handler.on_text(p, p + 1);
2609
- } else {
2610
- p = parse_arg_id(p, end, id_adapter<Handler, Char>{handler});
2611
- Char c = p != end ? *p : Char();
2612
- if (c == '}') {
2613
- handler.on_replacement_field(p);
2614
- } else if (c == ':') {
2615
- p = handler.on_format_specs(p + 1, end);
2616
- if (p == end || *p != '}')
2617
- return handler.on_error("unknown format specifier");
2618
- } else {
2619
- return handler.on_error("missing '}' in format string");
2620
- }
2621
- }
2622
- begin = p + 1;
2683
+ begin = parse_replacement_field(p, end, handler);
2623
2684
  }
2624
2685
  }
2625
2686
 
@@ -2629,44 +2690,121 @@ FMT_CONSTEXPR const typename ParseContext::char_type* parse_format_specs(
2629
2690
  using char_type = typename ParseContext::char_type;
2630
2691
  using context = buffer_context<char_type>;
2631
2692
  using mapped_type =
2632
- conditional_t<internal::mapped_type_constant<T, context>::value !=
2693
+ conditional_t<detail::mapped_type_constant<T, context>::value !=
2633
2694
  type::custom_type,
2634
2695
  decltype(arg_mapper<context>().map(std::declval<T>())), T>;
2635
2696
  auto f = conditional_t<has_formatter<mapped_type, context>::value,
2636
2697
  formatter<mapped_type, char_type>,
2637
- internal::fallback_formatter<T, char_type>>();
2698
+ detail::fallback_formatter<T, char_type>>();
2638
2699
  return f.parse(ctx);
2639
2700
  }
2640
2701
 
2702
+ template <typename ArgFormatter, typename Char, typename Context>
2703
+ struct format_handler : detail::error_handler {
2704
+ basic_format_parse_context<Char> parse_context;
2705
+ Context context;
2706
+
2707
+ format_handler(typename ArgFormatter::iterator out,
2708
+ basic_string_view<Char> str,
2709
+ basic_format_args<Context> format_args, detail::locale_ref loc)
2710
+ : parse_context(str), context(out, format_args, loc) {}
2711
+
2712
+ void on_text(const Char* begin, const Char* end) {
2713
+ auto size = to_unsigned(end - begin);
2714
+ auto out = context.out();
2715
+ auto&& it = reserve(out, size);
2716
+ it = std::copy_n(begin, size, it);
2717
+ context.advance_to(out);
2718
+ }
2719
+
2720
+ int on_arg_id() { return parse_context.next_arg_id(); }
2721
+ int on_arg_id(int id) { return parse_context.check_arg_id(id), id; }
2722
+ int on_arg_id(basic_string_view<Char> id) {
2723
+ int arg_id = context.arg_id(id);
2724
+ if (arg_id < 0) on_error("argument not found");
2725
+ return arg_id;
2726
+ }
2727
+
2728
+ FMT_INLINE void on_replacement_field(int id, const Char*) {
2729
+ auto arg = get_arg(context, id);
2730
+ context.advance_to(visit_format_arg(
2731
+ default_arg_formatter<typename ArgFormatter::iterator, Char>{
2732
+ context.out(), context.args(), context.locale()},
2733
+ arg));
2734
+ }
2735
+
2736
+ const Char* on_format_specs(int id, const Char* begin, const Char* end) {
2737
+ advance_to(parse_context, begin);
2738
+ auto arg = get_arg(context, id);
2739
+ custom_formatter<Context> f(parse_context, context);
2740
+ if (visit_format_arg(f, arg)) return parse_context.begin();
2741
+ basic_format_specs<Char> specs;
2742
+ using parse_context_t = basic_format_parse_context<Char>;
2743
+ specs_checker<specs_handler<parse_context_t, Context>> handler(
2744
+ specs_handler<parse_context_t, Context>(specs, parse_context, context),
2745
+ arg.type());
2746
+ begin = parse_format_specs(begin, end, handler);
2747
+ if (begin == end || *begin != '}') on_error("missing '}' in format string");
2748
+ advance_to(parse_context, begin);
2749
+ context.advance_to(
2750
+ visit_format_arg(ArgFormatter(context, &parse_context, &specs), arg));
2751
+ return begin;
2752
+ }
2753
+ };
2754
+
2755
+ // A parse context with extra argument id checks. It is only used at compile
2756
+ // time because adding checks at runtime would introduce substantial overhead
2757
+ // and would be redundant since argument ids are checked when arguments are
2758
+ // retrieved anyway.
2759
+ template <typename Char, typename ErrorHandler = error_handler>
2760
+ class compile_parse_context
2761
+ : public basic_format_parse_context<Char, ErrorHandler> {
2762
+ private:
2763
+ int num_args_;
2764
+ using base = basic_format_parse_context<Char, ErrorHandler>;
2765
+
2766
+ public:
2767
+ explicit FMT_CONSTEXPR compile_parse_context(
2768
+ basic_string_view<Char> format_str, int num_args = max_value<int>(),
2769
+ ErrorHandler eh = {})
2770
+ : base(format_str, eh), num_args_(num_args) {}
2771
+
2772
+ FMT_CONSTEXPR int next_arg_id() {
2773
+ int id = base::next_arg_id();
2774
+ if (id >= num_args_) this->on_error("argument not found");
2775
+ return id;
2776
+ }
2777
+
2778
+ FMT_CONSTEXPR void check_arg_id(int id) {
2779
+ base::check_arg_id(id);
2780
+ if (id >= num_args_) this->on_error("argument not found");
2781
+ }
2782
+ using base::check_arg_id;
2783
+ };
2784
+
2641
2785
  template <typename Char, typename ErrorHandler, typename... Args>
2642
2786
  class format_string_checker {
2643
2787
  public:
2644
2788
  explicit FMT_CONSTEXPR format_string_checker(
2645
2789
  basic_string_view<Char> format_str, ErrorHandler eh)
2646
- : arg_id_(-1),
2647
- context_(format_str, eh),
2790
+ : context_(format_str, num_args, eh),
2648
2791
  parse_funcs_{&parse_format_specs<Args, parse_context_type>...} {}
2649
2792
 
2650
2793
  FMT_CONSTEXPR void on_text(const Char*, const Char*) {}
2651
2794
 
2652
- FMT_CONSTEXPR void on_arg_id() {
2653
- arg_id_ = context_.next_arg_id();
2654
- check_arg_id();
2655
- }
2656
- FMT_CONSTEXPR void on_arg_id(int id) {
2657
- arg_id_ = id;
2658
- context_.check_arg_id(id);
2659
- check_arg_id();
2660
- }
2661
- FMT_CONSTEXPR void on_arg_id(basic_string_view<Char>) {
2795
+ FMT_CONSTEXPR int on_arg_id() { return context_.next_arg_id(); }
2796
+ FMT_CONSTEXPR int on_arg_id(int id) { return context_.check_arg_id(id), id; }
2797
+ FMT_CONSTEXPR int on_arg_id(basic_string_view<Char>) {
2662
2798
  on_error("compile-time checks don't support named arguments");
2799
+ return 0;
2663
2800
  }
2664
2801
 
2665
- FMT_CONSTEXPR void on_replacement_field(const Char*) {}
2802
+ FMT_CONSTEXPR void on_replacement_field(int, const Char*) {}
2666
2803
 
2667
- FMT_CONSTEXPR const Char* on_format_specs(const Char* begin, const Char*) {
2804
+ FMT_CONSTEXPR const Char* on_format_specs(int id, const Char* begin,
2805
+ const Char*) {
2668
2806
  advance_to(context_, begin);
2669
- return arg_id_ < num_args ? parse_funcs_[arg_id_](context_) : begin;
2807
+ return id < num_args ? parse_funcs_[id](context_) : begin;
2670
2808
  }
2671
2809
 
2672
2810
  FMT_CONSTEXPR void on_error(const char* message) {
@@ -2674,35 +2812,66 @@ class format_string_checker {
2674
2812
  }
2675
2813
 
2676
2814
  private:
2677
- using parse_context_type = basic_format_parse_context<Char, ErrorHandler>;
2815
+ using parse_context_type = compile_parse_context<Char, ErrorHandler>;
2678
2816
  enum { num_args = sizeof...(Args) };
2679
2817
 
2680
- FMT_CONSTEXPR void check_arg_id() {
2681
- if (arg_id_ >= num_args) context_.on_error("argument index out of range");
2682
- }
2683
-
2684
2818
  // Format specifier parsing function.
2685
2819
  using parse_func = const Char* (*)(parse_context_type&);
2686
2820
 
2687
- int arg_id_;
2688
2821
  parse_context_type context_;
2689
2822
  parse_func parse_funcs_[num_args > 0 ? num_args : 1];
2690
2823
  };
2691
2824
 
2692
- template <typename Char, typename ErrorHandler, typename... Args>
2693
- FMT_CONSTEXPR bool do_check_format_string(basic_string_view<Char> s,
2694
- ErrorHandler eh = ErrorHandler()) {
2695
- format_string_checker<Char, ErrorHandler, Args...> checker(s, eh);
2696
- parse_format_string<true>(s, checker);
2697
- return true;
2825
+ // Converts string literals to basic_string_view.
2826
+ template <typename Char, size_t N>
2827
+ FMT_CONSTEXPR basic_string_view<Char> compile_string_to_view(
2828
+ const Char (&s)[N]) {
2829
+ // Remove trailing null character if needed. Won't be present if this is used
2830
+ // with raw character array (i.e. not defined as a string).
2831
+ return {s,
2832
+ N - ((std::char_traits<Char>::to_int_type(s[N - 1]) == 0) ? 1 : 0)};
2833
+ }
2834
+
2835
+ // Converts string_view to basic_string_view.
2836
+ template <typename Char>
2837
+ FMT_CONSTEXPR basic_string_view<Char> compile_string_to_view(
2838
+ const std_string_view<Char>& s) {
2839
+ return {s.data(), s.size()};
2698
2840
  }
2699
2841
 
2842
+ #define FMT_STRING_IMPL(s, base) \
2843
+ [] { \
2844
+ /* Use a macro-like name to avoid shadowing warnings. */ \
2845
+ struct FMT_COMPILE_STRING : base { \
2846
+ using char_type = fmt::remove_cvref_t<decltype(s[0])>; \
2847
+ FMT_MAYBE_UNUSED FMT_CONSTEXPR \
2848
+ operator fmt::basic_string_view<char_type>() const { \
2849
+ return fmt::detail::compile_string_to_view<char_type>(s); \
2850
+ } \
2851
+ }; \
2852
+ return FMT_COMPILE_STRING(); \
2853
+ }()
2854
+
2855
+ /**
2856
+ \rst
2857
+ Constructs a compile-time format string from a string literal *s*.
2858
+
2859
+ **Example**::
2860
+
2861
+ // A compile-time error because 'd' is an invalid specifier for strings.
2862
+ std::string s = fmt::format(FMT_STRING("{:d}"), "foo");
2863
+ \endrst
2864
+ */
2865
+ #define FMT_STRING(s) FMT_STRING_IMPL(s, fmt::compile_string)
2866
+
2700
2867
  template <typename... Args, typename S,
2701
2868
  enable_if_t<(is_compile_string<S>::value), int>>
2702
2869
  void check_format_string(S format_str) {
2703
- FMT_CONSTEXPR_DECL bool invalid_format = internal::do_check_format_string<
2704
- typename S::char_type, internal::error_handler,
2705
- remove_const_t<remove_reference_t<Args>>...>(to_string_view(format_str));
2870
+ FMT_CONSTEXPR_DECL auto s = to_string_view(format_str);
2871
+ using checker = format_string_checker<typename S::char_type, error_handler,
2872
+ remove_cvref_t<Args>...>;
2873
+ FMT_CONSTEXPR_DECL bool invalid_format =
2874
+ (parse_format_string<true>(s, checker(s, {})), true);
2706
2875
  (void)invalid_format;
2707
2876
  }
2708
2877
 
@@ -2713,44 +2882,37 @@ void handle_dynamic_spec(int& value, arg_ref<typename Context::char_type> ref,
2713
2882
  case arg_id_kind::none:
2714
2883
  break;
2715
2884
  case arg_id_kind::index:
2716
- value = internal::get_dynamic_spec<Handler>(ctx.arg(ref.val.index),
2717
- ctx.error_handler());
2885
+ value = detail::get_dynamic_spec<Handler>(ctx.arg(ref.val.index),
2886
+ ctx.error_handler());
2718
2887
  break;
2719
2888
  case arg_id_kind::name:
2720
- value = internal::get_dynamic_spec<Handler>(ctx.arg(ref.val.name),
2721
- ctx.error_handler());
2889
+ value = detail::get_dynamic_spec<Handler>(ctx.arg(ref.val.name),
2890
+ ctx.error_handler());
2722
2891
  break;
2723
2892
  }
2724
2893
  }
2725
2894
 
2726
- using format_func = void (*)(internal::buffer<char>&, int, string_view);
2895
+ using format_func = void (*)(detail::buffer<char>&, int, string_view);
2727
2896
 
2728
2897
  FMT_API void format_error_code(buffer<char>& out, int error_code,
2729
2898
  string_view message) FMT_NOEXCEPT;
2730
2899
 
2731
2900
  FMT_API void report_error(format_func func, int error_code,
2732
2901
  string_view message) FMT_NOEXCEPT;
2733
- } // namespace internal
2734
-
2735
- template <typename Range>
2736
- using basic_writer FMT_DEPRECATED_ALIAS = internal::basic_writer<Range>;
2737
- using writer FMT_DEPRECATED_ALIAS = internal::writer;
2738
- using wwriter FMT_DEPRECATED_ALIAS =
2739
- internal::basic_writer<buffer_range<wchar_t>>;
2740
2902
 
2741
2903
  /** The default argument formatter. */
2742
- template <typename Range>
2743
- class arg_formatter : public internal::arg_formatter_base<Range> {
2904
+ template <typename OutputIt, typename Char>
2905
+ class arg_formatter : public arg_formatter_base<OutputIt, Char> {
2744
2906
  private:
2745
- using char_type = typename Range::value_type;
2746
- using base = internal::arg_formatter_base<Range>;
2747
- using context_type = basic_format_context<typename base::iterator, char_type>;
2907
+ using char_type = Char;
2908
+ using base = arg_formatter_base<OutputIt, Char>;
2909
+ using context_type = basic_format_context<OutputIt, Char>;
2748
2910
 
2749
2911
  context_type& ctx_;
2750
2912
  basic_format_parse_context<char_type>* parse_ctx_;
2913
+ const Char* ptr_;
2751
2914
 
2752
2915
  public:
2753
- using range = Range;
2754
2916
  using iterator = typename base::iterator;
2755
2917
  using format_specs = typename base::format_specs;
2756
2918
 
@@ -2764,19 +2926,26 @@ class arg_formatter : public internal::arg_formatter_base<Range> {
2764
2926
  explicit arg_formatter(
2765
2927
  context_type& ctx,
2766
2928
  basic_format_parse_context<char_type>* parse_ctx = nullptr,
2767
- format_specs* specs = nullptr)
2768
- : base(Range(ctx.out()), specs, ctx.locale()),
2929
+ format_specs* specs = nullptr, const Char* ptr = nullptr)
2930
+ : base(ctx.out(), specs, ctx.locale()),
2769
2931
  ctx_(ctx),
2770
- parse_ctx_(parse_ctx) {}
2932
+ parse_ctx_(parse_ctx),
2933
+ ptr_(ptr) {}
2771
2934
 
2772
2935
  using base::operator();
2773
2936
 
2774
2937
  /** Formats an argument of a user-defined type. */
2775
2938
  iterator operator()(typename basic_format_arg<context_type>::handle handle) {
2939
+ if (ptr_) advance_to(*parse_ctx_, ptr_);
2776
2940
  handle.format(*parse_ctx_, ctx_);
2777
2941
  return ctx_.out();
2778
2942
  }
2779
2943
  };
2944
+ } // namespace detail
2945
+
2946
+ template <typename OutputIt, typename Char>
2947
+ using arg_formatter FMT_DEPRECATED_ALIAS =
2948
+ detail::arg_formatter<OutputIt, Char>;
2780
2949
 
2781
2950
  /**
2782
2951
  An error returned by an operating system or a language runtime,
@@ -2841,7 +3010,7 @@ class FMT_API system_error : public std::runtime_error {
2841
3010
  may look like "Unknown error -1" and is platform-dependent.
2842
3011
  \endrst
2843
3012
  */
2844
- FMT_API void format_system_error(internal::buffer<char>& out, int error_code,
3013
+ FMT_API void format_system_error(detail::buffer<char>& out, int error_code,
2845
3014
  string_view message) FMT_NOEXCEPT;
2846
3015
 
2847
3016
  // Reports a system error without throwing an exception.
@@ -2858,47 +3027,32 @@ class format_int {
2858
3027
  mutable char buffer_[buffer_size];
2859
3028
  char* str_;
2860
3029
 
2861
- // Formats value in reverse and returns a pointer to the beginning.
2862
- char* format_decimal(unsigned long long value) {
2863
- char* ptr = buffer_ + (buffer_size - 1); // Parens to workaround MSVC bug.
2864
- while (value >= 100) {
2865
- // Integer division is slow so do it for a group of two digits instead
2866
- // of for every digit. The idea comes from the talk by Alexandrescu
2867
- // "Three Optimization Tips for C++". See speed-test for a comparison.
2868
- auto index = static_cast<unsigned>((value % 100) * 2);
2869
- value /= 100;
2870
- *--ptr = internal::data::digits[index + 1];
2871
- *--ptr = internal::data::digits[index];
2872
- }
2873
- if (value < 10) {
2874
- *--ptr = static_cast<char>('0' + value);
2875
- return ptr;
2876
- }
2877
- auto index = static_cast<unsigned>(value * 2);
2878
- *--ptr = internal::data::digits[index + 1];
2879
- *--ptr = internal::data::digits[index];
2880
- return ptr;
3030
+ template <typename UInt> char* format_unsigned(UInt value) {
3031
+ auto n = static_cast<detail::uint32_or_64_or_128_t<UInt>>(value);
3032
+ return detail::format_decimal(buffer_, n, buffer_size - 1).begin;
2881
3033
  }
2882
3034
 
2883
- void format_signed(long long value) {
2884
- auto abs_value = static_cast<unsigned long long>(value);
3035
+ template <typename Int> char* format_signed(Int value) {
3036
+ auto abs_value = static_cast<detail::uint32_or_64_or_128_t<Int>>(value);
2885
3037
  bool negative = value < 0;
2886
3038
  if (negative) abs_value = 0 - abs_value;
2887
- str_ = format_decimal(abs_value);
2888
- if (negative) *--str_ = '-';
3039
+ auto begin = format_unsigned(abs_value);
3040
+ if (negative) *--begin = '-';
3041
+ return begin;
2889
3042
  }
2890
3043
 
2891
3044
  public:
2892
- explicit format_int(int value) { format_signed(value); }
2893
- explicit format_int(long value) { format_signed(value); }
2894
- explicit format_int(long long value) { format_signed(value); }
2895
- explicit format_int(unsigned value) : str_(format_decimal(value)) {}
2896
- explicit format_int(unsigned long value) : str_(format_decimal(value)) {}
2897
- explicit format_int(unsigned long long value) : str_(format_decimal(value)) {}
3045
+ explicit format_int(int value) : str_(format_signed(value)) {}
3046
+ explicit format_int(long value) : str_(format_signed(value)) {}
3047
+ explicit format_int(long long value) : str_(format_signed(value)) {}
3048
+ explicit format_int(unsigned value) : str_(format_unsigned(value)) {}
3049
+ explicit format_int(unsigned long value) : str_(format_unsigned(value)) {}
3050
+ explicit format_int(unsigned long long value)
3051
+ : str_(format_unsigned(value)) {}
2898
3052
 
2899
3053
  /** Returns the number of characters written to the output buffer. */
2900
- std::size_t size() const {
2901
- return internal::to_unsigned(buffer_ - str_ + buffer_size - 1);
3054
+ size_t size() const {
3055
+ return detail::to_unsigned(buffer_ - str_ + buffer_size - 1);
2902
3056
  }
2903
3057
 
2904
3058
  /**
@@ -2924,75 +3078,71 @@ class format_int {
2924
3078
  std::string str() const { return std::string(str_, size()); }
2925
3079
  };
2926
3080
 
2927
- // A formatter specialization for the core types corresponding to internal::type
3081
+ // A formatter specialization for the core types corresponding to detail::type
2928
3082
  // constants.
2929
3083
  template <typename T, typename Char>
2930
3084
  struct formatter<T, Char,
2931
- enable_if_t<internal::type_constant<T, Char>::value !=
2932
- internal::type::custom_type>> {
3085
+ enable_if_t<detail::type_constant<T, Char>::value !=
3086
+ detail::type::custom_type>> {
2933
3087
  FMT_CONSTEXPR formatter() = default;
2934
3088
 
2935
3089
  // Parses format specifiers stopping either at the end of the range or at the
2936
3090
  // terminating '}'.
2937
3091
  template <typename ParseContext>
2938
3092
  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
2939
- using handler_type = internal::dynamic_specs_handler<ParseContext>;
2940
- auto type = internal::type_constant<T, Char>::value;
2941
- internal::specs_checker<handler_type> handler(handler_type(specs_, ctx),
2942
- type);
3093
+ using handler_type = detail::dynamic_specs_handler<ParseContext>;
3094
+ auto type = detail::type_constant<T, Char>::value;
3095
+ detail::specs_checker<handler_type> handler(handler_type(specs_, ctx),
3096
+ type);
2943
3097
  auto it = parse_format_specs(ctx.begin(), ctx.end(), handler);
2944
3098
  auto eh = ctx.error_handler();
2945
3099
  switch (type) {
2946
- case internal::type::none_type:
2947
- case internal::type::named_arg_type:
3100
+ case detail::type::none_type:
2948
3101
  FMT_ASSERT(false, "invalid argument type");
2949
3102
  break;
2950
- case internal::type::int_type:
2951
- case internal::type::uint_type:
2952
- case internal::type::long_long_type:
2953
- case internal::type::ulong_long_type:
2954
- case internal::type::int128_type:
2955
- case internal::type::uint128_type:
2956
- case internal::type::bool_type:
3103
+ case detail::type::int_type:
3104
+ case detail::type::uint_type:
3105
+ case detail::type::long_long_type:
3106
+ case detail::type::ulong_long_type:
3107
+ case detail::type::int128_type:
3108
+ case detail::type::uint128_type:
3109
+ case detail::type::bool_type:
2957
3110
  handle_int_type_spec(specs_.type,
2958
- internal::int_type_checker<decltype(eh)>(eh));
3111
+ detail::int_type_checker<decltype(eh)>(eh));
2959
3112
  break;
2960
- case internal::type::char_type:
3113
+ case detail::type::char_type:
2961
3114
  handle_char_specs(
2962
- &specs_, internal::char_specs_checker<decltype(eh)>(specs_.type, eh));
3115
+ &specs_, detail::char_specs_checker<decltype(eh)>(specs_.type, eh));
2963
3116
  break;
2964
- case internal::type::float_type:
2965
- if (internal::const_check(FMT_USE_FLOAT)) {
2966
- internal::parse_float_type_spec(specs_, eh);
2967
- } else {
3117
+ case detail::type::float_type:
3118
+ if (detail::const_check(FMT_USE_FLOAT))
3119
+ detail::parse_float_type_spec(specs_, eh);
3120
+ else
2968
3121
  FMT_ASSERT(false, "float support disabled");
2969
- }
2970
3122
  break;
2971
- case internal::type::double_type:
2972
- if (internal::const_check(FMT_USE_DOUBLE)) {
2973
- internal::parse_float_type_spec(specs_, eh);
2974
- } else {
3123
+ case detail::type::double_type:
3124
+ if (detail::const_check(FMT_USE_DOUBLE))
3125
+ detail::parse_float_type_spec(specs_, eh);
3126
+ else
2975
3127
  FMT_ASSERT(false, "double support disabled");
2976
- }
2977
3128
  break;
2978
- case internal::type::long_double_type:
2979
- if (internal::const_check(FMT_USE_LONG_DOUBLE)) {
2980
- internal::parse_float_type_spec(specs_, eh);
2981
- } else {
3129
+ case detail::type::long_double_type:
3130
+ if (detail::const_check(FMT_USE_LONG_DOUBLE))
3131
+ detail::parse_float_type_spec(specs_, eh);
3132
+ else
2982
3133
  FMT_ASSERT(false, "long double support disabled");
2983
- }
2984
3134
  break;
2985
- case internal::type::cstring_type:
2986
- internal::handle_cstring_type_spec(
2987
- specs_.type, internal::cstring_type_checker<decltype(eh)>(eh));
3135
+ case detail::type::cstring_type:
3136
+ detail::handle_cstring_type_spec(
3137
+ specs_.type, detail::cstring_type_checker<decltype(eh)>(eh));
2988
3138
  break;
2989
- case internal::type::string_type:
2990
- internal::check_string_type_spec(specs_.type, eh);
3139
+ case detail::type::string_type:
3140
+ detail::check_string_type_spec(specs_.type, eh);
2991
3141
  break;
2992
- case internal::type::pointer_type:
2993
- internal::check_pointer_type_spec(specs_.type, eh);
3142
+ case detail::type::pointer_type:
3143
+ detail::check_pointer_type_spec(specs_.type, eh);
2994
3144
  break;
2995
- case internal::type::custom_type:
3145
+ case detail::type::custom_type:
2996
3146
  // Custom format specifiers should be checked in parse functions of
2997
3147
  // formatter specializations.
2998
3148
  break;
@@ -3002,19 +3152,18 @@ struct formatter<T, Char,
3002
3152
 
3003
3153
  template <typename FormatContext>
3004
3154
  auto format(const T& val, FormatContext& ctx) -> decltype(ctx.out()) {
3005
- internal::handle_dynamic_spec<internal::width_checker>(
3006
- specs_.width, specs_.width_ref, ctx);
3007
- internal::handle_dynamic_spec<internal::precision_checker>(
3155
+ detail::handle_dynamic_spec<detail::width_checker>(specs_.width,
3156
+ specs_.width_ref, ctx);
3157
+ detail::handle_dynamic_spec<detail::precision_checker>(
3008
3158
  specs_.precision, specs_.precision_ref, ctx);
3009
- using range_type =
3010
- internal::output_range<typename FormatContext::iterator,
3011
- typename FormatContext::char_type>;
3012
- return visit_format_arg(arg_formatter<range_type>(ctx, nullptr, &specs_),
3013
- internal::make_arg<FormatContext>(val));
3159
+ using af = detail::arg_formatter<typename FormatContext::iterator,
3160
+ typename FormatContext::char_type>;
3161
+ return visit_format_arg(af(ctx, nullptr, &specs_),
3162
+ detail::make_arg<FormatContext>(val));
3014
3163
  }
3015
3164
 
3016
3165
  private:
3017
- internal::dynamic_format_specs<Char> specs_;
3166
+ detail::dynamic_format_specs<Char> specs_;
3018
3167
  };
3019
3168
 
3020
3169
  #define FMT_FORMAT_AS(Type, Base) \
@@ -3035,7 +3184,7 @@ FMT_FORMAT_AS(unsigned long, unsigned long long);
3035
3184
  FMT_FORMAT_AS(Char*, const Char*);
3036
3185
  FMT_FORMAT_AS(std::basic_string<Char>, basic_string_view<Char>);
3037
3186
  FMT_FORMAT_AS(std::nullptr_t, const void*);
3038
- FMT_FORMAT_AS(internal::std_string_view<Char>, basic_string_view<Char>);
3187
+ FMT_FORMAT_AS(detail::std_string_view<Char>, basic_string_view<Char>);
3039
3188
 
3040
3189
  template <typename Char>
3041
3190
  struct formatter<void*, Char> : formatter<const void*, Char> {
@@ -3065,7 +3214,7 @@ struct formatter<Char[N], Char> : formatter<basic_string_view<Char>, Char> {
3065
3214
  // };
3066
3215
  template <typename Char = char> class dynamic_formatter {
3067
3216
  private:
3068
- struct null_handler : internal::error_handler {
3217
+ struct null_handler : detail::error_handler {
3069
3218
  void on_align(align_t) {}
3070
3219
  void on_plus() {}
3071
3220
  void on_minus() {}
@@ -3078,16 +3227,15 @@ template <typename Char = char> class dynamic_formatter {
3078
3227
  auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
3079
3228
  format_str_ = ctx.begin();
3080
3229
  // Checks are deferred to formatting time when the argument type is known.
3081
- internal::dynamic_specs_handler<ParseContext> handler(specs_, ctx);
3230
+ detail::dynamic_specs_handler<ParseContext> handler(specs_, ctx);
3082
3231
  return parse_format_specs(ctx.begin(), ctx.end(), handler);
3083
3232
  }
3084
3233
 
3085
3234
  template <typename T, typename FormatContext>
3086
3235
  auto format(const T& val, FormatContext& ctx) -> decltype(ctx.out()) {
3087
3236
  handle_specs(ctx);
3088
- internal::specs_checker<null_handler> checker(
3089
- null_handler(),
3090
- internal::mapped_type_constant<T, FormatContext>::value);
3237
+ detail::specs_checker<null_handler> checker(
3238
+ null_handler(), detail::mapped_type_constant<T, FormatContext>::value);
3091
3239
  checker.on_align(specs_.align);
3092
3240
  switch (specs_.sign) {
3093
3241
  case sign::none:
@@ -3104,104 +3252,47 @@ template <typename Char = char> class dynamic_formatter {
3104
3252
  }
3105
3253
  if (specs_.alt) checker.on_hash();
3106
3254
  if (specs_.precision >= 0) checker.end_precision();
3107
- using range = internal::output_range<typename FormatContext::iterator,
3108
- typename FormatContext::char_type>;
3109
- visit_format_arg(arg_formatter<range>(ctx, nullptr, &specs_),
3110
- internal::make_arg<FormatContext>(val));
3255
+ using af = detail::arg_formatter<typename FormatContext::iterator,
3256
+ typename FormatContext::char_type>;
3257
+ visit_format_arg(af(ctx, nullptr, &specs_),
3258
+ detail::make_arg<FormatContext>(val));
3111
3259
  return ctx.out();
3112
3260
  }
3113
3261
 
3114
3262
  private:
3115
3263
  template <typename Context> void handle_specs(Context& ctx) {
3116
- internal::handle_dynamic_spec<internal::width_checker>(
3117
- specs_.width, specs_.width_ref, ctx);
3118
- internal::handle_dynamic_spec<internal::precision_checker>(
3264
+ detail::handle_dynamic_spec<detail::width_checker>(specs_.width,
3265
+ specs_.width_ref, ctx);
3266
+ detail::handle_dynamic_spec<detail::precision_checker>(
3119
3267
  specs_.precision, specs_.precision_ref, ctx);
3120
3268
  }
3121
3269
 
3122
- internal::dynamic_format_specs<Char> specs_;
3270
+ detail::dynamic_format_specs<Char> specs_;
3123
3271
  const Char* format_str_;
3124
3272
  };
3125
3273
 
3126
- template <typename Range, typename Char>
3127
- typename basic_format_context<Range, Char>::format_arg
3128
- basic_format_context<Range, Char>::arg(basic_string_view<char_type> name) {
3129
- map_.init(args_);
3130
- format_arg arg = map_.find(name);
3131
- if (arg.type() == internal::type::none_type)
3132
- this->on_error("argument not found");
3133
- return arg;
3134
- }
3135
-
3136
3274
  template <typename Char, typename ErrorHandler>
3137
3275
  FMT_CONSTEXPR void advance_to(
3138
3276
  basic_format_parse_context<Char, ErrorHandler>& ctx, const Char* p) {
3139
3277
  ctx.advance_to(ctx.begin() + (p - &*ctx.begin()));
3140
3278
  }
3141
3279
 
3142
- template <typename ArgFormatter, typename Char, typename Context>
3143
- struct format_handler : internal::error_handler {
3144
- using range = typename ArgFormatter::range;
3145
-
3146
- format_handler(range r, basic_string_view<Char> str,
3147
- basic_format_args<Context> format_args,
3148
- internal::locale_ref loc)
3149
- : parse_context(str), context(r.begin(), format_args, loc) {}
3150
-
3151
- void on_text(const Char* begin, const Char* end) {
3152
- auto size = internal::to_unsigned(end - begin);
3153
- auto out = context.out();
3154
- auto&& it = internal::reserve(out, size);
3155
- it = std::copy_n(begin, size, it);
3156
- context.advance_to(out);
3157
- }
3158
-
3159
- void get_arg(int id) { arg = internal::get_arg(context, id); }
3160
-
3161
- void on_arg_id() { get_arg(parse_context.next_arg_id()); }
3162
- void on_arg_id(int id) {
3163
- parse_context.check_arg_id(id);
3164
- get_arg(id);
3165
- }
3166
- void on_arg_id(basic_string_view<Char> id) { arg = context.arg(id); }
3167
-
3168
- void on_replacement_field(const Char* p) {
3169
- advance_to(parse_context, p);
3170
- context.advance_to(
3171
- visit_format_arg(ArgFormatter(context, &parse_context), arg));
3172
- }
3173
-
3174
- const Char* on_format_specs(const Char* begin, const Char* end) {
3175
- advance_to(parse_context, begin);
3176
- internal::custom_formatter<Context> f(parse_context, context);
3177
- if (visit_format_arg(f, arg)) return parse_context.begin();
3178
- basic_format_specs<Char> specs;
3179
- using internal::specs_handler;
3180
- using parse_context_t = basic_format_parse_context<Char>;
3181
- internal::specs_checker<specs_handler<parse_context_t, Context>> handler(
3182
- specs_handler<parse_context_t, Context>(specs, parse_context, context),
3183
- arg.type());
3184
- begin = parse_format_specs(begin, end, handler);
3185
- if (begin == end || *begin != '}') on_error("missing '}' in format string");
3186
- advance_to(parse_context, begin);
3187
- context.advance_to(
3188
- visit_format_arg(ArgFormatter(context, &parse_context, &specs), arg));
3189
- return begin;
3190
- }
3191
-
3192
- basic_format_parse_context<Char> parse_context;
3193
- Context context;
3194
- basic_format_arg<Context> arg;
3195
- };
3196
-
3197
3280
  /** Formats arguments and writes the output to the range. */
3198
3281
  template <typename ArgFormatter, typename Char, typename Context>
3199
3282
  typename Context::iterator vformat_to(
3200
- typename ArgFormatter::range out, basic_string_view<Char> format_str,
3283
+ typename ArgFormatter::iterator out, basic_string_view<Char> format_str,
3201
3284
  basic_format_args<Context> args,
3202
- internal::locale_ref loc = internal::locale_ref()) {
3203
- format_handler<ArgFormatter, Char, Context> h(out, format_str, args, loc);
3204
- internal::parse_format_string<false>(format_str, h);
3285
+ detail::locale_ref loc = detail::locale_ref()) {
3286
+ if (format_str.size() == 2 && detail::equal2(format_str.data(), "{}")) {
3287
+ auto arg = args.get(0);
3288
+ if (!arg) detail::error_handler().on_error("argument not found");
3289
+ using iterator = typename ArgFormatter::iterator;
3290
+ return visit_format_arg(
3291
+ detail::default_arg_formatter<iterator, Char>{out, args, loc}, arg);
3292
+ }
3293
+ detail::format_handler<ArgFormatter, Char, Context> h(out, format_str, args,
3294
+ loc);
3295
+ detail::parse_format_string<false>(format_str, h);
3205
3296
  return h.context.out();
3206
3297
  }
3207
3298
 
@@ -3228,44 +3319,42 @@ class bytes {
3228
3319
  template <> struct formatter<bytes> {
3229
3320
  template <typename ParseContext>
3230
3321
  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
3231
- using handler_type = internal::dynamic_specs_handler<ParseContext>;
3232
- internal::specs_checker<handler_type> handler(handler_type(specs_, ctx),
3233
- internal::type::string_type);
3322
+ using handler_type = detail::dynamic_specs_handler<ParseContext>;
3323
+ detail::specs_checker<handler_type> handler(handler_type(specs_, ctx),
3324
+ detail::type::string_type);
3234
3325
  auto it = parse_format_specs(ctx.begin(), ctx.end(), handler);
3235
- internal::check_string_type_spec(specs_.type, ctx.error_handler());
3326
+ detail::check_string_type_spec(specs_.type, ctx.error_handler());
3236
3327
  return it;
3237
3328
  }
3238
3329
 
3239
3330
  template <typename FormatContext>
3240
3331
  auto format(bytes b, FormatContext& ctx) -> decltype(ctx.out()) {
3241
- internal::handle_dynamic_spec<internal::width_checker>(
3242
- specs_.width, specs_.width_ref, ctx);
3243
- internal::handle_dynamic_spec<internal::precision_checker>(
3332
+ detail::handle_dynamic_spec<detail::width_checker>(specs_.width,
3333
+ specs_.width_ref, ctx);
3334
+ detail::handle_dynamic_spec<detail::precision_checker>(
3244
3335
  specs_.precision, specs_.precision_ref, ctx);
3245
- using range_type =
3246
- internal::output_range<typename FormatContext::iterator, char>;
3247
- internal::basic_writer<range_type> writer(range_type(ctx.out()));
3248
- writer.write_bytes(b.data_, specs_);
3249
- return writer.out();
3336
+ return detail::write_bytes(ctx.out(), b.data_, specs_);
3250
3337
  }
3251
3338
 
3252
3339
  private:
3253
- internal::dynamic_format_specs<char> specs_;
3340
+ detail::dynamic_format_specs<char> specs_;
3254
3341
  };
3255
3342
 
3256
- template <typename It, typename Char> struct arg_join : internal::view {
3343
+ template <typename It, typename Sentinel, typename Char>
3344
+ struct arg_join : detail::view {
3257
3345
  It begin;
3258
- It end;
3346
+ Sentinel end;
3259
3347
  basic_string_view<Char> sep;
3260
3348
 
3261
- arg_join(It b, It e, basic_string_view<Char> s) : begin(b), end(e), sep(s) {}
3349
+ arg_join(It b, Sentinel e, basic_string_view<Char> s)
3350
+ : begin(b), end(e), sep(s) {}
3262
3351
  };
3263
3352
 
3264
- template <typename It, typename Char>
3265
- struct formatter<arg_join<It, Char>, Char>
3353
+ template <typename It, typename Sentinel, typename Char>
3354
+ struct formatter<arg_join<It, Sentinel, Char>, Char>
3266
3355
  : formatter<typename std::iterator_traits<It>::value_type, Char> {
3267
3356
  template <typename FormatContext>
3268
- auto format(const arg_join<It, Char>& value, FormatContext& ctx)
3357
+ auto format(const arg_join<It, Sentinel, Char>& value, FormatContext& ctx)
3269
3358
  -> decltype(ctx.out()) {
3270
3359
  using base = formatter<typename std::iterator_traits<It>::value_type, Char>;
3271
3360
  auto it = value.begin;
@@ -3286,13 +3375,13 @@ struct formatter<arg_join<It, Char>, Char>
3286
3375
  Returns an object that formats the iterator range `[begin, end)` with elements
3287
3376
  separated by `sep`.
3288
3377
  */
3289
- template <typename It>
3290
- arg_join<It, char> join(It begin, It end, string_view sep) {
3378
+ template <typename It, typename Sentinel>
3379
+ arg_join<It, Sentinel, char> join(It begin, Sentinel end, string_view sep) {
3291
3380
  return {begin, end, sep};
3292
3381
  }
3293
3382
 
3294
- template <typename It>
3295
- arg_join<It, wchar_t> join(It begin, It end, wstring_view sep) {
3383
+ template <typename It, typename Sentinel>
3384
+ arg_join<It, Sentinel, wchar_t> join(It begin, Sentinel end, wstring_view sep) {
3296
3385
  return {begin, end, sep};
3297
3386
  }
3298
3387
 
@@ -3313,14 +3402,15 @@ arg_join<It, wchar_t> join(It begin, It end, wstring_view sep) {
3313
3402
  \endrst
3314
3403
  */
3315
3404
  template <typename Range>
3316
- arg_join<internal::iterator_t<const Range>, char> join(const Range& range,
3317
- string_view sep) {
3405
+ arg_join<detail::iterator_t<const Range>, detail::sentinel_t<const Range>, char>
3406
+ join(const Range& range, string_view sep) {
3318
3407
  return join(std::begin(range), std::end(range), sep);
3319
3408
  }
3320
3409
 
3321
3410
  template <typename Range>
3322
- arg_join<internal::iterator_t<const Range>, wchar_t> join(const Range& range,
3323
- wstring_view sep) {
3411
+ arg_join<detail::iterator_t<const Range>, detail::sentinel_t<const Range>,
3412
+ wchar_t>
3413
+ join(const Range& range, wstring_view sep) {
3324
3414
  return join(std::begin(range), std::end(range), sep);
3325
3415
  }
3326
3416
 
@@ -3335,8 +3425,21 @@ arg_join<internal::iterator_t<const Range>, wchar_t> join(const Range& range,
3335
3425
  std::string answer = fmt::to_string(42);
3336
3426
  \endrst
3337
3427
  */
3338
- template <typename T> inline std::string to_string(const T& value) {
3339
- return format("{}", value);
3428
+ template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)>
3429
+ inline std::string to_string(const T& value) {
3430
+ std::string result;
3431
+ detail::write<char>(std::back_inserter(result), value);
3432
+ return result;
3433
+ }
3434
+
3435
+ template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
3436
+ inline std::string to_string(T value) {
3437
+ // The buffer should be large enough to store the number including the sign or
3438
+ // "false" for bool.
3439
+ constexpr int max_size = detail::digits10<T>() + 2;
3440
+ char buffer[max_size > 5 ? max_size : 5];
3441
+ char* begin = buffer;
3442
+ return std::string(begin, detail::write<char>(begin, value));
3340
3443
  }
3341
3444
 
3342
3445
  /**
@@ -3346,36 +3449,65 @@ template <typename T> inline std::wstring to_wstring(const T& value) {
3346
3449
  return format(L"{}", value);
3347
3450
  }
3348
3451
 
3349
- template <typename Char, std::size_t SIZE>
3452
+ template <typename Char, size_t SIZE>
3350
3453
  std::basic_string<Char> to_string(const basic_memory_buffer<Char, SIZE>& buf) {
3351
- return std::basic_string<Char>(buf.data(), buf.size());
3454
+ auto size = buf.size();
3455
+ detail::assume(size < std::basic_string<Char>().max_size());
3456
+ return std::basic_string<Char>(buf.data(), size);
3352
3457
  }
3353
3458
 
3354
3459
  template <typename Char>
3355
- typename buffer_context<Char>::iterator internal::vformat_to(
3356
- internal::buffer<Char>& buf, basic_string_view<Char> format_str,
3460
+ typename buffer_context<Char>::iterator detail::vformat_to(
3461
+ detail::buffer<Char>& buf, basic_string_view<Char> format_str,
3357
3462
  basic_format_args<buffer_context<type_identity_t<Char>>> args) {
3358
- using range = buffer_range<Char>;
3359
- return vformat_to<arg_formatter<range>>(buf, to_string_view(format_str),
3360
- args);
3361
- }
3463
+ using af = arg_formatter<typename buffer_context<Char>::iterator, Char>;
3464
+ return vformat_to<af>(std::back_inserter(buf), to_string_view(format_str),
3465
+ args);
3466
+ }
3467
+
3468
+ #ifndef FMT_HEADER_ONLY
3469
+ extern template format_context::iterator detail::vformat_to(
3470
+ detail::buffer<char>&, string_view, basic_format_args<format_context>);
3471
+ namespace detail {
3472
+ extern template FMT_API std::string grouping_impl<char>(locale_ref loc);
3473
+ extern template FMT_API std::string grouping_impl<wchar_t>(locale_ref loc);
3474
+ extern template FMT_API char thousands_sep_impl<char>(locale_ref loc);
3475
+ extern template FMT_API wchar_t thousands_sep_impl<wchar_t>(locale_ref loc);
3476
+ extern template FMT_API char decimal_point_impl(locale_ref loc);
3477
+ extern template FMT_API wchar_t decimal_point_impl(locale_ref loc);
3478
+ extern template int format_float<double>(double value, int precision,
3479
+ float_specs specs, buffer<char>& buf);
3480
+ extern template int format_float<long double>(long double value, int precision,
3481
+ float_specs specs,
3482
+ buffer<char>& buf);
3483
+ int snprintf_float(float value, int precision, float_specs specs,
3484
+ buffer<char>& buf) = delete;
3485
+ extern template int snprintf_float<double>(double value, int precision,
3486
+ float_specs specs,
3487
+ buffer<char>& buf);
3488
+ extern template int snprintf_float<long double>(long double value,
3489
+ int precision,
3490
+ float_specs specs,
3491
+ buffer<char>& buf);
3492
+ } // namespace detail
3493
+ #endif
3362
3494
 
3363
3495
  template <typename S, typename Char = char_t<S>,
3364
- FMT_ENABLE_IF(internal::is_string<S>::value)>
3365
- inline typename buffer_context<Char>::iterator vformat_to(
3366
- internal::buffer<Char>& buf, const S& format_str,
3367
- basic_format_args<buffer_context<type_identity_t<Char>>> args) {
3368
- return internal::vformat_to(buf, to_string_view(format_str), args);
3496
+ FMT_ENABLE_IF(detail::is_string<S>::value)>
3497
+ inline typename FMT_BUFFER_CONTEXT(Char)::iterator vformat_to(
3498
+ detail::buffer<Char>& buf, const S& format_str,
3499
+ basic_format_args<FMT_BUFFER_CONTEXT(type_identity_t<Char>)> args) {
3500
+ return detail::vformat_to(buf, to_string_view(format_str), args);
3369
3501
  }
3370
3502
 
3371
- template <typename S, typename... Args, std::size_t SIZE = inline_buffer_size,
3372
- typename Char = enable_if_t<internal::is_string<S>::value, char_t<S>>>
3503
+ template <typename S, typename... Args, size_t SIZE = inline_buffer_size,
3504
+ typename Char = enable_if_t<detail::is_string<S>::value, char_t<S>>>
3373
3505
  inline typename buffer_context<Char>::iterator format_to(
3374
3506
  basic_memory_buffer<Char, SIZE>& buf, const S& format_str, Args&&... args) {
3375
- internal::check_format_string<Args...>(format_str);
3507
+ detail::check_format_string<Args...>(format_str);
3376
3508
  using context = buffer_context<Char>;
3377
- return internal::vformat_to(buf, to_string_view(format_str),
3378
- make_format_args<context>(args...));
3509
+ return detail::vformat_to(buf, to_string_view(format_str),
3510
+ make_format_args<context>(args...));
3379
3511
  }
3380
3512
 
3381
3513
  template <typename OutputIt, typename Char = char>
@@ -3384,16 +3516,15 @@ using format_context_t = basic_format_context<OutputIt, Char>;
3384
3516
  template <typename OutputIt, typename Char = char>
3385
3517
  using format_args_t = basic_format_args<format_context_t<OutputIt, Char>>;
3386
3518
 
3387
- template <typename S, typename OutputIt, typename... Args,
3388
- FMT_ENABLE_IF(
3389
- internal::is_output_iterator<OutputIt>::value &&
3390
- !internal::is_contiguous_back_insert_iterator<OutputIt>::value)>
3519
+ template <
3520
+ typename S, typename OutputIt, typename... Args,
3521
+ FMT_ENABLE_IF(detail::is_output_iterator<OutputIt>::value &&
3522
+ !detail::is_contiguous_back_insert_iterator<OutputIt>::value)>
3391
3523
  inline OutputIt vformat_to(
3392
3524
  OutputIt out, const S& format_str,
3393
3525
  format_args_t<type_identity_t<OutputIt>, char_t<S>> args) {
3394
- using range = internal::output_range<OutputIt, char_t<S>>;
3395
- return vformat_to<arg_formatter<range>>(range(out),
3396
- to_string_view(format_str), args);
3526
+ using af = detail::arg_formatter<OutputIt, char_t<S>>;
3527
+ return vformat_to<af>(out, to_string_view(format_str), args);
3397
3528
  }
3398
3529
 
3399
3530
  /**
@@ -3409,11 +3540,11 @@ inline OutputIt vformat_to(
3409
3540
  */
3410
3541
  template <typename OutputIt, typename S, typename... Args,
3411
3542
  FMT_ENABLE_IF(
3412
- internal::is_output_iterator<OutputIt>::value &&
3413
- !internal::is_contiguous_back_insert_iterator<OutputIt>::value &&
3414
- internal::is_string<S>::value)>
3543
+ detail::is_output_iterator<OutputIt>::value &&
3544
+ !detail::is_contiguous_back_insert_iterator<OutputIt>::value &&
3545
+ detail::is_string<S>::value)>
3415
3546
  inline OutputIt format_to(OutputIt out, const S& format_str, Args&&... args) {
3416
- internal::check_format_string<Args...>(format_str);
3547
+ detail::check_format_string<Args...>(format_str);
3417
3548
  using context = format_context_t<OutputIt, char_t<S>>;
3418
3549
  return vformat_to(out, to_string_view(format_str),
3419
3550
  make_format_args<context>(args...));
@@ -3423,12 +3554,12 @@ template <typename OutputIt> struct format_to_n_result {
3423
3554
  /** Iterator past the end of the output range. */
3424
3555
  OutputIt out;
3425
3556
  /** Total (not truncated) output size. */
3426
- std::size_t size;
3557
+ size_t size;
3427
3558
  };
3428
3559
 
3429
3560
  template <typename OutputIt, typename Char = typename OutputIt::value_type>
3430
3561
  using format_to_n_context =
3431
- format_context_t<internal::truncating_iterator<OutputIt>, Char>;
3562
+ format_context_t<detail::truncating_iterator<OutputIt>, Char>;
3432
3563
 
3433
3564
  template <typename OutputIt, typename Char = typename OutputIt::value_type>
3434
3565
  using format_to_n_args = basic_format_args<format_to_n_context<OutputIt, Char>>;
@@ -3441,11 +3572,11 @@ make_format_to_n_args(const Args&... args) {
3441
3572
  }
3442
3573
 
3443
3574
  template <typename OutputIt, typename Char, typename... Args,
3444
- FMT_ENABLE_IF(internal::is_output_iterator<OutputIt>::value)>
3575
+ FMT_ENABLE_IF(detail::is_output_iterator<OutputIt>::value)>
3445
3576
  inline format_to_n_result<OutputIt> vformat_to_n(
3446
- OutputIt out, std::size_t n, basic_string_view<Char> format_str,
3577
+ OutputIt out, size_t n, basic_string_view<Char> format_str,
3447
3578
  format_to_n_args<type_identity_t<OutputIt>, type_identity_t<Char>> args) {
3448
- auto it = vformat_to(internal::truncating_iterator<OutputIt>(out, n),
3579
+ auto it = vformat_to(detail::truncating_iterator<OutputIt>(out, n),
3449
3580
  format_str, args);
3450
3581
  return {it.base(), it.count()};
3451
3582
  }
@@ -3458,23 +3589,23 @@ inline format_to_n_result<OutputIt> vformat_to_n(
3458
3589
  \endrst
3459
3590
  */
3460
3591
  template <typename OutputIt, typename S, typename... Args,
3461
- FMT_ENABLE_IF(internal::is_string<S>::value&&
3462
- internal::is_output_iterator<OutputIt>::value)>
3463
- inline format_to_n_result<OutputIt> format_to_n(OutputIt out, std::size_t n,
3592
+ FMT_ENABLE_IF(detail::is_string<S>::value&&
3593
+ detail::is_output_iterator<OutputIt>::value)>
3594
+ inline format_to_n_result<OutputIt> format_to_n(OutputIt out, size_t n,
3464
3595
  const S& format_str,
3465
3596
  const Args&... args) {
3466
- internal::check_format_string<Args...>(format_str);
3597
+ detail::check_format_string<Args...>(format_str);
3467
3598
  using context = format_to_n_context<OutputIt, char_t<S>>;
3468
3599
  return vformat_to_n(out, n, to_string_view(format_str),
3469
3600
  make_format_args<context>(args...));
3470
3601
  }
3471
3602
 
3472
- template <typename Char>
3473
- inline std::basic_string<Char> internal::vformat(
3603
+ template <typename Char, enable_if_t<(!std::is_same<Char, char>::value), int>>
3604
+ std::basic_string<Char> detail::vformat(
3474
3605
  basic_string_view<Char> format_str,
3475
3606
  basic_format_args<buffer_context<type_identity_t<Char>>> args) {
3476
3607
  basic_memory_buffer<Char> buffer;
3477
- internal::vformat_to(buffer, format_str, args);
3608
+ detail::vformat_to(buffer, format_str, args);
3478
3609
  return to_string(buffer);
3479
3610
  }
3480
3611
 
@@ -3483,15 +3614,15 @@ inline std::basic_string<Char> internal::vformat(
3483
3614
  ``format(format_str, args...)``.
3484
3615
  */
3485
3616
  template <typename... Args>
3486
- inline std::size_t formatted_size(string_view format_str, const Args&... args) {
3487
- return format_to(internal::counting_iterator(), format_str, args...).count();
3617
+ inline size_t formatted_size(string_view format_str, const Args&... args) {
3618
+ return format_to(detail::counting_iterator(), format_str, args...).count();
3488
3619
  }
3489
3620
 
3490
3621
  template <typename Char, FMT_ENABLE_IF(std::is_same<Char, wchar_t>::value)>
3491
3622
  void vprint(std::FILE* f, basic_string_view<Char> format_str,
3492
3623
  wformat_args args) {
3493
3624
  wmemory_buffer buffer;
3494
- internal::vformat_to(buffer, format_str, args);
3625
+ detail::vformat_to(buffer, format_str, args);
3495
3626
  buffer.push_back(L'\0');
3496
3627
  if (std::fputws(buffer.data(), f) == -1)
3497
3628
  FMT_THROW(system_error(errno, "cannot write to file"));
@@ -3503,18 +3634,15 @@ void vprint(basic_string_view<Char> format_str, wformat_args args) {
3503
3634
  }
3504
3635
 
3505
3636
  #if FMT_USE_USER_DEFINED_LITERALS
3506
- namespace internal {
3637
+ namespace detail {
3507
3638
 
3508
3639
  # if FMT_USE_UDL_TEMPLATE
3509
3640
  template <typename Char, Char... CHARS> class udl_formatter {
3510
3641
  public:
3511
3642
  template <typename... Args>
3512
3643
  std::basic_string<Char> operator()(Args&&... args) const {
3513
- FMT_CONSTEXPR_DECL Char s[] = {CHARS..., '\0'};
3514
- FMT_CONSTEXPR_DECL bool invalid_format =
3515
- do_check_format_string<Char, error_handler, remove_cvref_t<Args>...>(
3516
- basic_string_view<Char>(s, sizeof...(CHARS)));
3517
- (void)invalid_format;
3644
+ static FMT_CONSTEXPR_DECL Char s[] = {CHARS..., '\0'};
3645
+ check_format_string<remove_cvref_t<Args>...>(FMT_STRING(s));
3518
3646
  return format(s, std::forward<Args>(args)...);
3519
3647
  }
3520
3648
  };
@@ -3530,39 +3658,23 @@ template <typename Char> struct udl_formatter {
3530
3658
  # endif // FMT_USE_UDL_TEMPLATE
3531
3659
 
3532
3660
  template <typename Char> struct udl_arg {
3533
- basic_string_view<Char> str;
3661
+ const Char* str;
3534
3662
 
3535
- template <typename T> named_arg<T, Char> operator=(T&& value) const {
3663
+ template <typename T> named_arg<Char, T> operator=(T&& value) const {
3536
3664
  return {str, std::forward<T>(value)};
3537
3665
  }
3538
3666
  };
3539
-
3540
- // Converts string literals to basic_string_view.
3541
- template <typename Char, size_t N>
3542
- FMT_CONSTEXPR basic_string_view<Char> compile_string_to_view(
3543
- const Char (&s)[N]) {
3544
- // Remove trailing null character if needed. Won't be present if this is used
3545
- // with raw character array (i.e. not defined as a string).
3546
- return {s,
3547
- N - ((std::char_traits<Char>::to_int_type(s[N - 1]) == 0) ? 1 : 0)};
3548
- }
3549
-
3550
- // Converts string_view to basic_string_view.
3551
- template <typename Char>
3552
- FMT_CONSTEXPR basic_string_view<Char> compile_string_to_view(
3553
- const std_string_view<Char>& s) {
3554
- return {s.data(), s.size()};
3555
- }
3556
- } // namespace internal
3667
+ } // namespace detail
3557
3668
 
3558
3669
  inline namespace literals {
3559
3670
  # if FMT_USE_UDL_TEMPLATE
3560
3671
  # pragma GCC diagnostic push
3672
+ # pragma GCC diagnostic ignored "-Wpedantic"
3561
3673
  # if FMT_CLANG_VERSION
3562
3674
  # pragma GCC diagnostic ignored "-Wgnu-string-literal-operator-template"
3563
3675
  # endif
3564
3676
  template <typename Char, Char... CHARS>
3565
- FMT_CONSTEXPR internal::udl_formatter<Char, CHARS...> operator""_format() {
3677
+ FMT_CONSTEXPR detail::udl_formatter<Char, CHARS...> operator""_format() {
3566
3678
  return {};
3567
3679
  }
3568
3680
  # pragma GCC diagnostic pop
@@ -3577,12 +3689,12 @@ FMT_CONSTEXPR internal::udl_formatter<Char, CHARS...> operator""_format() {
3577
3689
  std::string message = "The answer is {}"_format(42);
3578
3690
  \endrst
3579
3691
  */
3580
- FMT_CONSTEXPR internal::udl_formatter<char> operator"" _format(const char* s,
3581
- std::size_t n) {
3692
+ FMT_CONSTEXPR detail::udl_formatter<char> operator"" _format(const char* s,
3693
+ size_t n) {
3582
3694
  return {{s, n}};
3583
3695
  }
3584
- FMT_CONSTEXPR internal::udl_formatter<wchar_t> operator"" _format(
3585
- const wchar_t* s, std::size_t n) {
3696
+ FMT_CONSTEXPR detail::udl_formatter<wchar_t> operator"" _format(
3697
+ const wchar_t* s, size_t n) {
3586
3698
  return {{s, n}};
3587
3699
  }
3588
3700
  # endif // FMT_USE_UDL_TEMPLATE
@@ -3597,47 +3709,16 @@ FMT_CONSTEXPR internal::udl_formatter<wchar_t> operator"" _format(
3597
3709
  fmt::print("Elapsed time: {s:.2f} seconds", "s"_a=1.23);
3598
3710
  \endrst
3599
3711
  */
3600
- FMT_CONSTEXPR internal::udl_arg<char> operator"" _a(const char* s,
3601
- std::size_t n) {
3602
- return {{s, n}};
3712
+ FMT_CONSTEXPR detail::udl_arg<char> operator"" _a(const char* s, size_t) {
3713
+ return {s};
3603
3714
  }
3604
- FMT_CONSTEXPR internal::udl_arg<wchar_t> operator"" _a(const wchar_t* s,
3605
- std::size_t n) {
3606
- return {{s, n}};
3715
+ FMT_CONSTEXPR detail::udl_arg<wchar_t> operator"" _a(const wchar_t* s, size_t) {
3716
+ return {s};
3607
3717
  }
3608
3718
  } // namespace literals
3609
3719
  #endif // FMT_USE_USER_DEFINED_LITERALS
3610
3720
  FMT_END_NAMESPACE
3611
3721
 
3612
- #define FMT_STRING_IMPL(s, ...) \
3613
- [] { \
3614
- /* Use a macro-like name to avoid shadowing warnings. */ \
3615
- struct FMT_COMPILE_STRING : fmt::compile_string { \
3616
- using char_type = fmt::remove_cvref_t<decltype(s[0])>; \
3617
- FMT_MAYBE_UNUSED __VA_ARGS__ FMT_CONSTEXPR \
3618
- operator fmt::basic_string_view<char_type>() const { \
3619
- return fmt::internal::compile_string_to_view<char_type>(s); \
3620
- } \
3621
- }; \
3622
- return FMT_COMPILE_STRING(); \
3623
- }()
3624
-
3625
- /**
3626
- \rst
3627
- Constructs a compile-time format string from a string literal *s*.
3628
-
3629
- **Example**::
3630
-
3631
- // A compile-time error because 'd' is an invalid specifier for strings.
3632
- std::string s = format(FMT_STRING("{:d}"), "foo");
3633
- \endrst
3634
- */
3635
- #define FMT_STRING(s) FMT_STRING_IMPL(s, )
3636
-
3637
- #if defined(FMT_STRING_ALIAS) && FMT_STRING_ALIAS
3638
- # define fmt(s) FMT_STRING_IMPL(s, [[deprecated]])
3639
- #endif
3640
-
3641
3722
  #ifdef FMT_HEADER_ONLY
3642
3723
  # define FMT_FUNC inline
3643
3724
  # include "format-inl.h"