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

Sign up to get free protection for your applications and to get access to all the features.
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"