couchbase 3.5.4 → 3.5.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (441) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/ext/CMakeLists.txt +8 -6
  4. data/ext/cache/cpm/{CPM_0.38.6.cmake → CPM_0.40.5.cmake} +152 -22
  5. data/ext/cache/extconf_include.rb +3 -3
  6. data/ext/cache/mozilla-ca-bundle.crt +32 -87
  7. data/ext/cache/mozilla-ca-bundle.sha256 +1 -1
  8. data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/CMakeLists.txt +30 -6
  9. data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/cmake/utils.cmake +13 -2
  10. data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/async_logger-inl.h +5 -7
  11. data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/details/mpmc_blocking_q.h +3 -3
  12. data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/details/os-inl.h +3 -3
  13. data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/details/thread_pool-inl.h +3 -8
  14. data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/details/thread_pool.h +3 -14
  15. data/ext/cache/{fmt/141a17a028e6c29914e109691389f6cf87f9cfe3/fmt/include/fmt → spdlog/7251ead404dccd824789f8f3a13df2a6fb56440c/spdlog/include/spdlog/fmt/bundled}/base.h +47 -31
  16. data/ext/cache/{fmt/141a17a028e6c29914e109691389f6cf87f9cfe3/fmt/include/fmt → spdlog/7251ead404dccd824789f8f3a13df2a6fb56440c/spdlog/include/spdlog/fmt/bundled}/format-inl.h +32 -8
  17. data/ext/cache/{fmt/141a17a028e6c29914e109691389f6cf87f9cfe3/fmt/include/fmt → spdlog/7251ead404dccd824789f8f3a13df2a6fb56440c/spdlog/include/spdlog/fmt/bundled}/format.h +22 -14
  18. data/ext/cache/{fmt/141a17a028e6c29914e109691389f6cf87f9cfe3/fmt/include/fmt → spdlog/7251ead404dccd824789f8f3a13df2a6fb56440c/spdlog/include/spdlog/fmt/bundled}/ranges.h +1 -1
  19. data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/mdc.h +4 -0
  20. data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/pattern_formatter-inl.h +16 -2
  21. data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/sinks/ansicolor_sink.h +1 -1
  22. data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/sinks/base_sink.h +4 -4
  23. data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/sinks/callback_sink.h +1 -1
  24. data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/sinks/daily_file_sink.h +3 -0
  25. data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/sinks/hourly_file_sink.h +2 -0
  26. data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/sinks/msvc_sink.h +1 -1
  27. data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/sinks/rotating_file_sink-inl.h +1 -1
  28. data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/sinks/syslog_sink.h +3 -2
  29. data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/sinks/wincolor_sink-inl.h +9 -0
  30. data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/version.h +2 -2
  31. data/ext/cache/{fmt/141a17a028e6c29914e109691389f6cf87f9cfe3/fmt/src/format.cc → spdlog/7251ead404dccd824789f8f3a13df2a6fb56440c/spdlog/src/bundled_fmtlib_format.cpp} +10 -5
  32. data/ext/couchbase/CMakeLists.txt +3 -2
  33. data/ext/couchbase/cmake/APKBUILD.in +54 -0
  34. data/ext/couchbase/cmake/Backtrace.cmake +3 -1
  35. data/ext/couchbase/cmake/CPM.cmake +1 -1
  36. data/ext/couchbase/cmake/CompilerWarnings.cmake +0 -5
  37. data/ext/couchbase/cmake/Packaging.cmake +174 -11
  38. data/ext/couchbase/cmake/RPath.cmake +10 -0
  39. data/ext/couchbase/cmake/Testing.cmake +0 -4
  40. data/ext/couchbase/cmake/ThirdPartyDependencies.cmake +7 -26
  41. data/ext/couchbase/cmake/VersionInfo.cmake +4 -0
  42. data/ext/couchbase/cmake/build_version.hxx.in +1 -0
  43. data/ext/couchbase/cmake/couchbase-cxx-client.spec.in +2 -2
  44. data/ext/couchbase/cmake/couchbase_cxx_client.pc.in +2 -2
  45. data/ext/couchbase/core/agent_config.cxx +1 -1
  46. data/ext/couchbase/core/agent_group_config.cxx +1 -1
  47. data/ext/couchbase/core/bucket.cxx +9 -9
  48. data/ext/couchbase/core/cluster.cxx +0 -2
  49. data/ext/couchbase/core/cluster_agent_config.cxx +1 -1
  50. data/ext/couchbase/core/collections_component.cxx +1 -1
  51. data/ext/couchbase/core/columnar/agent_config.cxx +2 -2
  52. data/ext/couchbase/core/columnar/error.hxx +0 -1
  53. data/ext/couchbase/core/columnar/query_component.cxx +2 -2
  54. data/ext/couchbase/core/config_profiles.cxx +1 -1
  55. data/ext/couchbase/core/core_sdk_shim.cxx +1 -1
  56. data/ext/couchbase/core/crud_component.cxx +1 -1
  57. data/ext/couchbase/core/design_document_namespace_fmt.hxx +1 -1
  58. data/ext/couchbase/core/diagnostics_fmt.hxx +1 -1
  59. data/ext/couchbase/core/document_id.cxx +1 -1
  60. data/ext/couchbase/core/document_id_fmt.hxx +1 -1
  61. data/ext/couchbase/core/error_context/analytics_json.hxx +3 -1
  62. data/ext/couchbase/core/error_context/key_value_json.hxx +1 -1
  63. data/ext/couchbase/core/error_context/query_public_json.hxx +1 -1
  64. data/ext/couchbase/core/error_context/subdocument_json.hxx +1 -1
  65. data/ext/couchbase/core/fmt/key_value_error_map_attribute.hxx +1 -1
  66. data/ext/couchbase/core/fmt/key_value_extended_error_info.hxx +1 -1
  67. data/ext/couchbase/core/fmt/key_value_status_code.hxx +1 -1
  68. data/ext/couchbase/core/http_component.cxx +3 -3
  69. data/ext/couchbase/core/impl/analytics.cxx +1 -0
  70. data/ext/couchbase/core/impl/best_effort_retry_strategy.cxx +1 -1
  71. data/ext/couchbase/core/impl/collection.cxx +28 -4
  72. data/ext/couchbase/core/impl/date_range.cxx +2 -2
  73. data/ext/couchbase/core/impl/date_range_query.cxx +2 -2
  74. data/ext/couchbase/core/impl/dns_srv_tracker.cxx +1 -1
  75. data/ext/couchbase/core/impl/error.cxx +27 -4
  76. data/ext/couchbase/core/impl/expiry.cxx +2 -2
  77. data/ext/couchbase/core/impl/fail_fast_retry_strategy.cxx +1 -2
  78. data/ext/couchbase/core/impl/get_replica.hxx +2 -0
  79. data/ext/couchbase/core/impl/key_value_error_context.cxx +6 -4
  80. data/ext/couchbase/core/impl/lookup_in_replica.hxx +2 -0
  81. data/ext/couchbase/core/impl/numeric_range.cxx +1 -1
  82. data/ext/couchbase/core/impl/observe_seqno.hxx +2 -0
  83. data/ext/couchbase/core/impl/query.cxx +1 -0
  84. data/ext/couchbase/core/impl/query_error_context.cxx +3 -2
  85. data/ext/couchbase/core/impl/scope.cxx +5 -6
  86. data/ext/couchbase/core/impl/search.cxx +3 -1
  87. data/ext/couchbase/core/io/config_tracker.cxx +1 -1
  88. data/ext/couchbase/core/io/dns_client.cxx +23 -8
  89. data/ext/couchbase/core/io/http_command.hxx +2 -2
  90. data/ext/couchbase/core/io/http_parser.cxx +1 -1
  91. data/ext/couchbase/core/io/http_session.cxx +4 -0
  92. data/ext/couchbase/core/io/http_session.hxx +4 -2
  93. data/ext/couchbase/core/io/mcbp_command.hxx +2 -2
  94. data/ext/couchbase/core/key_value_config.cxx +2 -2
  95. data/ext/couchbase/core/logger/logger.hxx +1 -1
  96. data/ext/couchbase/core/management/rbac_fmt.hxx +1 -1
  97. data/ext/couchbase/core/mcbp/operation_queue.cxx +1 -1
  98. data/ext/couchbase/core/mcbp/packet.cxx +1 -1
  99. data/ext/couchbase/core/meta/features.hxx +11 -0
  100. data/ext/couchbase/core/meta/version.cxx +48 -7
  101. data/ext/couchbase/core/operations/document_analytics.cxx +23 -17
  102. data/ext/couchbase/core/operations/document_analytics.hxx +1 -0
  103. data/ext/couchbase/core/operations/document_append.hxx +2 -0
  104. data/ext/couchbase/core/operations/document_decrement.hxx +2 -0
  105. data/ext/couchbase/core/operations/document_exists.hxx +2 -0
  106. data/ext/couchbase/core/operations/document_get.hxx +2 -0
  107. data/ext/couchbase/core/operations/document_get_all_replicas.hxx +2 -0
  108. data/ext/couchbase/core/operations/document_get_and_lock.hxx +2 -0
  109. data/ext/couchbase/core/operations/document_get_and_touch.hxx +2 -0
  110. data/ext/couchbase/core/operations/document_get_any_replica.hxx +2 -0
  111. data/ext/couchbase/core/operations/document_get_projected.hxx +2 -0
  112. data/ext/couchbase/core/operations/document_increment.hxx +2 -0
  113. data/ext/couchbase/core/operations/document_insert.hxx +2 -0
  114. data/ext/couchbase/core/operations/document_lookup_in.hxx +2 -0
  115. data/ext/couchbase/core/operations/document_lookup_in_all_replicas.hxx +2 -0
  116. data/ext/couchbase/core/operations/document_lookup_in_any_replica.hxx +2 -0
  117. data/ext/couchbase/core/operations/document_mutate_in.hxx +2 -0
  118. data/ext/couchbase/core/operations/document_prepend.hxx +2 -0
  119. data/ext/couchbase/core/operations/document_query.hxx +1 -0
  120. data/ext/couchbase/core/operations/document_remove.hxx +2 -0
  121. data/ext/couchbase/core/operations/document_replace.hxx +2 -0
  122. data/ext/couchbase/core/operations/document_search.hxx +1 -0
  123. data/ext/couchbase/core/operations/document_touch.hxx +2 -0
  124. data/ext/couchbase/core/operations/document_unlock.hxx +2 -0
  125. data/ext/couchbase/core/operations/document_upsert.hxx +2 -0
  126. data/ext/couchbase/core/operations/document_view.hxx +1 -0
  127. data/ext/couchbase/core/operations/http_noop.hxx +2 -0
  128. data/ext/couchbase/core/operations/management/CMakeLists.txt +0 -1
  129. data/ext/couchbase/core/operations/management/analytics_dataset_create.cxx +1 -1
  130. data/ext/couchbase/core/operations/management/analytics_dataset_create.hxx +1 -0
  131. data/ext/couchbase/core/operations/management/analytics_dataset_drop.cxx +1 -1
  132. data/ext/couchbase/core/operations/management/analytics_dataset_drop.hxx +1 -0
  133. data/ext/couchbase/core/operations/management/analytics_dataset_get_all.hxx +1 -0
  134. data/ext/couchbase/core/operations/management/analytics_dataverse_create.cxx +1 -1
  135. data/ext/couchbase/core/operations/management/analytics_dataverse_create.hxx +1 -0
  136. data/ext/couchbase/core/operations/management/analytics_dataverse_drop.cxx +1 -1
  137. data/ext/couchbase/core/operations/management/analytics_dataverse_drop.hxx +1 -0
  138. data/ext/couchbase/core/operations/management/analytics_get_pending_mutations.cxx +1 -1
  139. data/ext/couchbase/core/operations/management/analytics_get_pending_mutations.hxx +2 -0
  140. data/ext/couchbase/core/operations/management/analytics_index_create.hxx +1 -0
  141. data/ext/couchbase/core/operations/management/analytics_index_drop.cxx +1 -1
  142. data/ext/couchbase/core/operations/management/analytics_index_drop.hxx +1 -0
  143. data/ext/couchbase/core/operations/management/analytics_index_get_all.hxx +1 -0
  144. data/ext/couchbase/core/operations/management/analytics_link_connect.cxx +1 -1
  145. data/ext/couchbase/core/operations/management/analytics_link_connect.hxx +1 -0
  146. data/ext/couchbase/core/operations/management/analytics_link_create.hxx +1 -0
  147. data/ext/couchbase/core/operations/management/analytics_link_disconnect.cxx +1 -1
  148. data/ext/couchbase/core/operations/management/analytics_link_disconnect.hxx +1 -0
  149. data/ext/couchbase/core/operations/management/analytics_link_drop.cxx +1 -1
  150. data/ext/couchbase/core/operations/management/analytics_link_drop.hxx +1 -0
  151. data/ext/couchbase/core/operations/management/analytics_link_get_all.cxx +24 -16
  152. data/ext/couchbase/core/operations/management/analytics_link_get_all.hxx +4 -3
  153. data/ext/couchbase/core/operations/management/analytics_link_replace.hxx +1 -0
  154. data/ext/couchbase/core/operations/management/analytics_link_utils.hxx +4 -3
  155. data/ext/couchbase/core/operations/management/bucket_create.hxx +1 -0
  156. data/ext/couchbase/core/operations/management/bucket_describe.cxx +1 -1
  157. data/ext/couchbase/core/operations/management/bucket_describe.hxx +1 -0
  158. data/ext/couchbase/core/operations/management/bucket_drop.cxx +1 -1
  159. data/ext/couchbase/core/operations/management/bucket_drop.hxx +1 -0
  160. data/ext/couchbase/core/operations/management/bucket_flush.cxx +1 -1
  161. data/ext/couchbase/core/operations/management/bucket_flush.hxx +1 -0
  162. data/ext/couchbase/core/operations/management/bucket_get.cxx +1 -1
  163. data/ext/couchbase/core/operations/management/bucket_get.hxx +1 -0
  164. data/ext/couchbase/core/operations/management/bucket_get_all.hxx +1 -0
  165. data/ext/couchbase/core/operations/management/bucket_update.hxx +1 -0
  166. data/ext/couchbase/core/operations/management/change_password.cxx +1 -1
  167. data/ext/couchbase/core/operations/management/change_password.hxx +1 -0
  168. data/ext/couchbase/core/operations/management/cluster_describe.hxx +1 -0
  169. data/ext/couchbase/core/operations/management/cluster_developer_preview_enable.hxx +1 -0
  170. data/ext/couchbase/core/operations/management/collection_create.cxx +1 -1
  171. data/ext/couchbase/core/operations/management/collection_create.hxx +2 -0
  172. data/ext/couchbase/core/operations/management/collection_drop.cxx +1 -1
  173. data/ext/couchbase/core/operations/management/collection_drop.hxx +1 -0
  174. data/ext/couchbase/core/operations/management/collection_update.cxx +1 -1
  175. data/ext/couchbase/core/operations/management/collection_update.hxx +2 -0
  176. data/ext/couchbase/core/operations/management/collections_manifest_get.hxx +2 -0
  177. data/ext/couchbase/core/operations/management/eventing_deploy_function.cxx +1 -1
  178. data/ext/couchbase/core/operations/management/eventing_deploy_function.hxx +3 -2
  179. data/ext/couchbase/core/operations/management/eventing_drop_function.cxx +1 -1
  180. data/ext/couchbase/core/operations/management/eventing_drop_function.hxx +3 -2
  181. data/ext/couchbase/core/operations/management/eventing_get_all_functions.hxx +3 -2
  182. data/ext/couchbase/core/operations/management/eventing_get_function.cxx +1 -1
  183. data/ext/couchbase/core/operations/management/eventing_get_function.hxx +3 -2
  184. data/ext/couchbase/core/operations/management/eventing_get_status.hxx +3 -2
  185. data/ext/couchbase/core/operations/management/eventing_pause_function.cxx +1 -1
  186. data/ext/couchbase/core/operations/management/eventing_pause_function.hxx +3 -2
  187. data/ext/couchbase/core/operations/management/eventing_resume_function.cxx +1 -1
  188. data/ext/couchbase/core/operations/management/eventing_resume_function.hxx +3 -2
  189. data/ext/couchbase/core/operations/management/eventing_undeploy_function.cxx +1 -1
  190. data/ext/couchbase/core/operations/management/eventing_undeploy_function.hxx +3 -2
  191. data/ext/couchbase/core/operations/management/eventing_upsert_function.cxx +1 -2
  192. data/ext/couchbase/core/operations/management/eventing_upsert_function.hxx +3 -2
  193. data/ext/couchbase/core/operations/management/freeform.hxx +2 -0
  194. data/ext/couchbase/core/operations/management/group_drop.cxx +1 -1
  195. data/ext/couchbase/core/operations/management/group_drop.hxx +1 -0
  196. data/ext/couchbase/core/operations/management/group_get.cxx +1 -1
  197. data/ext/couchbase/core/operations/management/group_get.hxx +1 -0
  198. data/ext/couchbase/core/operations/management/group_get_all.hxx +1 -0
  199. data/ext/couchbase/core/operations/management/group_upsert.hxx +1 -0
  200. data/ext/couchbase/core/operations/management/query_index_build.hxx +7 -5
  201. data/ext/couchbase/core/operations/management/query_index_build_deferred.hxx +3 -0
  202. data/ext/couchbase/core/operations/management/query_index_create.cxx +1 -1
  203. data/ext/couchbase/core/operations/management/query_index_create.hxx +1 -0
  204. data/ext/couchbase/core/operations/management/query_index_drop.cxx +1 -1
  205. data/ext/couchbase/core/operations/management/query_index_drop.hxx +1 -0
  206. data/ext/couchbase/core/operations/management/query_index_get_all.hxx +2 -0
  207. data/ext/couchbase/core/operations/management/query_index_get_all_deferred.hxx +3 -0
  208. data/ext/couchbase/core/operations/management/role_get_all.hxx +1 -0
  209. data/ext/couchbase/core/operations/management/scope_create.cxx +1 -1
  210. data/ext/couchbase/core/operations/management/scope_create.hxx +1 -0
  211. data/ext/couchbase/core/operations/management/scope_drop.cxx +1 -1
  212. data/ext/couchbase/core/operations/management/scope_drop.hxx +1 -0
  213. data/ext/couchbase/core/operations/management/scope_get_all.cxx +1 -1
  214. data/ext/couchbase/core/operations/management/scope_get_all.hxx +1 -0
  215. data/ext/couchbase/core/operations/management/search_get_stats.hxx +1 -0
  216. data/ext/couchbase/core/operations/management/search_index_analyze_document.cxx +1 -1
  217. data/ext/couchbase/core/operations/management/search_index_analyze_document.hxx +1 -0
  218. data/ext/couchbase/core/operations/management/search_index_control_ingest.cxx +1 -1
  219. data/ext/couchbase/core/operations/management/search_index_control_ingest.hxx +1 -0
  220. data/ext/couchbase/core/operations/management/search_index_control_plan_freeze.cxx +1 -1
  221. data/ext/couchbase/core/operations/management/search_index_control_plan_freeze.hxx +1 -0
  222. data/ext/couchbase/core/operations/management/search_index_control_query.cxx +1 -1
  223. data/ext/couchbase/core/operations/management/search_index_control_query.hxx +1 -0
  224. data/ext/couchbase/core/operations/management/search_index_drop.cxx +1 -1
  225. data/ext/couchbase/core/operations/management/search_index_drop.hxx +1 -0
  226. data/ext/couchbase/core/operations/management/search_index_get.cxx +1 -1
  227. data/ext/couchbase/core/operations/management/search_index_get.hxx +1 -0
  228. data/ext/couchbase/core/operations/management/search_index_get_all.cxx +1 -1
  229. data/ext/couchbase/core/operations/management/search_index_get_all.hxx +1 -0
  230. data/ext/couchbase/core/operations/management/search_index_get_documents_count.cxx +1 -1
  231. data/ext/couchbase/core/operations/management/search_index_get_documents_count.hxx +2 -0
  232. data/ext/couchbase/core/operations/management/search_index_get_stats.cxx +1 -1
  233. data/ext/couchbase/core/operations/management/search_index_get_stats.hxx +1 -0
  234. data/ext/couchbase/core/operations/management/search_index_upsert.cxx +1 -1
  235. data/ext/couchbase/core/operations/management/search_index_upsert.hxx +1 -0
  236. data/ext/couchbase/core/operations/management/user_drop.hxx +1 -0
  237. data/ext/couchbase/core/operations/management/user_get.hxx +1 -0
  238. data/ext/couchbase/core/operations/management/user_get_all.hxx +1 -0
  239. data/ext/couchbase/core/operations/management/user_upsert.cxx +3 -3
  240. data/ext/couchbase/core/operations/management/user_upsert.hxx +1 -0
  241. data/ext/couchbase/core/operations/management/view_index_drop.cxx +1 -1
  242. data/ext/couchbase/core/operations/management/view_index_drop.hxx +1 -0
  243. data/ext/couchbase/core/operations/management/view_index_get.cxx +1 -1
  244. data/ext/couchbase/core/operations/management/view_index_get.hxx +1 -0
  245. data/ext/couchbase/core/operations/management/view_index_get_all.cxx +1 -1
  246. data/ext/couchbase/core/operations/management/view_index_get_all.hxx +2 -0
  247. data/ext/couchbase/core/operations/management/view_index_upsert.cxx +1 -1
  248. data/ext/couchbase/core/operations/management/view_index_upsert.hxx +1 -0
  249. data/ext/couchbase/core/origin.cxx +3 -2
  250. data/ext/couchbase/core/platform/base64.h +8 -8
  251. data/ext/couchbase/core/protocol/client_opcode_fmt.hxx +1 -1
  252. data/ext/couchbase/core/protocol/client_response.hxx +1 -1
  253. data/ext/couchbase/core/protocol/frame_info_id_fmt.hxx +1 -1
  254. data/ext/couchbase/core/protocol/hello_feature_fmt.hxx +1 -1
  255. data/ext/couchbase/core/protocol/magic_fmt.hxx +1 -1
  256. data/ext/couchbase/core/protocol/server_opcode_fmt.hxx +1 -1
  257. data/ext/couchbase/core/query_context.hxx +7 -6
  258. data/ext/couchbase/core/retry_orchestrator.cxx +1 -1
  259. data/ext/couchbase/core/sasl/CMakeLists.txt +0 -1
  260. data/ext/couchbase/core/sasl/error_fmt.h +1 -1
  261. data/ext/couchbase/core/seed_config.cxx +2 -2
  262. data/ext/couchbase/core/service_type_fmt.hxx +1 -1
  263. data/ext/couchbase/core/topology/capabilities_fmt.hxx +1 -1
  264. data/ext/couchbase/core/topology/collections_manifest_fmt.hxx +2 -1
  265. data/ext/couchbase/core/topology/configuration_fmt.hxx +1 -1
  266. data/ext/couchbase/core/transactions/async_attempt_context.cxx +1 -1
  267. data/ext/couchbase/core/transactions/async_attempt_context.hxx +9 -22
  268. data/ext/couchbase/core/transactions/attempt_context.cxx +1 -1
  269. data/ext/couchbase/core/transactions/attempt_context.hxx +6 -33
  270. data/ext/couchbase/core/transactions/attempt_context_impl.cxx +41 -41
  271. data/ext/couchbase/core/transactions/attempt_context_impl.hxx +15 -16
  272. data/ext/couchbase/core/transactions/exceptions_fmt.hxx +1 -1
  273. data/ext/couchbase/core/transactions/internal/atr_cleanup_entry.hxx +1 -1
  274. data/ext/couchbase/core/transactions/internal/client_record.hxx +4 -3
  275. data/ext/couchbase/core/transactions/internal/doc_record_fmt.hxx +1 -1
  276. data/ext/couchbase/core/transactions/internal/exceptions_internal.hxx +0 -2
  277. data/ext/couchbase/core/transactions/internal/exceptions_internal_fmt.hxx +1 -1
  278. data/ext/couchbase/core/transactions/internal/logging.hxx +2 -0
  279. data/ext/couchbase/core/transactions/internal/transaction_context.hxx +3 -0
  280. data/ext/couchbase/core/transactions/result_fmt.hxx +1 -1
  281. data/ext/couchbase/core/transactions/transaction_context.cxx +12 -2
  282. data/ext/couchbase/core/transactions/transaction_get_result.hxx +0 -20
  283. data/ext/couchbase/core/transactions/transaction_links.hxx +1 -1
  284. data/ext/couchbase/core/utils/join_strings.hxx +2 -2
  285. data/ext/couchbase/core/utils/keyspace.hxx +2 -1
  286. data/ext/couchbase/core/utils/url_codec.cxx +1 -1
  287. data/ext/couchbase/couchbase/common_options.hxx +16 -1
  288. data/ext/couchbase/couchbase/fmt/analytics_scan_consistency.hxx +0 -2
  289. data/ext/couchbase/couchbase/fmt/analytics_status.hxx +0 -2
  290. data/ext/couchbase/couchbase/fmt/cas.hxx +0 -2
  291. data/ext/couchbase/couchbase/fmt/durability_level.hxx +0 -2
  292. data/ext/couchbase/couchbase/fmt/error.hxx +0 -2
  293. data/ext/couchbase/couchbase/fmt/error_context.hxx +0 -2
  294. data/ext/couchbase/couchbase/fmt/mutation_token.hxx +0 -2
  295. data/ext/couchbase/couchbase/fmt/query_profile.hxx +0 -2
  296. data/ext/couchbase/couchbase/fmt/query_scan_consistency.hxx +0 -2
  297. data/ext/couchbase/couchbase/fmt/query_status.hxx +0 -2
  298. data/ext/couchbase/couchbase/fmt/retry_reason.hxx +5 -1
  299. data/ext/couchbase/couchbase/fmt/search_scan_consistency.hxx +0 -2
  300. data/ext/couchbase/couchbase/fmt/tls_verify_mode.hxx +0 -2
  301. data/ext/couchbase/couchbase/fmt/transaction_keyspace.hxx +0 -2
  302. data/ext/couchbase/couchbase/metrics/otel_meter.hxx +16 -20
  303. data/ext/extconf.rb +1 -0
  304. data/ext/rcb_analytics.cxx +7 -7
  305. data/ext/rcb_backend.cxx +6 -1
  306. data/ext/rcb_buckets.cxx +1 -1
  307. data/ext/rcb_collections.cxx +1 -1
  308. data/ext/rcb_crud.cxx +51 -30
  309. data/ext/rcb_diagnostics.cxx +1 -1
  310. data/ext/rcb_exceptions.cxx +3 -2
  311. data/ext/rcb_extras.cxx +1 -1
  312. data/ext/rcb_range_scan.cxx +1 -1
  313. data/ext/rcb_search.cxx +1 -1
  314. data/ext/rcb_users.cxx +2 -2
  315. data/ext/rcb_utils.hxx +32 -0
  316. data/lib/couchbase/logger.rb +3 -3
  317. data/lib/couchbase/options.rb +48 -0
  318. data/lib/couchbase/version.rb +1 -1
  319. metadata +131 -153
  320. data/ext/cache/fmt/141a17a028e6c29914e109691389f6cf87f9cfe3/fmt/CMakeLists.txt +0 -520
  321. data/ext/cache/fmt/141a17a028e6c29914e109691389f6cf87f9cfe3/fmt/ChangeLog.md +0 -2598
  322. data/ext/cache/fmt/141a17a028e6c29914e109691389f6cf87f9cfe3/fmt/LICENSE +0 -27
  323. data/ext/cache/fmt/141a17a028e6c29914e109691389f6cf87f9cfe3/fmt/README.md +0 -484
  324. data/ext/cache/fmt/141a17a028e6c29914e109691389f6cf87f9cfe3/fmt/src/fmt.cc +0 -135
  325. data/ext/cache/fmt/141a17a028e6c29914e109691389f6cf87f9cfe3/fmt/src/os.cc +0 -403
  326. data/ext/cache/fmt/141a17a028e6c29914e109691389f6cf87f9cfe3/fmt/support/cmake/FindSetEnv.cmake +0 -7
  327. data/ext/cache/fmt/141a17a028e6c29914e109691389f6cf87f9cfe3/fmt/support/cmake/JoinPaths.cmake +0 -26
  328. data/ext/cache/fmt/141a17a028e6c29914e109691389f6cf87f9cfe3/fmt/support/cmake/fmt-config.cmake.in +0 -7
  329. data/ext/cache/fmt/141a17a028e6c29914e109691389f6cf87f9cfe3/fmt/support/cmake/fmt.pc.in +0 -11
  330. data/ext/cache/spdlog/19df5d3d8e5526c255d27414e09568671ef87483/spdlog/include/spdlog/fmt/bundled/args.h +0 -235
  331. data/ext/cache/spdlog/19df5d3d8e5526c255d27414e09568671ef87483/spdlog/include/spdlog/fmt/bundled/chrono.h +0 -2240
  332. data/ext/cache/spdlog/19df5d3d8e5526c255d27414e09568671ef87483/spdlog/include/spdlog/fmt/bundled/color.h +0 -643
  333. data/ext/cache/spdlog/19df5d3d8e5526c255d27414e09568671ef87483/spdlog/include/spdlog/fmt/bundled/compile.h +0 -535
  334. data/ext/cache/spdlog/19df5d3d8e5526c255d27414e09568671ef87483/spdlog/include/spdlog/fmt/bundled/core.h +0 -2969
  335. data/ext/cache/spdlog/19df5d3d8e5526c255d27414e09568671ef87483/spdlog/include/spdlog/fmt/bundled/format-inl.h +0 -1678
  336. data/ext/cache/spdlog/19df5d3d8e5526c255d27414e09568671ef87483/spdlog/include/spdlog/fmt/bundled/format.h +0 -4535
  337. data/ext/cache/spdlog/19df5d3d8e5526c255d27414e09568671ef87483/spdlog/include/spdlog/fmt/bundled/os.h +0 -455
  338. data/ext/cache/spdlog/19df5d3d8e5526c255d27414e09568671ef87483/spdlog/include/spdlog/fmt/bundled/ostream.h +0 -245
  339. data/ext/cache/spdlog/19df5d3d8e5526c255d27414e09568671ef87483/spdlog/include/spdlog/fmt/bundled/printf.h +0 -675
  340. data/ext/cache/spdlog/19df5d3d8e5526c255d27414e09568671ef87483/spdlog/include/spdlog/fmt/bundled/ranges.h +0 -738
  341. data/ext/cache/spdlog/19df5d3d8e5526c255d27414e09568671ef87483/spdlog/include/spdlog/fmt/bundled/std.h +0 -537
  342. data/ext/cache/spdlog/19df5d3d8e5526c255d27414e09568671ef87483/spdlog/include/spdlog/fmt/bundled/xchar.h +0 -259
  343. data/ext/cache/spdlog/19df5d3d8e5526c255d27414e09568671ef87483/spdlog/src/bundled_fmtlib_format.cpp +0 -46
  344. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/LICENSE +0 -0
  345. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/cmake/ide.cmake +0 -0
  346. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/cmake/pch.h.in +0 -0
  347. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/cmake/spdlog.pc.in +0 -0
  348. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/cmake/spdlogCPack.cmake +0 -0
  349. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/cmake/spdlogConfig.cmake.in +0 -0
  350. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/cmake/version.rc.in +0 -0
  351. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/async.h +0 -0
  352. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/async_logger.h +0 -0
  353. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/cfg/argv.h +0 -0
  354. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/cfg/env.h +0 -0
  355. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/cfg/helpers-inl.h +0 -0
  356. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/cfg/helpers.h +0 -0
  357. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/common-inl.h +0 -0
  358. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/common.h +0 -0
  359. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/details/backtracer-inl.h +0 -0
  360. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/details/backtracer.h +0 -0
  361. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/details/circular_q.h +0 -0
  362. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/details/console_globals.h +0 -0
  363. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/details/file_helper-inl.h +0 -0
  364. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/details/file_helper.h +0 -0
  365. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/details/fmt_helper.h +0 -0
  366. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/details/log_msg-inl.h +0 -0
  367. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/details/log_msg.h +0 -0
  368. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/details/log_msg_buffer-inl.h +0 -0
  369. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/details/log_msg_buffer.h +0 -0
  370. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/details/null_mutex.h +0 -0
  371. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/details/os.h +0 -0
  372. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/details/periodic_worker-inl.h +0 -0
  373. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/details/periodic_worker.h +0 -0
  374. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/details/registry-inl.h +0 -0
  375. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/details/registry.h +0 -0
  376. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/details/synchronous_factory.h +0 -0
  377. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/details/tcp_client-windows.h +0 -0
  378. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/details/tcp_client.h +0 -0
  379. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/details/udp_client-windows.h +0 -0
  380. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/details/udp_client.h +0 -0
  381. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/details/windows_include.h +0 -0
  382. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/fmt/bin_to_hex.h +0 -0
  383. /data/ext/cache/{fmt/141a17a028e6c29914e109691389f6cf87f9cfe3/fmt/include/fmt → spdlog/7251ead404dccd824789f8f3a13df2a6fb56440c/spdlog/include/spdlog/fmt/bundled}/args.h +0 -0
  384. /data/ext/cache/{fmt/141a17a028e6c29914e109691389f6cf87f9cfe3/fmt/include/fmt → spdlog/7251ead404dccd824789f8f3a13df2a6fb56440c/spdlog/include/spdlog/fmt/bundled}/chrono.h +0 -0
  385. /data/ext/cache/{fmt/141a17a028e6c29914e109691389f6cf87f9cfe3/fmt/include/fmt → spdlog/7251ead404dccd824789f8f3a13df2a6fb56440c/spdlog/include/spdlog/fmt/bundled}/color.h +0 -0
  386. /data/ext/cache/{fmt/141a17a028e6c29914e109691389f6cf87f9cfe3/fmt/include/fmt → spdlog/7251ead404dccd824789f8f3a13df2a6fb56440c/spdlog/include/spdlog/fmt/bundled}/compile.h +0 -0
  387. /data/ext/cache/{fmt/141a17a028e6c29914e109691389f6cf87f9cfe3/fmt/include/fmt → spdlog/7251ead404dccd824789f8f3a13df2a6fb56440c/spdlog/include/spdlog/fmt/bundled}/core.h +0 -0
  388. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/fmt/bundled/fmt.license.rst +0 -0
  389. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/fmt/bundled/locale.h +0 -0
  390. /data/ext/cache/{fmt/141a17a028e6c29914e109691389f6cf87f9cfe3/fmt/include/fmt → spdlog/7251ead404dccd824789f8f3a13df2a6fb56440c/spdlog/include/spdlog/fmt/bundled}/os.h +0 -0
  391. /data/ext/cache/{fmt/141a17a028e6c29914e109691389f6cf87f9cfe3/fmt/include/fmt → spdlog/7251ead404dccd824789f8f3a13df2a6fb56440c/spdlog/include/spdlog/fmt/bundled}/ostream.h +0 -0
  392. /data/ext/cache/{fmt/141a17a028e6c29914e109691389f6cf87f9cfe3/fmt/include/fmt → spdlog/7251ead404dccd824789f8f3a13df2a6fb56440c/spdlog/include/spdlog/fmt/bundled}/printf.h +0 -0
  393. /data/ext/cache/{fmt/141a17a028e6c29914e109691389f6cf87f9cfe3/fmt/include/fmt → spdlog/7251ead404dccd824789f8f3a13df2a6fb56440c/spdlog/include/spdlog/fmt/bundled}/std.h +0 -0
  394. /data/ext/cache/{fmt/141a17a028e6c29914e109691389f6cf87f9cfe3/fmt/include/fmt → spdlog/7251ead404dccd824789f8f3a13df2a6fb56440c/spdlog/include/spdlog/fmt/bundled}/xchar.h +0 -0
  395. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/fmt/chrono.h +0 -0
  396. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/fmt/compile.h +0 -0
  397. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/fmt/fmt.h +0 -0
  398. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/fmt/ostr.h +0 -0
  399. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/fmt/ranges.h +0 -0
  400. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/fmt/std.h +0 -0
  401. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/fmt/xchar.h +0 -0
  402. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/formatter.h +0 -0
  403. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/fwd.h +0 -0
  404. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/logger-inl.h +0 -0
  405. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/logger.h +0 -0
  406. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/pattern_formatter.h +0 -0
  407. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/sinks/android_sink.h +0 -0
  408. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/sinks/ansicolor_sink-inl.h +0 -0
  409. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/sinks/base_sink-inl.h +0 -0
  410. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/sinks/basic_file_sink-inl.h +0 -0
  411. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/sinks/basic_file_sink.h +0 -0
  412. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/sinks/dist_sink.h +0 -0
  413. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/sinks/dup_filter_sink.h +0 -0
  414. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/sinks/kafka_sink.h +0 -0
  415. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/sinks/mongo_sink.h +0 -0
  416. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/sinks/null_sink.h +0 -0
  417. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/sinks/ostream_sink.h +0 -0
  418. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/sinks/qt_sinks.h +0 -0
  419. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/sinks/ringbuffer_sink.h +0 -0
  420. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/sinks/rotating_file_sink.h +0 -0
  421. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/sinks/sink-inl.h +0 -0
  422. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/sinks/sink.h +0 -0
  423. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/sinks/stdout_color_sinks-inl.h +0 -0
  424. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/sinks/stdout_color_sinks.h +0 -0
  425. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/sinks/stdout_sinks-inl.h +0 -0
  426. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/sinks/stdout_sinks.h +0 -0
  427. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/sinks/systemd_sink.h +0 -0
  428. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/sinks/tcp_sink.h +0 -0
  429. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/sinks/udp_sink.h +0 -0
  430. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/sinks/win_eventlog_sink.h +0 -0
  431. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/sinks/wincolor_sink.h +0 -0
  432. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/spdlog-inl.h +0 -0
  433. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/spdlog.h +0 -0
  434. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/stopwatch.h +0 -0
  435. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/include/spdlog/tweakme.h +0 -0
  436. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/src/async.cpp +0 -0
  437. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/src/cfg.cpp +0 -0
  438. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/src/color_sinks.cpp +0 -0
  439. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/src/file_sinks.cpp +0 -0
  440. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/src/spdlog.cpp +0 -0
  441. /data/ext/cache/spdlog/{19df5d3d8e5526c255d27414e09568671ef87483 → 7251ead404dccd824789f8f3a13df2a6fb56440c}/spdlog/src/stdout_sinks.cpp +0 -0
@@ -1,4535 +0,0 @@
1
- /*
2
- Formatting library for C++
3
-
4
- Copyright (c) 2012 - present, Victor Zverovich
5
-
6
- Permission is hereby granted, free of charge, to any person obtaining
7
- a copy of this software and associated documentation files (the
8
- "Software"), to deal in the Software without restriction, including
9
- without limitation the rights to use, copy, modify, merge, publish,
10
- distribute, sublicense, and/or sell copies of the Software, and to
11
- permit persons to whom the Software is furnished to do so, subject to
12
- the following conditions:
13
-
14
- The above copyright notice and this permission notice shall be
15
- included in all copies or substantial portions of the Software.
16
-
17
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
-
25
- --- Optional exception to the license ---
26
-
27
- As an exception, if, as a result of your compiling your source code, portions
28
- of this Software are embedded into a machine-executable object form of such
29
- source code, you may redistribute such embedded portions in such object form
30
- without including the above copyright and permission notices.
31
- */
32
-
33
- #ifndef FMT_FORMAT_H_
34
- #define FMT_FORMAT_H_
35
-
36
- #include <cmath> // std::signbit
37
- #include <cstdint> // uint32_t
38
- #include <cstring> // std::memcpy
39
- #include <initializer_list> // std::initializer_list
40
- #include <limits> // std::numeric_limits
41
- #include <memory> // std::uninitialized_copy
42
- #include <stdexcept> // std::runtime_error
43
- #include <system_error> // std::system_error
44
-
45
- #ifdef __cpp_lib_bit_cast
46
- # include <bit> // std::bit_cast
47
- #endif
48
-
49
- #include "core.h"
50
-
51
- #if defined __cpp_inline_variables && __cpp_inline_variables >= 201606L
52
- # define FMT_INLINE_VARIABLE inline
53
- #else
54
- # define FMT_INLINE_VARIABLE
55
- #endif
56
-
57
- #if FMT_HAS_CPP17_ATTRIBUTE(fallthrough)
58
- # define FMT_FALLTHROUGH [[fallthrough]]
59
- #elif defined(__clang__)
60
- # define FMT_FALLTHROUGH [[clang::fallthrough]]
61
- #elif FMT_GCC_VERSION >= 700 && \
62
- (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= 520)
63
- # define FMT_FALLTHROUGH [[gnu::fallthrough]]
64
- #else
65
- # define FMT_FALLTHROUGH
66
- #endif
67
-
68
- #ifndef FMT_DEPRECATED
69
- # if FMT_HAS_CPP14_ATTRIBUTE(deprecated) || FMT_MSC_VERSION >= 1900
70
- # define FMT_DEPRECATED [[deprecated]]
71
- # else
72
- # if (defined(__GNUC__) && !defined(__LCC__)) || defined(__clang__)
73
- # define FMT_DEPRECATED __attribute__((deprecated))
74
- # elif FMT_MSC_VERSION
75
- # define FMT_DEPRECATED __declspec(deprecated)
76
- # else
77
- # define FMT_DEPRECATED /* deprecated */
78
- # endif
79
- # endif
80
- #endif
81
-
82
- #ifndef FMT_NO_UNIQUE_ADDRESS
83
- # if FMT_CPLUSPLUS >= 202002L
84
- # if FMT_HAS_CPP_ATTRIBUTE(no_unique_address)
85
- # define FMT_NO_UNIQUE_ADDRESS [[no_unique_address]]
86
- // VS2019 v16.10 and later except clang-cl (https://reviews.llvm.org/D110485)
87
- # elif (FMT_MSC_VERSION >= 1929) && !FMT_CLANG_VERSION
88
- # define FMT_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]]
89
- # endif
90
- # endif
91
- #endif
92
- #ifndef FMT_NO_UNIQUE_ADDRESS
93
- # define FMT_NO_UNIQUE_ADDRESS
94
- #endif
95
-
96
- // Visibility when compiled as a shared library/object.
97
- #if defined(FMT_LIB_EXPORT) || defined(FMT_SHARED)
98
- # define FMT_SO_VISIBILITY(value) FMT_VISIBILITY(value)
99
- #else
100
- # define FMT_SO_VISIBILITY(value)
101
- #endif
102
-
103
- #ifdef __has_builtin
104
- # define FMT_HAS_BUILTIN(x) __has_builtin(x)
105
- #else
106
- # define FMT_HAS_BUILTIN(x) 0
107
- #endif
108
-
109
- #if FMT_GCC_VERSION || FMT_CLANG_VERSION
110
- # define FMT_NOINLINE __attribute__((noinline))
111
- #else
112
- # define FMT_NOINLINE
113
- #endif
114
-
115
- #ifndef FMT_THROW
116
- # if FMT_EXCEPTIONS
117
- # if FMT_MSC_VERSION || defined(__NVCC__)
118
- FMT_BEGIN_NAMESPACE
119
- namespace detail {
120
- template <typename Exception> inline void do_throw(const Exception& x) {
121
- // Silence unreachable code warnings in MSVC and NVCC because these
122
- // are nearly impossible to fix in a generic code.
123
- volatile bool b = true;
124
- if (b) throw x;
125
- }
126
- } // namespace detail
127
- FMT_END_NAMESPACE
128
- # define FMT_THROW(x) detail::do_throw(x)
129
- # else
130
- # define FMT_THROW(x) throw x
131
- # endif
132
- # else
133
- # define FMT_THROW(x) \
134
- ::fmt::detail::assert_fail(__FILE__, __LINE__, (x).what())
135
- # endif
136
- #endif
137
-
138
- #if FMT_EXCEPTIONS
139
- # define FMT_TRY try
140
- # define FMT_CATCH(x) catch (x)
141
- #else
142
- # define FMT_TRY if (true)
143
- # define FMT_CATCH(x) if (false)
144
- #endif
145
-
146
- #ifndef FMT_MAYBE_UNUSED
147
- # if FMT_HAS_CPP17_ATTRIBUTE(maybe_unused)
148
- # define FMT_MAYBE_UNUSED [[maybe_unused]]
149
- # else
150
- # define FMT_MAYBE_UNUSED
151
- # endif
152
- #endif
153
-
154
- #ifndef FMT_USE_USER_DEFINED_LITERALS
155
- // EDG based compilers (Intel, NVIDIA, Elbrus, etc), GCC and MSVC support UDLs.
156
- //
157
- // GCC before 4.9 requires a space in `operator"" _a` which is invalid in later
158
- // compiler versions.
159
- # if (FMT_HAS_FEATURE(cxx_user_literals) || FMT_GCC_VERSION >= 409 || \
160
- FMT_MSC_VERSION >= 1900) && \
161
- (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= /* UDL feature */ 480)
162
- # define FMT_USE_USER_DEFINED_LITERALS 1
163
- # else
164
- # define FMT_USE_USER_DEFINED_LITERALS 0
165
- # endif
166
- #endif
167
-
168
- // Defining FMT_REDUCE_INT_INSTANTIATIONS to 1, will reduce the number of
169
- // integer formatter template instantiations to just one by only using the
170
- // largest integer type. This results in a reduction in binary size but will
171
- // cause a decrease in integer formatting performance.
172
- #if !defined(FMT_REDUCE_INT_INSTANTIATIONS)
173
- # define FMT_REDUCE_INT_INSTANTIATIONS 0
174
- #endif
175
-
176
- // __builtin_clz is broken in clang with Microsoft CodeGen:
177
- // https://github.com/fmtlib/fmt/issues/519.
178
- #if !FMT_MSC_VERSION
179
- # if FMT_HAS_BUILTIN(__builtin_clz) || FMT_GCC_VERSION || FMT_ICC_VERSION
180
- # define FMT_BUILTIN_CLZ(n) __builtin_clz(n)
181
- # endif
182
- # if FMT_HAS_BUILTIN(__builtin_clzll) || FMT_GCC_VERSION || FMT_ICC_VERSION
183
- # define FMT_BUILTIN_CLZLL(n) __builtin_clzll(n)
184
- # endif
185
- #endif
186
-
187
- // __builtin_ctz is broken in Intel Compiler Classic on Windows:
188
- // https://github.com/fmtlib/fmt/issues/2510.
189
- #ifndef __ICL
190
- # if FMT_HAS_BUILTIN(__builtin_ctz) || FMT_GCC_VERSION || FMT_ICC_VERSION || \
191
- defined(__NVCOMPILER)
192
- # define FMT_BUILTIN_CTZ(n) __builtin_ctz(n)
193
- # endif
194
- # if FMT_HAS_BUILTIN(__builtin_ctzll) || FMT_GCC_VERSION || \
195
- FMT_ICC_VERSION || defined(__NVCOMPILER)
196
- # define FMT_BUILTIN_CTZLL(n) __builtin_ctzll(n)
197
- # endif
198
- #endif
199
-
200
- #if FMT_MSC_VERSION
201
- # include <intrin.h> // _BitScanReverse[64], _BitScanForward[64], _umul128
202
- #endif
203
-
204
- // Some compilers masquerade as both MSVC and GCC-likes or otherwise support
205
- // __builtin_clz and __builtin_clzll, so only define FMT_BUILTIN_CLZ using the
206
- // MSVC intrinsics if the clz and clzll builtins are not available.
207
- #if FMT_MSC_VERSION && !defined(FMT_BUILTIN_CLZLL) && \
208
- !defined(FMT_BUILTIN_CTZLL)
209
- FMT_BEGIN_NAMESPACE
210
- namespace detail {
211
- // Avoid Clang with Microsoft CodeGen's -Wunknown-pragmas warning.
212
- # if !defined(__clang__)
213
- # pragma intrinsic(_BitScanForward)
214
- # pragma intrinsic(_BitScanReverse)
215
- # if defined(_WIN64)
216
- # pragma intrinsic(_BitScanForward64)
217
- # pragma intrinsic(_BitScanReverse64)
218
- # endif
219
- # endif
220
-
221
- inline auto clz(uint32_t x) -> int {
222
- unsigned long r = 0;
223
- _BitScanReverse(&r, x);
224
- FMT_ASSERT(x != 0, "");
225
- // Static analysis complains about using uninitialized data
226
- // "r", but the only way that can happen is if "x" is 0,
227
- // which the callers guarantee to not happen.
228
- FMT_MSC_WARNING(suppress : 6102)
229
- return 31 ^ static_cast<int>(r);
230
- }
231
- # define FMT_BUILTIN_CLZ(n) detail::clz(n)
232
-
233
- inline auto clzll(uint64_t x) -> int {
234
- unsigned long r = 0;
235
- # ifdef _WIN64
236
- _BitScanReverse64(&r, x);
237
- # else
238
- // Scan the high 32 bits.
239
- if (_BitScanReverse(&r, static_cast<uint32_t>(x >> 32)))
240
- return 63 ^ static_cast<int>(r + 32);
241
- // Scan the low 32 bits.
242
- _BitScanReverse(&r, static_cast<uint32_t>(x));
243
- # endif
244
- FMT_ASSERT(x != 0, "");
245
- FMT_MSC_WARNING(suppress : 6102) // Suppress a bogus static analysis warning.
246
- return 63 ^ static_cast<int>(r);
247
- }
248
- # define FMT_BUILTIN_CLZLL(n) detail::clzll(n)
249
-
250
- inline auto ctz(uint32_t x) -> int {
251
- unsigned long r = 0;
252
- _BitScanForward(&r, x);
253
- FMT_ASSERT(x != 0, "");
254
- FMT_MSC_WARNING(suppress : 6102) // Suppress a bogus static analysis warning.
255
- return static_cast<int>(r);
256
- }
257
- # define FMT_BUILTIN_CTZ(n) detail::ctz(n)
258
-
259
- inline auto ctzll(uint64_t x) -> int {
260
- unsigned long r = 0;
261
- FMT_ASSERT(x != 0, "");
262
- FMT_MSC_WARNING(suppress : 6102) // Suppress a bogus static analysis warning.
263
- # ifdef _WIN64
264
- _BitScanForward64(&r, x);
265
- # else
266
- // Scan the low 32 bits.
267
- if (_BitScanForward(&r, static_cast<uint32_t>(x))) return static_cast<int>(r);
268
- // Scan the high 32 bits.
269
- _BitScanForward(&r, static_cast<uint32_t>(x >> 32));
270
- r += 32;
271
- # endif
272
- return static_cast<int>(r);
273
- }
274
- # define FMT_BUILTIN_CTZLL(n) detail::ctzll(n)
275
- } // namespace detail
276
- FMT_END_NAMESPACE
277
- #endif
278
-
279
- FMT_BEGIN_NAMESPACE
280
- namespace detail {
281
-
282
- FMT_CONSTEXPR inline void abort_fuzzing_if(bool condition) {
283
- ignore_unused(condition);
284
- #ifdef FMT_FUZZ
285
- if (condition) throw std::runtime_error("fuzzing limit reached");
286
- #endif
287
- }
288
-
289
- template <typename CharT, CharT... C> struct string_literal {
290
- static constexpr CharT value[sizeof...(C)] = {C...};
291
- constexpr operator basic_string_view<CharT>() const {
292
- return {value, sizeof...(C)};
293
- }
294
- };
295
-
296
- #if FMT_CPLUSPLUS < 201703L
297
- template <typename CharT, CharT... C>
298
- constexpr CharT string_literal<CharT, C...>::value[sizeof...(C)];
299
- #endif
300
-
301
- // Implementation of std::bit_cast for pre-C++20.
302
- template <typename To, typename From, FMT_ENABLE_IF(sizeof(To) == sizeof(From))>
303
- FMT_CONSTEXPR20 auto bit_cast(const From& from) -> To {
304
- #ifdef __cpp_lib_bit_cast
305
- if (is_constant_evaluated()) return std::bit_cast<To>(from);
306
- #endif
307
- auto to = To();
308
- // The cast suppresses a bogus -Wclass-memaccess on GCC.
309
- std::memcpy(static_cast<void*>(&to), &from, sizeof(to));
310
- return to;
311
- }
312
-
313
- inline auto is_big_endian() -> bool {
314
- #ifdef _WIN32
315
- return false;
316
- #elif defined(__BIG_ENDIAN__)
317
- return true;
318
- #elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__)
319
- return __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__;
320
- #else
321
- struct bytes {
322
- char data[sizeof(int)];
323
- };
324
- return bit_cast<bytes>(1).data[0] == 0;
325
- #endif
326
- }
327
-
328
- class uint128_fallback {
329
- private:
330
- uint64_t lo_, hi_;
331
-
332
- public:
333
- constexpr uint128_fallback(uint64_t hi, uint64_t lo) : lo_(lo), hi_(hi) {}
334
- constexpr uint128_fallback(uint64_t value = 0) : lo_(value), hi_(0) {}
335
-
336
- constexpr auto high() const noexcept -> uint64_t { return hi_; }
337
- constexpr auto low() const noexcept -> uint64_t { return lo_; }
338
-
339
- template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
340
- constexpr explicit operator T() const {
341
- return static_cast<T>(lo_);
342
- }
343
-
344
- friend constexpr auto operator==(const uint128_fallback& lhs,
345
- const uint128_fallback& rhs) -> bool {
346
- return lhs.hi_ == rhs.hi_ && lhs.lo_ == rhs.lo_;
347
- }
348
- friend constexpr auto operator!=(const uint128_fallback& lhs,
349
- const uint128_fallback& rhs) -> bool {
350
- return !(lhs == rhs);
351
- }
352
- friend constexpr auto operator>(const uint128_fallback& lhs,
353
- const uint128_fallback& rhs) -> bool {
354
- return lhs.hi_ != rhs.hi_ ? lhs.hi_ > rhs.hi_ : lhs.lo_ > rhs.lo_;
355
- }
356
- friend constexpr auto operator|(const uint128_fallback& lhs,
357
- const uint128_fallback& rhs)
358
- -> uint128_fallback {
359
- return {lhs.hi_ | rhs.hi_, lhs.lo_ | rhs.lo_};
360
- }
361
- friend constexpr auto operator&(const uint128_fallback& lhs,
362
- const uint128_fallback& rhs)
363
- -> uint128_fallback {
364
- return {lhs.hi_ & rhs.hi_, lhs.lo_ & rhs.lo_};
365
- }
366
- friend constexpr auto operator~(const uint128_fallback& n)
367
- -> uint128_fallback {
368
- return {~n.hi_, ~n.lo_};
369
- }
370
- friend auto operator+(const uint128_fallback& lhs,
371
- const uint128_fallback& rhs) -> uint128_fallback {
372
- auto result = uint128_fallback(lhs);
373
- result += rhs;
374
- return result;
375
- }
376
- friend auto operator*(const uint128_fallback& lhs, uint32_t rhs)
377
- -> uint128_fallback {
378
- FMT_ASSERT(lhs.hi_ == 0, "");
379
- uint64_t hi = (lhs.lo_ >> 32) * rhs;
380
- uint64_t lo = (lhs.lo_ & ~uint32_t()) * rhs;
381
- uint64_t new_lo = (hi << 32) + lo;
382
- return {(hi >> 32) + (new_lo < lo ? 1 : 0), new_lo};
383
- }
384
- friend auto operator-(const uint128_fallback& lhs, uint64_t rhs)
385
- -> uint128_fallback {
386
- return {lhs.hi_ - (lhs.lo_ < rhs ? 1 : 0), lhs.lo_ - rhs};
387
- }
388
- FMT_CONSTEXPR auto operator>>(int shift) const -> uint128_fallback {
389
- if (shift == 64) return {0, hi_};
390
- if (shift > 64) return uint128_fallback(0, hi_) >> (shift - 64);
391
- return {hi_ >> shift, (hi_ << (64 - shift)) | (lo_ >> shift)};
392
- }
393
- FMT_CONSTEXPR auto operator<<(int shift) const -> uint128_fallback {
394
- if (shift == 64) return {lo_, 0};
395
- if (shift > 64) return uint128_fallback(lo_, 0) << (shift - 64);
396
- return {hi_ << shift | (lo_ >> (64 - shift)), (lo_ << shift)};
397
- }
398
- FMT_CONSTEXPR auto operator>>=(int shift) -> uint128_fallback& {
399
- return *this = *this >> shift;
400
- }
401
- FMT_CONSTEXPR void operator+=(uint128_fallback n) {
402
- uint64_t new_lo = lo_ + n.lo_;
403
- uint64_t new_hi = hi_ + n.hi_ + (new_lo < lo_ ? 1 : 0);
404
- FMT_ASSERT(new_hi >= hi_, "");
405
- lo_ = new_lo;
406
- hi_ = new_hi;
407
- }
408
- FMT_CONSTEXPR void operator&=(uint128_fallback n) {
409
- lo_ &= n.lo_;
410
- hi_ &= n.hi_;
411
- }
412
-
413
- FMT_CONSTEXPR20 auto operator+=(uint64_t n) noexcept -> uint128_fallback& {
414
- if (is_constant_evaluated()) {
415
- lo_ += n;
416
- hi_ += (lo_ < n ? 1 : 0);
417
- return *this;
418
- }
419
- #if FMT_HAS_BUILTIN(__builtin_addcll) && !defined(__ibmxl__)
420
- unsigned long long carry;
421
- lo_ = __builtin_addcll(lo_, n, 0, &carry);
422
- hi_ += carry;
423
- #elif FMT_HAS_BUILTIN(__builtin_ia32_addcarryx_u64) && !defined(__ibmxl__)
424
- unsigned long long result;
425
- auto carry = __builtin_ia32_addcarryx_u64(0, lo_, n, &result);
426
- lo_ = result;
427
- hi_ += carry;
428
- #elif defined(_MSC_VER) && defined(_M_X64)
429
- auto carry = _addcarry_u64(0, lo_, n, &lo_);
430
- _addcarry_u64(carry, hi_, 0, &hi_);
431
- #else
432
- lo_ += n;
433
- hi_ += (lo_ < n ? 1 : 0);
434
- #endif
435
- return *this;
436
- }
437
- };
438
-
439
- using uint128_t = conditional_t<FMT_USE_INT128, uint128_opt, uint128_fallback>;
440
-
441
- #ifdef UINTPTR_MAX
442
- using uintptr_t = ::uintptr_t;
443
- #else
444
- using uintptr_t = uint128_t;
445
- #endif
446
-
447
- // Returns the largest possible value for type T. Same as
448
- // std::numeric_limits<T>::max() but shorter and not affected by the max macro.
449
- template <typename T> constexpr auto max_value() -> T {
450
- return (std::numeric_limits<T>::max)();
451
- }
452
- template <typename T> constexpr auto num_bits() -> int {
453
- return std::numeric_limits<T>::digits;
454
- }
455
- // std::numeric_limits<T>::digits may return 0 for 128-bit ints.
456
- template <> constexpr auto num_bits<int128_opt>() -> int { return 128; }
457
- template <> constexpr auto num_bits<uint128_t>() -> int { return 128; }
458
-
459
- // A heterogeneous bit_cast used for converting 96-bit long double to uint128_t
460
- // and 128-bit pointers to uint128_fallback.
461
- template <typename To, typename From, FMT_ENABLE_IF(sizeof(To) > sizeof(From))>
462
- inline auto bit_cast(const From& from) -> To {
463
- constexpr auto size = static_cast<int>(sizeof(From) / sizeof(unsigned));
464
- struct data_t {
465
- unsigned value[static_cast<unsigned>(size)];
466
- } data = bit_cast<data_t>(from);
467
- auto result = To();
468
- if (const_check(is_big_endian())) {
469
- for (int i = 0; i < size; ++i)
470
- result = (result << num_bits<unsigned>()) | data.value[i];
471
- } else {
472
- for (int i = size - 1; i >= 0; --i)
473
- result = (result << num_bits<unsigned>()) | data.value[i];
474
- }
475
- return result;
476
- }
477
-
478
- template <typename UInt>
479
- FMT_CONSTEXPR20 inline auto countl_zero_fallback(UInt n) -> int {
480
- int lz = 0;
481
- constexpr UInt msb_mask = static_cast<UInt>(1) << (num_bits<UInt>() - 1);
482
- for (; (n & msb_mask) == 0; n <<= 1) lz++;
483
- return lz;
484
- }
485
-
486
- FMT_CONSTEXPR20 inline auto countl_zero(uint32_t n) -> int {
487
- #ifdef FMT_BUILTIN_CLZ
488
- if (!is_constant_evaluated()) return FMT_BUILTIN_CLZ(n);
489
- #endif
490
- return countl_zero_fallback(n);
491
- }
492
-
493
- FMT_CONSTEXPR20 inline auto countl_zero(uint64_t n) -> int {
494
- #ifdef FMT_BUILTIN_CLZLL
495
- if (!is_constant_evaluated()) return FMT_BUILTIN_CLZLL(n);
496
- #endif
497
- return countl_zero_fallback(n);
498
- }
499
-
500
- FMT_INLINE void assume(bool condition) {
501
- (void)condition;
502
- #if FMT_HAS_BUILTIN(__builtin_assume) && !FMT_ICC_VERSION
503
- __builtin_assume(condition);
504
- #elif FMT_GCC_VERSION
505
- if (!condition) __builtin_unreachable();
506
- #endif
507
- }
508
-
509
- // An approximation of iterator_t for pre-C++20 systems.
510
- template <typename T>
511
- using iterator_t = decltype(std::begin(std::declval<T&>()));
512
- template <typename T> using sentinel_t = decltype(std::end(std::declval<T&>()));
513
-
514
- // A workaround for std::string not having mutable data() until C++17.
515
- template <typename Char>
516
- inline auto get_data(std::basic_string<Char>& s) -> Char* {
517
- return &s[0];
518
- }
519
- template <typename Container>
520
- inline auto get_data(Container& c) -> typename Container::value_type* {
521
- return c.data();
522
- }
523
-
524
- // Attempts to reserve space for n extra characters in the output range.
525
- // Returns a pointer to the reserved range or a reference to it.
526
- template <typename Container, FMT_ENABLE_IF(is_contiguous<Container>::value)>
527
- #if FMT_CLANG_VERSION >= 307 && !FMT_ICC_VERSION
528
- __attribute__((no_sanitize("undefined")))
529
- #endif
530
- inline auto
531
- reserve(std::back_insert_iterator<Container> it, size_t n) ->
532
- typename Container::value_type* {
533
- Container& c = get_container(it);
534
- size_t size = c.size();
535
- c.resize(size + n);
536
- return get_data(c) + size;
537
- }
538
-
539
- template <typename T>
540
- inline auto reserve(buffer_appender<T> it, size_t n) -> buffer_appender<T> {
541
- buffer<T>& buf = get_container(it);
542
- buf.try_reserve(buf.size() + n);
543
- return it;
544
- }
545
-
546
- template <typename Iterator>
547
- constexpr auto reserve(Iterator& it, size_t) -> Iterator& {
548
- return it;
549
- }
550
-
551
- template <typename OutputIt>
552
- using reserve_iterator =
553
- remove_reference_t<decltype(reserve(std::declval<OutputIt&>(), 0))>;
554
-
555
- template <typename T, typename OutputIt>
556
- constexpr auto to_pointer(OutputIt, size_t) -> T* {
557
- return nullptr;
558
- }
559
- template <typename T> auto to_pointer(buffer_appender<T> it, size_t n) -> T* {
560
- buffer<T>& buf = get_container(it);
561
- auto size = buf.size();
562
- if (buf.capacity() < size + n) return nullptr;
563
- buf.try_resize(size + n);
564
- return buf.data() + size;
565
- }
566
-
567
- template <typename Container, FMT_ENABLE_IF(is_contiguous<Container>::value)>
568
- inline auto base_iterator(std::back_insert_iterator<Container> it,
569
- typename Container::value_type*)
570
- -> std::back_insert_iterator<Container> {
571
- return it;
572
- }
573
-
574
- template <typename Iterator>
575
- constexpr auto base_iterator(Iterator, Iterator it) -> Iterator {
576
- return it;
577
- }
578
-
579
- // <algorithm> is spectacularly slow to compile in C++20 so use a simple fill_n
580
- // instead (#1998).
581
- template <typename OutputIt, typename Size, typename T>
582
- FMT_CONSTEXPR auto fill_n(OutputIt out, Size count, const T& value)
583
- -> OutputIt {
584
- for (Size i = 0; i < count; ++i) *out++ = value;
585
- return out;
586
- }
587
- template <typename T, typename Size>
588
- FMT_CONSTEXPR20 auto fill_n(T* out, Size count, char value) -> T* {
589
- if (is_constant_evaluated()) {
590
- return fill_n<T*, Size, T>(out, count, value);
591
- }
592
- std::memset(out, value, to_unsigned(count));
593
- return out + count;
594
- }
595
-
596
- #ifdef __cpp_char8_t
597
- using char8_type = char8_t;
598
- #else
599
- enum char8_type : unsigned char {};
600
- #endif
601
-
602
- template <typename OutChar, typename InputIt, typename OutputIt>
603
- FMT_CONSTEXPR FMT_NOINLINE auto copy_str_noinline(InputIt begin, InputIt end,
604
- OutputIt out) -> OutputIt {
605
- return copy_str<OutChar>(begin, end, out);
606
- }
607
-
608
- // A public domain branchless UTF-8 decoder by Christopher Wellons:
609
- // https://github.com/skeeto/branchless-utf8
610
- /* Decode the next character, c, from s, reporting errors in e.
611
- *
612
- * Since this is a branchless decoder, four bytes will be read from the
613
- * buffer regardless of the actual length of the next character. This
614
- * means the buffer _must_ have at least three bytes of zero padding
615
- * following the end of the data stream.
616
- *
617
- * Errors are reported in e, which will be non-zero if the parsed
618
- * character was somehow invalid: invalid byte sequence, non-canonical
619
- * encoding, or a surrogate half.
620
- *
621
- * The function returns a pointer to the next character. When an error
622
- * occurs, this pointer will be a guess that depends on the particular
623
- * error, but it will always advance at least one byte.
624
- */
625
- FMT_CONSTEXPR inline auto utf8_decode(const char* s, uint32_t* c, int* e)
626
- -> const char* {
627
- constexpr const int masks[] = {0x00, 0x7f, 0x1f, 0x0f, 0x07};
628
- constexpr const uint32_t mins[] = {4194304, 0, 128, 2048, 65536};
629
- constexpr const int shiftc[] = {0, 18, 12, 6, 0};
630
- constexpr const int shifte[] = {0, 6, 4, 2, 0};
631
-
632
- int len = "\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\0\0\0\0\0\0\0\0\2\2\2\2\3\3\4"
633
- [static_cast<unsigned char>(*s) >> 3];
634
- // Compute the pointer to the next character early so that the next
635
- // iteration can start working on the next character. Neither Clang
636
- // nor GCC figure out this reordering on their own.
637
- const char* next = s + len + !len;
638
-
639
- using uchar = unsigned char;
640
-
641
- // Assume a four-byte character and load four bytes. Unused bits are
642
- // shifted out.
643
- *c = uint32_t(uchar(s[0]) & masks[len]) << 18;
644
- *c |= uint32_t(uchar(s[1]) & 0x3f) << 12;
645
- *c |= uint32_t(uchar(s[2]) & 0x3f) << 6;
646
- *c |= uint32_t(uchar(s[3]) & 0x3f) << 0;
647
- *c >>= shiftc[len];
648
-
649
- // Accumulate the various error conditions.
650
- *e = (*c < mins[len]) << 6; // non-canonical encoding
651
- *e |= ((*c >> 11) == 0x1b) << 7; // surrogate half?
652
- *e |= (*c > 0x10FFFF) << 8; // out of range?
653
- *e |= (uchar(s[1]) & 0xc0) >> 2;
654
- *e |= (uchar(s[2]) & 0xc0) >> 4;
655
- *e |= uchar(s[3]) >> 6;
656
- *e ^= 0x2a; // top two bits of each tail byte correct?
657
- *e >>= shifte[len];
658
-
659
- return next;
660
- }
661
-
662
- constexpr FMT_INLINE_VARIABLE uint32_t invalid_code_point = ~uint32_t();
663
-
664
- // Invokes f(cp, sv) for every code point cp in s with sv being the string view
665
- // corresponding to the code point. cp is invalid_code_point on error.
666
- template <typename F>
667
- FMT_CONSTEXPR void for_each_codepoint(string_view s, F f) {
668
- auto decode = [f](const char* buf_ptr, const char* ptr) {
669
- auto cp = uint32_t();
670
- auto error = 0;
671
- auto end = utf8_decode(buf_ptr, &cp, &error);
672
- bool result = f(error ? invalid_code_point : cp,
673
- string_view(ptr, error ? 1 : to_unsigned(end - buf_ptr)));
674
- return result ? (error ? buf_ptr + 1 : end) : nullptr;
675
- };
676
- auto p = s.data();
677
- const size_t block_size = 4; // utf8_decode always reads blocks of 4 chars.
678
- if (s.size() >= block_size) {
679
- for (auto end = p + s.size() - block_size + 1; p < end;) {
680
- p = decode(p, p);
681
- if (!p) return;
682
- }
683
- }
684
- if (auto num_chars_left = s.data() + s.size() - p) {
685
- char buf[2 * block_size - 1] = {};
686
- copy_str<char>(p, p + num_chars_left, buf);
687
- const char* buf_ptr = buf;
688
- do {
689
- auto end = decode(buf_ptr, p);
690
- if (!end) return;
691
- p += end - buf_ptr;
692
- buf_ptr = end;
693
- } while (buf_ptr - buf < num_chars_left);
694
- }
695
- }
696
-
697
- template <typename Char>
698
- inline auto compute_width(basic_string_view<Char> s) -> size_t {
699
- return s.size();
700
- }
701
-
702
- // Computes approximate display width of a UTF-8 string.
703
- FMT_CONSTEXPR inline auto compute_width(string_view s) -> size_t {
704
- size_t num_code_points = 0;
705
- // It is not a lambda for compatibility with C++14.
706
- struct count_code_points {
707
- size_t* count;
708
- FMT_CONSTEXPR auto operator()(uint32_t cp, string_view) const -> bool {
709
- *count += detail::to_unsigned(
710
- 1 +
711
- (cp >= 0x1100 &&
712
- (cp <= 0x115f || // Hangul Jamo init. consonants
713
- cp == 0x2329 || // LEFT-POINTING ANGLE BRACKET
714
- cp == 0x232a || // RIGHT-POINTING ANGLE BRACKET
715
- // CJK ... Yi except IDEOGRAPHIC HALF FILL SPACE:
716
- (cp >= 0x2e80 && cp <= 0xa4cf && cp != 0x303f) ||
717
- (cp >= 0xac00 && cp <= 0xd7a3) || // Hangul Syllables
718
- (cp >= 0xf900 && cp <= 0xfaff) || // CJK Compatibility Ideographs
719
- (cp >= 0xfe10 && cp <= 0xfe19) || // Vertical Forms
720
- (cp >= 0xfe30 && cp <= 0xfe6f) || // CJK Compatibility Forms
721
- (cp >= 0xff00 && cp <= 0xff60) || // Fullwidth Forms
722
- (cp >= 0xffe0 && cp <= 0xffe6) || // Fullwidth Forms
723
- (cp >= 0x20000 && cp <= 0x2fffd) || // CJK
724
- (cp >= 0x30000 && cp <= 0x3fffd) ||
725
- // Miscellaneous Symbols and Pictographs + Emoticons:
726
- (cp >= 0x1f300 && cp <= 0x1f64f) ||
727
- // Supplemental Symbols and Pictographs:
728
- (cp >= 0x1f900 && cp <= 0x1f9ff))));
729
- return true;
730
- }
731
- };
732
- // We could avoid branches by using utf8_decode directly.
733
- for_each_codepoint(s, count_code_points{&num_code_points});
734
- return num_code_points;
735
- }
736
-
737
- inline auto compute_width(basic_string_view<char8_type> s) -> size_t {
738
- return compute_width(
739
- string_view(reinterpret_cast<const char*>(s.data()), s.size()));
740
- }
741
-
742
- template <typename Char>
743
- inline auto code_point_index(basic_string_view<Char> s, size_t n) -> size_t {
744
- size_t size = s.size();
745
- return n < size ? n : size;
746
- }
747
-
748
- // Calculates the index of the nth code point in a UTF-8 string.
749
- inline auto code_point_index(string_view s, size_t n) -> size_t {
750
- size_t result = s.size();
751
- const char* begin = s.begin();
752
- for_each_codepoint(s, [begin, &n, &result](uint32_t, string_view sv) {
753
- if (n != 0) {
754
- --n;
755
- return true;
756
- }
757
- result = to_unsigned(sv.begin() - begin);
758
- return false;
759
- });
760
- return result;
761
- }
762
-
763
- inline auto code_point_index(basic_string_view<char8_type> s, size_t n)
764
- -> size_t {
765
- return code_point_index(
766
- string_view(reinterpret_cast<const char*>(s.data()), s.size()), n);
767
- }
768
-
769
- template <typename T> struct is_integral : std::is_integral<T> {};
770
- template <> struct is_integral<int128_opt> : std::true_type {};
771
- template <> struct is_integral<uint128_t> : std::true_type {};
772
-
773
- template <typename T>
774
- using is_signed =
775
- std::integral_constant<bool, std::numeric_limits<T>::is_signed ||
776
- std::is_same<T, int128_opt>::value>;
777
-
778
- template <typename T>
779
- using is_integer =
780
- bool_constant<is_integral<T>::value && !std::is_same<T, bool>::value &&
781
- !std::is_same<T, char>::value &&
782
- !std::is_same<T, wchar_t>::value>;
783
-
784
- #ifndef FMT_USE_FLOAT
785
- # define FMT_USE_FLOAT 1
786
- #endif
787
- #ifndef FMT_USE_DOUBLE
788
- # define FMT_USE_DOUBLE 1
789
- #endif
790
- #ifndef FMT_USE_LONG_DOUBLE
791
- # define FMT_USE_LONG_DOUBLE 1
792
- #endif
793
-
794
- #ifndef FMT_USE_FLOAT128
795
- # ifdef __clang__
796
- // Clang emulates GCC, so it has to appear early.
797
- # if FMT_HAS_INCLUDE(<quadmath.h>)
798
- # define FMT_USE_FLOAT128 1
799
- # endif
800
- # elif defined(__GNUC__)
801
- // GNU C++:
802
- # if defined(_GLIBCXX_USE_FLOAT128) && !defined(__STRICT_ANSI__)
803
- # define FMT_USE_FLOAT128 1
804
- # endif
805
- # endif
806
- # ifndef FMT_USE_FLOAT128
807
- # define FMT_USE_FLOAT128 0
808
- # endif
809
- #endif
810
-
811
- #if FMT_USE_FLOAT128
812
- using float128 = __float128;
813
- #else
814
- using float128 = void;
815
- #endif
816
- template <typename T> using is_float128 = std::is_same<T, float128>;
817
-
818
- template <typename T>
819
- using is_floating_point =
820
- bool_constant<std::is_floating_point<T>::value || is_float128<T>::value>;
821
-
822
- template <typename T, bool = std::is_floating_point<T>::value>
823
- struct is_fast_float : bool_constant<std::numeric_limits<T>::is_iec559 &&
824
- sizeof(T) <= sizeof(double)> {};
825
- template <typename T> struct is_fast_float<T, false> : std::false_type {};
826
-
827
- template <typename T>
828
- using is_double_double = bool_constant<std::numeric_limits<T>::digits == 106>;
829
-
830
- #ifndef FMT_USE_FULL_CACHE_DRAGONBOX
831
- # define FMT_USE_FULL_CACHE_DRAGONBOX 0
832
- #endif
833
-
834
- template <typename T>
835
- template <typename U>
836
- void buffer<T>::append(const U* begin, const U* end) {
837
- while (begin != end) {
838
- auto count = to_unsigned(end - begin);
839
- try_reserve(size_ + count);
840
- auto free_cap = capacity_ - size_;
841
- if (free_cap < count) count = free_cap;
842
- std::uninitialized_copy_n(begin, count, ptr_ + size_);
843
- size_ += count;
844
- begin += count;
845
- }
846
- }
847
-
848
- template <typename T, typename Enable = void>
849
- struct is_locale : std::false_type {};
850
- template <typename T>
851
- struct is_locale<T, void_t<decltype(T::classic())>> : std::true_type {};
852
- } // namespace detail
853
-
854
- FMT_BEGIN_EXPORT
855
-
856
- // The number of characters to store in the basic_memory_buffer object itself
857
- // to avoid dynamic memory allocation.
858
- enum { inline_buffer_size = 500 };
859
-
860
- /**
861
- \rst
862
- A dynamically growing memory buffer for trivially copyable/constructible types
863
- with the first ``SIZE`` elements stored in the object itself.
864
-
865
- You can use the ``memory_buffer`` type alias for ``char`` instead.
866
-
867
- **Example**::
868
-
869
- auto out = fmt::memory_buffer();
870
- fmt::format_to(std::back_inserter(out), "The answer is {}.", 42);
871
-
872
- This will append the following output to the ``out`` object:
873
-
874
- .. code-block:: none
875
-
876
- The answer is 42.
877
-
878
- The output can be converted to an ``std::string`` with ``to_string(out)``.
879
- \endrst
880
- */
881
- template <typename T, size_t SIZE = inline_buffer_size,
882
- typename Allocator = std::allocator<T>>
883
- class basic_memory_buffer final : public detail::buffer<T> {
884
- private:
885
- T store_[SIZE];
886
-
887
- // Don't inherit from Allocator to avoid generating type_info for it.
888
- FMT_NO_UNIQUE_ADDRESS Allocator alloc_;
889
-
890
- // Deallocate memory allocated by the buffer.
891
- FMT_CONSTEXPR20 void deallocate() {
892
- T* data = this->data();
893
- if (data != store_) alloc_.deallocate(data, this->capacity());
894
- }
895
-
896
- protected:
897
- FMT_CONSTEXPR20 void grow(size_t size) override {
898
- detail::abort_fuzzing_if(size > 5000);
899
- const size_t max_size = std::allocator_traits<Allocator>::max_size(alloc_);
900
- size_t old_capacity = this->capacity();
901
- size_t new_capacity = old_capacity + old_capacity / 2;
902
- if (size > new_capacity)
903
- new_capacity = size;
904
- else if (new_capacity > max_size)
905
- new_capacity = size > max_size ? size : max_size;
906
- T* old_data = this->data();
907
- T* new_data =
908
- std::allocator_traits<Allocator>::allocate(alloc_, new_capacity);
909
- // Suppress a bogus -Wstringop-overflow in gcc 13.1 (#3481).
910
- detail::assume(this->size() <= new_capacity);
911
- // The following code doesn't throw, so the raw pointer above doesn't leak.
912
- std::uninitialized_copy_n(old_data, this->size(), new_data);
913
- this->set(new_data, new_capacity);
914
- // deallocate must not throw according to the standard, but even if it does,
915
- // the buffer already uses the new storage and will deallocate it in
916
- // destructor.
917
- if (old_data != store_) alloc_.deallocate(old_data, old_capacity);
918
- }
919
-
920
- public:
921
- using value_type = T;
922
- using const_reference = const T&;
923
-
924
- FMT_CONSTEXPR20 explicit basic_memory_buffer(
925
- const Allocator& alloc = Allocator())
926
- : alloc_(alloc) {
927
- this->set(store_, SIZE);
928
- if (detail::is_constant_evaluated()) detail::fill_n(store_, SIZE, T());
929
- }
930
- FMT_CONSTEXPR20 ~basic_memory_buffer() { deallocate(); }
931
-
932
- private:
933
- // Move data from other to this buffer.
934
- FMT_CONSTEXPR20 void move(basic_memory_buffer& other) {
935
- alloc_ = std::move(other.alloc_);
936
- T* data = other.data();
937
- size_t size = other.size(), capacity = other.capacity();
938
- if (data == other.store_) {
939
- this->set(store_, capacity);
940
- detail::copy_str<T>(other.store_, other.store_ + size, store_);
941
- } else {
942
- this->set(data, capacity);
943
- // Set pointer to the inline array so that delete is not called
944
- // when deallocating.
945
- other.set(other.store_, 0);
946
- other.clear();
947
- }
948
- this->resize(size);
949
- }
950
-
951
- public:
952
- /**
953
- \rst
954
- Constructs a :class:`fmt::basic_memory_buffer` object moving the content
955
- of the other object to it.
956
- \endrst
957
- */
958
- FMT_CONSTEXPR20 basic_memory_buffer(basic_memory_buffer&& other) noexcept {
959
- move(other);
960
- }
961
-
962
- /**
963
- \rst
964
- Moves the content of the other ``basic_memory_buffer`` object to this one.
965
- \endrst
966
- */
967
- auto operator=(basic_memory_buffer&& other) noexcept -> basic_memory_buffer& {
968
- FMT_ASSERT(this != &other, "");
969
- deallocate();
970
- move(other);
971
- return *this;
972
- }
973
-
974
- // Returns a copy of the allocator associated with this buffer.
975
- auto get_allocator() const -> Allocator { return alloc_; }
976
-
977
- /**
978
- Resizes the buffer to contain *count* elements. If T is a POD type new
979
- elements may not be initialized.
980
- */
981
- FMT_CONSTEXPR20 void resize(size_t count) { this->try_resize(count); }
982
-
983
- /** Increases the buffer capacity to *new_capacity*. */
984
- void reserve(size_t new_capacity) { this->try_reserve(new_capacity); }
985
-
986
- using detail::buffer<T>::append;
987
- template <typename ContiguousRange>
988
- void append(const ContiguousRange& range) {
989
- append(range.data(), range.data() + range.size());
990
- }
991
- };
992
-
993
- using memory_buffer = basic_memory_buffer<char>;
994
-
995
- template <typename T, size_t SIZE, typename Allocator>
996
- struct is_contiguous<basic_memory_buffer<T, SIZE, Allocator>> : std::true_type {
997
- };
998
-
999
- FMT_END_EXPORT
1000
- namespace detail {
1001
- FMT_API auto write_console(int fd, string_view text) -> bool;
1002
- FMT_API auto write_console(std::FILE* f, string_view text) -> bool;
1003
- FMT_API void print(std::FILE*, string_view);
1004
- } // namespace detail
1005
-
1006
- FMT_BEGIN_EXPORT
1007
-
1008
- // Suppress a misleading warning in older versions of clang.
1009
- #if FMT_CLANG_VERSION
1010
- # pragma clang diagnostic ignored "-Wweak-vtables"
1011
- #endif
1012
-
1013
- /** An error reported from a formatting function. */
1014
- class FMT_SO_VISIBILITY("default") format_error : public std::runtime_error {
1015
- public:
1016
- using std::runtime_error::runtime_error;
1017
- };
1018
-
1019
- namespace detail_exported {
1020
- #if FMT_USE_NONTYPE_TEMPLATE_ARGS
1021
- template <typename Char, size_t N> struct fixed_string {
1022
- constexpr fixed_string(const Char (&str)[N]) {
1023
- detail::copy_str<Char, const Char*, Char*>(static_cast<const Char*>(str),
1024
- str + N, data);
1025
- }
1026
- Char data[N] = {};
1027
- };
1028
- #endif
1029
-
1030
- // Converts a compile-time string to basic_string_view.
1031
- template <typename Char, size_t N>
1032
- constexpr auto compile_string_to_view(const Char (&s)[N])
1033
- -> basic_string_view<Char> {
1034
- // Remove trailing NUL character if needed. Won't be present if this is used
1035
- // with a raw character array (i.e. not defined as a string).
1036
- return {s, N - (std::char_traits<Char>::to_int_type(s[N - 1]) == 0 ? 1 : 0)};
1037
- }
1038
- template <typename Char>
1039
- constexpr auto compile_string_to_view(detail::std_string_view<Char> s)
1040
- -> basic_string_view<Char> {
1041
- return {s.data(), s.size()};
1042
- }
1043
- } // namespace detail_exported
1044
-
1045
- class loc_value {
1046
- private:
1047
- basic_format_arg<format_context> value_;
1048
-
1049
- public:
1050
- template <typename T, FMT_ENABLE_IF(!detail::is_float128<T>::value)>
1051
- loc_value(T value) : value_(detail::make_arg<format_context>(value)) {}
1052
-
1053
- template <typename T, FMT_ENABLE_IF(detail::is_float128<T>::value)>
1054
- loc_value(T) {}
1055
-
1056
- template <typename Visitor> auto visit(Visitor&& vis) -> decltype(vis(0)) {
1057
- return visit_format_arg(vis, value_);
1058
- }
1059
- };
1060
-
1061
- // A locale facet that formats values in UTF-8.
1062
- // It is parameterized on the locale to avoid the heavy <locale> include.
1063
- template <typename Locale> class format_facet : public Locale::facet {
1064
- private:
1065
- std::string separator_;
1066
- std::string grouping_;
1067
- std::string decimal_point_;
1068
-
1069
- protected:
1070
- virtual auto do_put(appender out, loc_value val,
1071
- const format_specs<>& specs) const -> bool;
1072
-
1073
- public:
1074
- static FMT_API typename Locale::id id;
1075
-
1076
- explicit format_facet(Locale& loc);
1077
- explicit format_facet(string_view sep = "",
1078
- std::initializer_list<unsigned char> g = {3},
1079
- std::string decimal_point = ".")
1080
- : separator_(sep.data(), sep.size()),
1081
- grouping_(g.begin(), g.end()),
1082
- decimal_point_(decimal_point) {}
1083
-
1084
- auto put(appender out, loc_value val, const format_specs<>& specs) const
1085
- -> bool {
1086
- return do_put(out, val, specs);
1087
- }
1088
- };
1089
-
1090
- namespace detail {
1091
-
1092
- // Returns true if value is negative, false otherwise.
1093
- // Same as `value < 0` but doesn't produce warnings if T is an unsigned type.
1094
- template <typename T, FMT_ENABLE_IF(is_signed<T>::value)>
1095
- constexpr auto is_negative(T value) -> bool {
1096
- return value < 0;
1097
- }
1098
- template <typename T, FMT_ENABLE_IF(!is_signed<T>::value)>
1099
- constexpr auto is_negative(T) -> bool {
1100
- return false;
1101
- }
1102
-
1103
- template <typename T>
1104
- FMT_CONSTEXPR auto is_supported_floating_point(T) -> bool {
1105
- if (std::is_same<T, float>()) return FMT_USE_FLOAT;
1106
- if (std::is_same<T, double>()) return FMT_USE_DOUBLE;
1107
- if (std::is_same<T, long double>()) return FMT_USE_LONG_DOUBLE;
1108
- return true;
1109
- }
1110
-
1111
- // Smallest of uint32_t, uint64_t, uint128_t that is large enough to
1112
- // represent all values of an integral type T.
1113
- template <typename T>
1114
- using uint32_or_64_or_128_t =
1115
- conditional_t<num_bits<T>() <= 32 && !FMT_REDUCE_INT_INSTANTIATIONS,
1116
- uint32_t,
1117
- conditional_t<num_bits<T>() <= 64, uint64_t, uint128_t>>;
1118
- template <typename T>
1119
- using uint64_or_128_t = conditional_t<num_bits<T>() <= 64, uint64_t, uint128_t>;
1120
-
1121
- #define FMT_POWERS_OF_10(factor) \
1122
- factor * 10, (factor) * 100, (factor) * 1000, (factor) * 10000, \
1123
- (factor) * 100000, (factor) * 1000000, (factor) * 10000000, \
1124
- (factor) * 100000000, (factor) * 1000000000
1125
-
1126
- // Converts value in the range [0, 100) to a string.
1127
- constexpr auto digits2(size_t value) -> const char* {
1128
- // GCC generates slightly better code when value is pointer-size.
1129
- return &"0001020304050607080910111213141516171819"
1130
- "2021222324252627282930313233343536373839"
1131
- "4041424344454647484950515253545556575859"
1132
- "6061626364656667686970717273747576777879"
1133
- "8081828384858687888990919293949596979899"[value * 2];
1134
- }
1135
-
1136
- // Sign is a template parameter to workaround a bug in gcc 4.8.
1137
- template <typename Char, typename Sign> constexpr auto sign(Sign s) -> Char {
1138
- #if !FMT_GCC_VERSION || FMT_GCC_VERSION >= 604
1139
- static_assert(std::is_same<Sign, sign_t>::value, "");
1140
- #endif
1141
- return static_cast<Char>("\0-+ "[s]);
1142
- }
1143
-
1144
- template <typename T> FMT_CONSTEXPR auto count_digits_fallback(T n) -> int {
1145
- int count = 1;
1146
- for (;;) {
1147
- // Integer division is slow so do it for a group of four digits instead
1148
- // of for every digit. The idea comes from the talk by Alexandrescu
1149
- // "Three Optimization Tips for C++". See speed-test for a comparison.
1150
- if (n < 10) return count;
1151
- if (n < 100) return count + 1;
1152
- if (n < 1000) return count + 2;
1153
- if (n < 10000) return count + 3;
1154
- n /= 10000u;
1155
- count += 4;
1156
- }
1157
- }
1158
- #if FMT_USE_INT128
1159
- FMT_CONSTEXPR inline auto count_digits(uint128_opt n) -> int {
1160
- return count_digits_fallback(n);
1161
- }
1162
- #endif
1163
-
1164
- #ifdef FMT_BUILTIN_CLZLL
1165
- // It is a separate function rather than a part of count_digits to workaround
1166
- // the lack of static constexpr in constexpr functions.
1167
- inline auto do_count_digits(uint64_t n) -> int {
1168
- // This has comparable performance to the version by Kendall Willets
1169
- // (https://github.com/fmtlib/format-benchmark/blob/master/digits10)
1170
- // but uses smaller tables.
1171
- // Maps bsr(n) to ceil(log10(pow(2, bsr(n) + 1) - 1)).
1172
- static constexpr uint8_t bsr2log10[] = {
1173
- 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5,
1174
- 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10,
1175
- 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 15, 15,
1176
- 15, 16, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 19, 20};
1177
- auto t = bsr2log10[FMT_BUILTIN_CLZLL(n | 1) ^ 63];
1178
- static constexpr const uint64_t zero_or_powers_of_10[] = {
1179
- 0, 0, FMT_POWERS_OF_10(1U), FMT_POWERS_OF_10(1000000000ULL),
1180
- 10000000000000000000ULL};
1181
- return t - (n < zero_or_powers_of_10[t]);
1182
- }
1183
- #endif
1184
-
1185
- // Returns the number of decimal digits in n. Leading zeros are not counted
1186
- // except for n == 0 in which case count_digits returns 1.
1187
- FMT_CONSTEXPR20 inline auto count_digits(uint64_t n) -> int {
1188
- #ifdef FMT_BUILTIN_CLZLL
1189
- if (!is_constant_evaluated()) {
1190
- return do_count_digits(n);
1191
- }
1192
- #endif
1193
- return count_digits_fallback(n);
1194
- }
1195
-
1196
- // Counts the number of digits in n. BITS = log2(radix).
1197
- template <int BITS, typename UInt>
1198
- FMT_CONSTEXPR auto count_digits(UInt n) -> int {
1199
- #ifdef FMT_BUILTIN_CLZ
1200
- if (!is_constant_evaluated() && num_bits<UInt>() == 32)
1201
- return (FMT_BUILTIN_CLZ(static_cast<uint32_t>(n) | 1) ^ 31) / BITS + 1;
1202
- #endif
1203
- // Lambda avoids unreachable code warnings from NVHPC.
1204
- return [](UInt m) {
1205
- int num_digits = 0;
1206
- do {
1207
- ++num_digits;
1208
- } while ((m >>= BITS) != 0);
1209
- return num_digits;
1210
- }(n);
1211
- }
1212
-
1213
- #ifdef FMT_BUILTIN_CLZ
1214
- // It is a separate function rather than a part of count_digits to workaround
1215
- // the lack of static constexpr in constexpr functions.
1216
- FMT_INLINE auto do_count_digits(uint32_t n) -> int {
1217
- // An optimization by Kendall Willets from https://bit.ly/3uOIQrB.
1218
- // This increments the upper 32 bits (log10(T) - 1) when >= T is added.
1219
- # define FMT_INC(T) (((sizeof(#T) - 1ull) << 32) - T)
1220
- static constexpr uint64_t table[] = {
1221
- FMT_INC(0), FMT_INC(0), FMT_INC(0), // 8
1222
- FMT_INC(10), FMT_INC(10), FMT_INC(10), // 64
1223
- FMT_INC(100), FMT_INC(100), FMT_INC(100), // 512
1224
- FMT_INC(1000), FMT_INC(1000), FMT_INC(1000), // 4096
1225
- FMT_INC(10000), FMT_INC(10000), FMT_INC(10000), // 32k
1226
- FMT_INC(100000), FMT_INC(100000), FMT_INC(100000), // 256k
1227
- FMT_INC(1000000), FMT_INC(1000000), FMT_INC(1000000), // 2048k
1228
- FMT_INC(10000000), FMT_INC(10000000), FMT_INC(10000000), // 16M
1229
- FMT_INC(100000000), FMT_INC(100000000), FMT_INC(100000000), // 128M
1230
- FMT_INC(1000000000), FMT_INC(1000000000), FMT_INC(1000000000), // 1024M
1231
- FMT_INC(1000000000), FMT_INC(1000000000) // 4B
1232
- };
1233
- auto inc = table[FMT_BUILTIN_CLZ(n | 1) ^ 31];
1234
- return static_cast<int>((n + inc) >> 32);
1235
- }
1236
- #endif
1237
-
1238
- // Optional version of count_digits for better performance on 32-bit platforms.
1239
- FMT_CONSTEXPR20 inline auto count_digits(uint32_t n) -> int {
1240
- #ifdef FMT_BUILTIN_CLZ
1241
- if (!is_constant_evaluated()) {
1242
- return do_count_digits(n);
1243
- }
1244
- #endif
1245
- return count_digits_fallback(n);
1246
- }
1247
-
1248
- template <typename Int> constexpr auto digits10() noexcept -> int {
1249
- return std::numeric_limits<Int>::digits10;
1250
- }
1251
- template <> constexpr auto digits10<int128_opt>() noexcept -> int { return 38; }
1252
- template <> constexpr auto digits10<uint128_t>() noexcept -> int { return 38; }
1253
-
1254
- template <typename Char> struct thousands_sep_result {
1255
- std::string grouping;
1256
- Char thousands_sep;
1257
- };
1258
-
1259
- template <typename Char>
1260
- FMT_API auto thousands_sep_impl(locale_ref loc) -> thousands_sep_result<Char>;
1261
- template <typename Char>
1262
- inline auto thousands_sep(locale_ref loc) -> thousands_sep_result<Char> {
1263
- auto result = thousands_sep_impl<char>(loc);
1264
- return {result.grouping, Char(result.thousands_sep)};
1265
- }
1266
- template <>
1267
- inline auto thousands_sep(locale_ref loc) -> thousands_sep_result<wchar_t> {
1268
- return thousands_sep_impl<wchar_t>(loc);
1269
- }
1270
-
1271
- template <typename Char>
1272
- FMT_API auto decimal_point_impl(locale_ref loc) -> Char;
1273
- template <typename Char> inline auto decimal_point(locale_ref loc) -> Char {
1274
- return Char(decimal_point_impl<char>(loc));
1275
- }
1276
- template <> inline auto decimal_point(locale_ref loc) -> wchar_t {
1277
- return decimal_point_impl<wchar_t>(loc);
1278
- }
1279
-
1280
- // Compares two characters for equality.
1281
- template <typename Char> auto equal2(const Char* lhs, const char* rhs) -> bool {
1282
- return lhs[0] == Char(rhs[0]) && lhs[1] == Char(rhs[1]);
1283
- }
1284
- inline auto equal2(const char* lhs, const char* rhs) -> bool {
1285
- return memcmp(lhs, rhs, 2) == 0;
1286
- }
1287
-
1288
- // Copies two characters from src to dst.
1289
- template <typename Char>
1290
- FMT_CONSTEXPR20 FMT_INLINE void copy2(Char* dst, const char* src) {
1291
- if (!is_constant_evaluated() && sizeof(Char) == sizeof(char)) {
1292
- memcpy(dst, src, 2);
1293
- return;
1294
- }
1295
- *dst++ = static_cast<Char>(*src++);
1296
- *dst = static_cast<Char>(*src);
1297
- }
1298
-
1299
- template <typename Iterator> struct format_decimal_result {
1300
- Iterator begin;
1301
- Iterator end;
1302
- };
1303
-
1304
- // Formats a decimal unsigned integer value writing into out pointing to a
1305
- // buffer of specified size. The caller must ensure that the buffer is large
1306
- // enough.
1307
- template <typename Char, typename UInt>
1308
- FMT_CONSTEXPR20 auto format_decimal(Char* out, UInt value, int size)
1309
- -> format_decimal_result<Char*> {
1310
- FMT_ASSERT(size >= count_digits(value), "invalid digit count");
1311
- out += size;
1312
- Char* end = out;
1313
- while (value >= 100) {
1314
- // Integer division is slow so do it for a group of two digits instead
1315
- // of for every digit. The idea comes from the talk by Alexandrescu
1316
- // "Three Optimization Tips for C++". See speed-test for a comparison.
1317
- out -= 2;
1318
- copy2(out, digits2(static_cast<size_t>(value % 100)));
1319
- value /= 100;
1320
- }
1321
- if (value < 10) {
1322
- *--out = static_cast<Char>('0' + value);
1323
- return {out, end};
1324
- }
1325
- out -= 2;
1326
- copy2(out, digits2(static_cast<size_t>(value)));
1327
- return {out, end};
1328
- }
1329
-
1330
- template <typename Char, typename UInt, typename Iterator,
1331
- FMT_ENABLE_IF(!std::is_pointer<remove_cvref_t<Iterator>>::value)>
1332
- FMT_CONSTEXPR inline auto format_decimal(Iterator out, UInt value, int size)
1333
- -> format_decimal_result<Iterator> {
1334
- // Buffer is large enough to hold all digits (digits10 + 1).
1335
- Char buffer[digits10<UInt>() + 1] = {};
1336
- auto end = format_decimal(buffer, value, size).end;
1337
- return {out, detail::copy_str_noinline<Char>(buffer, end, out)};
1338
- }
1339
-
1340
- template <unsigned BASE_BITS, typename Char, typename UInt>
1341
- FMT_CONSTEXPR auto format_uint(Char* buffer, UInt value, int num_digits,
1342
- bool upper = false) -> Char* {
1343
- buffer += num_digits;
1344
- Char* end = buffer;
1345
- do {
1346
- const char* digits = upper ? "0123456789ABCDEF" : "0123456789abcdef";
1347
- unsigned digit = static_cast<unsigned>(value & ((1 << BASE_BITS) - 1));
1348
- *--buffer = static_cast<Char>(BASE_BITS < 4 ? static_cast<char>('0' + digit)
1349
- : digits[digit]);
1350
- } while ((value >>= BASE_BITS) != 0);
1351
- return end;
1352
- }
1353
-
1354
- template <unsigned BASE_BITS, typename Char, typename It, typename UInt>
1355
- FMT_CONSTEXPR inline auto format_uint(It out, UInt value, int num_digits,
1356
- bool upper = false) -> It {
1357
- if (auto ptr = to_pointer<Char>(out, to_unsigned(num_digits))) {
1358
- format_uint<BASE_BITS>(ptr, value, num_digits, upper);
1359
- return out;
1360
- }
1361
- // Buffer should be large enough to hold all digits (digits / BASE_BITS + 1).
1362
- char buffer[num_bits<UInt>() / BASE_BITS + 1] = {};
1363
- format_uint<BASE_BITS>(buffer, value, num_digits, upper);
1364
- return detail::copy_str_noinline<Char>(buffer, buffer + num_digits, out);
1365
- }
1366
-
1367
- // A converter from UTF-8 to UTF-16.
1368
- class utf8_to_utf16 {
1369
- private:
1370
- basic_memory_buffer<wchar_t> buffer_;
1371
-
1372
- public:
1373
- FMT_API explicit utf8_to_utf16(string_view s);
1374
- operator basic_string_view<wchar_t>() const { return {&buffer_[0], size()}; }
1375
- auto size() const -> size_t { return buffer_.size() - 1; }
1376
- auto c_str() const -> const wchar_t* { return &buffer_[0]; }
1377
- auto str() const -> std::wstring { return {&buffer_[0], size()}; }
1378
- };
1379
-
1380
- enum class to_utf8_error_policy { abort, replace };
1381
-
1382
- // A converter from UTF-16/UTF-32 (host endian) to UTF-8.
1383
- template <typename WChar, typename Buffer = memory_buffer> class to_utf8 {
1384
- private:
1385
- Buffer buffer_;
1386
-
1387
- public:
1388
- to_utf8() {}
1389
- explicit to_utf8(basic_string_view<WChar> s,
1390
- to_utf8_error_policy policy = to_utf8_error_policy::abort) {
1391
- static_assert(sizeof(WChar) == 2 || sizeof(WChar) == 4,
1392
- "Expect utf16 or utf32");
1393
- if (!convert(s, policy))
1394
- FMT_THROW(std::runtime_error(sizeof(WChar) == 2 ? "invalid utf16"
1395
- : "invalid utf32"));
1396
- }
1397
- operator string_view() const { return string_view(&buffer_[0], size()); }
1398
- auto size() const -> size_t { return buffer_.size() - 1; }
1399
- auto c_str() const -> const char* { return &buffer_[0]; }
1400
- auto str() const -> std::string { return std::string(&buffer_[0], size()); }
1401
-
1402
- // Performs conversion returning a bool instead of throwing exception on
1403
- // conversion error. This method may still throw in case of memory allocation
1404
- // error.
1405
- auto convert(basic_string_view<WChar> s,
1406
- to_utf8_error_policy policy = to_utf8_error_policy::abort)
1407
- -> bool {
1408
- if (!convert(buffer_, s, policy)) return false;
1409
- buffer_.push_back(0);
1410
- return true;
1411
- }
1412
- static auto convert(Buffer& buf, basic_string_view<WChar> s,
1413
- to_utf8_error_policy policy = to_utf8_error_policy::abort)
1414
- -> bool {
1415
- for (auto p = s.begin(); p != s.end(); ++p) {
1416
- uint32_t c = static_cast<uint32_t>(*p);
1417
- if (sizeof(WChar) == 2 && c >= 0xd800 && c <= 0xdfff) {
1418
- // Handle a surrogate pair.
1419
- ++p;
1420
- if (p == s.end() || (c & 0xfc00) != 0xd800 || (*p & 0xfc00) != 0xdc00) {
1421
- if (policy == to_utf8_error_policy::abort) return false;
1422
- buf.append(string_view("\xEF\xBF\xBD"));
1423
- --p;
1424
- } else {
1425
- c = (c << 10) + static_cast<uint32_t>(*p) - 0x35fdc00;
1426
- }
1427
- } else if (c < 0x80) {
1428
- buf.push_back(static_cast<char>(c));
1429
- } else if (c < 0x800) {
1430
- buf.push_back(static_cast<char>(0xc0 | (c >> 6)));
1431
- buf.push_back(static_cast<char>(0x80 | (c & 0x3f)));
1432
- } else if ((c >= 0x800 && c <= 0xd7ff) || (c >= 0xe000 && c <= 0xffff)) {
1433
- buf.push_back(static_cast<char>(0xe0 | (c >> 12)));
1434
- buf.push_back(static_cast<char>(0x80 | ((c & 0xfff) >> 6)));
1435
- buf.push_back(static_cast<char>(0x80 | (c & 0x3f)));
1436
- } else if (c >= 0x10000 && c <= 0x10ffff) {
1437
- buf.push_back(static_cast<char>(0xf0 | (c >> 18)));
1438
- buf.push_back(static_cast<char>(0x80 | ((c & 0x3ffff) >> 12)));
1439
- buf.push_back(static_cast<char>(0x80 | ((c & 0xfff) >> 6)));
1440
- buf.push_back(static_cast<char>(0x80 | (c & 0x3f)));
1441
- } else {
1442
- return false;
1443
- }
1444
- }
1445
- return true;
1446
- }
1447
- };
1448
-
1449
- // Computes 128-bit result of multiplication of two 64-bit unsigned integers.
1450
- inline auto umul128(uint64_t x, uint64_t y) noexcept -> uint128_fallback {
1451
- #if FMT_USE_INT128
1452
- auto p = static_cast<uint128_opt>(x) * static_cast<uint128_opt>(y);
1453
- return {static_cast<uint64_t>(p >> 64), static_cast<uint64_t>(p)};
1454
- #elif defined(_MSC_VER) && defined(_M_X64)
1455
- auto hi = uint64_t();
1456
- auto lo = _umul128(x, y, &hi);
1457
- return {hi, lo};
1458
- #else
1459
- const uint64_t mask = static_cast<uint64_t>(max_value<uint32_t>());
1460
-
1461
- uint64_t a = x >> 32;
1462
- uint64_t b = x & mask;
1463
- uint64_t c = y >> 32;
1464
- uint64_t d = y & mask;
1465
-
1466
- uint64_t ac = a * c;
1467
- uint64_t bc = b * c;
1468
- uint64_t ad = a * d;
1469
- uint64_t bd = b * d;
1470
-
1471
- uint64_t intermediate = (bd >> 32) + (ad & mask) + (bc & mask);
1472
-
1473
- return {ac + (intermediate >> 32) + (ad >> 32) + (bc >> 32),
1474
- (intermediate << 32) + (bd & mask)};
1475
- #endif
1476
- }
1477
-
1478
- namespace dragonbox {
1479
- // Computes floor(log10(pow(2, e))) for e in [-2620, 2620] using the method from
1480
- // https://fmt.dev/papers/Dragonbox.pdf#page=28, section 6.1.
1481
- inline auto floor_log10_pow2(int e) noexcept -> int {
1482
- FMT_ASSERT(e <= 2620 && e >= -2620, "too large exponent");
1483
- static_assert((-1 >> 1) == -1, "right shift is not arithmetic");
1484
- return (e * 315653) >> 20;
1485
- }
1486
-
1487
- inline auto floor_log2_pow10(int e) noexcept -> int {
1488
- FMT_ASSERT(e <= 1233 && e >= -1233, "too large exponent");
1489
- return (e * 1741647) >> 19;
1490
- }
1491
-
1492
- // Computes upper 64 bits of multiplication of two 64-bit unsigned integers.
1493
- inline auto umul128_upper64(uint64_t x, uint64_t y) noexcept -> uint64_t {
1494
- #if FMT_USE_INT128
1495
- auto p = static_cast<uint128_opt>(x) * static_cast<uint128_opt>(y);
1496
- return static_cast<uint64_t>(p >> 64);
1497
- #elif defined(_MSC_VER) && defined(_M_X64)
1498
- return __umulh(x, y);
1499
- #else
1500
- return umul128(x, y).high();
1501
- #endif
1502
- }
1503
-
1504
- // Computes upper 128 bits of multiplication of a 64-bit unsigned integer and a
1505
- // 128-bit unsigned integer.
1506
- inline auto umul192_upper128(uint64_t x, uint128_fallback y) noexcept
1507
- -> uint128_fallback {
1508
- uint128_fallback r = umul128(x, y.high());
1509
- r += umul128_upper64(x, y.low());
1510
- return r;
1511
- }
1512
-
1513
- FMT_API auto get_cached_power(int k) noexcept -> uint128_fallback;
1514
-
1515
- // Type-specific information that Dragonbox uses.
1516
- template <typename T, typename Enable = void> struct float_info;
1517
-
1518
- template <> struct float_info<float> {
1519
- using carrier_uint = uint32_t;
1520
- static const int exponent_bits = 8;
1521
- static const int kappa = 1;
1522
- static const int big_divisor = 100;
1523
- static const int small_divisor = 10;
1524
- static const int min_k = -31;
1525
- static const int max_k = 46;
1526
- static const int shorter_interval_tie_lower_threshold = -35;
1527
- static const int shorter_interval_tie_upper_threshold = -35;
1528
- };
1529
-
1530
- template <> struct float_info<double> {
1531
- using carrier_uint = uint64_t;
1532
- static const int exponent_bits = 11;
1533
- static const int kappa = 2;
1534
- static const int big_divisor = 1000;
1535
- static const int small_divisor = 100;
1536
- static const int min_k = -292;
1537
- static const int max_k = 341;
1538
- static const int shorter_interval_tie_lower_threshold = -77;
1539
- static const int shorter_interval_tie_upper_threshold = -77;
1540
- };
1541
-
1542
- // An 80- or 128-bit floating point number.
1543
- template <typename T>
1544
- struct float_info<T, enable_if_t<std::numeric_limits<T>::digits == 64 ||
1545
- std::numeric_limits<T>::digits == 113 ||
1546
- is_float128<T>::value>> {
1547
- using carrier_uint = detail::uint128_t;
1548
- static const int exponent_bits = 15;
1549
- };
1550
-
1551
- // A double-double floating point number.
1552
- template <typename T>
1553
- struct float_info<T, enable_if_t<is_double_double<T>::value>> {
1554
- using carrier_uint = detail::uint128_t;
1555
- };
1556
-
1557
- template <typename T> struct decimal_fp {
1558
- using significand_type = typename float_info<T>::carrier_uint;
1559
- significand_type significand;
1560
- int exponent;
1561
- };
1562
-
1563
- template <typename T> FMT_API auto to_decimal(T x) noexcept -> decimal_fp<T>;
1564
- } // namespace dragonbox
1565
-
1566
- // Returns true iff Float has the implicit bit which is not stored.
1567
- template <typename Float> constexpr auto has_implicit_bit() -> bool {
1568
- // An 80-bit FP number has a 64-bit significand an no implicit bit.
1569
- return std::numeric_limits<Float>::digits != 64;
1570
- }
1571
-
1572
- // Returns the number of significand bits stored in Float. The implicit bit is
1573
- // not counted since it is not stored.
1574
- template <typename Float> constexpr auto num_significand_bits() -> int {
1575
- // std::numeric_limits may not support __float128.
1576
- return is_float128<Float>() ? 112
1577
- : (std::numeric_limits<Float>::digits -
1578
- (has_implicit_bit<Float>() ? 1 : 0));
1579
- }
1580
-
1581
- template <typename Float>
1582
- constexpr auto exponent_mask() ->
1583
- typename dragonbox::float_info<Float>::carrier_uint {
1584
- using float_uint = typename dragonbox::float_info<Float>::carrier_uint;
1585
- return ((float_uint(1) << dragonbox::float_info<Float>::exponent_bits) - 1)
1586
- << num_significand_bits<Float>();
1587
- }
1588
- template <typename Float> constexpr auto exponent_bias() -> int {
1589
- // std::numeric_limits may not support __float128.
1590
- return is_float128<Float>() ? 16383
1591
- : std::numeric_limits<Float>::max_exponent - 1;
1592
- }
1593
-
1594
- // Writes the exponent exp in the form "[+-]d{2,3}" to buffer.
1595
- template <typename Char, typename It>
1596
- FMT_CONSTEXPR auto write_exponent(int exp, It it) -> It {
1597
- FMT_ASSERT(-10000 < exp && exp < 10000, "exponent out of range");
1598
- if (exp < 0) {
1599
- *it++ = static_cast<Char>('-');
1600
- exp = -exp;
1601
- } else {
1602
- *it++ = static_cast<Char>('+');
1603
- }
1604
- if (exp >= 100) {
1605
- const char* top = digits2(to_unsigned(exp / 100));
1606
- if (exp >= 1000) *it++ = static_cast<Char>(top[0]);
1607
- *it++ = static_cast<Char>(top[1]);
1608
- exp %= 100;
1609
- }
1610
- const char* d = digits2(to_unsigned(exp));
1611
- *it++ = static_cast<Char>(d[0]);
1612
- *it++ = static_cast<Char>(d[1]);
1613
- return it;
1614
- }
1615
-
1616
- // A floating-point number f * pow(2, e) where F is an unsigned type.
1617
- template <typename F> struct basic_fp {
1618
- F f;
1619
- int e;
1620
-
1621
- static constexpr const int num_significand_bits =
1622
- static_cast<int>(sizeof(F) * num_bits<unsigned char>());
1623
-
1624
- constexpr basic_fp() : f(0), e(0) {}
1625
- constexpr basic_fp(uint64_t f_val, int e_val) : f(f_val), e(e_val) {}
1626
-
1627
- // Constructs fp from an IEEE754 floating-point number.
1628
- template <typename Float> FMT_CONSTEXPR basic_fp(Float n) { assign(n); }
1629
-
1630
- // Assigns n to this and return true iff predecessor is closer than successor.
1631
- template <typename Float, FMT_ENABLE_IF(!is_double_double<Float>::value)>
1632
- FMT_CONSTEXPR auto assign(Float n) -> bool {
1633
- static_assert(std::numeric_limits<Float>::digits <= 113, "unsupported FP");
1634
- // Assume Float is in the format [sign][exponent][significand].
1635
- using carrier_uint = typename dragonbox::float_info<Float>::carrier_uint;
1636
- const auto num_float_significand_bits =
1637
- detail::num_significand_bits<Float>();
1638
- const auto implicit_bit = carrier_uint(1) << num_float_significand_bits;
1639
- const auto significand_mask = implicit_bit - 1;
1640
- auto u = bit_cast<carrier_uint>(n);
1641
- f = static_cast<F>(u & significand_mask);
1642
- auto biased_e = static_cast<int>((u & exponent_mask<Float>()) >>
1643
- num_float_significand_bits);
1644
- // The predecessor is closer if n is a normalized power of 2 (f == 0)
1645
- // other than the smallest normalized number (biased_e > 1).
1646
- auto is_predecessor_closer = f == 0 && biased_e > 1;
1647
- if (biased_e == 0)
1648
- biased_e = 1; // Subnormals use biased exponent 1 (min exponent).
1649
- else if (has_implicit_bit<Float>())
1650
- f += static_cast<F>(implicit_bit);
1651
- e = biased_e - exponent_bias<Float>() - num_float_significand_bits;
1652
- if (!has_implicit_bit<Float>()) ++e;
1653
- return is_predecessor_closer;
1654
- }
1655
-
1656
- template <typename Float, FMT_ENABLE_IF(is_double_double<Float>::value)>
1657
- FMT_CONSTEXPR auto assign(Float n) -> bool {
1658
- static_assert(std::numeric_limits<double>::is_iec559, "unsupported FP");
1659
- return assign(static_cast<double>(n));
1660
- }
1661
- };
1662
-
1663
- using fp = basic_fp<unsigned long long>;
1664
-
1665
- // Normalizes the value converted from double and multiplied by (1 << SHIFT).
1666
- template <int SHIFT = 0, typename F>
1667
- FMT_CONSTEXPR auto normalize(basic_fp<F> value) -> basic_fp<F> {
1668
- // Handle subnormals.
1669
- const auto implicit_bit = F(1) << num_significand_bits<double>();
1670
- const auto shifted_implicit_bit = implicit_bit << SHIFT;
1671
- while ((value.f & shifted_implicit_bit) == 0) {
1672
- value.f <<= 1;
1673
- --value.e;
1674
- }
1675
- // Subtract 1 to account for hidden bit.
1676
- const auto offset = basic_fp<F>::num_significand_bits -
1677
- num_significand_bits<double>() - SHIFT - 1;
1678
- value.f <<= offset;
1679
- value.e -= offset;
1680
- return value;
1681
- }
1682
-
1683
- // Computes lhs * rhs / pow(2, 64) rounded to nearest with half-up tie breaking.
1684
- FMT_CONSTEXPR inline auto multiply(uint64_t lhs, uint64_t rhs) -> uint64_t {
1685
- #if FMT_USE_INT128
1686
- auto product = static_cast<__uint128_t>(lhs) * rhs;
1687
- auto f = static_cast<uint64_t>(product >> 64);
1688
- return (static_cast<uint64_t>(product) & (1ULL << 63)) != 0 ? f + 1 : f;
1689
- #else
1690
- // Multiply 32-bit parts of significands.
1691
- uint64_t mask = (1ULL << 32) - 1;
1692
- uint64_t a = lhs >> 32, b = lhs & mask;
1693
- uint64_t c = rhs >> 32, d = rhs & mask;
1694
- uint64_t ac = a * c, bc = b * c, ad = a * d, bd = b * d;
1695
- // Compute mid 64-bit of result and round.
1696
- uint64_t mid = (bd >> 32) + (ad & mask) + (bc & mask) + (1U << 31);
1697
- return ac + (ad >> 32) + (bc >> 32) + (mid >> 32);
1698
- #endif
1699
- }
1700
-
1701
- FMT_CONSTEXPR inline auto operator*(fp x, fp y) -> fp {
1702
- return {multiply(x.f, y.f), x.e + y.e + 64};
1703
- }
1704
-
1705
- template <typename T, bool doublish = num_bits<T>() == num_bits<double>()>
1706
- using convert_float_result =
1707
- conditional_t<std::is_same<T, float>::value || doublish, double, T>;
1708
-
1709
- template <typename T>
1710
- constexpr auto convert_float(T value) -> convert_float_result<T> {
1711
- return static_cast<convert_float_result<T>>(value);
1712
- }
1713
-
1714
- template <typename OutputIt, typename Char>
1715
- FMT_NOINLINE FMT_CONSTEXPR auto fill(OutputIt it, size_t n,
1716
- const fill_t<Char>& fill) -> OutputIt {
1717
- auto fill_size = fill.size();
1718
- if (fill_size == 1) return detail::fill_n(it, n, fill[0]);
1719
- auto data = fill.data();
1720
- for (size_t i = 0; i < n; ++i)
1721
- it = copy_str<Char>(data, data + fill_size, it);
1722
- return it;
1723
- }
1724
-
1725
- // Writes the output of f, padded according to format specifications in specs.
1726
- // size: output size in code units.
1727
- // width: output display width in (terminal) column positions.
1728
- template <align::type align = align::left, typename OutputIt, typename Char,
1729
- typename F>
1730
- FMT_CONSTEXPR auto write_padded(OutputIt out, const format_specs<Char>& specs,
1731
- size_t size, size_t width, F&& f) -> OutputIt {
1732
- static_assert(align == align::left || align == align::right, "");
1733
- unsigned spec_width = to_unsigned(specs.width);
1734
- size_t padding = spec_width > width ? spec_width - width : 0;
1735
- // Shifts are encoded as string literals because static constexpr is not
1736
- // supported in constexpr functions.
1737
- auto* shifts = align == align::left ? "\x1f\x1f\x00\x01" : "\x00\x1f\x00\x01";
1738
- size_t left_padding = padding >> shifts[specs.align];
1739
- size_t right_padding = padding - left_padding;
1740
- auto it = reserve(out, size + padding * specs.fill.size());
1741
- if (left_padding != 0) it = fill(it, left_padding, specs.fill);
1742
- it = f(it);
1743
- if (right_padding != 0) it = fill(it, right_padding, specs.fill);
1744
- return base_iterator(out, it);
1745
- }
1746
-
1747
- template <align::type align = align::left, typename OutputIt, typename Char,
1748
- typename F>
1749
- constexpr auto write_padded(OutputIt out, const format_specs<Char>& specs,
1750
- size_t size, F&& f) -> OutputIt {
1751
- return write_padded<align>(out, specs, size, size, f);
1752
- }
1753
-
1754
- template <align::type align = align::left, typename Char, typename OutputIt>
1755
- FMT_CONSTEXPR auto write_bytes(OutputIt out, string_view bytes,
1756
- const format_specs<Char>& specs) -> OutputIt {
1757
- return write_padded<align>(
1758
- out, specs, bytes.size(), [bytes](reserve_iterator<OutputIt> it) {
1759
- const char* data = bytes.data();
1760
- return copy_str<Char>(data, data + bytes.size(), it);
1761
- });
1762
- }
1763
-
1764
- template <typename Char, typename OutputIt, typename UIntPtr>
1765
- auto write_ptr(OutputIt out, UIntPtr value, const format_specs<Char>* specs)
1766
- -> OutputIt {
1767
- int num_digits = count_digits<4>(value);
1768
- auto size = to_unsigned(num_digits) + size_t(2);
1769
- auto write = [=](reserve_iterator<OutputIt> it) {
1770
- *it++ = static_cast<Char>('0');
1771
- *it++ = static_cast<Char>('x');
1772
- return format_uint<4, Char>(it, value, num_digits);
1773
- };
1774
- return specs ? write_padded<align::right>(out, *specs, size, write)
1775
- : base_iterator(out, write(reserve(out, size)));
1776
- }
1777
-
1778
- // Returns true iff the code point cp is printable.
1779
- FMT_API auto is_printable(uint32_t cp) -> bool;
1780
-
1781
- inline auto needs_escape(uint32_t cp) -> bool {
1782
- return cp < 0x20 || cp == 0x7f || cp == '"' || cp == '\\' ||
1783
- !is_printable(cp);
1784
- }
1785
-
1786
- template <typename Char> struct find_escape_result {
1787
- const Char* begin;
1788
- const Char* end;
1789
- uint32_t cp;
1790
- };
1791
-
1792
- template <typename Char>
1793
- using make_unsigned_char =
1794
- typename conditional_t<std::is_integral<Char>::value,
1795
- std::make_unsigned<Char>,
1796
- type_identity<uint32_t>>::type;
1797
-
1798
- template <typename Char>
1799
- auto find_escape(const Char* begin, const Char* end)
1800
- -> find_escape_result<Char> {
1801
- for (; begin != end; ++begin) {
1802
- uint32_t cp = static_cast<make_unsigned_char<Char>>(*begin);
1803
- if (const_check(sizeof(Char) == 1) && cp >= 0x80) continue;
1804
- if (needs_escape(cp)) return {begin, begin + 1, cp};
1805
- }
1806
- return {begin, nullptr, 0};
1807
- }
1808
-
1809
- inline auto find_escape(const char* begin, const char* end)
1810
- -> find_escape_result<char> {
1811
- if (!is_utf8()) return find_escape<char>(begin, end);
1812
- auto result = find_escape_result<char>{end, nullptr, 0};
1813
- for_each_codepoint(string_view(begin, to_unsigned(end - begin)),
1814
- [&](uint32_t cp, string_view sv) {
1815
- if (needs_escape(cp)) {
1816
- result = {sv.begin(), sv.end(), cp};
1817
- return false;
1818
- }
1819
- return true;
1820
- });
1821
- return result;
1822
- }
1823
-
1824
- #define FMT_STRING_IMPL(s, base, explicit) \
1825
- [] { \
1826
- /* Use the hidden visibility as a workaround for a GCC bug (#1973). */ \
1827
- /* Use a macro-like name to avoid shadowing warnings. */ \
1828
- struct FMT_VISIBILITY("hidden") FMT_COMPILE_STRING : base { \
1829
- using char_type FMT_MAYBE_UNUSED = fmt::remove_cvref_t<decltype(s[0])>; \
1830
- FMT_MAYBE_UNUSED FMT_CONSTEXPR explicit \
1831
- operator fmt::basic_string_view<char_type>() const { \
1832
- return fmt::detail_exported::compile_string_to_view<char_type>(s); \
1833
- } \
1834
- }; \
1835
- return FMT_COMPILE_STRING(); \
1836
- }()
1837
-
1838
- /**
1839
- \rst
1840
- Constructs a compile-time format string from a string literal *s*.
1841
-
1842
- **Example**::
1843
-
1844
- // A compile-time error because 'd' is an invalid specifier for strings.
1845
- std::string s = fmt::format(FMT_STRING("{:d}"), "foo");
1846
- \endrst
1847
- */
1848
- #define FMT_STRING(s) FMT_STRING_IMPL(s, fmt::detail::compile_string, )
1849
-
1850
- template <size_t width, typename Char, typename OutputIt>
1851
- auto write_codepoint(OutputIt out, char prefix, uint32_t cp) -> OutputIt {
1852
- *out++ = static_cast<Char>('\\');
1853
- *out++ = static_cast<Char>(prefix);
1854
- Char buf[width];
1855
- fill_n(buf, width, static_cast<Char>('0'));
1856
- format_uint<4>(buf, cp, width);
1857
- return copy_str<Char>(buf, buf + width, out);
1858
- }
1859
-
1860
- template <typename OutputIt, typename Char>
1861
- auto write_escaped_cp(OutputIt out, const find_escape_result<Char>& escape)
1862
- -> OutputIt {
1863
- auto c = static_cast<Char>(escape.cp);
1864
- switch (escape.cp) {
1865
- case '\n':
1866
- *out++ = static_cast<Char>('\\');
1867
- c = static_cast<Char>('n');
1868
- break;
1869
- case '\r':
1870
- *out++ = static_cast<Char>('\\');
1871
- c = static_cast<Char>('r');
1872
- break;
1873
- case '\t':
1874
- *out++ = static_cast<Char>('\\');
1875
- c = static_cast<Char>('t');
1876
- break;
1877
- case '"':
1878
- FMT_FALLTHROUGH;
1879
- case '\'':
1880
- FMT_FALLTHROUGH;
1881
- case '\\':
1882
- *out++ = static_cast<Char>('\\');
1883
- break;
1884
- default:
1885
- if (escape.cp < 0x100) {
1886
- return write_codepoint<2, Char>(out, 'x', escape.cp);
1887
- }
1888
- if (escape.cp < 0x10000) {
1889
- return write_codepoint<4, Char>(out, 'u', escape.cp);
1890
- }
1891
- if (escape.cp < 0x110000) {
1892
- return write_codepoint<8, Char>(out, 'U', escape.cp);
1893
- }
1894
- for (Char escape_char : basic_string_view<Char>(
1895
- escape.begin, to_unsigned(escape.end - escape.begin))) {
1896
- out = write_codepoint<2, Char>(out, 'x',
1897
- static_cast<uint32_t>(escape_char) & 0xFF);
1898
- }
1899
- return out;
1900
- }
1901
- *out++ = c;
1902
- return out;
1903
- }
1904
-
1905
- template <typename Char, typename OutputIt>
1906
- auto write_escaped_string(OutputIt out, basic_string_view<Char> str)
1907
- -> OutputIt {
1908
- *out++ = static_cast<Char>('"');
1909
- auto begin = str.begin(), end = str.end();
1910
- do {
1911
- auto escape = find_escape(begin, end);
1912
- out = copy_str<Char>(begin, escape.begin, out);
1913
- begin = escape.end;
1914
- if (!begin) break;
1915
- out = write_escaped_cp<OutputIt, Char>(out, escape);
1916
- } while (begin != end);
1917
- *out++ = static_cast<Char>('"');
1918
- return out;
1919
- }
1920
-
1921
- template <typename Char, typename OutputIt>
1922
- auto write_escaped_char(OutputIt out, Char v) -> OutputIt {
1923
- Char v_array[1] = {v};
1924
- *out++ = static_cast<Char>('\'');
1925
- if ((needs_escape(static_cast<uint32_t>(v)) && v != static_cast<Char>('"')) ||
1926
- v == static_cast<Char>('\'')) {
1927
- out = write_escaped_cp(out,
1928
- find_escape_result<Char>{v_array, v_array + 1,
1929
- static_cast<uint32_t>(v)});
1930
- } else {
1931
- *out++ = v;
1932
- }
1933
- *out++ = static_cast<Char>('\'');
1934
- return out;
1935
- }
1936
-
1937
- template <typename Char, typename OutputIt>
1938
- FMT_CONSTEXPR auto write_char(OutputIt out, Char value,
1939
- const format_specs<Char>& specs) -> OutputIt {
1940
- bool is_debug = specs.type == presentation_type::debug;
1941
- return write_padded(out, specs, 1, [=](reserve_iterator<OutputIt> it) {
1942
- if (is_debug) return write_escaped_char(it, value);
1943
- *it++ = value;
1944
- return it;
1945
- });
1946
- }
1947
- template <typename Char, typename OutputIt>
1948
- FMT_CONSTEXPR auto write(OutputIt out, Char value,
1949
- const format_specs<Char>& specs, locale_ref loc = {})
1950
- -> OutputIt {
1951
- // char is formatted as unsigned char for consistency across platforms.
1952
- using unsigned_type =
1953
- conditional_t<std::is_same<Char, char>::value, unsigned char, unsigned>;
1954
- return check_char_specs(specs)
1955
- ? write_char(out, value, specs)
1956
- : write(out, static_cast<unsigned_type>(value), specs, loc);
1957
- }
1958
-
1959
- // Data for write_int that doesn't depend on output iterator type. It is used to
1960
- // avoid template code bloat.
1961
- template <typename Char> struct write_int_data {
1962
- size_t size;
1963
- size_t padding;
1964
-
1965
- FMT_CONSTEXPR write_int_data(int num_digits, unsigned prefix,
1966
- const format_specs<Char>& specs)
1967
- : size((prefix >> 24) + to_unsigned(num_digits)), padding(0) {
1968
- if (specs.align == align::numeric) {
1969
- auto width = to_unsigned(specs.width);
1970
- if (width > size) {
1971
- padding = width - size;
1972
- size = width;
1973
- }
1974
- } else if (specs.precision > num_digits) {
1975
- size = (prefix >> 24) + to_unsigned(specs.precision);
1976
- padding = to_unsigned(specs.precision - num_digits);
1977
- }
1978
- }
1979
- };
1980
-
1981
- // Writes an integer in the format
1982
- // <left-padding><prefix><numeric-padding><digits><right-padding>
1983
- // where <digits> are written by write_digits(it).
1984
- // prefix contains chars in three lower bytes and the size in the fourth byte.
1985
- template <typename OutputIt, typename Char, typename W>
1986
- FMT_CONSTEXPR FMT_INLINE auto write_int(OutputIt out, int num_digits,
1987
- unsigned prefix,
1988
- const format_specs<Char>& specs,
1989
- W write_digits) -> OutputIt {
1990
- // Slightly faster check for specs.width == 0 && specs.precision == -1.
1991
- if ((specs.width | (specs.precision + 1)) == 0) {
1992
- auto it = reserve(out, to_unsigned(num_digits) + (prefix >> 24));
1993
- if (prefix != 0) {
1994
- for (unsigned p = prefix & 0xffffff; p != 0; p >>= 8)
1995
- *it++ = static_cast<Char>(p & 0xff);
1996
- }
1997
- return base_iterator(out, write_digits(it));
1998
- }
1999
- auto data = write_int_data<Char>(num_digits, prefix, specs);
2000
- return write_padded<align::right>(
2001
- out, specs, data.size, [=](reserve_iterator<OutputIt> it) {
2002
- for (unsigned p = prefix & 0xffffff; p != 0; p >>= 8)
2003
- *it++ = static_cast<Char>(p & 0xff);
2004
- it = detail::fill_n(it, data.padding, static_cast<Char>('0'));
2005
- return write_digits(it);
2006
- });
2007
- }
2008
-
2009
- template <typename Char> class digit_grouping {
2010
- private:
2011
- std::string grouping_;
2012
- std::basic_string<Char> thousands_sep_;
2013
-
2014
- struct next_state {
2015
- std::string::const_iterator group;
2016
- int pos;
2017
- };
2018
- auto initial_state() const -> next_state { return {grouping_.begin(), 0}; }
2019
-
2020
- // Returns the next digit group separator position.
2021
- auto next(next_state& state) const -> int {
2022
- if (thousands_sep_.empty()) return max_value<int>();
2023
- if (state.group == grouping_.end()) return state.pos += grouping_.back();
2024
- if (*state.group <= 0 || *state.group == max_value<char>())
2025
- return max_value<int>();
2026
- state.pos += *state.group++;
2027
- return state.pos;
2028
- }
2029
-
2030
- public:
2031
- explicit digit_grouping(locale_ref loc, bool localized = true) {
2032
- if (!localized) return;
2033
- auto sep = thousands_sep<Char>(loc);
2034
- grouping_ = sep.grouping;
2035
- if (sep.thousands_sep) thousands_sep_.assign(1, sep.thousands_sep);
2036
- }
2037
- digit_grouping(std::string grouping, std::basic_string<Char> sep)
2038
- : grouping_(std::move(grouping)), thousands_sep_(std::move(sep)) {}
2039
-
2040
- auto has_separator() const -> bool { return !thousands_sep_.empty(); }
2041
-
2042
- auto count_separators(int num_digits) const -> int {
2043
- int count = 0;
2044
- auto state = initial_state();
2045
- while (num_digits > next(state)) ++count;
2046
- return count;
2047
- }
2048
-
2049
- // Applies grouping to digits and write the output to out.
2050
- template <typename Out, typename C>
2051
- auto apply(Out out, basic_string_view<C> digits) const -> Out {
2052
- auto num_digits = static_cast<int>(digits.size());
2053
- auto separators = basic_memory_buffer<int>();
2054
- separators.push_back(0);
2055
- auto state = initial_state();
2056
- while (int i = next(state)) {
2057
- if (i >= num_digits) break;
2058
- separators.push_back(i);
2059
- }
2060
- for (int i = 0, sep_index = static_cast<int>(separators.size() - 1);
2061
- i < num_digits; ++i) {
2062
- if (num_digits - i == separators[sep_index]) {
2063
- out =
2064
- copy_str<Char>(thousands_sep_.data(),
2065
- thousands_sep_.data() + thousands_sep_.size(), out);
2066
- --sep_index;
2067
- }
2068
- *out++ = static_cast<Char>(digits[to_unsigned(i)]);
2069
- }
2070
- return out;
2071
- }
2072
- };
2073
-
2074
- FMT_CONSTEXPR inline void prefix_append(unsigned& prefix, unsigned value) {
2075
- prefix |= prefix != 0 ? value << 8 : value;
2076
- prefix += (1u + (value > 0xff ? 1 : 0)) << 24;
2077
- }
2078
-
2079
- // Writes a decimal integer with digit grouping.
2080
- template <typename OutputIt, typename UInt, typename Char>
2081
- auto write_int(OutputIt out, UInt value, unsigned prefix,
2082
- const format_specs<Char>& specs,
2083
- const digit_grouping<Char>& grouping) -> OutputIt {
2084
- static_assert(std::is_same<uint64_or_128_t<UInt>, UInt>::value, "");
2085
- int num_digits = 0;
2086
- auto buffer = memory_buffer();
2087
- switch (specs.type) {
2088
- case presentation_type::none:
2089
- case presentation_type::dec: {
2090
- num_digits = count_digits(value);
2091
- format_decimal<char>(appender(buffer), value, num_digits);
2092
- break;
2093
- }
2094
- case presentation_type::hex_lower:
2095
- case presentation_type::hex_upper: {
2096
- bool upper = specs.type == presentation_type::hex_upper;
2097
- if (specs.alt)
2098
- prefix_append(prefix, unsigned(upper ? 'X' : 'x') << 8 | '0');
2099
- num_digits = count_digits<4>(value);
2100
- format_uint<4, char>(appender(buffer), value, num_digits, upper);
2101
- break;
2102
- }
2103
- case presentation_type::bin_lower:
2104
- case presentation_type::bin_upper: {
2105
- bool upper = specs.type == presentation_type::bin_upper;
2106
- if (specs.alt)
2107
- prefix_append(prefix, unsigned(upper ? 'B' : 'b') << 8 | '0');
2108
- num_digits = count_digits<1>(value);
2109
- format_uint<1, char>(appender(buffer), value, num_digits);
2110
- break;
2111
- }
2112
- case presentation_type::oct: {
2113
- num_digits = count_digits<3>(value);
2114
- // Octal prefix '0' is counted as a digit, so only add it if precision
2115
- // is not greater than the number of digits.
2116
- if (specs.alt && specs.precision <= num_digits && value != 0)
2117
- prefix_append(prefix, '0');
2118
- format_uint<3, char>(appender(buffer), value, num_digits);
2119
- break;
2120
- }
2121
- case presentation_type::chr:
2122
- return write_char(out, static_cast<Char>(value), specs);
2123
- default:
2124
- throw_format_error("invalid format specifier");
2125
- }
2126
-
2127
- unsigned size = (prefix != 0 ? prefix >> 24 : 0) + to_unsigned(num_digits) +
2128
- to_unsigned(grouping.count_separators(num_digits));
2129
- return write_padded<align::right>(
2130
- out, specs, size, size, [&](reserve_iterator<OutputIt> it) {
2131
- for (unsigned p = prefix & 0xffffff; p != 0; p >>= 8)
2132
- *it++ = static_cast<Char>(p & 0xff);
2133
- return grouping.apply(it, string_view(buffer.data(), buffer.size()));
2134
- });
2135
- }
2136
-
2137
- // Writes a localized value.
2138
- FMT_API auto write_loc(appender out, loc_value value,
2139
- const format_specs<>& specs, locale_ref loc) -> bool;
2140
- template <typename OutputIt, typename Char>
2141
- inline auto write_loc(OutputIt, loc_value, const format_specs<Char>&,
2142
- locale_ref) -> bool {
2143
- return false;
2144
- }
2145
-
2146
- template <typename UInt> struct write_int_arg {
2147
- UInt abs_value;
2148
- unsigned prefix;
2149
- };
2150
-
2151
- template <typename T>
2152
- FMT_CONSTEXPR auto make_write_int_arg(T value, sign_t sign)
2153
- -> write_int_arg<uint32_or_64_or_128_t<T>> {
2154
- auto prefix = 0u;
2155
- auto abs_value = static_cast<uint32_or_64_or_128_t<T>>(value);
2156
- if (is_negative(value)) {
2157
- prefix = 0x01000000 | '-';
2158
- abs_value = 0 - abs_value;
2159
- } else {
2160
- constexpr const unsigned prefixes[4] = {0, 0, 0x1000000u | '+',
2161
- 0x1000000u | ' '};
2162
- prefix = prefixes[sign];
2163
- }
2164
- return {abs_value, prefix};
2165
- }
2166
-
2167
- template <typename Char = char> struct loc_writer {
2168
- buffer_appender<Char> out;
2169
- const format_specs<Char>& specs;
2170
- std::basic_string<Char> sep;
2171
- std::string grouping;
2172
- std::basic_string<Char> decimal_point;
2173
-
2174
- template <typename T, FMT_ENABLE_IF(is_integer<T>::value)>
2175
- auto operator()(T value) -> bool {
2176
- auto arg = make_write_int_arg(value, specs.sign);
2177
- write_int(out, static_cast<uint64_or_128_t<T>>(arg.abs_value), arg.prefix,
2178
- specs, digit_grouping<Char>(grouping, sep));
2179
- return true;
2180
- }
2181
-
2182
- template <typename T, FMT_ENABLE_IF(!is_integer<T>::value)>
2183
- auto operator()(T) -> bool {
2184
- return false;
2185
- }
2186
- };
2187
-
2188
- template <typename Char, typename OutputIt, typename T>
2189
- FMT_CONSTEXPR FMT_INLINE auto write_int(OutputIt out, write_int_arg<T> arg,
2190
- const format_specs<Char>& specs,
2191
- locale_ref) -> OutputIt {
2192
- static_assert(std::is_same<T, uint32_or_64_or_128_t<T>>::value, "");
2193
- auto abs_value = arg.abs_value;
2194
- auto prefix = arg.prefix;
2195
- switch (specs.type) {
2196
- case presentation_type::none:
2197
- case presentation_type::dec: {
2198
- auto num_digits = count_digits(abs_value);
2199
- return write_int(
2200
- out, num_digits, prefix, specs, [=](reserve_iterator<OutputIt> it) {
2201
- return format_decimal<Char>(it, abs_value, num_digits).end;
2202
- });
2203
- }
2204
- case presentation_type::hex_lower:
2205
- case presentation_type::hex_upper: {
2206
- bool upper = specs.type == presentation_type::hex_upper;
2207
- if (specs.alt)
2208
- prefix_append(prefix, unsigned(upper ? 'X' : 'x') << 8 | '0');
2209
- int num_digits = count_digits<4>(abs_value);
2210
- return write_int(
2211
- out, num_digits, prefix, specs, [=](reserve_iterator<OutputIt> it) {
2212
- return format_uint<4, Char>(it, abs_value, num_digits, upper);
2213
- });
2214
- }
2215
- case presentation_type::bin_lower:
2216
- case presentation_type::bin_upper: {
2217
- bool upper = specs.type == presentation_type::bin_upper;
2218
- if (specs.alt)
2219
- prefix_append(prefix, unsigned(upper ? 'B' : 'b') << 8 | '0');
2220
- int num_digits = count_digits<1>(abs_value);
2221
- return write_int(out, num_digits, prefix, specs,
2222
- [=](reserve_iterator<OutputIt> it) {
2223
- return format_uint<1, Char>(it, abs_value, num_digits);
2224
- });
2225
- }
2226
- case presentation_type::oct: {
2227
- int num_digits = count_digits<3>(abs_value);
2228
- // Octal prefix '0' is counted as a digit, so only add it if precision
2229
- // is not greater than the number of digits.
2230
- if (specs.alt && specs.precision <= num_digits && abs_value != 0)
2231
- prefix_append(prefix, '0');
2232
- return write_int(out, num_digits, prefix, specs,
2233
- [=](reserve_iterator<OutputIt> it) {
2234
- return format_uint<3, Char>(it, abs_value, num_digits);
2235
- });
2236
- }
2237
- case presentation_type::chr:
2238
- return write_char(out, static_cast<Char>(abs_value), specs);
2239
- default:
2240
- throw_format_error("invalid format specifier");
2241
- }
2242
- return out;
2243
- }
2244
- template <typename Char, typename OutputIt, typename T>
2245
- FMT_CONSTEXPR FMT_NOINLINE auto write_int_noinline(
2246
- OutputIt out, write_int_arg<T> arg, const format_specs<Char>& specs,
2247
- locale_ref loc) -> OutputIt {
2248
- return write_int(out, arg, specs, loc);
2249
- }
2250
- template <typename Char, typename OutputIt, typename T,
2251
- FMT_ENABLE_IF(is_integral<T>::value &&
2252
- !std::is_same<T, bool>::value &&
2253
- std::is_same<OutputIt, buffer_appender<Char>>::value)>
2254
- FMT_CONSTEXPR FMT_INLINE auto write(OutputIt out, T value,
2255
- const format_specs<Char>& specs,
2256
- locale_ref loc) -> OutputIt {
2257
- if (specs.localized && write_loc(out, value, specs, loc)) return out;
2258
- return write_int_noinline(out, make_write_int_arg(value, specs.sign), specs,
2259
- loc);
2260
- }
2261
- // An inlined version of write used in format string compilation.
2262
- template <typename Char, typename OutputIt, typename T,
2263
- FMT_ENABLE_IF(is_integral<T>::value &&
2264
- !std::is_same<T, bool>::value &&
2265
- !std::is_same<OutputIt, buffer_appender<Char>>::value)>
2266
- FMT_CONSTEXPR FMT_INLINE auto write(OutputIt out, T value,
2267
- const format_specs<Char>& specs,
2268
- locale_ref loc) -> OutputIt {
2269
- if (specs.localized && write_loc(out, value, specs, loc)) return out;
2270
- return write_int(out, make_write_int_arg(value, specs.sign), specs, loc);
2271
- }
2272
-
2273
- // An output iterator that counts the number of objects written to it and
2274
- // discards them.
2275
- class counting_iterator {
2276
- private:
2277
- size_t count_;
2278
-
2279
- public:
2280
- using iterator_category = std::output_iterator_tag;
2281
- using difference_type = std::ptrdiff_t;
2282
- using pointer = void;
2283
- using reference = void;
2284
- FMT_UNCHECKED_ITERATOR(counting_iterator);
2285
-
2286
- struct value_type {
2287
- template <typename T> FMT_CONSTEXPR void operator=(const T&) {}
2288
- };
2289
-
2290
- FMT_CONSTEXPR counting_iterator() : count_(0) {}
2291
-
2292
- FMT_CONSTEXPR auto count() const -> size_t { return count_; }
2293
-
2294
- FMT_CONSTEXPR auto operator++() -> counting_iterator& {
2295
- ++count_;
2296
- return *this;
2297
- }
2298
- FMT_CONSTEXPR auto operator++(int) -> counting_iterator {
2299
- auto it = *this;
2300
- ++*this;
2301
- return it;
2302
- }
2303
-
2304
- FMT_CONSTEXPR friend auto operator+(counting_iterator it, difference_type n)
2305
- -> counting_iterator {
2306
- it.count_ += static_cast<size_t>(n);
2307
- return it;
2308
- }
2309
-
2310
- FMT_CONSTEXPR auto operator*() const -> value_type { return {}; }
2311
- };
2312
-
2313
- template <typename Char, typename OutputIt>
2314
- FMT_CONSTEXPR auto write(OutputIt out, basic_string_view<Char> s,
2315
- const format_specs<Char>& specs) -> OutputIt {
2316
- auto data = s.data();
2317
- auto size = s.size();
2318
- if (specs.precision >= 0 && to_unsigned(specs.precision) < size)
2319
- size = code_point_index(s, to_unsigned(specs.precision));
2320
- bool is_debug = specs.type == presentation_type::debug;
2321
- size_t width = 0;
2322
- if (specs.width != 0) {
2323
- if (is_debug)
2324
- width = write_escaped_string(counting_iterator{}, s).count();
2325
- else
2326
- width = compute_width(basic_string_view<Char>(data, size));
2327
- }
2328
- return write_padded(out, specs, size, width,
2329
- [=](reserve_iterator<OutputIt> it) {
2330
- if (is_debug) return write_escaped_string(it, s);
2331
- return copy_str<Char>(data, data + size, it);
2332
- });
2333
- }
2334
- template <typename Char, typename OutputIt>
2335
- FMT_CONSTEXPR auto write(OutputIt out,
2336
- basic_string_view<type_identity_t<Char>> s,
2337
- const format_specs<Char>& specs, locale_ref)
2338
- -> OutputIt {
2339
- return write(out, s, specs);
2340
- }
2341
- template <typename Char, typename OutputIt>
2342
- FMT_CONSTEXPR auto write(OutputIt out, const Char* s,
2343
- const format_specs<Char>& specs, locale_ref)
2344
- -> OutputIt {
2345
- if (specs.type == presentation_type::pointer)
2346
- return write_ptr<Char>(out, bit_cast<uintptr_t>(s), &specs);
2347
- if (!s) throw_format_error("string pointer is null");
2348
- return write(out, basic_string_view<Char>(s), specs, {});
2349
- }
2350
-
2351
- template <typename Char, typename OutputIt, typename T,
2352
- FMT_ENABLE_IF(is_integral<T>::value &&
2353
- !std::is_same<T, bool>::value &&
2354
- !std::is_same<T, Char>::value)>
2355
- FMT_CONSTEXPR auto write(OutputIt out, T value) -> OutputIt {
2356
- auto abs_value = static_cast<uint32_or_64_or_128_t<T>>(value);
2357
- bool negative = is_negative(value);
2358
- // Don't do -abs_value since it trips unsigned-integer-overflow sanitizer.
2359
- if (negative) abs_value = ~abs_value + 1;
2360
- int num_digits = count_digits(abs_value);
2361
- auto size = (negative ? 1 : 0) + static_cast<size_t>(num_digits);
2362
- auto it = reserve(out, size);
2363
- if (auto ptr = to_pointer<Char>(it, size)) {
2364
- if (negative) *ptr++ = static_cast<Char>('-');
2365
- format_decimal<Char>(ptr, abs_value, num_digits);
2366
- return out;
2367
- }
2368
- if (negative) *it++ = static_cast<Char>('-');
2369
- it = format_decimal<Char>(it, abs_value, num_digits).end;
2370
- return base_iterator(out, it);
2371
- }
2372
-
2373
- // DEPRECATED!
2374
- template <typename Char>
2375
- FMT_CONSTEXPR auto parse_align(const Char* begin, const Char* end,
2376
- format_specs<Char>& specs) -> const Char* {
2377
- FMT_ASSERT(begin != end, "");
2378
- auto align = align::none;
2379
- auto p = begin + code_point_length(begin);
2380
- if (end - p <= 0) p = begin;
2381
- for (;;) {
2382
- switch (to_ascii(*p)) {
2383
- case '<':
2384
- align = align::left;
2385
- break;
2386
- case '>':
2387
- align = align::right;
2388
- break;
2389
- case '^':
2390
- align = align::center;
2391
- break;
2392
- }
2393
- if (align != align::none) {
2394
- if (p != begin) {
2395
- auto c = *begin;
2396
- if (c == '}') return begin;
2397
- if (c == '{') {
2398
- throw_format_error("invalid fill character '{'");
2399
- return begin;
2400
- }
2401
- specs.fill = {begin, to_unsigned(p - begin)};
2402
- begin = p + 1;
2403
- } else {
2404
- ++begin;
2405
- }
2406
- break;
2407
- } else if (p == begin) {
2408
- break;
2409
- }
2410
- p = begin;
2411
- }
2412
- specs.align = align;
2413
- return begin;
2414
- }
2415
-
2416
- // A floating-point presentation format.
2417
- enum class float_format : unsigned char {
2418
- general, // General: exponent notation or fixed point based on magnitude.
2419
- exp, // Exponent notation with the default precision of 6, e.g. 1.2e-3.
2420
- fixed, // Fixed point with the default precision of 6, e.g. 0.0012.
2421
- hex
2422
- };
2423
-
2424
- struct float_specs {
2425
- int precision;
2426
- float_format format : 8;
2427
- sign_t sign : 8;
2428
- bool upper : 1;
2429
- bool locale : 1;
2430
- bool binary32 : 1;
2431
- bool showpoint : 1;
2432
- };
2433
-
2434
- template <typename Char>
2435
- FMT_CONSTEXPR auto parse_float_type_spec(const format_specs<Char>& specs)
2436
- -> float_specs {
2437
- auto result = float_specs();
2438
- result.showpoint = specs.alt;
2439
- result.locale = specs.localized;
2440
- switch (specs.type) {
2441
- case presentation_type::none:
2442
- result.format = float_format::general;
2443
- break;
2444
- case presentation_type::general_upper:
2445
- result.upper = true;
2446
- FMT_FALLTHROUGH;
2447
- case presentation_type::general_lower:
2448
- result.format = float_format::general;
2449
- break;
2450
- case presentation_type::exp_upper:
2451
- result.upper = true;
2452
- FMT_FALLTHROUGH;
2453
- case presentation_type::exp_lower:
2454
- result.format = float_format::exp;
2455
- result.showpoint |= specs.precision != 0;
2456
- break;
2457
- case presentation_type::fixed_upper:
2458
- result.upper = true;
2459
- FMT_FALLTHROUGH;
2460
- case presentation_type::fixed_lower:
2461
- result.format = float_format::fixed;
2462
- result.showpoint |= specs.precision != 0;
2463
- break;
2464
- case presentation_type::hexfloat_upper:
2465
- result.upper = true;
2466
- FMT_FALLTHROUGH;
2467
- case presentation_type::hexfloat_lower:
2468
- result.format = float_format::hex;
2469
- break;
2470
- default:
2471
- throw_format_error("invalid format specifier");
2472
- break;
2473
- }
2474
- return result;
2475
- }
2476
-
2477
- template <typename Char, typename OutputIt>
2478
- FMT_CONSTEXPR20 auto write_nonfinite(OutputIt out, bool isnan,
2479
- format_specs<Char> specs,
2480
- const float_specs& fspecs) -> OutputIt {
2481
- auto str =
2482
- isnan ? (fspecs.upper ? "NAN" : "nan") : (fspecs.upper ? "INF" : "inf");
2483
- constexpr size_t str_size = 3;
2484
- auto sign = fspecs.sign;
2485
- auto size = str_size + (sign ? 1 : 0);
2486
- // Replace '0'-padding with space for non-finite values.
2487
- const bool is_zero_fill =
2488
- specs.fill.size() == 1 && *specs.fill.data() == static_cast<Char>('0');
2489
- if (is_zero_fill) specs.fill[0] = static_cast<Char>(' ');
2490
- return write_padded(out, specs, size, [=](reserve_iterator<OutputIt> it) {
2491
- if (sign) *it++ = detail::sign<Char>(sign);
2492
- return copy_str<Char>(str, str + str_size, it);
2493
- });
2494
- }
2495
-
2496
- // A decimal floating-point number significand * pow(10, exp).
2497
- struct big_decimal_fp {
2498
- const char* significand;
2499
- int significand_size;
2500
- int exponent;
2501
- };
2502
-
2503
- constexpr auto get_significand_size(const big_decimal_fp& f) -> int {
2504
- return f.significand_size;
2505
- }
2506
- template <typename T>
2507
- inline auto get_significand_size(const dragonbox::decimal_fp<T>& f) -> int {
2508
- return count_digits(f.significand);
2509
- }
2510
-
2511
- template <typename Char, typename OutputIt>
2512
- constexpr auto write_significand(OutputIt out, const char* significand,
2513
- int significand_size) -> OutputIt {
2514
- return copy_str<Char>(significand, significand + significand_size, out);
2515
- }
2516
- template <typename Char, typename OutputIt, typename UInt>
2517
- inline auto write_significand(OutputIt out, UInt significand,
2518
- int significand_size) -> OutputIt {
2519
- return format_decimal<Char>(out, significand, significand_size).end;
2520
- }
2521
- template <typename Char, typename OutputIt, typename T, typename Grouping>
2522
- FMT_CONSTEXPR20 auto write_significand(OutputIt out, T significand,
2523
- int significand_size, int exponent,
2524
- const Grouping& grouping) -> OutputIt {
2525
- if (!grouping.has_separator()) {
2526
- out = write_significand<Char>(out, significand, significand_size);
2527
- return detail::fill_n(out, exponent, static_cast<Char>('0'));
2528
- }
2529
- auto buffer = memory_buffer();
2530
- write_significand<char>(appender(buffer), significand, significand_size);
2531
- detail::fill_n(appender(buffer), exponent, '0');
2532
- return grouping.apply(out, string_view(buffer.data(), buffer.size()));
2533
- }
2534
-
2535
- template <typename Char, typename UInt,
2536
- FMT_ENABLE_IF(std::is_integral<UInt>::value)>
2537
- inline auto write_significand(Char* out, UInt significand, int significand_size,
2538
- int integral_size, Char decimal_point) -> Char* {
2539
- if (!decimal_point)
2540
- return format_decimal(out, significand, significand_size).end;
2541
- out += significand_size + 1;
2542
- Char* end = out;
2543
- int floating_size = significand_size - integral_size;
2544
- for (int i = floating_size / 2; i > 0; --i) {
2545
- out -= 2;
2546
- copy2(out, digits2(static_cast<std::size_t>(significand % 100)));
2547
- significand /= 100;
2548
- }
2549
- if (floating_size % 2 != 0) {
2550
- *--out = static_cast<Char>('0' + significand % 10);
2551
- significand /= 10;
2552
- }
2553
- *--out = decimal_point;
2554
- format_decimal(out - integral_size, significand, integral_size);
2555
- return end;
2556
- }
2557
-
2558
- template <typename OutputIt, typename UInt, typename Char,
2559
- FMT_ENABLE_IF(!std::is_pointer<remove_cvref_t<OutputIt>>::value)>
2560
- inline auto write_significand(OutputIt out, UInt significand,
2561
- int significand_size, int integral_size,
2562
- Char decimal_point) -> OutputIt {
2563
- // Buffer is large enough to hold digits (digits10 + 1) and a decimal point.
2564
- Char buffer[digits10<UInt>() + 2];
2565
- auto end = write_significand(buffer, significand, significand_size,
2566
- integral_size, decimal_point);
2567
- return detail::copy_str_noinline<Char>(buffer, end, out);
2568
- }
2569
-
2570
- template <typename OutputIt, typename Char>
2571
- FMT_CONSTEXPR auto write_significand(OutputIt out, const char* significand,
2572
- int significand_size, int integral_size,
2573
- Char decimal_point) -> OutputIt {
2574
- out = detail::copy_str_noinline<Char>(significand,
2575
- significand + integral_size, out);
2576
- if (!decimal_point) return out;
2577
- *out++ = decimal_point;
2578
- return detail::copy_str_noinline<Char>(significand + integral_size,
2579
- significand + significand_size, out);
2580
- }
2581
-
2582
- template <typename OutputIt, typename Char, typename T, typename Grouping>
2583
- FMT_CONSTEXPR20 auto write_significand(OutputIt out, T significand,
2584
- int significand_size, int integral_size,
2585
- Char decimal_point,
2586
- const Grouping& grouping) -> OutputIt {
2587
- if (!grouping.has_separator()) {
2588
- return write_significand(out, significand, significand_size, integral_size,
2589
- decimal_point);
2590
- }
2591
- auto buffer = basic_memory_buffer<Char>();
2592
- write_significand(buffer_appender<Char>(buffer), significand,
2593
- significand_size, integral_size, decimal_point);
2594
- grouping.apply(
2595
- out, basic_string_view<Char>(buffer.data(), to_unsigned(integral_size)));
2596
- return detail::copy_str_noinline<Char>(buffer.data() + integral_size,
2597
- buffer.end(), out);
2598
- }
2599
-
2600
- template <typename OutputIt, typename DecimalFP, typename Char,
2601
- typename Grouping = digit_grouping<Char>>
2602
- FMT_CONSTEXPR20 auto do_write_float(OutputIt out, const DecimalFP& f,
2603
- const format_specs<Char>& specs,
2604
- float_specs fspecs, locale_ref loc)
2605
- -> OutputIt {
2606
- auto significand = f.significand;
2607
- int significand_size = get_significand_size(f);
2608
- const Char zero = static_cast<Char>('0');
2609
- auto sign = fspecs.sign;
2610
- size_t size = to_unsigned(significand_size) + (sign ? 1 : 0);
2611
- using iterator = reserve_iterator<OutputIt>;
2612
-
2613
- Char decimal_point =
2614
- fspecs.locale ? detail::decimal_point<Char>(loc) : static_cast<Char>('.');
2615
-
2616
- int output_exp = f.exponent + significand_size - 1;
2617
- auto use_exp_format = [=]() {
2618
- if (fspecs.format == float_format::exp) return true;
2619
- if (fspecs.format != float_format::general) return false;
2620
- // Use the fixed notation if the exponent is in [exp_lower, exp_upper),
2621
- // e.g. 0.0001 instead of 1e-04. Otherwise use the exponent notation.
2622
- const int exp_lower = -4, exp_upper = 16;
2623
- return output_exp < exp_lower ||
2624
- output_exp >= (fspecs.precision > 0 ? fspecs.precision : exp_upper);
2625
- };
2626
- if (use_exp_format()) {
2627
- int num_zeros = 0;
2628
- if (fspecs.showpoint) {
2629
- num_zeros = fspecs.precision - significand_size;
2630
- if (num_zeros < 0) num_zeros = 0;
2631
- size += to_unsigned(num_zeros);
2632
- } else if (significand_size == 1) {
2633
- decimal_point = Char();
2634
- }
2635
- auto abs_output_exp = output_exp >= 0 ? output_exp : -output_exp;
2636
- int exp_digits = 2;
2637
- if (abs_output_exp >= 100) exp_digits = abs_output_exp >= 1000 ? 4 : 3;
2638
-
2639
- size += to_unsigned((decimal_point ? 1 : 0) + 2 + exp_digits);
2640
- char exp_char = fspecs.upper ? 'E' : 'e';
2641
- auto write = [=](iterator it) {
2642
- if (sign) *it++ = detail::sign<Char>(sign);
2643
- // Insert a decimal point after the first digit and add an exponent.
2644
- it = write_significand(it, significand, significand_size, 1,
2645
- decimal_point);
2646
- if (num_zeros > 0) it = detail::fill_n(it, num_zeros, zero);
2647
- *it++ = static_cast<Char>(exp_char);
2648
- return write_exponent<Char>(output_exp, it);
2649
- };
2650
- return specs.width > 0 ? write_padded<align::right>(out, specs, size, write)
2651
- : base_iterator(out, write(reserve(out, size)));
2652
- }
2653
-
2654
- int exp = f.exponent + significand_size;
2655
- if (f.exponent >= 0) {
2656
- // 1234e5 -> 123400000[.0+]
2657
- size += to_unsigned(f.exponent);
2658
- int num_zeros = fspecs.precision - exp;
2659
- abort_fuzzing_if(num_zeros > 5000);
2660
- if (fspecs.showpoint) {
2661
- ++size;
2662
- if (num_zeros <= 0 && fspecs.format != float_format::fixed) num_zeros = 0;
2663
- if (num_zeros > 0) size += to_unsigned(num_zeros);
2664
- }
2665
- auto grouping = Grouping(loc, fspecs.locale);
2666
- size += to_unsigned(grouping.count_separators(exp));
2667
- return write_padded<align::right>(out, specs, size, [&](iterator it) {
2668
- if (sign) *it++ = detail::sign<Char>(sign);
2669
- it = write_significand<Char>(it, significand, significand_size,
2670
- f.exponent, grouping);
2671
- if (!fspecs.showpoint) return it;
2672
- *it++ = decimal_point;
2673
- return num_zeros > 0 ? detail::fill_n(it, num_zeros, zero) : it;
2674
- });
2675
- } else if (exp > 0) {
2676
- // 1234e-2 -> 12.34[0+]
2677
- int num_zeros = fspecs.showpoint ? fspecs.precision - significand_size : 0;
2678
- size += 1 + to_unsigned(num_zeros > 0 ? num_zeros : 0);
2679
- auto grouping = Grouping(loc, fspecs.locale);
2680
- size += to_unsigned(grouping.count_separators(exp));
2681
- return write_padded<align::right>(out, specs, size, [&](iterator it) {
2682
- if (sign) *it++ = detail::sign<Char>(sign);
2683
- it = write_significand(it, significand, significand_size, exp,
2684
- decimal_point, grouping);
2685
- return num_zeros > 0 ? detail::fill_n(it, num_zeros, zero) : it;
2686
- });
2687
- }
2688
- // 1234e-6 -> 0.001234
2689
- int num_zeros = -exp;
2690
- if (significand_size == 0 && fspecs.precision >= 0 &&
2691
- fspecs.precision < num_zeros) {
2692
- num_zeros = fspecs.precision;
2693
- }
2694
- bool pointy = num_zeros != 0 || significand_size != 0 || fspecs.showpoint;
2695
- size += 1 + (pointy ? 1 : 0) + to_unsigned(num_zeros);
2696
- return write_padded<align::right>(out, specs, size, [&](iterator it) {
2697
- if (sign) *it++ = detail::sign<Char>(sign);
2698
- *it++ = zero;
2699
- if (!pointy) return it;
2700
- *it++ = decimal_point;
2701
- it = detail::fill_n(it, num_zeros, zero);
2702
- return write_significand<Char>(it, significand, significand_size);
2703
- });
2704
- }
2705
-
2706
- template <typename Char> class fallback_digit_grouping {
2707
- public:
2708
- constexpr fallback_digit_grouping(locale_ref, bool) {}
2709
-
2710
- constexpr auto has_separator() const -> bool { return false; }
2711
-
2712
- constexpr auto count_separators(int) const -> int { return 0; }
2713
-
2714
- template <typename Out, typename C>
2715
- constexpr auto apply(Out out, basic_string_view<C>) const -> Out {
2716
- return out;
2717
- }
2718
- };
2719
-
2720
- template <typename OutputIt, typename DecimalFP, typename Char>
2721
- FMT_CONSTEXPR20 auto write_float(OutputIt out, const DecimalFP& f,
2722
- const format_specs<Char>& specs,
2723
- float_specs fspecs, locale_ref loc)
2724
- -> OutputIt {
2725
- if (is_constant_evaluated()) {
2726
- return do_write_float<OutputIt, DecimalFP, Char,
2727
- fallback_digit_grouping<Char>>(out, f, specs, fspecs,
2728
- loc);
2729
- } else {
2730
- return do_write_float(out, f, specs, fspecs, loc);
2731
- }
2732
- }
2733
-
2734
- template <typename T> constexpr auto isnan(T value) -> bool {
2735
- return !(value >= value); // std::isnan doesn't support __float128.
2736
- }
2737
-
2738
- template <typename T, typename Enable = void>
2739
- struct has_isfinite : std::false_type {};
2740
-
2741
- template <typename T>
2742
- struct has_isfinite<T, enable_if_t<sizeof(std::isfinite(T())) != 0>>
2743
- : std::true_type {};
2744
-
2745
- template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value&&
2746
- has_isfinite<T>::value)>
2747
- FMT_CONSTEXPR20 auto isfinite(T value) -> bool {
2748
- constexpr T inf = T(std::numeric_limits<double>::infinity());
2749
- if (is_constant_evaluated())
2750
- return !detail::isnan(value) && value < inf && value > -inf;
2751
- return std::isfinite(value);
2752
- }
2753
- template <typename T, FMT_ENABLE_IF(!has_isfinite<T>::value)>
2754
- FMT_CONSTEXPR auto isfinite(T value) -> bool {
2755
- T inf = T(std::numeric_limits<double>::infinity());
2756
- // std::isfinite doesn't support __float128.
2757
- return !detail::isnan(value) && value < inf && value > -inf;
2758
- }
2759
-
2760
- template <typename T, FMT_ENABLE_IF(is_floating_point<T>::value)>
2761
- FMT_INLINE FMT_CONSTEXPR bool signbit(T value) {
2762
- if (is_constant_evaluated()) {
2763
- #ifdef __cpp_if_constexpr
2764
- if constexpr (std::numeric_limits<double>::is_iec559) {
2765
- auto bits = detail::bit_cast<uint64_t>(static_cast<double>(value));
2766
- return (bits >> (num_bits<uint64_t>() - 1)) != 0;
2767
- }
2768
- #endif
2769
- }
2770
- return std::signbit(static_cast<double>(value));
2771
- }
2772
-
2773
- inline FMT_CONSTEXPR20 void adjust_precision(int& precision, int exp10) {
2774
- // Adjust fixed precision by exponent because it is relative to decimal
2775
- // point.
2776
- if (exp10 > 0 && precision > max_value<int>() - exp10)
2777
- FMT_THROW(format_error("number is too big"));
2778
- precision += exp10;
2779
- }
2780
-
2781
- class bigint {
2782
- private:
2783
- // A bigint is stored as an array of bigits (big digits), with bigit at index
2784
- // 0 being the least significant one.
2785
- using bigit = uint32_t;
2786
- using double_bigit = uint64_t;
2787
- enum { bigits_capacity = 32 };
2788
- basic_memory_buffer<bigit, bigits_capacity> bigits_;
2789
- int exp_;
2790
-
2791
- FMT_CONSTEXPR20 auto operator[](int index) const -> bigit {
2792
- return bigits_[to_unsigned(index)];
2793
- }
2794
- FMT_CONSTEXPR20 auto operator[](int index) -> bigit& {
2795
- return bigits_[to_unsigned(index)];
2796
- }
2797
-
2798
- static constexpr const int bigit_bits = num_bits<bigit>();
2799
-
2800
- friend struct formatter<bigint>;
2801
-
2802
- FMT_CONSTEXPR20 void subtract_bigits(int index, bigit other, bigit& borrow) {
2803
- auto result = static_cast<double_bigit>((*this)[index]) - other - borrow;
2804
- (*this)[index] = static_cast<bigit>(result);
2805
- borrow = static_cast<bigit>(result >> (bigit_bits * 2 - 1));
2806
- }
2807
-
2808
- FMT_CONSTEXPR20 void remove_leading_zeros() {
2809
- int num_bigits = static_cast<int>(bigits_.size()) - 1;
2810
- while (num_bigits > 0 && (*this)[num_bigits] == 0) --num_bigits;
2811
- bigits_.resize(to_unsigned(num_bigits + 1));
2812
- }
2813
-
2814
- // Computes *this -= other assuming aligned bigints and *this >= other.
2815
- FMT_CONSTEXPR20 void subtract_aligned(const bigint& other) {
2816
- FMT_ASSERT(other.exp_ >= exp_, "unaligned bigints");
2817
- FMT_ASSERT(compare(*this, other) >= 0, "");
2818
- bigit borrow = 0;
2819
- int i = other.exp_ - exp_;
2820
- for (size_t j = 0, n = other.bigits_.size(); j != n; ++i, ++j)
2821
- subtract_bigits(i, other.bigits_[j], borrow);
2822
- while (borrow > 0) subtract_bigits(i, 0, borrow);
2823
- remove_leading_zeros();
2824
- }
2825
-
2826
- FMT_CONSTEXPR20 void multiply(uint32_t value) {
2827
- const double_bigit wide_value = value;
2828
- bigit carry = 0;
2829
- for (size_t i = 0, n = bigits_.size(); i < n; ++i) {
2830
- double_bigit result = bigits_[i] * wide_value + carry;
2831
- bigits_[i] = static_cast<bigit>(result);
2832
- carry = static_cast<bigit>(result >> bigit_bits);
2833
- }
2834
- if (carry != 0) bigits_.push_back(carry);
2835
- }
2836
-
2837
- template <typename UInt, FMT_ENABLE_IF(std::is_same<UInt, uint64_t>::value ||
2838
- std::is_same<UInt, uint128_t>::value)>
2839
- FMT_CONSTEXPR20 void multiply(UInt value) {
2840
- using half_uint =
2841
- conditional_t<std::is_same<UInt, uint128_t>::value, uint64_t, uint32_t>;
2842
- const int shift = num_bits<half_uint>() - bigit_bits;
2843
- const UInt lower = static_cast<half_uint>(value);
2844
- const UInt upper = value >> num_bits<half_uint>();
2845
- UInt carry = 0;
2846
- for (size_t i = 0, n = bigits_.size(); i < n; ++i) {
2847
- UInt result = lower * bigits_[i] + static_cast<bigit>(carry);
2848
- carry = (upper * bigits_[i] << shift) + (result >> bigit_bits) +
2849
- (carry >> bigit_bits);
2850
- bigits_[i] = static_cast<bigit>(result);
2851
- }
2852
- while (carry != 0) {
2853
- bigits_.push_back(static_cast<bigit>(carry));
2854
- carry >>= bigit_bits;
2855
- }
2856
- }
2857
-
2858
- template <typename UInt, FMT_ENABLE_IF(std::is_same<UInt, uint64_t>::value ||
2859
- std::is_same<UInt, uint128_t>::value)>
2860
- FMT_CONSTEXPR20 void assign(UInt n) {
2861
- size_t num_bigits = 0;
2862
- do {
2863
- bigits_[num_bigits++] = static_cast<bigit>(n);
2864
- n >>= bigit_bits;
2865
- } while (n != 0);
2866
- bigits_.resize(num_bigits);
2867
- exp_ = 0;
2868
- }
2869
-
2870
- public:
2871
- FMT_CONSTEXPR20 bigint() : exp_(0) {}
2872
- explicit bigint(uint64_t n) { assign(n); }
2873
-
2874
- bigint(const bigint&) = delete;
2875
- void operator=(const bigint&) = delete;
2876
-
2877
- FMT_CONSTEXPR20 void assign(const bigint& other) {
2878
- auto size = other.bigits_.size();
2879
- bigits_.resize(size);
2880
- auto data = other.bigits_.data();
2881
- copy_str<bigit>(data, data + size, bigits_.data());
2882
- exp_ = other.exp_;
2883
- }
2884
-
2885
- template <typename Int> FMT_CONSTEXPR20 void operator=(Int n) {
2886
- FMT_ASSERT(n > 0, "");
2887
- assign(uint64_or_128_t<Int>(n));
2888
- }
2889
-
2890
- FMT_CONSTEXPR20 auto num_bigits() const -> int {
2891
- return static_cast<int>(bigits_.size()) + exp_;
2892
- }
2893
-
2894
- FMT_NOINLINE FMT_CONSTEXPR20 auto operator<<=(int shift) -> bigint& {
2895
- FMT_ASSERT(shift >= 0, "");
2896
- exp_ += shift / bigit_bits;
2897
- shift %= bigit_bits;
2898
- if (shift == 0) return *this;
2899
- bigit carry = 0;
2900
- for (size_t i = 0, n = bigits_.size(); i < n; ++i) {
2901
- bigit c = bigits_[i] >> (bigit_bits - shift);
2902
- bigits_[i] = (bigits_[i] << shift) + carry;
2903
- carry = c;
2904
- }
2905
- if (carry != 0) bigits_.push_back(carry);
2906
- return *this;
2907
- }
2908
-
2909
- template <typename Int>
2910
- FMT_CONSTEXPR20 auto operator*=(Int value) -> bigint& {
2911
- FMT_ASSERT(value > 0, "");
2912
- multiply(uint32_or_64_or_128_t<Int>(value));
2913
- return *this;
2914
- }
2915
-
2916
- friend FMT_CONSTEXPR20 auto compare(const bigint& lhs, const bigint& rhs)
2917
- -> int {
2918
- int num_lhs_bigits = lhs.num_bigits(), num_rhs_bigits = rhs.num_bigits();
2919
- if (num_lhs_bigits != num_rhs_bigits)
2920
- return num_lhs_bigits > num_rhs_bigits ? 1 : -1;
2921
- int i = static_cast<int>(lhs.bigits_.size()) - 1;
2922
- int j = static_cast<int>(rhs.bigits_.size()) - 1;
2923
- int end = i - j;
2924
- if (end < 0) end = 0;
2925
- for (; i >= end; --i, --j) {
2926
- bigit lhs_bigit = lhs[i], rhs_bigit = rhs[j];
2927
- if (lhs_bigit != rhs_bigit) return lhs_bigit > rhs_bigit ? 1 : -1;
2928
- }
2929
- if (i != j) return i > j ? 1 : -1;
2930
- return 0;
2931
- }
2932
-
2933
- // Returns compare(lhs1 + lhs2, rhs).
2934
- friend FMT_CONSTEXPR20 auto add_compare(const bigint& lhs1,
2935
- const bigint& lhs2, const bigint& rhs)
2936
- -> int {
2937
- auto minimum = [](int a, int b) { return a < b ? a : b; };
2938
- auto maximum = [](int a, int b) { return a > b ? a : b; };
2939
- int max_lhs_bigits = maximum(lhs1.num_bigits(), lhs2.num_bigits());
2940
- int num_rhs_bigits = rhs.num_bigits();
2941
- if (max_lhs_bigits + 1 < num_rhs_bigits) return -1;
2942
- if (max_lhs_bigits > num_rhs_bigits) return 1;
2943
- auto get_bigit = [](const bigint& n, int i) -> bigit {
2944
- return i >= n.exp_ && i < n.num_bigits() ? n[i - n.exp_] : 0;
2945
- };
2946
- double_bigit borrow = 0;
2947
- int min_exp = minimum(minimum(lhs1.exp_, lhs2.exp_), rhs.exp_);
2948
- for (int i = num_rhs_bigits - 1; i >= min_exp; --i) {
2949
- double_bigit sum =
2950
- static_cast<double_bigit>(get_bigit(lhs1, i)) + get_bigit(lhs2, i);
2951
- bigit rhs_bigit = get_bigit(rhs, i);
2952
- if (sum > rhs_bigit + borrow) return 1;
2953
- borrow = rhs_bigit + borrow - sum;
2954
- if (borrow > 1) return -1;
2955
- borrow <<= bigit_bits;
2956
- }
2957
- return borrow != 0 ? -1 : 0;
2958
- }
2959
-
2960
- // Assigns pow(10, exp) to this bigint.
2961
- FMT_CONSTEXPR20 void assign_pow10(int exp) {
2962
- FMT_ASSERT(exp >= 0, "");
2963
- if (exp == 0) return *this = 1;
2964
- // Find the top bit.
2965
- int bitmask = 1;
2966
- while (exp >= bitmask) bitmask <<= 1;
2967
- bitmask >>= 1;
2968
- // pow(10, exp) = pow(5, exp) * pow(2, exp). First compute pow(5, exp) by
2969
- // repeated squaring and multiplication.
2970
- *this = 5;
2971
- bitmask >>= 1;
2972
- while (bitmask != 0) {
2973
- square();
2974
- if ((exp & bitmask) != 0) *this *= 5;
2975
- bitmask >>= 1;
2976
- }
2977
- *this <<= exp; // Multiply by pow(2, exp) by shifting.
2978
- }
2979
-
2980
- FMT_CONSTEXPR20 void square() {
2981
- int num_bigits = static_cast<int>(bigits_.size());
2982
- int num_result_bigits = 2 * num_bigits;
2983
- basic_memory_buffer<bigit, bigits_capacity> n(std::move(bigits_));
2984
- bigits_.resize(to_unsigned(num_result_bigits));
2985
- auto sum = uint128_t();
2986
- for (int bigit_index = 0; bigit_index < num_bigits; ++bigit_index) {
2987
- // Compute bigit at position bigit_index of the result by adding
2988
- // cross-product terms n[i] * n[j] such that i + j == bigit_index.
2989
- for (int i = 0, j = bigit_index; j >= 0; ++i, --j) {
2990
- // Most terms are multiplied twice which can be optimized in the future.
2991
- sum += static_cast<double_bigit>(n[i]) * n[j];
2992
- }
2993
- (*this)[bigit_index] = static_cast<bigit>(sum);
2994
- sum >>= num_bits<bigit>(); // Compute the carry.
2995
- }
2996
- // Do the same for the top half.
2997
- for (int bigit_index = num_bigits; bigit_index < num_result_bigits;
2998
- ++bigit_index) {
2999
- for (int j = num_bigits - 1, i = bigit_index - j; i < num_bigits;)
3000
- sum += static_cast<double_bigit>(n[i++]) * n[j--];
3001
- (*this)[bigit_index] = static_cast<bigit>(sum);
3002
- sum >>= num_bits<bigit>();
3003
- }
3004
- remove_leading_zeros();
3005
- exp_ *= 2;
3006
- }
3007
-
3008
- // If this bigint has a bigger exponent than other, adds trailing zero to make
3009
- // exponents equal. This simplifies some operations such as subtraction.
3010
- FMT_CONSTEXPR20 void align(const bigint& other) {
3011
- int exp_difference = exp_ - other.exp_;
3012
- if (exp_difference <= 0) return;
3013
- int num_bigits = static_cast<int>(bigits_.size());
3014
- bigits_.resize(to_unsigned(num_bigits + exp_difference));
3015
- for (int i = num_bigits - 1, j = i + exp_difference; i >= 0; --i, --j)
3016
- bigits_[j] = bigits_[i];
3017
- std::uninitialized_fill_n(bigits_.data(), exp_difference, 0u);
3018
- exp_ -= exp_difference;
3019
- }
3020
-
3021
- // Divides this bignum by divisor, assigning the remainder to this and
3022
- // returning the quotient.
3023
- FMT_CONSTEXPR20 auto divmod_assign(const bigint& divisor) -> int {
3024
- FMT_ASSERT(this != &divisor, "");
3025
- if (compare(*this, divisor) < 0) return 0;
3026
- FMT_ASSERT(divisor.bigits_[divisor.bigits_.size() - 1u] != 0, "");
3027
- align(divisor);
3028
- int quotient = 0;
3029
- do {
3030
- subtract_aligned(divisor);
3031
- ++quotient;
3032
- } while (compare(*this, divisor) >= 0);
3033
- return quotient;
3034
- }
3035
- };
3036
-
3037
- // format_dragon flags.
3038
- enum dragon {
3039
- predecessor_closer = 1,
3040
- fixup = 2, // Run fixup to correct exp10 which can be off by one.
3041
- fixed = 4,
3042
- };
3043
-
3044
- // Formats a floating-point number using a variation of the Fixed-Precision
3045
- // Positive Floating-Point Printout ((FPP)^2) algorithm by Steele & White:
3046
- // https://fmt.dev/papers/p372-steele.pdf.
3047
- FMT_CONSTEXPR20 inline void format_dragon(basic_fp<uint128_t> value,
3048
- unsigned flags, int num_digits,
3049
- buffer<char>& buf, int& exp10) {
3050
- bigint numerator; // 2 * R in (FPP)^2.
3051
- bigint denominator; // 2 * S in (FPP)^2.
3052
- // lower and upper are differences between value and corresponding boundaries.
3053
- bigint lower; // (M^- in (FPP)^2).
3054
- bigint upper_store; // upper's value if different from lower.
3055
- bigint* upper = nullptr; // (M^+ in (FPP)^2).
3056
- // Shift numerator and denominator by an extra bit or two (if lower boundary
3057
- // is closer) to make lower and upper integers. This eliminates multiplication
3058
- // by 2 during later computations.
3059
- bool is_predecessor_closer = (flags & dragon::predecessor_closer) != 0;
3060
- int shift = is_predecessor_closer ? 2 : 1;
3061
- if (value.e >= 0) {
3062
- numerator = value.f;
3063
- numerator <<= value.e + shift;
3064
- lower = 1;
3065
- lower <<= value.e;
3066
- if (is_predecessor_closer) {
3067
- upper_store = 1;
3068
- upper_store <<= value.e + 1;
3069
- upper = &upper_store;
3070
- }
3071
- denominator.assign_pow10(exp10);
3072
- denominator <<= shift;
3073
- } else if (exp10 < 0) {
3074
- numerator.assign_pow10(-exp10);
3075
- lower.assign(numerator);
3076
- if (is_predecessor_closer) {
3077
- upper_store.assign(numerator);
3078
- upper_store <<= 1;
3079
- upper = &upper_store;
3080
- }
3081
- numerator *= value.f;
3082
- numerator <<= shift;
3083
- denominator = 1;
3084
- denominator <<= shift - value.e;
3085
- } else {
3086
- numerator = value.f;
3087
- numerator <<= shift;
3088
- denominator.assign_pow10(exp10);
3089
- denominator <<= shift - value.e;
3090
- lower = 1;
3091
- if (is_predecessor_closer) {
3092
- upper_store = 1ULL << 1;
3093
- upper = &upper_store;
3094
- }
3095
- }
3096
- int even = static_cast<int>((value.f & 1) == 0);
3097
- if (!upper) upper = &lower;
3098
- bool shortest = num_digits < 0;
3099
- if ((flags & dragon::fixup) != 0) {
3100
- if (add_compare(numerator, *upper, denominator) + even <= 0) {
3101
- --exp10;
3102
- numerator *= 10;
3103
- if (num_digits < 0) {
3104
- lower *= 10;
3105
- if (upper != &lower) *upper *= 10;
3106
- }
3107
- }
3108
- if ((flags & dragon::fixed) != 0) adjust_precision(num_digits, exp10 + 1);
3109
- }
3110
- // Invariant: value == (numerator / denominator) * pow(10, exp10).
3111
- if (shortest) {
3112
- // Generate the shortest representation.
3113
- num_digits = 0;
3114
- char* data = buf.data();
3115
- for (;;) {
3116
- int digit = numerator.divmod_assign(denominator);
3117
- bool low = compare(numerator, lower) - even < 0; // numerator <[=] lower.
3118
- // numerator + upper >[=] pow10:
3119
- bool high = add_compare(numerator, *upper, denominator) + even > 0;
3120
- data[num_digits++] = static_cast<char>('0' + digit);
3121
- if (low || high) {
3122
- if (!low) {
3123
- ++data[num_digits - 1];
3124
- } else if (high) {
3125
- int result = add_compare(numerator, numerator, denominator);
3126
- // Round half to even.
3127
- if (result > 0 || (result == 0 && (digit % 2) != 0))
3128
- ++data[num_digits - 1];
3129
- }
3130
- buf.try_resize(to_unsigned(num_digits));
3131
- exp10 -= num_digits - 1;
3132
- return;
3133
- }
3134
- numerator *= 10;
3135
- lower *= 10;
3136
- if (upper != &lower) *upper *= 10;
3137
- }
3138
- }
3139
- // Generate the given number of digits.
3140
- exp10 -= num_digits - 1;
3141
- if (num_digits <= 0) {
3142
- denominator *= 10;
3143
- auto digit = add_compare(numerator, numerator, denominator) > 0 ? '1' : '0';
3144
- buf.push_back(digit);
3145
- return;
3146
- }
3147
- buf.try_resize(to_unsigned(num_digits));
3148
- for (int i = 0; i < num_digits - 1; ++i) {
3149
- int digit = numerator.divmod_assign(denominator);
3150
- buf[i] = static_cast<char>('0' + digit);
3151
- numerator *= 10;
3152
- }
3153
- int digit = numerator.divmod_assign(denominator);
3154
- auto result = add_compare(numerator, numerator, denominator);
3155
- if (result > 0 || (result == 0 && (digit % 2) != 0)) {
3156
- if (digit == 9) {
3157
- const auto overflow = '0' + 10;
3158
- buf[num_digits - 1] = overflow;
3159
- // Propagate the carry.
3160
- for (int i = num_digits - 1; i > 0 && buf[i] == overflow; --i) {
3161
- buf[i] = '0';
3162
- ++buf[i - 1];
3163
- }
3164
- if (buf[0] == overflow) {
3165
- buf[0] = '1';
3166
- if ((flags & dragon::fixed) != 0)
3167
- buf.push_back('0');
3168
- else
3169
- ++exp10;
3170
- }
3171
- return;
3172
- }
3173
- ++digit;
3174
- }
3175
- buf[num_digits - 1] = static_cast<char>('0' + digit);
3176
- }
3177
-
3178
- // Formats a floating-point number using the hexfloat format.
3179
- template <typename Float, FMT_ENABLE_IF(!is_double_double<Float>::value)>
3180
- FMT_CONSTEXPR20 void format_hexfloat(Float value, int precision,
3181
- float_specs specs, buffer<char>& buf) {
3182
- // float is passed as double to reduce the number of instantiations and to
3183
- // simplify implementation.
3184
- static_assert(!std::is_same<Float, float>::value, "");
3185
-
3186
- using info = dragonbox::float_info<Float>;
3187
-
3188
- // Assume Float is in the format [sign][exponent][significand].
3189
- using carrier_uint = typename info::carrier_uint;
3190
-
3191
- constexpr auto num_float_significand_bits =
3192
- detail::num_significand_bits<Float>();
3193
-
3194
- basic_fp<carrier_uint> f(value);
3195
- f.e += num_float_significand_bits;
3196
- if (!has_implicit_bit<Float>()) --f.e;
3197
-
3198
- constexpr auto num_fraction_bits =
3199
- num_float_significand_bits + (has_implicit_bit<Float>() ? 1 : 0);
3200
- constexpr auto num_xdigits = (num_fraction_bits + 3) / 4;
3201
-
3202
- constexpr auto leading_shift = ((num_xdigits - 1) * 4);
3203
- const auto leading_mask = carrier_uint(0xF) << leading_shift;
3204
- const auto leading_xdigit =
3205
- static_cast<uint32_t>((f.f & leading_mask) >> leading_shift);
3206
- if (leading_xdigit > 1) f.e -= (32 - countl_zero(leading_xdigit) - 1);
3207
-
3208
- int print_xdigits = num_xdigits - 1;
3209
- if (precision >= 0 && print_xdigits > precision) {
3210
- const int shift = ((print_xdigits - precision - 1) * 4);
3211
- const auto mask = carrier_uint(0xF) << shift;
3212
- const auto v = static_cast<uint32_t>((f.f & mask) >> shift);
3213
-
3214
- if (v >= 8) {
3215
- const auto inc = carrier_uint(1) << (shift + 4);
3216
- f.f += inc;
3217
- f.f &= ~(inc - 1);
3218
- }
3219
-
3220
- // Check long double overflow
3221
- if (!has_implicit_bit<Float>()) {
3222
- const auto implicit_bit = carrier_uint(1) << num_float_significand_bits;
3223
- if ((f.f & implicit_bit) == implicit_bit) {
3224
- f.f >>= 4;
3225
- f.e += 4;
3226
- }
3227
- }
3228
-
3229
- print_xdigits = precision;
3230
- }
3231
-
3232
- char xdigits[num_bits<carrier_uint>() / 4];
3233
- detail::fill_n(xdigits, sizeof(xdigits), '0');
3234
- format_uint<4>(xdigits, f.f, num_xdigits, specs.upper);
3235
-
3236
- // Remove zero tail
3237
- while (print_xdigits > 0 && xdigits[print_xdigits] == '0') --print_xdigits;
3238
-
3239
- buf.push_back('0');
3240
- buf.push_back(specs.upper ? 'X' : 'x');
3241
- buf.push_back(xdigits[0]);
3242
- if (specs.showpoint || print_xdigits > 0 || print_xdigits < precision)
3243
- buf.push_back('.');
3244
- buf.append(xdigits + 1, xdigits + 1 + print_xdigits);
3245
- for (; print_xdigits < precision; ++print_xdigits) buf.push_back('0');
3246
-
3247
- buf.push_back(specs.upper ? 'P' : 'p');
3248
-
3249
- uint32_t abs_e;
3250
- if (f.e < 0) {
3251
- buf.push_back('-');
3252
- abs_e = static_cast<uint32_t>(-f.e);
3253
- } else {
3254
- buf.push_back('+');
3255
- abs_e = static_cast<uint32_t>(f.e);
3256
- }
3257
- format_decimal<char>(appender(buf), abs_e, detail::count_digits(abs_e));
3258
- }
3259
-
3260
- template <typename Float, FMT_ENABLE_IF(is_double_double<Float>::value)>
3261
- FMT_CONSTEXPR20 void format_hexfloat(Float value, int precision,
3262
- float_specs specs, buffer<char>& buf) {
3263
- format_hexfloat(static_cast<double>(value), precision, specs, buf);
3264
- }
3265
-
3266
- constexpr auto fractional_part_rounding_thresholds(int index) -> uint32_t {
3267
- // For checking rounding thresholds.
3268
- // The kth entry is chosen to be the smallest integer such that the
3269
- // upper 32-bits of 10^(k+1) times it is strictly bigger than 5 * 10^k.
3270
- // It is equal to ceil(2^31 + 2^32/10^(k + 1)).
3271
- // These are stored in a string literal because we cannot have static arrays
3272
- // in constexpr functions and non-static ones are poorly optimized.
3273
- return U"\x9999999a\x828f5c29\x80418938\x80068db9\x8000a7c6\x800010c7"
3274
- U"\x800001ae\x8000002b"[index];
3275
- }
3276
-
3277
- template <typename Float>
3278
- FMT_CONSTEXPR20 auto format_float(Float value, int precision, float_specs specs,
3279
- buffer<char>& buf) -> int {
3280
- // float is passed as double to reduce the number of instantiations.
3281
- static_assert(!std::is_same<Float, float>::value, "");
3282
- FMT_ASSERT(value >= 0, "value is negative");
3283
- auto converted_value = convert_float(value);
3284
-
3285
- const bool fixed = specs.format == float_format::fixed;
3286
- if (value <= 0) { // <= instead of == to silence a warning.
3287
- if (precision <= 0 || !fixed) {
3288
- buf.push_back('0');
3289
- return 0;
3290
- }
3291
- buf.try_resize(to_unsigned(precision));
3292
- fill_n(buf.data(), precision, '0');
3293
- return -precision;
3294
- }
3295
-
3296
- int exp = 0;
3297
- bool use_dragon = true;
3298
- unsigned dragon_flags = 0;
3299
- if (!is_fast_float<Float>() || is_constant_evaluated()) {
3300
- const auto inv_log2_10 = 0.3010299956639812; // 1 / log2(10)
3301
- using info = dragonbox::float_info<decltype(converted_value)>;
3302
- const auto f = basic_fp<typename info::carrier_uint>(converted_value);
3303
- // Compute exp, an approximate power of 10, such that
3304
- // 10^(exp - 1) <= value < 10^exp or 10^exp <= value < 10^(exp + 1).
3305
- // This is based on log10(value) == log2(value) / log2(10) and approximation
3306
- // of log2(value) by e + num_fraction_bits idea from double-conversion.
3307
- auto e = (f.e + count_digits<1>(f.f) - 1) * inv_log2_10 - 1e-10;
3308
- exp = static_cast<int>(e);
3309
- if (e > exp) ++exp; // Compute ceil.
3310
- dragon_flags = dragon::fixup;
3311
- } else if (precision < 0) {
3312
- // Use Dragonbox for the shortest format.
3313
- if (specs.binary32) {
3314
- auto dec = dragonbox::to_decimal(static_cast<float>(value));
3315
- write<char>(buffer_appender<char>(buf), dec.significand);
3316
- return dec.exponent;
3317
- }
3318
- auto dec = dragonbox::to_decimal(static_cast<double>(value));
3319
- write<char>(buffer_appender<char>(buf), dec.significand);
3320
- return dec.exponent;
3321
- } else {
3322
- // Extract significand bits and exponent bits.
3323
- using info = dragonbox::float_info<double>;
3324
- auto br = bit_cast<uint64_t>(static_cast<double>(value));
3325
-
3326
- const uint64_t significand_mask =
3327
- (static_cast<uint64_t>(1) << num_significand_bits<double>()) - 1;
3328
- uint64_t significand = (br & significand_mask);
3329
- int exponent = static_cast<int>((br & exponent_mask<double>()) >>
3330
- num_significand_bits<double>());
3331
-
3332
- if (exponent != 0) { // Check if normal.
3333
- exponent -= exponent_bias<double>() + num_significand_bits<double>();
3334
- significand |=
3335
- (static_cast<uint64_t>(1) << num_significand_bits<double>());
3336
- significand <<= 1;
3337
- } else {
3338
- // Normalize subnormal inputs.
3339
- FMT_ASSERT(significand != 0, "zeros should not appear here");
3340
- int shift = countl_zero(significand);
3341
- FMT_ASSERT(shift >= num_bits<uint64_t>() - num_significand_bits<double>(),
3342
- "");
3343
- shift -= (num_bits<uint64_t>() - num_significand_bits<double>() - 2);
3344
- exponent = (std::numeric_limits<double>::min_exponent -
3345
- num_significand_bits<double>()) -
3346
- shift;
3347
- significand <<= shift;
3348
- }
3349
-
3350
- // Compute the first several nonzero decimal significand digits.
3351
- // We call the number we get the first segment.
3352
- const int k = info::kappa - dragonbox::floor_log10_pow2(exponent);
3353
- exp = -k;
3354
- const int beta = exponent + dragonbox::floor_log2_pow10(k);
3355
- uint64_t first_segment;
3356
- bool has_more_segments;
3357
- int digits_in_the_first_segment;
3358
- {
3359
- const auto r = dragonbox::umul192_upper128(
3360
- significand << beta, dragonbox::get_cached_power(k));
3361
- first_segment = r.high();
3362
- has_more_segments = r.low() != 0;
3363
-
3364
- // The first segment can have 18 ~ 19 digits.
3365
- if (first_segment >= 1000000000000000000ULL) {
3366
- digits_in_the_first_segment = 19;
3367
- } else {
3368
- // When it is of 18-digits, we align it to 19-digits by adding a bogus
3369
- // zero at the end.
3370
- digits_in_the_first_segment = 18;
3371
- first_segment *= 10;
3372
- }
3373
- }
3374
-
3375
- // Compute the actual number of decimal digits to print.
3376
- if (fixed) adjust_precision(precision, exp + digits_in_the_first_segment);
3377
-
3378
- // Use Dragon4 only when there might be not enough digits in the first
3379
- // segment.
3380
- if (digits_in_the_first_segment > precision) {
3381
- use_dragon = false;
3382
-
3383
- if (precision <= 0) {
3384
- exp += digits_in_the_first_segment;
3385
-
3386
- if (precision < 0) {
3387
- // Nothing to do, since all we have are just leading zeros.
3388
- buf.try_resize(0);
3389
- } else {
3390
- // We may need to round-up.
3391
- buf.try_resize(1);
3392
- if ((first_segment | static_cast<uint64_t>(has_more_segments)) >
3393
- 5000000000000000000ULL) {
3394
- buf[0] = '1';
3395
- } else {
3396
- buf[0] = '0';
3397
- }
3398
- }
3399
- } // precision <= 0
3400
- else {
3401
- exp += digits_in_the_first_segment - precision;
3402
-
3403
- // When precision > 0, we divide the first segment into three
3404
- // subsegments, each with 9, 9, and 0 ~ 1 digits so that each fits
3405
- // in 32-bits which usually allows faster calculation than in
3406
- // 64-bits. Since some compiler (e.g. MSVC) doesn't know how to optimize
3407
- // division-by-constant for large 64-bit divisors, we do it here
3408
- // manually. The magic number 7922816251426433760 below is equal to
3409
- // ceil(2^(64+32) / 10^10).
3410
- const uint32_t first_subsegment = static_cast<uint32_t>(
3411
- dragonbox::umul128_upper64(first_segment, 7922816251426433760ULL) >>
3412
- 32);
3413
- const uint64_t second_third_subsegments =
3414
- first_segment - first_subsegment * 10000000000ULL;
3415
-
3416
- uint64_t prod;
3417
- uint32_t digits;
3418
- bool should_round_up;
3419
- int number_of_digits_to_print = precision > 9 ? 9 : precision;
3420
-
3421
- // Print a 9-digits subsegment, either the first or the second.
3422
- auto print_subsegment = [&](uint32_t subsegment, char* buffer) {
3423
- int number_of_digits_printed = 0;
3424
-
3425
- // If we want to print an odd number of digits from the subsegment,
3426
- if ((number_of_digits_to_print & 1) != 0) {
3427
- // Convert to 64-bit fixed-point fractional form with 1-digit
3428
- // integer part. The magic number 720575941 is a good enough
3429
- // approximation of 2^(32 + 24) / 10^8; see
3430
- // https://jk-jeon.github.io/posts/2022/12/fixed-precision-formatting/#fixed-length-case
3431
- // for details.
3432
- prod = ((subsegment * static_cast<uint64_t>(720575941)) >> 24) + 1;
3433
- digits = static_cast<uint32_t>(prod >> 32);
3434
- *buffer = static_cast<char>('0' + digits);
3435
- number_of_digits_printed++;
3436
- }
3437
- // If we want to print an even number of digits from the
3438
- // first_subsegment,
3439
- else {
3440
- // Convert to 64-bit fixed-point fractional form with 2-digits
3441
- // integer part. The magic number 450359963 is a good enough
3442
- // approximation of 2^(32 + 20) / 10^7; see
3443
- // https://jk-jeon.github.io/posts/2022/12/fixed-precision-formatting/#fixed-length-case
3444
- // for details.
3445
- prod = ((subsegment * static_cast<uint64_t>(450359963)) >> 20) + 1;
3446
- digits = static_cast<uint32_t>(prod >> 32);
3447
- copy2(buffer, digits2(digits));
3448
- number_of_digits_printed += 2;
3449
- }
3450
-
3451
- // Print all digit pairs.
3452
- while (number_of_digits_printed < number_of_digits_to_print) {
3453
- prod = static_cast<uint32_t>(prod) * static_cast<uint64_t>(100);
3454
- digits = static_cast<uint32_t>(prod >> 32);
3455
- copy2(buffer + number_of_digits_printed, digits2(digits));
3456
- number_of_digits_printed += 2;
3457
- }
3458
- };
3459
-
3460
- // Print first subsegment.
3461
- print_subsegment(first_subsegment, buf.data());
3462
-
3463
- // Perform rounding if the first subsegment is the last subsegment to
3464
- // print.
3465
- if (precision <= 9) {
3466
- // Rounding inside the subsegment.
3467
- // We round-up if:
3468
- // - either the fractional part is strictly larger than 1/2, or
3469
- // - the fractional part is exactly 1/2 and the last digit is odd.
3470
- // We rely on the following observations:
3471
- // - If fractional_part >= threshold, then the fractional part is
3472
- // strictly larger than 1/2.
3473
- // - If the MSB of fractional_part is set, then the fractional part
3474
- // must be at least 1/2.
3475
- // - When the MSB of fractional_part is set, either
3476
- // second_third_subsegments being nonzero or has_more_segments
3477
- // being true means there are further digits not printed, so the
3478
- // fractional part is strictly larger than 1/2.
3479
- if (precision < 9) {
3480
- uint32_t fractional_part = static_cast<uint32_t>(prod);
3481
- should_round_up =
3482
- fractional_part >= fractional_part_rounding_thresholds(
3483
- 8 - number_of_digits_to_print) ||
3484
- ((fractional_part >> 31) &
3485
- ((digits & 1) | (second_third_subsegments != 0) |
3486
- has_more_segments)) != 0;
3487
- }
3488
- // Rounding at the subsegment boundary.
3489
- // In this case, the fractional part is at least 1/2 if and only if
3490
- // second_third_subsegments >= 5000000000ULL, and is strictly larger
3491
- // than 1/2 if we further have either second_third_subsegments >
3492
- // 5000000000ULL or has_more_segments == true.
3493
- else {
3494
- should_round_up = second_third_subsegments > 5000000000ULL ||
3495
- (second_third_subsegments == 5000000000ULL &&
3496
- ((digits & 1) != 0 || has_more_segments));
3497
- }
3498
- }
3499
- // Otherwise, print the second subsegment.
3500
- else {
3501
- // Compilers are not aware of how to leverage the maximum value of
3502
- // second_third_subsegments to find out a better magic number which
3503
- // allows us to eliminate an additional shift. 1844674407370955162 =
3504
- // ceil(2^64/10) < ceil(2^64*(10^9/(10^10 - 1))).
3505
- const uint32_t second_subsegment =
3506
- static_cast<uint32_t>(dragonbox::umul128_upper64(
3507
- second_third_subsegments, 1844674407370955162ULL));
3508
- const uint32_t third_subsegment =
3509
- static_cast<uint32_t>(second_third_subsegments) -
3510
- second_subsegment * 10;
3511
-
3512
- number_of_digits_to_print = precision - 9;
3513
- print_subsegment(second_subsegment, buf.data() + 9);
3514
-
3515
- // Rounding inside the subsegment.
3516
- if (precision < 18) {
3517
- // The condition third_subsegment != 0 implies that the segment was
3518
- // of 19 digits, so in this case the third segment should be
3519
- // consisting of a genuine digit from the input.
3520
- uint32_t fractional_part = static_cast<uint32_t>(prod);
3521
- should_round_up =
3522
- fractional_part >= fractional_part_rounding_thresholds(
3523
- 8 - number_of_digits_to_print) ||
3524
- ((fractional_part >> 31) &
3525
- ((digits & 1) | (third_subsegment != 0) |
3526
- has_more_segments)) != 0;
3527
- }
3528
- // Rounding at the subsegment boundary.
3529
- else {
3530
- // In this case, the segment must be of 19 digits, thus
3531
- // the third subsegment should be consisting of a genuine digit from
3532
- // the input.
3533
- should_round_up = third_subsegment > 5 ||
3534
- (third_subsegment == 5 &&
3535
- ((digits & 1) != 0 || has_more_segments));
3536
- }
3537
- }
3538
-
3539
- // Round-up if necessary.
3540
- if (should_round_up) {
3541
- ++buf[precision - 1];
3542
- for (int i = precision - 1; i > 0 && buf[i] > '9'; --i) {
3543
- buf[i] = '0';
3544
- ++buf[i - 1];
3545
- }
3546
- if (buf[0] > '9') {
3547
- buf[0] = '1';
3548
- if (fixed)
3549
- buf[precision++] = '0';
3550
- else
3551
- ++exp;
3552
- }
3553
- }
3554
- buf.try_resize(to_unsigned(precision));
3555
- }
3556
- } // if (digits_in_the_first_segment > precision)
3557
- else {
3558
- // Adjust the exponent for its use in Dragon4.
3559
- exp += digits_in_the_first_segment - 1;
3560
- }
3561
- }
3562
- if (use_dragon) {
3563
- auto f = basic_fp<uint128_t>();
3564
- bool is_predecessor_closer = specs.binary32
3565
- ? f.assign(static_cast<float>(value))
3566
- : f.assign(converted_value);
3567
- if (is_predecessor_closer) dragon_flags |= dragon::predecessor_closer;
3568
- if (fixed) dragon_flags |= dragon::fixed;
3569
- // Limit precision to the maximum possible number of significant digits in
3570
- // an IEEE754 double because we don't need to generate zeros.
3571
- const int max_double_digits = 767;
3572
- if (precision > max_double_digits) precision = max_double_digits;
3573
- format_dragon(f, dragon_flags, precision, buf, exp);
3574
- }
3575
- if (!fixed && !specs.showpoint) {
3576
- // Remove trailing zeros.
3577
- auto num_digits = buf.size();
3578
- while (num_digits > 0 && buf[num_digits - 1] == '0') {
3579
- --num_digits;
3580
- ++exp;
3581
- }
3582
- buf.try_resize(num_digits);
3583
- }
3584
- return exp;
3585
- }
3586
- template <typename Char, typename OutputIt, typename T>
3587
- FMT_CONSTEXPR20 auto write_float(OutputIt out, T value,
3588
- format_specs<Char> specs, locale_ref loc)
3589
- -> OutputIt {
3590
- float_specs fspecs = parse_float_type_spec(specs);
3591
- fspecs.sign = specs.sign;
3592
- if (detail::signbit(value)) { // value < 0 is false for NaN so use signbit.
3593
- fspecs.sign = sign::minus;
3594
- value = -value;
3595
- } else if (fspecs.sign == sign::minus) {
3596
- fspecs.sign = sign::none;
3597
- }
3598
-
3599
- if (!detail::isfinite(value))
3600
- return write_nonfinite(out, detail::isnan(value), specs, fspecs);
3601
-
3602
- if (specs.align == align::numeric && fspecs.sign) {
3603
- auto it = reserve(out, 1);
3604
- *it++ = detail::sign<Char>(fspecs.sign);
3605
- out = base_iterator(out, it);
3606
- fspecs.sign = sign::none;
3607
- if (specs.width != 0) --specs.width;
3608
- }
3609
-
3610
- memory_buffer buffer;
3611
- if (fspecs.format == float_format::hex) {
3612
- if (fspecs.sign) buffer.push_back(detail::sign<char>(fspecs.sign));
3613
- format_hexfloat(convert_float(value), specs.precision, fspecs, buffer);
3614
- return write_bytes<align::right>(out, {buffer.data(), buffer.size()},
3615
- specs);
3616
- }
3617
- int precision = specs.precision >= 0 || specs.type == presentation_type::none
3618
- ? specs.precision
3619
- : 6;
3620
- if (fspecs.format == float_format::exp) {
3621
- if (precision == max_value<int>())
3622
- throw_format_error("number is too big");
3623
- else
3624
- ++precision;
3625
- } else if (fspecs.format != float_format::fixed && precision == 0) {
3626
- precision = 1;
3627
- }
3628
- if (const_check(std::is_same<T, float>())) fspecs.binary32 = true;
3629
- int exp = format_float(convert_float(value), precision, fspecs, buffer);
3630
- fspecs.precision = precision;
3631
- auto f = big_decimal_fp{buffer.data(), static_cast<int>(buffer.size()), exp};
3632
- return write_float(out, f, specs, fspecs, loc);
3633
- }
3634
-
3635
- template <typename Char, typename OutputIt, typename T,
3636
- FMT_ENABLE_IF(is_floating_point<T>::value)>
3637
- FMT_CONSTEXPR20 auto write(OutputIt out, T value, format_specs<Char> specs,
3638
- locale_ref loc = {}) -> OutputIt {
3639
- if (const_check(!is_supported_floating_point(value))) return out;
3640
- return specs.localized && write_loc(out, value, specs, loc)
3641
- ? out
3642
- : write_float(out, value, specs, loc);
3643
- }
3644
-
3645
- template <typename Char, typename OutputIt, typename T,
3646
- FMT_ENABLE_IF(is_fast_float<T>::value)>
3647
- FMT_CONSTEXPR20 auto write(OutputIt out, T value) -> OutputIt {
3648
- if (is_constant_evaluated()) return write(out, value, format_specs<Char>());
3649
- if (const_check(!is_supported_floating_point(value))) return out;
3650
-
3651
- auto fspecs = float_specs();
3652
- if (detail::signbit(value)) {
3653
- fspecs.sign = sign::minus;
3654
- value = -value;
3655
- }
3656
-
3657
- constexpr auto specs = format_specs<Char>();
3658
- using floaty = conditional_t<std::is_same<T, long double>::value, double, T>;
3659
- using floaty_uint = typename dragonbox::float_info<floaty>::carrier_uint;
3660
- floaty_uint mask = exponent_mask<floaty>();
3661
- if ((bit_cast<floaty_uint>(value) & mask) == mask)
3662
- return write_nonfinite(out, std::isnan(value), specs, fspecs);
3663
-
3664
- auto dec = dragonbox::to_decimal(static_cast<floaty>(value));
3665
- return write_float(out, dec, specs, fspecs, {});
3666
- }
3667
-
3668
- template <typename Char, typename OutputIt, typename T,
3669
- FMT_ENABLE_IF(is_floating_point<T>::value &&
3670
- !is_fast_float<T>::value)>
3671
- inline auto write(OutputIt out, T value) -> OutputIt {
3672
- return write(out, value, format_specs<Char>());
3673
- }
3674
-
3675
- template <typename Char, typename OutputIt>
3676
- auto write(OutputIt out, monostate, format_specs<Char> = {}, locale_ref = {})
3677
- -> OutputIt {
3678
- FMT_ASSERT(false, "");
3679
- return out;
3680
- }
3681
-
3682
- template <typename Char, typename OutputIt>
3683
- FMT_CONSTEXPR auto write(OutputIt out, basic_string_view<Char> value)
3684
- -> OutputIt {
3685
- auto it = reserve(out, value.size());
3686
- it = copy_str_noinline<Char>(value.begin(), value.end(), it);
3687
- return base_iterator(out, it);
3688
- }
3689
-
3690
- template <typename Char, typename OutputIt, typename T,
3691
- FMT_ENABLE_IF(is_string<T>::value)>
3692
- constexpr auto write(OutputIt out, const T& value) -> OutputIt {
3693
- return write<Char>(out, to_string_view(value));
3694
- }
3695
-
3696
- // FMT_ENABLE_IF() condition separated to workaround an MSVC bug.
3697
- template <
3698
- typename Char, typename OutputIt, typename T,
3699
- bool check =
3700
- std::is_enum<T>::value && !std::is_same<T, Char>::value &&
3701
- mapped_type_constant<T, basic_format_context<OutputIt, Char>>::value !=
3702
- type::custom_type,
3703
- FMT_ENABLE_IF(check)>
3704
- FMT_CONSTEXPR auto write(OutputIt out, T value) -> OutputIt {
3705
- return write<Char>(out, static_cast<underlying_t<T>>(value));
3706
- }
3707
-
3708
- template <typename Char, typename OutputIt, typename T,
3709
- FMT_ENABLE_IF(std::is_same<T, bool>::value)>
3710
- FMT_CONSTEXPR auto write(OutputIt out, T value,
3711
- const format_specs<Char>& specs = {}, locale_ref = {})
3712
- -> OutputIt {
3713
- return specs.type != presentation_type::none &&
3714
- specs.type != presentation_type::string
3715
- ? write(out, value ? 1 : 0, specs, {})
3716
- : write_bytes(out, value ? "true" : "false", specs);
3717
- }
3718
-
3719
- template <typename Char, typename OutputIt>
3720
- FMT_CONSTEXPR auto write(OutputIt out, Char value) -> OutputIt {
3721
- auto it = reserve(out, 1);
3722
- *it++ = value;
3723
- return base_iterator(out, it);
3724
- }
3725
-
3726
- template <typename Char, typename OutputIt>
3727
- FMT_CONSTEXPR_CHAR_TRAITS auto write(OutputIt out, const Char* value)
3728
- -> OutputIt {
3729
- if (value) return write(out, basic_string_view<Char>(value));
3730
- throw_format_error("string pointer is null");
3731
- return out;
3732
- }
3733
-
3734
- template <typename Char, typename OutputIt, typename T,
3735
- FMT_ENABLE_IF(std::is_same<T, void>::value)>
3736
- auto write(OutputIt out, const T* value, const format_specs<Char>& specs = {},
3737
- locale_ref = {}) -> OutputIt {
3738
- return write_ptr<Char>(out, bit_cast<uintptr_t>(value), &specs);
3739
- }
3740
-
3741
- // A write overload that handles implicit conversions.
3742
- template <typename Char, typename OutputIt, typename T,
3743
- typename Context = basic_format_context<OutputIt, Char>>
3744
- FMT_CONSTEXPR auto write(OutputIt out, const T& value) -> enable_if_t<
3745
- std::is_class<T>::value && !is_string<T>::value &&
3746
- !is_floating_point<T>::value && !std::is_same<T, Char>::value &&
3747
- !std::is_same<T, remove_cvref_t<decltype(arg_mapper<Context>().map(
3748
- value))>>::value,
3749
- OutputIt> {
3750
- return write<Char>(out, arg_mapper<Context>().map(value));
3751
- }
3752
-
3753
- template <typename Char, typename OutputIt, typename T,
3754
- typename Context = basic_format_context<OutputIt, Char>>
3755
- FMT_CONSTEXPR auto write(OutputIt out, const T& value)
3756
- -> enable_if_t<mapped_type_constant<T, Context>::value == type::custom_type,
3757
- OutputIt> {
3758
- auto formatter = typename Context::template formatter_type<T>();
3759
- auto parse_ctx = typename Context::parse_context_type({});
3760
- formatter.parse(parse_ctx);
3761
- auto ctx = Context(out, {}, {});
3762
- return formatter.format(value, ctx);
3763
- }
3764
-
3765
- // An argument visitor that formats the argument and writes it via the output
3766
- // iterator. It's a class and not a generic lambda for compatibility with C++11.
3767
- template <typename Char> struct default_arg_formatter {
3768
- using iterator = buffer_appender<Char>;
3769
- using context = buffer_context<Char>;
3770
-
3771
- iterator out;
3772
- basic_format_args<context> args;
3773
- locale_ref loc;
3774
-
3775
- template <typename T> auto operator()(T value) -> iterator {
3776
- return write<Char>(out, value);
3777
- }
3778
- auto operator()(typename basic_format_arg<context>::handle h) -> iterator {
3779
- basic_format_parse_context<Char> parse_ctx({});
3780
- context format_ctx(out, args, loc);
3781
- h.format(parse_ctx, format_ctx);
3782
- return format_ctx.out();
3783
- }
3784
- };
3785
-
3786
- template <typename Char> struct arg_formatter {
3787
- using iterator = buffer_appender<Char>;
3788
- using context = buffer_context<Char>;
3789
-
3790
- iterator out;
3791
- const format_specs<Char>& specs;
3792
- locale_ref locale;
3793
-
3794
- template <typename T>
3795
- FMT_CONSTEXPR FMT_INLINE auto operator()(T value) -> iterator {
3796
- return detail::write(out, value, specs, locale);
3797
- }
3798
- auto operator()(typename basic_format_arg<context>::handle) -> iterator {
3799
- // User-defined types are handled separately because they require access
3800
- // to the parse context.
3801
- return out;
3802
- }
3803
- };
3804
-
3805
- struct width_checker {
3806
- template <typename T, FMT_ENABLE_IF(is_integer<T>::value)>
3807
- FMT_CONSTEXPR auto operator()(T value) -> unsigned long long {
3808
- if (is_negative(value)) throw_format_error("negative width");
3809
- return static_cast<unsigned long long>(value);
3810
- }
3811
-
3812
- template <typename T, FMT_ENABLE_IF(!is_integer<T>::value)>
3813
- FMT_CONSTEXPR auto operator()(T) -> unsigned long long {
3814
- throw_format_error("width is not integer");
3815
- return 0;
3816
- }
3817
- };
3818
-
3819
- struct precision_checker {
3820
- template <typename T, FMT_ENABLE_IF(is_integer<T>::value)>
3821
- FMT_CONSTEXPR auto operator()(T value) -> unsigned long long {
3822
- if (is_negative(value)) throw_format_error("negative precision");
3823
- return static_cast<unsigned long long>(value);
3824
- }
3825
-
3826
- template <typename T, FMT_ENABLE_IF(!is_integer<T>::value)>
3827
- FMT_CONSTEXPR auto operator()(T) -> unsigned long long {
3828
- throw_format_error("precision is not integer");
3829
- return 0;
3830
- }
3831
- };
3832
-
3833
- template <typename Handler, typename FormatArg>
3834
- FMT_CONSTEXPR auto get_dynamic_spec(FormatArg arg) -> int {
3835
- unsigned long long value = visit_format_arg(Handler(), arg);
3836
- if (value > to_unsigned(max_value<int>()))
3837
- throw_format_error("number is too big");
3838
- return static_cast<int>(value);
3839
- }
3840
-
3841
- template <typename Context, typename ID>
3842
- FMT_CONSTEXPR auto get_arg(Context& ctx, ID id) -> decltype(ctx.arg(id)) {
3843
- auto arg = ctx.arg(id);
3844
- if (!arg) ctx.on_error("argument not found");
3845
- return arg;
3846
- }
3847
-
3848
- template <typename Handler, typename Context>
3849
- FMT_CONSTEXPR void handle_dynamic_spec(int& value,
3850
- arg_ref<typename Context::char_type> ref,
3851
- Context& ctx) {
3852
- switch (ref.kind) {
3853
- case arg_id_kind::none:
3854
- break;
3855
- case arg_id_kind::index:
3856
- value = detail::get_dynamic_spec<Handler>(get_arg(ctx, ref.val.index));
3857
- break;
3858
- case arg_id_kind::name:
3859
- value = detail::get_dynamic_spec<Handler>(get_arg(ctx, ref.val.name));
3860
- break;
3861
- }
3862
- }
3863
-
3864
- #if FMT_USE_USER_DEFINED_LITERALS
3865
- # if FMT_USE_NONTYPE_TEMPLATE_ARGS
3866
- template <typename T, typename Char, size_t N,
3867
- fmt::detail_exported::fixed_string<Char, N> Str>
3868
- struct statically_named_arg : view {
3869
- static constexpr auto name = Str.data;
3870
-
3871
- const T& value;
3872
- statically_named_arg(const T& v) : value(v) {}
3873
- };
3874
-
3875
- template <typename T, typename Char, size_t N,
3876
- fmt::detail_exported::fixed_string<Char, N> Str>
3877
- struct is_named_arg<statically_named_arg<T, Char, N, Str>> : std::true_type {};
3878
-
3879
- template <typename T, typename Char, size_t N,
3880
- fmt::detail_exported::fixed_string<Char, N> Str>
3881
- struct is_statically_named_arg<statically_named_arg<T, Char, N, Str>>
3882
- : std::true_type {};
3883
-
3884
- template <typename Char, size_t N,
3885
- fmt::detail_exported::fixed_string<Char, N> Str>
3886
- struct udl_arg {
3887
- template <typename T> auto operator=(T&& value) const {
3888
- return statically_named_arg<T, Char, N, Str>(std::forward<T>(value));
3889
- }
3890
- };
3891
- # else
3892
- template <typename Char> struct udl_arg {
3893
- const Char* str;
3894
-
3895
- template <typename T> auto operator=(T&& value) const -> named_arg<Char, T> {
3896
- return {str, std::forward<T>(value)};
3897
- }
3898
- };
3899
- # endif
3900
- #endif // FMT_USE_USER_DEFINED_LITERALS
3901
-
3902
- template <typename Locale, typename Char>
3903
- auto vformat(const Locale& loc, basic_string_view<Char> fmt,
3904
- basic_format_args<buffer_context<type_identity_t<Char>>> args)
3905
- -> std::basic_string<Char> {
3906
- auto buf = basic_memory_buffer<Char>();
3907
- detail::vformat_to(buf, fmt, args, detail::locale_ref(loc));
3908
- return {buf.data(), buf.size()};
3909
- }
3910
-
3911
- using format_func = void (*)(detail::buffer<char>&, int, const char*);
3912
-
3913
- FMT_API void format_error_code(buffer<char>& out, int error_code,
3914
- string_view message) noexcept;
3915
-
3916
- FMT_API void report_error(format_func func, int error_code,
3917
- const char* message) noexcept;
3918
- } // namespace detail
3919
-
3920
- FMT_API auto vsystem_error(int error_code, string_view format_str,
3921
- format_args args) -> std::system_error;
3922
-
3923
- /**
3924
- \rst
3925
- Constructs :class:`std::system_error` with a message formatted with
3926
- ``fmt::format(fmt, args...)``.
3927
- *error_code* is a system error code as given by ``errno``.
3928
-
3929
- **Example**::
3930
-
3931
- // This throws std::system_error with the description
3932
- // cannot open file 'madeup': No such file or directory
3933
- // or similar (system message may vary).
3934
- const char* filename = "madeup";
3935
- std::FILE* file = std::fopen(filename, "r");
3936
- if (!file)
3937
- throw fmt::system_error(errno, "cannot open file '{}'", filename);
3938
- \endrst
3939
- */
3940
- template <typename... T>
3941
- auto system_error(int error_code, format_string<T...> fmt, T&&... args)
3942
- -> std::system_error {
3943
- return vsystem_error(error_code, fmt, fmt::make_format_args(args...));
3944
- }
3945
-
3946
- /**
3947
- \rst
3948
- Formats an error message for an error returned by an operating system or a
3949
- language runtime, for example a file opening error, and writes it to *out*.
3950
- The format is the same as the one used by ``std::system_error(ec, message)``
3951
- where ``ec`` is ``std::error_code(error_code, std::generic_category()})``.
3952
- It is implementation-defined but normally looks like:
3953
-
3954
- .. parsed-literal::
3955
- *<message>*: *<system-message>*
3956
-
3957
- where *<message>* is the passed message and *<system-message>* is the system
3958
- message corresponding to the error code.
3959
- *error_code* is a system error code as given by ``errno``.
3960
- \endrst
3961
- */
3962
- FMT_API void format_system_error(detail::buffer<char>& out, int error_code,
3963
- const char* message) noexcept;
3964
-
3965
- // Reports a system error without throwing an exception.
3966
- // Can be used to report errors from destructors.
3967
- FMT_API void report_system_error(int error_code, const char* message) noexcept;
3968
-
3969
- /** Fast integer formatter. */
3970
- class format_int {
3971
- private:
3972
- // Buffer should be large enough to hold all digits (digits10 + 1),
3973
- // a sign and a null character.
3974
- enum { buffer_size = std::numeric_limits<unsigned long long>::digits10 + 3 };
3975
- mutable char buffer_[buffer_size];
3976
- char* str_;
3977
-
3978
- template <typename UInt> auto format_unsigned(UInt value) -> char* {
3979
- auto n = static_cast<detail::uint32_or_64_or_128_t<UInt>>(value);
3980
- return detail::format_decimal(buffer_, n, buffer_size - 1).begin;
3981
- }
3982
-
3983
- template <typename Int> auto format_signed(Int value) -> char* {
3984
- auto abs_value = static_cast<detail::uint32_or_64_or_128_t<Int>>(value);
3985
- bool negative = value < 0;
3986
- if (negative) abs_value = 0 - abs_value;
3987
- auto begin = format_unsigned(abs_value);
3988
- if (negative) *--begin = '-';
3989
- return begin;
3990
- }
3991
-
3992
- public:
3993
- explicit format_int(int value) : str_(format_signed(value)) {}
3994
- explicit format_int(long value) : str_(format_signed(value)) {}
3995
- explicit format_int(long long value) : str_(format_signed(value)) {}
3996
- explicit format_int(unsigned value) : str_(format_unsigned(value)) {}
3997
- explicit format_int(unsigned long value) : str_(format_unsigned(value)) {}
3998
- explicit format_int(unsigned long long value)
3999
- : str_(format_unsigned(value)) {}
4000
-
4001
- /** Returns the number of characters written to the output buffer. */
4002
- auto size() const -> size_t {
4003
- return detail::to_unsigned(buffer_ - str_ + buffer_size - 1);
4004
- }
4005
-
4006
- /**
4007
- Returns a pointer to the output buffer content. No terminating null
4008
- character is appended.
4009
- */
4010
- auto data() const -> const char* { return str_; }
4011
-
4012
- /**
4013
- Returns a pointer to the output buffer content with terminating null
4014
- character appended.
4015
- */
4016
- auto c_str() const -> const char* {
4017
- buffer_[buffer_size - 1] = '\0';
4018
- return str_;
4019
- }
4020
-
4021
- /**
4022
- \rst
4023
- Returns the content of the output buffer as an ``std::string``.
4024
- \endrst
4025
- */
4026
- auto str() const -> std::string { return std::string(str_, size()); }
4027
- };
4028
-
4029
- template <typename T, typename Char>
4030
- struct formatter<T, Char, enable_if_t<detail::has_format_as<T>::value>>
4031
- : formatter<detail::format_as_t<T>, Char> {
4032
- template <typename FormatContext>
4033
- auto format(const T& value, FormatContext& ctx) const -> decltype(ctx.out()) {
4034
- using base = formatter<detail::format_as_t<T>, Char>;
4035
- return base::format(format_as(value), ctx);
4036
- }
4037
- };
4038
-
4039
- #define FMT_FORMAT_AS(Type, Base) \
4040
- template <typename Char> \
4041
- struct formatter<Type, Char> : formatter<Base, Char> {}
4042
-
4043
- FMT_FORMAT_AS(signed char, int);
4044
- FMT_FORMAT_AS(unsigned char, unsigned);
4045
- FMT_FORMAT_AS(short, int);
4046
- FMT_FORMAT_AS(unsigned short, unsigned);
4047
- FMT_FORMAT_AS(long, detail::long_type);
4048
- FMT_FORMAT_AS(unsigned long, detail::ulong_type);
4049
- FMT_FORMAT_AS(Char*, const Char*);
4050
- FMT_FORMAT_AS(std::basic_string<Char>, basic_string_view<Char>);
4051
- FMT_FORMAT_AS(std::nullptr_t, const void*);
4052
- FMT_FORMAT_AS(detail::std_string_view<Char>, basic_string_view<Char>);
4053
- FMT_FORMAT_AS(void*, const void*);
4054
-
4055
- template <typename Char, size_t N>
4056
- struct formatter<Char[N], Char> : formatter<basic_string_view<Char>, Char> {};
4057
-
4058
- /**
4059
- \rst
4060
- Converts ``p`` to ``const void*`` for pointer formatting.
4061
-
4062
- **Example**::
4063
-
4064
- auto s = fmt::format("{}", fmt::ptr(p));
4065
- \endrst
4066
- */
4067
- template <typename T> auto ptr(T p) -> const void* {
4068
- static_assert(std::is_pointer<T>::value, "");
4069
- return detail::bit_cast<const void*>(p);
4070
- }
4071
- template <typename T, typename Deleter>
4072
- auto ptr(const std::unique_ptr<T, Deleter>& p) -> const void* {
4073
- return p.get();
4074
- }
4075
- template <typename T> auto ptr(const std::shared_ptr<T>& p) -> const void* {
4076
- return p.get();
4077
- }
4078
-
4079
- /**
4080
- \rst
4081
- Converts ``e`` to the underlying type.
4082
-
4083
- **Example**::
4084
-
4085
- enum class color { red, green, blue };
4086
- auto s = fmt::format("{}", fmt::underlying(color::red));
4087
- \endrst
4088
- */
4089
- template <typename Enum>
4090
- constexpr auto underlying(Enum e) noexcept -> underlying_t<Enum> {
4091
- return static_cast<underlying_t<Enum>>(e);
4092
- }
4093
-
4094
- namespace enums {
4095
- template <typename Enum, FMT_ENABLE_IF(std::is_enum<Enum>::value)>
4096
- constexpr auto format_as(Enum e) noexcept -> underlying_t<Enum> {
4097
- return static_cast<underlying_t<Enum>>(e);
4098
- }
4099
- } // namespace enums
4100
-
4101
- class bytes {
4102
- private:
4103
- string_view data_;
4104
- friend struct formatter<bytes>;
4105
-
4106
- public:
4107
- explicit bytes(string_view data) : data_(data) {}
4108
- };
4109
-
4110
- template <> struct formatter<bytes> {
4111
- private:
4112
- detail::dynamic_format_specs<> specs_;
4113
-
4114
- public:
4115
- template <typename ParseContext>
4116
- FMT_CONSTEXPR auto parse(ParseContext& ctx) -> const char* {
4117
- return parse_format_specs(ctx.begin(), ctx.end(), specs_, ctx,
4118
- detail::type::string_type);
4119
- }
4120
-
4121
- template <typename FormatContext>
4122
- auto format(bytes b, FormatContext& ctx) -> decltype(ctx.out()) {
4123
- detail::handle_dynamic_spec<detail::width_checker>(specs_.width,
4124
- specs_.width_ref, ctx);
4125
- detail::handle_dynamic_spec<detail::precision_checker>(
4126
- specs_.precision, specs_.precision_ref, ctx);
4127
- return detail::write_bytes(ctx.out(), b.data_, specs_);
4128
- }
4129
- };
4130
-
4131
- // group_digits_view is not derived from view because it copies the argument.
4132
- template <typename T> struct group_digits_view {
4133
- T value;
4134
- };
4135
-
4136
- /**
4137
- \rst
4138
- Returns a view that formats an integer value using ',' as a locale-independent
4139
- thousands separator.
4140
-
4141
- **Example**::
4142
-
4143
- fmt::print("{}", fmt::group_digits(12345));
4144
- // Output: "12,345"
4145
- \endrst
4146
- */
4147
- template <typename T> auto group_digits(T value) -> group_digits_view<T> {
4148
- return {value};
4149
- }
4150
-
4151
- template <typename T> struct formatter<group_digits_view<T>> : formatter<T> {
4152
- private:
4153
- detail::dynamic_format_specs<> specs_;
4154
-
4155
- public:
4156
- template <typename ParseContext>
4157
- FMT_CONSTEXPR auto parse(ParseContext& ctx) -> const char* {
4158
- return parse_format_specs(ctx.begin(), ctx.end(), specs_, ctx,
4159
- detail::type::int_type);
4160
- }
4161
-
4162
- template <typename FormatContext>
4163
- auto format(group_digits_view<T> t, FormatContext& ctx)
4164
- -> decltype(ctx.out()) {
4165
- detail::handle_dynamic_spec<detail::width_checker>(specs_.width,
4166
- specs_.width_ref, ctx);
4167
- detail::handle_dynamic_spec<detail::precision_checker>(
4168
- specs_.precision, specs_.precision_ref, ctx);
4169
- return detail::write_int(
4170
- ctx.out(), static_cast<detail::uint64_or_128_t<T>>(t.value), 0, specs_,
4171
- detail::digit_grouping<char>("\3", ","));
4172
- }
4173
- };
4174
-
4175
- template <typename T> struct nested_view {
4176
- const formatter<T>* fmt;
4177
- const T* value;
4178
- };
4179
-
4180
- template <typename T> struct formatter<nested_view<T>> {
4181
- FMT_CONSTEXPR auto parse(format_parse_context& ctx) -> const char* {
4182
- return ctx.begin();
4183
- }
4184
- auto format(nested_view<T> view, format_context& ctx) const
4185
- -> decltype(ctx.out()) {
4186
- return view.fmt->format(*view.value, ctx);
4187
- }
4188
- };
4189
-
4190
- template <typename T> struct nested_formatter {
4191
- private:
4192
- int width_;
4193
- detail::fill_t<char> fill_;
4194
- align_t align_ : 4;
4195
- formatter<T> formatter_;
4196
-
4197
- public:
4198
- constexpr nested_formatter() : width_(0), align_(align_t::none) {}
4199
-
4200
- FMT_CONSTEXPR auto parse(format_parse_context& ctx) -> const char* {
4201
- auto specs = detail::dynamic_format_specs<char>();
4202
- auto it = parse_format_specs(ctx.begin(), ctx.end(), specs, ctx,
4203
- detail::type::none_type);
4204
- width_ = specs.width;
4205
- fill_ = specs.fill;
4206
- align_ = specs.align;
4207
- ctx.advance_to(it);
4208
- return formatter_.parse(ctx);
4209
- }
4210
-
4211
- template <typename F>
4212
- auto write_padded(format_context& ctx, F write) const -> decltype(ctx.out()) {
4213
- if (width_ == 0) return write(ctx.out());
4214
- auto buf = memory_buffer();
4215
- write(std::back_inserter(buf));
4216
- auto specs = format_specs<>();
4217
- specs.width = width_;
4218
- specs.fill = fill_;
4219
- specs.align = align_;
4220
- return detail::write(ctx.out(), string_view(buf.data(), buf.size()), specs);
4221
- }
4222
-
4223
- auto nested(const T& value) const -> nested_view<T> {
4224
- return nested_view<T>{&formatter_, &value};
4225
- }
4226
- };
4227
-
4228
- // DEPRECATED! join_view will be moved to ranges.h.
4229
- template <typename It, typename Sentinel, typename Char = char>
4230
- struct join_view : detail::view {
4231
- It begin;
4232
- Sentinel end;
4233
- basic_string_view<Char> sep;
4234
-
4235
- join_view(It b, Sentinel e, basic_string_view<Char> s)
4236
- : begin(b), end(e), sep(s) {}
4237
- };
4238
-
4239
- template <typename It, typename Sentinel, typename Char>
4240
- struct formatter<join_view<It, Sentinel, Char>, Char> {
4241
- private:
4242
- using value_type =
4243
- #ifdef __cpp_lib_ranges
4244
- std::iter_value_t<It>;
4245
- #else
4246
- typename std::iterator_traits<It>::value_type;
4247
- #endif
4248
- formatter<remove_cvref_t<value_type>, Char> value_formatter_;
4249
-
4250
- public:
4251
- template <typename ParseContext>
4252
- FMT_CONSTEXPR auto parse(ParseContext& ctx) -> const Char* {
4253
- return value_formatter_.parse(ctx);
4254
- }
4255
-
4256
- template <typename FormatContext>
4257
- auto format(const join_view<It, Sentinel, Char>& value,
4258
- FormatContext& ctx) const -> decltype(ctx.out()) {
4259
- auto it = value.begin;
4260
- auto out = ctx.out();
4261
- if (it != value.end) {
4262
- out = value_formatter_.format(*it, ctx);
4263
- ++it;
4264
- while (it != value.end) {
4265
- out = detail::copy_str<Char>(value.sep.begin(), value.sep.end(), out);
4266
- ctx.advance_to(out);
4267
- out = value_formatter_.format(*it, ctx);
4268
- ++it;
4269
- }
4270
- }
4271
- return out;
4272
- }
4273
- };
4274
-
4275
- /**
4276
- Returns a view that formats the iterator range `[begin, end)` with elements
4277
- separated by `sep`.
4278
- */
4279
- template <typename It, typename Sentinel>
4280
- auto join(It begin, Sentinel end, string_view sep) -> join_view<It, Sentinel> {
4281
- return {begin, end, sep};
4282
- }
4283
-
4284
- /**
4285
- \rst
4286
- Returns a view that formats `range` with elements separated by `sep`.
4287
-
4288
- **Example**::
4289
-
4290
- std::vector<int> v = {1, 2, 3};
4291
- fmt::print("{}", fmt::join(v, ", "));
4292
- // Output: "1, 2, 3"
4293
-
4294
- ``fmt::join`` applies passed format specifiers to the range elements::
4295
-
4296
- fmt::print("{:02}", fmt::join(v, ", "));
4297
- // Output: "01, 02, 03"
4298
- \endrst
4299
- */
4300
- template <typename Range>
4301
- auto join(Range&& range, string_view sep)
4302
- -> join_view<detail::iterator_t<Range>, detail::sentinel_t<Range>> {
4303
- return join(std::begin(range), std::end(range), sep);
4304
- }
4305
-
4306
- /**
4307
- \rst
4308
- Converts *value* to ``std::string`` using the default format for type *T*.
4309
-
4310
- **Example**::
4311
-
4312
- #include <fmt/format.h>
4313
-
4314
- std::string answer = fmt::to_string(42);
4315
- \endrst
4316
- */
4317
- template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value &&
4318
- !detail::has_format_as<T>::value)>
4319
- inline auto to_string(const T& value) -> std::string {
4320
- auto buffer = memory_buffer();
4321
- detail::write<char>(appender(buffer), value);
4322
- return {buffer.data(), buffer.size()};
4323
- }
4324
-
4325
- template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
4326
- FMT_NODISCARD inline auto to_string(T value) -> std::string {
4327
- // The buffer should be large enough to store the number including the sign
4328
- // or "false" for bool.
4329
- constexpr int max_size = detail::digits10<T>() + 2;
4330
- char buffer[max_size > 5 ? static_cast<unsigned>(max_size) : 5];
4331
- char* begin = buffer;
4332
- return std::string(begin, detail::write<char>(begin, value));
4333
- }
4334
-
4335
- template <typename Char, size_t SIZE>
4336
- FMT_NODISCARD auto to_string(const basic_memory_buffer<Char, SIZE>& buf)
4337
- -> std::basic_string<Char> {
4338
- auto size = buf.size();
4339
- detail::assume(size < std::basic_string<Char>().max_size());
4340
- return std::basic_string<Char>(buf.data(), size);
4341
- }
4342
-
4343
- template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value &&
4344
- detail::has_format_as<T>::value)>
4345
- inline auto to_string(const T& value) -> std::string {
4346
- return to_string(format_as(value));
4347
- }
4348
-
4349
- FMT_END_EXPORT
4350
-
4351
- namespace detail {
4352
-
4353
- template <typename Char>
4354
- void vformat_to(buffer<Char>& buf, basic_string_view<Char> fmt,
4355
- typename vformat_args<Char>::type args, locale_ref loc) {
4356
- auto out = buffer_appender<Char>(buf);
4357
- if (fmt.size() == 2 && equal2(fmt.data(), "{}")) {
4358
- auto arg = args.get(0);
4359
- if (!arg) throw_format_error("argument not found");
4360
- visit_format_arg(default_arg_formatter<Char>{out, args, loc}, arg);
4361
- return;
4362
- }
4363
-
4364
- struct format_handler : error_handler {
4365
- basic_format_parse_context<Char> parse_context;
4366
- buffer_context<Char> context;
4367
-
4368
- format_handler(buffer_appender<Char> p_out, basic_string_view<Char> str,
4369
- basic_format_args<buffer_context<Char>> p_args,
4370
- locale_ref p_loc)
4371
- : parse_context(str), context(p_out, p_args, p_loc) {}
4372
-
4373
- void on_text(const Char* begin, const Char* end) {
4374
- auto text = basic_string_view<Char>(begin, to_unsigned(end - begin));
4375
- context.advance_to(write<Char>(context.out(), text));
4376
- }
4377
-
4378
- FMT_CONSTEXPR auto on_arg_id() -> int {
4379
- return parse_context.next_arg_id();
4380
- }
4381
- FMT_CONSTEXPR auto on_arg_id(int id) -> int {
4382
- return parse_context.check_arg_id(id), id;
4383
- }
4384
- FMT_CONSTEXPR auto on_arg_id(basic_string_view<Char> id) -> int {
4385
- int arg_id = context.arg_id(id);
4386
- if (arg_id < 0) throw_format_error("argument not found");
4387
- return arg_id;
4388
- }
4389
-
4390
- FMT_INLINE void on_replacement_field(int id, const Char*) {
4391
- auto arg = get_arg(context, id);
4392
- context.advance_to(visit_format_arg(
4393
- default_arg_formatter<Char>{context.out(), context.args(),
4394
- context.locale()},
4395
- arg));
4396
- }
4397
-
4398
- auto on_format_specs(int id, const Char* begin, const Char* end)
4399
- -> const Char* {
4400
- auto arg = get_arg(context, id);
4401
- // Not using a visitor for custom types gives better codegen.
4402
- if (arg.format_custom(begin, parse_context, context))
4403
- return parse_context.begin();
4404
- auto specs = detail::dynamic_format_specs<Char>();
4405
- begin = parse_format_specs(begin, end, specs, parse_context, arg.type());
4406
- detail::handle_dynamic_spec<detail::width_checker>(
4407
- specs.width, specs.width_ref, context);
4408
- detail::handle_dynamic_spec<detail::precision_checker>(
4409
- specs.precision, specs.precision_ref, context);
4410
- if (begin == end || *begin != '}')
4411
- throw_format_error("missing '}' in format string");
4412
- auto f = arg_formatter<Char>{context.out(), specs, context.locale()};
4413
- context.advance_to(visit_format_arg(f, arg));
4414
- return begin;
4415
- }
4416
- };
4417
- detail::parse_format_string<false>(fmt, format_handler(out, fmt, args, loc));
4418
- }
4419
-
4420
- FMT_BEGIN_EXPORT
4421
-
4422
- #ifndef FMT_HEADER_ONLY
4423
- extern template FMT_API void vformat_to(buffer<char>&, string_view,
4424
- typename vformat_args<>::type,
4425
- locale_ref);
4426
- extern template FMT_API auto thousands_sep_impl<char>(locale_ref)
4427
- -> thousands_sep_result<char>;
4428
- extern template FMT_API auto thousands_sep_impl<wchar_t>(locale_ref)
4429
- -> thousands_sep_result<wchar_t>;
4430
- extern template FMT_API auto decimal_point_impl(locale_ref) -> char;
4431
- extern template FMT_API auto decimal_point_impl(locale_ref) -> wchar_t;
4432
- #endif // FMT_HEADER_ONLY
4433
-
4434
- } // namespace detail
4435
-
4436
- #if FMT_USE_USER_DEFINED_LITERALS
4437
- inline namespace literals {
4438
- /**
4439
- \rst
4440
- User-defined literal equivalent of :func:`fmt::arg`.
4441
-
4442
- **Example**::
4443
-
4444
- using namespace fmt::literals;
4445
- fmt::print("Elapsed time: {s:.2f} seconds", "s"_a=1.23);
4446
- \endrst
4447
- */
4448
- # if FMT_USE_NONTYPE_TEMPLATE_ARGS
4449
- template <detail_exported::fixed_string Str> constexpr auto operator""_a() {
4450
- using char_t = remove_cvref_t<decltype(Str.data[0])>;
4451
- return detail::udl_arg<char_t, sizeof(Str.data) / sizeof(char_t), Str>();
4452
- }
4453
- # else
4454
- constexpr auto operator""_a(const char* s, size_t) -> detail::udl_arg<char> {
4455
- return {s};
4456
- }
4457
- # endif
4458
- } // namespace literals
4459
- #endif // FMT_USE_USER_DEFINED_LITERALS
4460
-
4461
- template <typename Locale, FMT_ENABLE_IF(detail::is_locale<Locale>::value)>
4462
- inline auto vformat(const Locale& loc, string_view fmt, format_args args)
4463
- -> std::string {
4464
- return detail::vformat(loc, fmt, args);
4465
- }
4466
-
4467
- template <typename Locale, typename... T,
4468
- FMT_ENABLE_IF(detail::is_locale<Locale>::value)>
4469
- inline auto format(const Locale& loc, format_string<T...> fmt, T&&... args)
4470
- -> std::string {
4471
- return fmt::vformat(loc, string_view(fmt), fmt::make_format_args(args...));
4472
- }
4473
-
4474
- template <typename OutputIt, typename Locale,
4475
- FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value&&
4476
- detail::is_locale<Locale>::value)>
4477
- auto vformat_to(OutputIt out, const Locale& loc, string_view fmt,
4478
- format_args args) -> OutputIt {
4479
- using detail::get_buffer;
4480
- auto&& buf = get_buffer<char>(out);
4481
- detail::vformat_to(buf, fmt, args, detail::locale_ref(loc));
4482
- return detail::get_iterator(buf, out);
4483
- }
4484
-
4485
- template <typename OutputIt, typename Locale, typename... T,
4486
- FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value&&
4487
- detail::is_locale<Locale>::value)>
4488
- FMT_INLINE auto format_to(OutputIt out, const Locale& loc,
4489
- format_string<T...> fmt, T&&... args) -> OutputIt {
4490
- return vformat_to(out, loc, fmt, fmt::make_format_args(args...));
4491
- }
4492
-
4493
- template <typename Locale, typename... T,
4494
- FMT_ENABLE_IF(detail::is_locale<Locale>::value)>
4495
- FMT_NODISCARD FMT_INLINE auto formatted_size(const Locale& loc,
4496
- format_string<T...> fmt,
4497
- T&&... args) -> size_t {
4498
- auto buf = detail::counting_buffer<>();
4499
- detail::vformat_to<char>(buf, fmt, fmt::make_format_args(args...),
4500
- detail::locale_ref(loc));
4501
- return buf.count();
4502
- }
4503
-
4504
- FMT_END_EXPORT
4505
-
4506
- template <typename T, typename Char>
4507
- template <typename FormatContext>
4508
- FMT_CONSTEXPR FMT_INLINE auto
4509
- formatter<T, Char,
4510
- enable_if_t<detail::type_constant<T, Char>::value !=
4511
- detail::type::custom_type>>::format(const T& val,
4512
- FormatContext& ctx)
4513
- const -> decltype(ctx.out()) {
4514
- if (specs_.width_ref.kind == detail::arg_id_kind::none &&
4515
- specs_.precision_ref.kind == detail::arg_id_kind::none) {
4516
- return detail::write<Char>(ctx.out(), val, specs_, ctx.locale());
4517
- }
4518
- auto specs = specs_;
4519
- detail::handle_dynamic_spec<detail::width_checker>(specs.width,
4520
- specs.width_ref, ctx);
4521
- detail::handle_dynamic_spec<detail::precision_checker>(
4522
- specs.precision, specs.precision_ref, ctx);
4523
- return detail::write<Char>(ctx.out(), val, specs, ctx.locale());
4524
- }
4525
-
4526
- FMT_END_NAMESPACE
4527
-
4528
- #ifdef FMT_HEADER_ONLY
4529
- # define FMT_FUNC inline
4530
- # include "format-inl.h"
4531
- #else
4532
- # define FMT_FUNC
4533
- #endif
4534
-
4535
- #endif // FMT_FORMAT_H_