mirror of
https://github.com/boostorg/charconv.git
synced 2026-02-09 11:02:30 +00:00
Merge pull request #10 from mborland/to_chars_int
to_chars integer parser
This commit is contained in:
@@ -18,6 +18,7 @@ Peter Dimov and Matt Borland
|
||||
|
||||
include::charconv/overview.adoc[]
|
||||
include::charconv/from_chars.adoc[]
|
||||
include::charconv/to_chars.adoc[]
|
||||
include::charconv/reference.adoc[]
|
||||
include::charconv/copyright.adoc[]
|
||||
|
||||
|
||||
@@ -1,981 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="generator" content="Asciidoctor 2.0.18">
|
||||
<meta name="author" content="Peter Dimov and Matt Borland">
|
||||
<title>CharConv: An Implementation of <charconv> in C++11</title>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
|
||||
<style>
|
||||
/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */
|
||||
/* Uncomment the following line when using as a custom stylesheet */
|
||||
/* @import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700"; */
|
||||
html{font-family:sans-serif;-webkit-text-size-adjust:100%}
|
||||
a{background:none}
|
||||
a:focus{outline:thin dotted}
|
||||
a:active,a:hover{outline:0}
|
||||
h1{font-size:2em;margin:.67em 0}
|
||||
b,strong{font-weight:bold}
|
||||
abbr{font-size:.9em}
|
||||
abbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}
|
||||
dfn{font-style:italic}
|
||||
hr{height:0}
|
||||
mark{background:#ff0;color:#000}
|
||||
code,kbd,pre,samp{font-family:monospace;font-size:1em}
|
||||
pre{white-space:pre-wrap}
|
||||
q{quotes:"\201C" "\201D" "\2018" "\2019"}
|
||||
small{font-size:80%}
|
||||
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
|
||||
sup{top:-.5em}
|
||||
sub{bottom:-.25em}
|
||||
img{border:0}
|
||||
svg:not(:root){overflow:hidden}
|
||||
figure{margin:0}
|
||||
audio,video{display:inline-block}
|
||||
audio:not([controls]){display:none;height:0}
|
||||
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
|
||||
legend{border:0;padding:0}
|
||||
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
|
||||
button,input{line-height:normal}
|
||||
button,select{text-transform:none}
|
||||
button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}
|
||||
button[disabled],html input[disabled]{cursor:default}
|
||||
input[type=checkbox],input[type=radio]{padding:0}
|
||||
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
|
||||
textarea{overflow:auto;vertical-align:top}
|
||||
table{border-collapse:collapse;border-spacing:0}
|
||||
*,::before,::after{box-sizing:border-box}
|
||||
html,body{font-size:100%}
|
||||
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
|
||||
a:hover{cursor:pointer}
|
||||
img,object,embed{max-width:100%;height:auto}
|
||||
object,embed{height:100%}
|
||||
img{-ms-interpolation-mode:bicubic}
|
||||
.left{float:left!important}
|
||||
.right{float:right!important}
|
||||
.text-left{text-align:left!important}
|
||||
.text-right{text-align:right!important}
|
||||
.text-center{text-align:center!important}
|
||||
.text-justify{text-align:justify!important}
|
||||
.hide{display:none}
|
||||
img,object,svg{display:inline-block;vertical-align:middle}
|
||||
textarea{height:auto;min-height:50px}
|
||||
select{width:100%}
|
||||
.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
|
||||
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}
|
||||
a{color:#2156a5;text-decoration:underline;line-height:inherit}
|
||||
a:hover,a:focus{color:#1d4b8f}
|
||||
a img{border:0}
|
||||
p{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
|
||||
p aside{font-size:.875em;line-height:1.35;font-style:italic}
|
||||
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
|
||||
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
|
||||
h1{font-size:2.125em}
|
||||
h2{font-size:1.6875em}
|
||||
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
|
||||
h4,h5{font-size:1.125em}
|
||||
h6{font-size:1em}
|
||||
hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}
|
||||
em,i{font-style:italic;line-height:inherit}
|
||||
strong,b{font-weight:bold;line-height:inherit}
|
||||
small{font-size:60%;line-height:inherit}
|
||||
code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
|
||||
ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
|
||||
ul,ol{margin-left:1.5em}
|
||||
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}
|
||||
ul.circle{list-style-type:circle}
|
||||
ul.disc{list-style-type:disc}
|
||||
ul.square{list-style-type:square}
|
||||
ul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}
|
||||
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
|
||||
dl dt{margin-bottom:.3125em;font-weight:bold}
|
||||
dl dd{margin-bottom:1.25em}
|
||||
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
|
||||
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
|
||||
@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
|
||||
h1{font-size:2.75em}
|
||||
h2{font-size:2.3125em}
|
||||
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}
|
||||
h4{font-size:1.4375em}}
|
||||
table{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}
|
||||
table thead,table tfoot{background:#f7f8f7}
|
||||
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
|
||||
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
|
||||
table tr.even,table tr.alt{background:#f8f8f7}
|
||||
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}
|
||||
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
|
||||
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
|
||||
.center{margin-left:auto;margin-right:auto}
|
||||
.stretch{width:100%}
|
||||
.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:" ";display:table}
|
||||
.clearfix::after,.float-group::after{clear:both}
|
||||
:not(pre).nobreak{word-wrap:normal}
|
||||
:not(pre).nowrap{white-space:nowrap}
|
||||
:not(pre).pre-wrap{white-space:pre-wrap}
|
||||
:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
|
||||
pre{color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;line-height:1.45;text-rendering:optimizeSpeed}
|
||||
pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}
|
||||
pre>code{display:block}
|
||||
pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}
|
||||
em em{font-style:normal}
|
||||
strong strong{font-weight:400}
|
||||
.keyseq{color:rgba(51,51,51,.8)}
|
||||
kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
|
||||
.keyseq kbd:first-child{margin-left:0}
|
||||
.keyseq kbd:last-child{margin-right:0}
|
||||
.menuseq,.menuref{color:#000}
|
||||
.menuseq b:not(.caret),.menuref{font-weight:inherit}
|
||||
.menuseq{word-spacing:-.02em}
|
||||
.menuseq b.caret{font-size:1.25em;line-height:.8}
|
||||
.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
|
||||
b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
|
||||
b.button::before{content:"[";padding:0 3px 0 2px}
|
||||
b.button::after{content:"]";padding:0 2px 0 3px}
|
||||
p a>code:hover{color:rgba(0,0,0,.9)}
|
||||
#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
|
||||
#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:" ";display:table}
|
||||
#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
|
||||
#content{margin-top:1.25em}
|
||||
#content::before{content:none}
|
||||
#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
|
||||
#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
|
||||
#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
|
||||
#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}
|
||||
#header .details span:first-child{margin-left:-.125em}
|
||||
#header .details span.email a{color:rgba(0,0,0,.85)}
|
||||
#header .details br{display:none}
|
||||
#header .details br+span::before{content:"\00a0\2013\00a0"}
|
||||
#header .details br+span.author::before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}
|
||||
#header .details br+span#revremark::before{content:"\00a0|\00a0"}
|
||||
#header #revnumber{text-transform:capitalize}
|
||||
#header #revnumber::after{content:"\00a0"}
|
||||
#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
|
||||
#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}
|
||||
#toc>ul{margin-left:.125em}
|
||||
#toc ul.sectlevel0>li>a{font-style:italic}
|
||||
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
|
||||
#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}
|
||||
#toc li{line-height:1.3334;margin-top:.3334em}
|
||||
#toc a{text-decoration:none}
|
||||
#toc a:active{text-decoration:underline}
|
||||
#toctitle{color:#7a2518;font-size:1.2em}
|
||||
@media screen and (min-width:768px){#toctitle{font-size:1.375em}
|
||||
body.toc2{padding-left:15em;padding-right:0}
|
||||
#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
|
||||
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
|
||||
#toc.toc2>ul{font-size:.9em;margin-bottom:0}
|
||||
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
|
||||
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
|
||||
body.toc2.toc-right{padding-left:0;padding-right:15em}
|
||||
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}
|
||||
@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
|
||||
#toc.toc2{width:20em}
|
||||
#toc.toc2 #toctitle{font-size:1.375em}
|
||||
#toc.toc2>ul{font-size:.95em}
|
||||
#toc.toc2 ul ul{padding-left:1.25em}
|
||||
body.toc2.toc-right{padding-left:0;padding-right:20em}}
|
||||
#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}
|
||||
#content #toc>:first-child{margin-top:0}
|
||||
#content #toc>:last-child{margin-bottom:0}
|
||||
#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}
|
||||
#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}
|
||||
#content{margin-bottom:.625em}
|
||||
.sect1{padding-bottom:.625em}
|
||||
@media screen and (min-width:768px){#content{margin-bottom:1.25em}
|
||||
.sect1{padding-bottom:1.25em}}
|
||||
.sect1:last-child{padding-bottom:0}
|
||||
.sect1+.sect1{border-top:1px solid #e7e7e9}
|
||||
#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
|
||||
#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em}
|
||||
#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}
|
||||
#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}
|
||||
#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}
|
||||
details,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
|
||||
details{margin-left:1.25rem}
|
||||
details>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}
|
||||
details>summary::-webkit-details-marker{display:none}
|
||||
details>summary::before{content:"";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}
|
||||
details[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}
|
||||
details>summary::after{content:"";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}
|
||||
.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic}
|
||||
table.tableblock.fit-content>caption.title{white-space:nowrap;width:0}
|
||||
.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
|
||||
.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}
|
||||
.admonitionblock>table td.icon{text-align:center;width:80px}
|
||||
.admonitionblock>table td.icon img{max-width:none}
|
||||
.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}
|
||||
.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}
|
||||
.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
|
||||
.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}
|
||||
.exampleblock>.content>:first-child{margin-top:0}
|
||||
.exampleblock>.content>:last-child{margin-bottom:0}
|
||||
.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}
|
||||
.sidebarblock>:first-child{margin-top:0}
|
||||
.sidebarblock>:last-child{margin-bottom:0}
|
||||
.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
|
||||
.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
|
||||
.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}
|
||||
@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}
|
||||
@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}
|
||||
.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^="highlight "]{background:#f7f7f8}
|
||||
.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}
|
||||
.listingblock>.content{position:relative}
|
||||
.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}
|
||||
.listingblock:hover code[data-lang]::before{display:block}
|
||||
.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}
|
||||
.listingblock.terminal pre .command:not([data-prompt])::before{content:"$"}
|
||||
.listingblock pre.highlightjs{padding:0}
|
||||
.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}
|
||||
.listingblock pre.prettyprint{border-width:0}
|
||||
.prettyprint{background:#f7f7f8}
|
||||
pre.prettyprint .linenums{line-height:1.45;margin-left:2em}
|
||||
pre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}
|
||||
pre.prettyprint li code[data-lang]::before{opacity:1}
|
||||
pre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}
|
||||
table.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}
|
||||
table.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}
|
||||
table.linenotable td.code{padding-left:.75em}
|
||||
table.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
|
||||
pre.pygments span.linenos{display:inline-block;margin-right:.75em}
|
||||
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
|
||||
.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}
|
||||
.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
|
||||
.quoteblock blockquote{margin:0;padding:0;border:0}
|
||||
.quoteblock blockquote::before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
|
||||
.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}
|
||||
.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}
|
||||
.verseblock{margin:0 1em 1.25em}
|
||||
.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
|
||||
.verseblock pre strong{font-weight:400}
|
||||
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
|
||||
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
|
||||
.quoteblock .attribution br,.verseblock .attribution br{display:none}
|
||||
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
|
||||
.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
|
||||
.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
|
||||
.quoteblock.abstract{margin:0 1em 1.25em;display:block}
|
||||
.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
|
||||
.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
|
||||
.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}
|
||||
.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
|
||||
.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}
|
||||
p.tableblock:last-child{margin-bottom:0}
|
||||
td.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}
|
||||
td.tableblock>.content>:last-child{margin-bottom:-1.25em}
|
||||
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
|
||||
table.grid-all>*>tr>*{border-width:1px}
|
||||
table.grid-cols>*>tr>*{border-width:0 1px}
|
||||
table.grid-rows>*>tr>*{border-width:1px 0}
|
||||
table.frame-all{border-width:1px}
|
||||
table.frame-ends{border-width:1px 0}
|
||||
table.frame-sides{border-width:0 1px}
|
||||
table.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}
|
||||
table.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}
|
||||
table.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}
|
||||
table.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}
|
||||
table.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}
|
||||
th.halign-left,td.halign-left{text-align:left}
|
||||
th.halign-right,td.halign-right{text-align:right}
|
||||
th.halign-center,td.halign-center{text-align:center}
|
||||
th.valign-top,td.valign-top{vertical-align:top}
|
||||
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
|
||||
th.valign-middle,td.valign-middle{vertical-align:middle}
|
||||
table thead th,table tfoot th{font-weight:bold}
|
||||
tbody tr th{background:#f7f8f7}
|
||||
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
|
||||
p.tableblock>code:only-child{background:none;padding:0}
|
||||
p.tableblock{font-size:1em}
|
||||
ol{margin-left:1.75em}
|
||||
ul li ol{margin-left:1.5em}
|
||||
dl dd{margin-left:1.125em}
|
||||
dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}
|
||||
li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
|
||||
ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
|
||||
ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
|
||||
ul.unstyled,ol.unstyled{margin-left:0}
|
||||
li>p:empty:only-child::before{content:"";display:inline-block}
|
||||
ul.checklist>li>p:first-child{margin-left:-1em}
|
||||
ul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
|
||||
ul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}
|
||||
ul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
|
||||
ul.inline>li{margin-left:1.25em}
|
||||
.unstyled dl dt{font-weight:400;font-style:normal}
|
||||
ol.arabic{list-style-type:decimal}
|
||||
ol.decimal{list-style-type:decimal-leading-zero}
|
||||
ol.loweralpha{list-style-type:lower-alpha}
|
||||
ol.upperalpha{list-style-type:upper-alpha}
|
||||
ol.lowerroman{list-style-type:lower-roman}
|
||||
ol.upperroman{list-style-type:upper-roman}
|
||||
ol.lowergreek{list-style-type:lower-greek}
|
||||
.hdlist>table,.colist>table{border:0;background:none}
|
||||
.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}
|
||||
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
|
||||
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
|
||||
td.hdlist2{word-wrap:anywhere}
|
||||
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
|
||||
.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
|
||||
.colist td:not([class]):first-child img{max-width:none}
|
||||
.colist td:not([class]):last-child{padding:.25em 0}
|
||||
.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}
|
||||
.imageblock.left{margin:.25em .625em 1.25em 0}
|
||||
.imageblock.right{margin:.25em 0 1.25em .625em}
|
||||
.imageblock>.title{margin-bottom:0}
|
||||
.imageblock.thumb,.imageblock.th{border-width:6px}
|
||||
.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}
|
||||
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
|
||||
.image.left{margin-right:.625em}
|
||||
.image.right{margin-left:.625em}
|
||||
a.image{text-decoration:none;display:inline-block}
|
||||
a.image object{pointer-events:none}
|
||||
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
|
||||
sup.footnote a,sup.footnoteref a{text-decoration:none}
|
||||
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
|
||||
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
|
||||
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
|
||||
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
|
||||
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
|
||||
#footnotes .footnote:last-of-type{margin-bottom:0}
|
||||
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
|
||||
div.unbreakable{page-break-inside:avoid}
|
||||
.big{font-size:larger}
|
||||
.small{font-size:smaller}
|
||||
.underline{text-decoration:underline}
|
||||
.overline{text-decoration:overline}
|
||||
.line-through{text-decoration:line-through}
|
||||
.aqua{color:#00bfbf}
|
||||
.aqua-background{background:#00fafa}
|
||||
.black{color:#000}
|
||||
.black-background{background:#000}
|
||||
.blue{color:#0000bf}
|
||||
.blue-background{background:#0000fa}
|
||||
.fuchsia{color:#bf00bf}
|
||||
.fuchsia-background{background:#fa00fa}
|
||||
.gray{color:#606060}
|
||||
.gray-background{background:#7d7d7d}
|
||||
.green{color:#006000}
|
||||
.green-background{background:#007d00}
|
||||
.lime{color:#00bf00}
|
||||
.lime-background{background:#00fa00}
|
||||
.maroon{color:#600000}
|
||||
.maroon-background{background:#7d0000}
|
||||
.navy{color:#000060}
|
||||
.navy-background{background:#00007d}
|
||||
.olive{color:#606000}
|
||||
.olive-background{background:#7d7d00}
|
||||
.purple{color:#600060}
|
||||
.purple-background{background:#7d007d}
|
||||
.red{color:#bf0000}
|
||||
.red-background{background:#fa0000}
|
||||
.silver{color:#909090}
|
||||
.silver-background{background:#bcbcbc}
|
||||
.teal{color:#006060}
|
||||
.teal-background{background:#007d7d}
|
||||
.white{color:#bfbfbf}
|
||||
.white-background{background:#fafafa}
|
||||
.yellow{color:#bfbf00}
|
||||
.yellow-background{background:#fafa00}
|
||||
span.icon>.fa{cursor:default}
|
||||
a span.icon>.fa{cursor:inherit}
|
||||
.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
|
||||
.admonitionblock td.icon .icon-note::before{content:"\f05a";color:#19407c}
|
||||
.admonitionblock td.icon .icon-tip::before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
|
||||
.admonitionblock td.icon .icon-warning::before{content:"\f071";color:#bf6900}
|
||||
.admonitionblock td.icon .icon-caution::before{content:"\f06d";color:#bf3400}
|
||||
.admonitionblock td.icon .icon-important::before{content:"\f06a";color:#bf0000}
|
||||
.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
|
||||
.conum[data-value] *{color:#fff!important}
|
||||
.conum[data-value]+b{display:none}
|
||||
.conum[data-value]::after{content:attr(data-value)}
|
||||
pre .conum[data-value]{position:relative;top:-.125em}
|
||||
b.conum *{color:inherit!important}
|
||||
.conum:not([data-value]):empty{display:none}
|
||||
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
|
||||
h1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}
|
||||
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
|
||||
p,blockquote,dt,td.content,span.alt,summary{font-size:1.0625rem}
|
||||
p{margin-bottom:1.25rem}
|
||||
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
|
||||
.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}
|
||||
.print-only{display:none!important}
|
||||
@page{margin:1.25cm .75cm}
|
||||
@media print{*{box-shadow:none!important;text-shadow:none!important}
|
||||
html{font-size:80%}
|
||||
a{color:inherit!important;text-decoration:underline!important}
|
||||
a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}
|
||||
a[href^="http:"]:not(.bare)::after,a[href^="https:"]:not(.bare)::after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}
|
||||
abbr[title]{border-bottom:1px dotted}
|
||||
abbr[title]::after{content:" (" attr(title) ")"}
|
||||
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
|
||||
thead{display:table-header-group}
|
||||
svg{max-width:100%}
|
||||
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
|
||||
h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}
|
||||
#header,#content,#footnotes,#footer{max-width:none}
|
||||
#toc,.sidebarblock,.exampleblock>.content{background:none!important}
|
||||
#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
|
||||
body.book #header{text-align:center}
|
||||
body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}
|
||||
body.book #header .details{border:0!important;display:block;padding:0!important}
|
||||
body.book #header .details span:first-child{margin-left:0!important}
|
||||
body.book #header .details br{display:block}
|
||||
body.book #header .details br+span::before{content:none!important}
|
||||
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
|
||||
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}
|
||||
.listingblock code[data-lang]::before{display:block}
|
||||
#footer{padding:0 .9375em}
|
||||
.hide-on-print{display:none!important}
|
||||
.print-only{display:block!important}
|
||||
.hide-for-print{display:none!important}
|
||||
.show-for-print{display:inherit!important}}
|
||||
@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}
|
||||
.sect1{padding:0!important}
|
||||
.sect1+.sect1{border:0}
|
||||
#footer{background:none}
|
||||
#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
|
||||
@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}
|
||||
</style>
|
||||
<style>
|
||||
pre.rouge table td { padding: 5px; }
|
||||
pre.rouge table pre { margin: 0; }
|
||||
pre.rouge .cm {
|
||||
color: #999988;
|
||||
font-style: italic;
|
||||
}
|
||||
pre.rouge .cp {
|
||||
color: #999999;
|
||||
font-weight: bold;
|
||||
}
|
||||
pre.rouge .c1 {
|
||||
color: #999988;
|
||||
font-style: italic;
|
||||
}
|
||||
pre.rouge .cs {
|
||||
color: #999999;
|
||||
font-weight: bold;
|
||||
font-style: italic;
|
||||
}
|
||||
pre.rouge .c, pre.rouge .ch, pre.rouge .cd, pre.rouge .cpf {
|
||||
color: #999988;
|
||||
font-style: italic;
|
||||
}
|
||||
pre.rouge .err {
|
||||
color: #a61717;
|
||||
background-color: #e3d2d2;
|
||||
}
|
||||
pre.rouge .gd {
|
||||
color: #000000;
|
||||
background-color: #ffdddd;
|
||||
}
|
||||
pre.rouge .ge {
|
||||
color: #000000;
|
||||
font-style: italic;
|
||||
}
|
||||
pre.rouge .gr {
|
||||
color: #aa0000;
|
||||
}
|
||||
pre.rouge .gh {
|
||||
color: #999999;
|
||||
}
|
||||
pre.rouge .gi {
|
||||
color: #000000;
|
||||
background-color: #ddffdd;
|
||||
}
|
||||
pre.rouge .go {
|
||||
color: #888888;
|
||||
}
|
||||
pre.rouge .gp {
|
||||
color: #555555;
|
||||
}
|
||||
pre.rouge .gs {
|
||||
font-weight: bold;
|
||||
}
|
||||
pre.rouge .gu {
|
||||
color: #aaaaaa;
|
||||
}
|
||||
pre.rouge .gt {
|
||||
color: #aa0000;
|
||||
}
|
||||
pre.rouge .kc {
|
||||
color: #000000;
|
||||
font-weight: bold;
|
||||
}
|
||||
pre.rouge .kd {
|
||||
color: #000000;
|
||||
font-weight: bold;
|
||||
}
|
||||
pre.rouge .kn {
|
||||
color: #000000;
|
||||
font-weight: bold;
|
||||
}
|
||||
pre.rouge .kp {
|
||||
color: #000000;
|
||||
font-weight: bold;
|
||||
}
|
||||
pre.rouge .kr {
|
||||
color: #000000;
|
||||
font-weight: bold;
|
||||
}
|
||||
pre.rouge .kt {
|
||||
color: #445588;
|
||||
font-weight: bold;
|
||||
}
|
||||
pre.rouge .k, pre.rouge .kv {
|
||||
color: #000000;
|
||||
font-weight: bold;
|
||||
}
|
||||
pre.rouge .mf {
|
||||
color: #009999;
|
||||
}
|
||||
pre.rouge .mh {
|
||||
color: #009999;
|
||||
}
|
||||
pre.rouge .il {
|
||||
color: #009999;
|
||||
}
|
||||
pre.rouge .mi {
|
||||
color: #009999;
|
||||
}
|
||||
pre.rouge .mo {
|
||||
color: #009999;
|
||||
}
|
||||
pre.rouge .m, pre.rouge .mb, pre.rouge .mx {
|
||||
color: #009999;
|
||||
}
|
||||
pre.rouge .sa {
|
||||
color: #000000;
|
||||
font-weight: bold;
|
||||
}
|
||||
pre.rouge .sb {
|
||||
color: #d14;
|
||||
}
|
||||
pre.rouge .sc {
|
||||
color: #d14;
|
||||
}
|
||||
pre.rouge .sd {
|
||||
color: #d14;
|
||||
}
|
||||
pre.rouge .s2 {
|
||||
color: #d14;
|
||||
}
|
||||
pre.rouge .se {
|
||||
color: #d14;
|
||||
}
|
||||
pre.rouge .sh {
|
||||
color: #d14;
|
||||
}
|
||||
pre.rouge .si {
|
||||
color: #d14;
|
||||
}
|
||||
pre.rouge .sx {
|
||||
color: #d14;
|
||||
}
|
||||
pre.rouge .sr {
|
||||
color: #009926;
|
||||
}
|
||||
pre.rouge .s1 {
|
||||
color: #d14;
|
||||
}
|
||||
pre.rouge .ss {
|
||||
color: #990073;
|
||||
}
|
||||
pre.rouge .s, pre.rouge .dl {
|
||||
color: #d14;
|
||||
}
|
||||
pre.rouge .na {
|
||||
color: #008080;
|
||||
}
|
||||
pre.rouge .bp {
|
||||
color: #999999;
|
||||
}
|
||||
pre.rouge .nb {
|
||||
color: #0086B3;
|
||||
}
|
||||
pre.rouge .nc {
|
||||
color: #445588;
|
||||
font-weight: bold;
|
||||
}
|
||||
pre.rouge .no {
|
||||
color: #008080;
|
||||
}
|
||||
pre.rouge .nd {
|
||||
color: #3c5d5d;
|
||||
font-weight: bold;
|
||||
}
|
||||
pre.rouge .ni {
|
||||
color: #800080;
|
||||
}
|
||||
pre.rouge .ne {
|
||||
color: #990000;
|
||||
font-weight: bold;
|
||||
}
|
||||
pre.rouge .nf, pre.rouge .fm {
|
||||
color: #990000;
|
||||
font-weight: bold;
|
||||
}
|
||||
pre.rouge .nl {
|
||||
color: #990000;
|
||||
font-weight: bold;
|
||||
}
|
||||
pre.rouge .nn {
|
||||
color: #555555;
|
||||
}
|
||||
pre.rouge .nt {
|
||||
color: #000080;
|
||||
}
|
||||
pre.rouge .vc {
|
||||
color: #008080;
|
||||
}
|
||||
pre.rouge .vg {
|
||||
color: #008080;
|
||||
}
|
||||
pre.rouge .vi {
|
||||
color: #008080;
|
||||
}
|
||||
pre.rouge .nv, pre.rouge .vm {
|
||||
color: #008080;
|
||||
}
|
||||
pre.rouge .ow {
|
||||
color: #000000;
|
||||
font-weight: bold;
|
||||
}
|
||||
pre.rouge .o {
|
||||
color: #000000;
|
||||
font-weight: bold;
|
||||
}
|
||||
pre.rouge .w {
|
||||
color: #bbbbbb;
|
||||
}
|
||||
pre.rouge {
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="article toc2 toc-left">
|
||||
<div id="header">
|
||||
<h1>CharConv: An Implementation of <charconv> in C++11</h1>
|
||||
<div class="details">
|
||||
<span id="author" class="author">Peter Dimov and Matt Borland</span><br>
|
||||
</div>
|
||||
<div id="toc" class="toc2">
|
||||
<div id="toctitle">Table of Contents</div>
|
||||
<ul class="sectlevel1">
|
||||
<li><a href="#overview">Overview</a>
|
||||
<ul class="sectlevel2">
|
||||
<li><a href="#overview_description">Description</a></li>
|
||||
<li><a href="#overview_usage_examples">Usage Examples</a></li>
|
||||
<li><a href="#overview_supported_compilers">Supported Compilers</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#overview_from_chars">from_chars</a>
|
||||
<ul class="sectlevel2">
|
||||
<li><a href="#from_chars_from_chars_overview">from_chars overview</a></li>
|
||||
<li><a href="#from_chars_from_chars_result">from_chars_result</a></li>
|
||||
<li><a href="#from_chars_from_chars">from_chars</a></li>
|
||||
<li><a href="#from_chars_from_chars_for_integral_types">from_chars for integral types</a></li>
|
||||
<li><a href="#from_chars_examples">Examples</a>
|
||||
<ul class="sectlevel3">
|
||||
<li><a href="#from_chars_basic_usage">Basic usage</a></li>
|
||||
<li><a href="#from_chars_hexadecimal">Hexadecimal</a></li>
|
||||
<li><a href="#from_chars_einval">EINVAL</a></li>
|
||||
<li><a href="#from_chars_erange">ERANGE</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#reference">Reference</a>
|
||||
<ul class="sectlevel2">
|
||||
<li><a href="#ref_boostcharconvfrom_chars_hpp"><boost/charconv/from_chars.hpp></a>
|
||||
<ul class="sectlevel3">
|
||||
<li><a href="#ref_synopsis">Synopsis</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#ref_boostcharconvto_chars_hpp"><boost/charconv/to_chars.hpp></a>
|
||||
<ul class="sectlevel3">
|
||||
<li><a href="#ref_synopsis_2">Synopsis</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#ref_boostcharconv_hpp"><boost/charconv.hpp></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#copyright">Copyright and License</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div id="content">
|
||||
<div class="sect1">
|
||||
<h2 id="overview">Overview</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="sect2">
|
||||
<h3 id="overview_description">Description</h3>
|
||||
<div class="paragraph">
|
||||
<p>Charconv is a collection of parsing functions that are locale-independent, non-allocating, and non-throwing.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="overview_usage_examples">Usage Examples</h3>
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="rouge highlight"><code data-lang="c++"><span class="cp">#include <boost/charconv.hpp>
|
||||
</span>
|
||||
<span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">buffer</span> <span class="o">=</span> <span class="s">"42"</span><span class="p">;</span>
|
||||
<span class="kt">int</span> <span class="n">v</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
|
||||
<span class="k">auto</span> <span class="n">r</span> <span class="o">=</span> <span class="n">boost</span><span class="o">::</span><span class="n">charconv</span><span class="o">::</span><span class="n">from_chars</span><span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="n">buffer</span> <span class="o">+</span> <span class="n">std</span><span class="o">::</span><span class="n">strlen</span><span class="p">(</span><span class="n">buffer</span><span class="p">),</span> <span class="n">v</span><span class="p">);</span>
|
||||
<span class="n">assert</span><span class="p">(</span><span class="n">r</span> <span class="o">==</span> <span class="mi">42</span><span class="p">);</span></code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="overview_supported_compilers">Supported Compilers</h3>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>GCC 5 or later with <code>-std=c++11</code> or above</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Clang 3.9 or later with <code>-std=c++11</code> or above</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Visual Studio 2015, 2017, 2019</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Tested on <a href="https://github.com/cppalliance/charconv/actions">Github Actions</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="overview_from_chars">from_chars</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="sect2">
|
||||
<h3 id="from_chars_from_chars_overview">from_chars overview</h3>
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="rouge highlight"><code data-lang="c++"><span class="k">struct</span> <span class="nc">from_chars_result</span>
|
||||
<span class="p">{</span>
|
||||
<span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">ptr</span><span class="p">;</span>
|
||||
<span class="kt">int</span> <span class="n">ec</span><span class="p">;</span>
|
||||
|
||||
<span class="k">friend</span> <span class="k">constexpr</span> <span class="kt">bool</span> <span class="k">operator</span><span class="o">==</span><span class="p">(</span><span class="k">const</span> <span class="n">from_chars_result</span><span class="o">&</span> <span class="n">lhs</span><span class="p">,</span> <span class="k">const</span> <span class="n">from_chars_result</span><span class="o">&</span> <span class="n">rhs</span><span class="p">)</span> <span class="k">noexcept</span>
|
||||
<span class="k">friend</span> <span class="k">constexpr</span> <span class="kt">bool</span> <span class="k">operator</span><span class="o">!=</span><span class="p">(</span><span class="k">const</span> <span class="n">from_chars_result</span><span class="o">&</span> <span class="n">lhs</span><span class="p">,</span> <span class="k">const</span> <span class="n">from_chars_result</span><span class="o">&</span> <span class="n">rhs</span><span class="p">)</span> <span class="k">noexcept</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="k">template</span> <span class="o"><</span><span class="k">typename</span> <span class="nc">Integral</span><span class="p">></span>
|
||||
<span class="n">BOOST_CXX14_CONSTEXPR</span> <span class="n">from_chars_result</span> <span class="n">from_chars</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">first</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">last</span><span class="p">,</span> <span class="n">Integral</span><span class="o">&</span> <span class="n">value</span><span class="p">,</span> <span class="kt">int</span> <span class="n">base</span> <span class="o">=</span> <span class="mi">10</span><span class="p">)</span> <span class="k">noexcept</span><span class="p">;</span>
|
||||
|
||||
<span class="n">BOOST_CXX14_CONSTEXPR</span> <span class="n">from_chars_result</span> <span class="n">from_chars</span><span class="o"><</span><span class="kt">bool</span><span class="o">></span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">first</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">last</span><span class="p">,</span> <span class="kt">bool</span><span class="o">&</span> <span class="n">value</span><span class="p">,</span> <span class="kt">int</span> <span class="n">base</span><span class="p">)</span> <span class="o">=</span> <span class="k">delete</span><span class="p">;</span></code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="from_chars_from_chars_result">from_chars_result</h3>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>ptr - points to the first character not matching the pattern, or has the value of last if all characters are successfully parsed.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>ec - the error code. Valid values for <cerrno> are:</p>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>0 - successful parsing</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>EINVAL - invalid argument (e.g. parsing a negative number into an unsigned type)</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>ERANGE - result out of range (e.g. overflow)</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<p>operator== - compares the values of ptr and ec for equality</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>operator!- - compares the value of ptr and ec for inequality</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="from_chars_from_chars">from_chars</h3>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>first, last - valid range to parse</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>value - where the output is stored upon successful parsing</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>base - the integer base to use. Must be between 2 and 36 inclusive</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>from_chars for integral types is constexpr when compiled using <code>-std=c++14</code> or newer</p>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>One known exception is GCC 5 which does not support constexpr comparison of const char*.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="from_chars_from_chars_for_integral_types">from_chars for integral types</h3>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>All built-in integral types are allowed except bool which is deleted</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>These function have been tested to support <code><em>int128</code> and <code>unsigned </em>int128</code> when compiling with <code>-std=gnu++11</code> or newer</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="from_chars_examples">Examples</h3>
|
||||
<div class="sect3">
|
||||
<h4 id="from_chars_basic_usage">Basic usage</h4>
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="rouge highlight"><code data-lang="c++"><span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">buffer</span> <span class="o">=</span> <span class="s">"42"</span><span class="p">;</span>
|
||||
<span class="kt">int</span> <span class="n">v</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
|
||||
<span class="n">from_chars_result</span> <span class="n">r</span> <span class="o">=</span> <span class="n">boost</span><span class="o">::</span><span class="n">charconv</span><span class="o">::</span><span class="n">from_chars</span><span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="n">buffer</span> <span class="o">+</span> <span class="n">std</span><span class="o">::</span><span class="n">strlen</span><span class="p">(</span><span class="n">buffer</span><span class="p">),</span> <span class="n">v</span><span class="p">);</span>
|
||||
<span class="n">assert</span><span class="p">(</span><span class="n">r</span><span class="p">.</span><span class="n">ec</span> <span class="o">==</span> <span class="mi">0</span><span class="p">);</span>
|
||||
<span class="n">assert</span><span class="p">(</span><span class="n">v</span> <span class="o">==</span> <span class="mi">42</span><span class="p">);</span></code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect3">
|
||||
<h4 id="from_chars_hexadecimal">Hexadecimal</h4>
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="rouge highlight"><code data-lang="c++"><span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">buffer</span> <span class="o">=</span> <span class="s">"2a"</span><span class="p">;</span>
|
||||
<span class="kt">unsigned</span> <span class="n">v</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
|
||||
<span class="k">auto</span> <span class="n">r</span> <span class="o">=</span> <span class="n">boost</span><span class="o">::</span><span class="n">charconv</span><span class="o">::</span><span class="n">from_chars</span><span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="n">buffer</span> <span class="o">+</span> <span class="n">std</span><span class="o">::</span><span class="n">strlen</span><span class="p">(</span><span class="n">buffer</span><span class="p">),</span> <span class="n">v</span><span class="p">,</span> <span class="mi">16</span><span class="p">);</span>
|
||||
<span class="n">assert</span><span class="p">(</span><span class="n">r</span><span class="p">.</span><span class="n">ec</span> <span class="o">==</span> <span class="mi">0</span><span class="p">);</span>
|
||||
<span class="n">assert</span><span class="p">(</span><span class="n">v</span> <span class="o">==</span> <span class="mi">42</span><span class="p">);</span></code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect3">
|
||||
<h4 id="from_chars_einval">EINVAL</h4>
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="rouge highlight"><code data-lang="c++"><span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">buffer</span> <span class="o">=</span> <span class="s">"-123"</span><span class="p">;</span>
|
||||
<span class="kt">unsigned</span> <span class="n">v</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
|
||||
<span class="k">auto</span> <span class="n">r</span> <span class="o">=</span> <span class="n">boost</span><span class="o">::</span><span class="n">charconv</span><span class="o">::</span><span class="n">from_chars</span><span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="n">buffer</span> <span class="o">+</span> <span class="n">std</span><span class="o">::</span><span class="n">strlen</span><span class="p">(</span><span class="n">buffer</span><span class="p">),</span> <span class="n">v</span><span class="p">);</span>
|
||||
<span class="n">assert</span><span class="p">(</span><span class="n">r</span><span class="p">.</span><span class="n">ec</span><span class="p">,</span> <span class="n">EINVAL</span><span class="p">);</span>
|
||||
<span class="n">assert</span><span class="p">(</span><span class="n">v</span> <span class="o">==</span> <span class="mi">0</span><span class="p">);</span></code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>In the event of EINVAL v is not set by <code>from_chars</code></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect3">
|
||||
<h4 id="from_chars_erange">ERANGE</h4>
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="rouge highlight"><code data-lang="c++"><span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">buffer</span> <span class="o">=</span> <span class="s">"1234"</span><span class="p">;</span>
|
||||
<span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">v</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
|
||||
<span class="k">auto</span> <span class="n">r</span> <span class="o">=</span> <span class="n">boost</span><span class="o">::</span><span class="n">charconv</span><span class="o">::</span><span class="n">from_chars</span><span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="n">buffer</span> <span class="o">+</span> <span class="n">std</span><span class="o">::</span><span class="n">strlen</span><span class="p">(</span><span class="n">buffer</span><span class="p">),</span> <span class="n">v</span><span class="p">);</span>
|
||||
<span class="n">assert</span><span class="p">(</span><span class="n">r</span><span class="p">.</span><span class="n">ec</span> <span class="o">==</span> <span class="n">ERANGE</span><span class="p">);</span>
|
||||
<span class="n">assert</span><span class="p">(</span><span class="n">v</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span></code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>In the event of ERANGE v is not set by <code>from_chars</code></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="reference">Reference</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="sect2">
|
||||
<h3 id="ref_boostcharconvfrom_chars_hpp"><boost/charconv/from_chars.hpp></h3>
|
||||
<div class="sect3">
|
||||
<h4 id="ref_synopsis">Synopsis</h4>
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="rouge highlight"><code data-lang="c++"><span class="k">namespace</span> <span class="n">boost</span> <span class="p">{</span>
|
||||
<span class="k">namespace</span> <span class="n">charconv</span> <span class="p">{</span>
|
||||
|
||||
<span class="k">struct</span> <span class="nc">from_chars_result</span><span class="p">;</span>
|
||||
|
||||
<span class="k">template</span> <span class="o"><</span><span class="k">typename</span> <span class="nc">Integral</span><span class="p">></span>
|
||||
<span class="n">BOOST_CXX14_CONSTEXPR</span> <span class="n">from_chars_result</span> <span class="n">from_chars</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">first</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">last</span><span class="p">,</span> <span class="n">Integral</span><span class="o">&</span> <span class="n">value</span><span class="p">,</span> <span class="kt">int</span> <span class="n">base</span> <span class="o">=</span> <span class="mi">10</span><span class="p">)</span> <span class="k">noexcept</span><span class="p">;</span>
|
||||
|
||||
<span class="c1">// ...</span>
|
||||
|
||||
<span class="p">}</span> <span class="c1">// namespace charconv</span>
|
||||
<span class="p">}</span> <span class="c1">// namespace boost</span></code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="ref_boostcharconvto_chars_hpp"><boost/charconv/to_chars.hpp></h3>
|
||||
<div class="sect3">
|
||||
<h4 id="ref_synopsis_2">Synopsis</h4>
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="rouge highlight"><code data-lang="c++"><span class="k">namespace</span> <span class="n">boost</span> <span class="p">{</span>
|
||||
<span class="k">namespace</span> <span class="n">charconv</span> <span class="p">{</span>
|
||||
|
||||
<span class="k">struct</span> <span class="nc">to_chars_result</span><span class="p">;</span>
|
||||
|
||||
<span class="k">template</span><span class="o"><</span><span class="k">class</span> <span class="nc">Integral</span><span class="p">></span>
|
||||
<span class="n">to_chars_result</span> <span class="n">to_chars</span><span class="p">(</span> <span class="kt">char</span><span class="o">*</span> <span class="n">first</span><span class="p">,</span> <span class="kt">char</span><span class="o">*</span> <span class="n">last</span><span class="p">,</span> <span class="n">Integral</span> <span class="n">value</span><span class="p">,</span> <span class="kt">int</span> <span class="n">base</span> <span class="o">=</span> <span class="mi">10</span> <span class="p">);</span>
|
||||
|
||||
<span class="c1">// ...</span>
|
||||
|
||||
<span class="p">}</span> <span class="c1">// namespace charconv</span>
|
||||
<span class="p">}</span> <span class="c1">// namespace boost</span></code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="ref_boostcharconv_hpp"><boost/charconv.hpp></h3>
|
||||
<div class="paragraph">
|
||||
<p>This convenience header includes all headers previously
|
||||
mentioned.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="copyright">Copyright and License</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>This documentation is copyright 2022-2023 Peter Dimov and Matt Borland and is distributed under
|
||||
the <a href="http://www.boost.org/LICENSE_1_0.txt">Boost Software License, Version 1.0</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="footer">
|
||||
<div id="footer-text">
|
||||
Last updated 2023-01-16 08:01:11 -0800
|
||||
</div>
|
||||
</div>
|
||||
<style>
|
||||
|
||||
*:not(pre)>code { background: none; color: #600000; }
|
||||
:not(pre):not([class^=L])>code { background: none; color: #600000; }
|
||||
|
||||
</style>
|
||||
</body>
|
||||
</html>
|
||||
@@ -13,15 +13,21 @@ https://www.boost.org/LICENSE_1_0.txt
|
||||
Charconv is a collection of parsing functions that are locale-independent, non-allocating, and non-throwing.
|
||||
|
||||
== Usage Examples
|
||||
|
||||
```
|
||||
[source, c++]
|
||||
----
|
||||
#include <boost/charconv.hpp>
|
||||
|
||||
const char* buffer = "42";
|
||||
int v = 0;
|
||||
auto r = boost::charconv::from_chars(buffer, buffer + std::strlen(buffer), v);
|
||||
assert(r == 42);
|
||||
```
|
||||
|
||||
char buffer[64];
|
||||
int v = 12345;
|
||||
auto r = boost::charconv::to_chars(buffer, buffer + sizeof(buffer) - 1, v);
|
||||
assert(!strcmp(buffer, "123456")); // Strcmp returns 0 on match
|
||||
|
||||
----
|
||||
|
||||
== Supported Compilers
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
////
|
||||
Copyright 2022 Peter Dimov
|
||||
Copyright 2023 Matt Borland
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
https://www.boost.org/LICENSE_1_0.txt
|
||||
////
|
||||
@@ -11,8 +12,8 @@ https://www.boost.org/LICENSE_1_0.txt
|
||||
== <boost/charconv/from_chars.hpp>
|
||||
|
||||
=== Synopsis
|
||||
|
||||
```
|
||||
[source, c++]
|
||||
----
|
||||
namespace boost {
|
||||
namespace charconv {
|
||||
|
||||
@@ -25,26 +26,26 @@ BOOST_CXX14_CONSTEXPR from_chars_result from_chars(const char* first, const char
|
||||
|
||||
} // namespace charconv
|
||||
} // namespace boost
|
||||
```
|
||||
----
|
||||
|
||||
== <boost/charconv/to_chars.hpp>
|
||||
|
||||
=== Synopsis
|
||||
|
||||
```
|
||||
[source, c++]
|
||||
----
|
||||
namespace boost {
|
||||
namespace charconv {
|
||||
|
||||
struct to_chars_result;
|
||||
|
||||
template<class Integral>
|
||||
to_chars_result to_chars( char* first, char* last, Integral value, int base = 10 );
|
||||
template <typename Integral>
|
||||
BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars( char* first, char* last, Integral value, int base = 10 ) noexcept;
|
||||
|
||||
// ...
|
||||
|
||||
} // namespace charconv
|
||||
} // namespace boost
|
||||
```
|
||||
----
|
||||
|
||||
== <boost/charconv.hpp>
|
||||
|
||||
|
||||
77
doc/charconv/to_chars.adoc
Normal file
77
doc/charconv/to_chars.adoc
Normal file
@@ -0,0 +1,77 @@
|
||||
////
|
||||
Copyright 2023 Matt Borland
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
https://www.boost.org/LICENSE_1_0.txt
|
||||
////
|
||||
|
||||
= to_chars
|
||||
:idprefix: to_chars_
|
||||
|
||||
== to_chars overview
|
||||
[source, c++]
|
||||
----
|
||||
struct to_chars_result
|
||||
{
|
||||
char* ptr;
|
||||
int ec;
|
||||
|
||||
friend constexpr bool operator==(const to_chars_result& lhs, const to_chars_result& rhs) noexcept;
|
||||
friend constexpr bool operator!=(const to_chars_result& lhs, const to_chars_result& rhs) noexcept;
|
||||
};
|
||||
|
||||
template <typename Integral>
|
||||
BOOST_CHARCONV_CONSTEXPR to_chars_result(char* first, char* last, Integral value, int base = 10) noexcept;
|
||||
|
||||
template <typename Integral>
|
||||
BOOST_CHARCONV_CONSTEXPR to_chars_result<bool>(char* first, char* last, Integral value, int base) noexcept = delete;
|
||||
----
|
||||
|
||||
== to_chars_result
|
||||
* ptr - points to the first character
|
||||
* ec - the error code. Valid values from <cerrno> are:
|
||||
** 0 - successful parsing
|
||||
** EINVAL - invalid argument
|
||||
** ERANGE - result out of range (e.g. overflow)
|
||||
* operator== - compares the value of ptr and ec for equality
|
||||
* operator!= - compares the value of ptr and ec for inequality
|
||||
|
||||
== to_chars
|
||||
* first, last - pointers to the character buffer
|
||||
* value - the value to be paresed into the buffer
|
||||
* base - the integer base to use. Must be between 2 and 36 inclusive
|
||||
* from_chars for integral type is constexpr (BOOST_CHARCONV_CONSTEXPR is defined) when compiled using `-std=c++14` or newer and a compiler with `__builtin_ is_constant_evaluated`
|
||||
|
||||
== to_chars for integral types
|
||||
* All built-in integral types are allowed except bool which is deleted
|
||||
|
||||
== Examples
|
||||
|
||||
=== Basic Usage
|
||||
[source, c++]
|
||||
----
|
||||
char buffer[64] {};
|
||||
int v = 42;
|
||||
to_chars_result r = boost::charconv::to_chars(buffer, buffer + sizeof(buffer) - 1, v);
|
||||
assert(r.ec == 0);
|
||||
assert(!strcmp(buffer, "42")); // strcmp returns 0 on match
|
||||
----
|
||||
|
||||
=== Hexadecimal
|
||||
[source, c++]
|
||||
----
|
||||
char buffer[64] {};
|
||||
int v = 42;
|
||||
to_chars_result r = boost::charconv::to_chars(buffer, buffer + sizeof(buffer) - 1, v, 16);
|
||||
assert(r.ec == 0);
|
||||
assert(!strcmp(buffer, "2a")); // strcmp returns 0 on match
|
||||
----
|
||||
|
||||
=== ERANGE
|
||||
[source, c++]
|
||||
----
|
||||
char buffer[3] {};
|
||||
int v = -1234;
|
||||
to_chars_result r = boost::charconv::to_chars(buffer, buffer + sizeof(buffer) - 1, v, 16);
|
||||
assert(r.ec == ERANGE);
|
||||
----
|
||||
In the event of ERANGE to_chars_result.ptr is first
|
||||
29
include/boost/charconv/detail/apply_sign.hpp
Normal file
29
include/boost/charconv/detail/apply_sign.hpp
Normal file
@@ -0,0 +1,29 @@
|
||||
// Copyright 2023 Matt Borland
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#ifndef BOOST_CHARCONV_DETAIL_APPLY_SIGN_HPP
|
||||
#define BOOST_CHARCONV_DETAIL_APPLY_SIGN_HPP
|
||||
|
||||
// Workaround for warning C4146: unary minus operator applied to unsigned type, result still unsigned
|
||||
// Occurs using MSVC with pre-C++17 language standards
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost { namespace charconv { namespace detail {
|
||||
|
||||
template <typename Integer, typename std::enable_if<std::is_signed<Integer>::value, bool>::type = true>
|
||||
constexpr Integer apply_sign(Integer val) noexcept
|
||||
{
|
||||
return -val;
|
||||
}
|
||||
|
||||
template <typename Integer, typename std::enable_if<std::is_unsigned<Integer>::value, bool>::type = true>
|
||||
constexpr Integer apply_sign(Integer val) noexcept
|
||||
{
|
||||
return val;
|
||||
}
|
||||
|
||||
}}} // Namespaces
|
||||
|
||||
#endif // BOOST_CHARCONV_DETAIL_APPLY_SIGN_HPP
|
||||
45
include/boost/charconv/detail/integer_conversion.hpp
Normal file
45
include/boost/charconv/detail/integer_conversion.hpp
Normal file
@@ -0,0 +1,45 @@
|
||||
// Copyright 2023 Matt Borland
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#ifndef BOOST_CHARCONV_DETAIL_CONCATENATE_HPP
|
||||
#define BOOST_CHARCONV_DETAIL_CONCATENATE_HPP
|
||||
|
||||
#include <boost/charconv/config.hpp>
|
||||
#include <utility>
|
||||
#include <limits>
|
||||
#include <cstdint>
|
||||
|
||||
namespace boost { namespace charconv { namespace detail {
|
||||
|
||||
constexpr std::uint64_t pack(std::uint32_t word1, std::uint32_t word2) noexcept
|
||||
{
|
||||
return static_cast<std::uint64_t>(word1) << 32 | word2;
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR std::pair<std::uint32_t, std::uint32_t> unpack(std::uint64_t value)
|
||||
{
|
||||
auto x = static_cast<std::uint32_t>(value >> UINT64_C(32));
|
||||
auto y = static_cast<std::uint32_t>(value & UINT32_MAX);
|
||||
|
||||
return std::make_pair(x, y);
|
||||
}
|
||||
|
||||
#ifdef __GLIBCXX_TYPE_INT_N_0
|
||||
constexpr unsigned __int128 pack(std::uint64_t word1, std::uint64_t word2) noexcept
|
||||
{
|
||||
return static_cast<unsigned __int128>(word1) << 64 | word2;
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR std::pair<std::uint64_t, std::uint64_t> unpack(unsigned __int128 value)
|
||||
{
|
||||
auto x = static_cast<std::uint64_t>(value >> 64);
|
||||
auto y = static_cast<std::uint64_t>(value);
|
||||
|
||||
return std::make_pair(x, y);
|
||||
}
|
||||
#endif // defined(__GLIBCXX_TYPE_INT_N_0)
|
||||
|
||||
}}} // Namespaces
|
||||
|
||||
#endif // BOOST_CHARCONV_DETAIL_CONCATENATE_HPP
|
||||
239
include/boost/charconv/detail/integer_search_trees.hpp
Normal file
239
include/boost/charconv/detail/integer_search_trees.hpp
Normal file
@@ -0,0 +1,239 @@
|
||||
// Copyright 2023 Matt Borland
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#ifndef BOOST_CHARCONV_DETAIL_INTEGER_SEARCH_TREES_HPP
|
||||
#define BOOST_CHARCONV_DETAIL_INTEGER_SEARCH_TREES_HPP
|
||||
|
||||
// https://stackoverflow.com/questions/1489830/efficient-way-to-determine-number-of-digits-in-an-integer?page=1&tab=scoredesc#tab-top
|
||||
// https://graphics.stanford.edu/~seander/bithacks.html
|
||||
|
||||
#include "../config.hpp"
|
||||
#include <limits>
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
|
||||
namespace boost { namespace charconv { namespace detail {
|
||||
|
||||
// Generic solution
|
||||
template <typename T>
|
||||
BOOST_CXX14_CONSTEXPR int num_digits(T x) noexcept
|
||||
{
|
||||
int digits = 0;
|
||||
|
||||
while (x)
|
||||
{
|
||||
x /= 10;
|
||||
++digits;
|
||||
}
|
||||
|
||||
return digits;
|
||||
}
|
||||
|
||||
template <>
|
||||
BOOST_CXX14_CONSTEXPR int num_digits(std::uint32_t x) noexcept
|
||||
{
|
||||
if (x >= UINT32_C(10000))
|
||||
{
|
||||
if (x >= UINT32_C(10000000))
|
||||
{
|
||||
if (x >= UINT32_C(100000000))
|
||||
{
|
||||
if (x >= UINT32_C(1000000000))
|
||||
{
|
||||
return 10;
|
||||
}
|
||||
return 9;
|
||||
}
|
||||
return 8;
|
||||
}
|
||||
|
||||
else if (x >= UINT32_C(100000))
|
||||
{
|
||||
if (x >= UINT32_C(1000000))
|
||||
{
|
||||
return 7;
|
||||
}
|
||||
return 6;
|
||||
}
|
||||
return 5;
|
||||
}
|
||||
else if (x >= UINT32_C(100))
|
||||
{
|
||||
if (x >= UINT32_C(1000))
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
return 3;
|
||||
}
|
||||
else if (x >= UINT32_C(10))
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
template <>
|
||||
BOOST_CXX14_CONSTEXPR int num_digits(std::uint64_t x) noexcept
|
||||
{
|
||||
if (x >= UINT64_C(10000000000))
|
||||
{
|
||||
if (x >= UINT64_C(100000000000000))
|
||||
{
|
||||
if (x >= UINT64_C(10000000000000000))
|
||||
{
|
||||
if (x >= UINT64_C(100000000000000000))
|
||||
{
|
||||
if (x >= UINT64_C(1000000000000000000))
|
||||
{
|
||||
if (x >= UINT64_C(10000000000000000000))
|
||||
{
|
||||
return 20;
|
||||
}
|
||||
return 19;
|
||||
}
|
||||
return 18;
|
||||
}
|
||||
return 17;
|
||||
}
|
||||
else if (x >= UINT64_C(1000000000000000))
|
||||
{
|
||||
return 16;
|
||||
}
|
||||
return 15;
|
||||
}
|
||||
if (x >= UINT64_C(1000000000000))
|
||||
{
|
||||
if (x >= UINT64_C(10000000000000))
|
||||
{
|
||||
return 14;
|
||||
}
|
||||
return 13;
|
||||
}
|
||||
if (x >= UINT64_C(100000000000))
|
||||
{
|
||||
return 12;
|
||||
}
|
||||
return 11;
|
||||
}
|
||||
else if (x >= UINT64_C(100000))
|
||||
{
|
||||
if (x >= UINT64_C(10000000))
|
||||
{
|
||||
if (x >= UINT64_C(100000000))
|
||||
{
|
||||
if (x >= UINT64_C(1000000000))
|
||||
{
|
||||
return 10;
|
||||
}
|
||||
return 9;
|
||||
}
|
||||
return 8;
|
||||
}
|
||||
if (x >= UINT64_C(1000000))
|
||||
{
|
||||
return 7;
|
||||
}
|
||||
return 6;
|
||||
}
|
||||
if (x >= UINT64_C(100))
|
||||
{
|
||||
if (x >= UINT64_C(1000))
|
||||
{
|
||||
if (x >= UINT64_C(10000))
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
return 3;
|
||||
}
|
||||
if (x >= UINT64_C(10))
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef __GLIBCXX_TYPE_INT_N_0
|
||||
static constexpr std::array<std::uint64_t, 20> powers_of_10 =
|
||||
{{
|
||||
UINT64_C(1), UINT64_C(10), UINT64_C(100), UINT64_C(1000), UINT64_C(10000), UINT64_C(100000), UINT64_C(1000000),
|
||||
UINT64_C(10000000), UINT64_C(100000000), UINT64_C(1000000000), UINT64_C(10000000000), UINT64_C(100000000000),
|
||||
UINT64_C(1000000000000), UINT64_C(10000000000000), UINT64_C(100000000000000), UINT64_C(1000000000000000),
|
||||
UINT64_C(10000000000000000), UINT64_C(100000000000000000), UINT64_C(1000000000000000000), UINT64_C(10000000000000000000)
|
||||
}};
|
||||
|
||||
// Assume that if someone is using 128 bit ints they are favoring the top end of the range
|
||||
// Max value is 340,282,366,920,938,463,463,374,607,431,768,211,455 (39 digits)
|
||||
BOOST_CXX14_CONSTEXPR int num_digits(unsigned __int128 x) noexcept
|
||||
{
|
||||
// There is not literal for unsigned __int128 so we need to calculate them using the max value of the
|
||||
// std::uint64_t powers of 10
|
||||
constexpr unsigned __int128 digits_39 = static_cast<unsigned __int128>(UINT64_C(10000000000000000000)) *
|
||||
static_cast<unsigned __int128>(UINT64_C(1000000000000000000));
|
||||
constexpr unsigned __int128 digits_38 = digits_39 / 10;
|
||||
constexpr unsigned __int128 digits_37 = digits_38 / 10;
|
||||
constexpr unsigned __int128 digits_36 = digits_37 / 10;
|
||||
constexpr unsigned __int128 digits_35 = digits_36 / 10;
|
||||
constexpr unsigned __int128 digits_34 = digits_35 / 10;
|
||||
constexpr unsigned __int128 digits_33 = digits_34 / 10;
|
||||
constexpr unsigned __int128 digits_32 = digits_33 / 10;
|
||||
constexpr unsigned __int128 digits_31 = digits_32 / 10;
|
||||
constexpr unsigned __int128 digits_30 = digits_31 / 10;
|
||||
constexpr unsigned __int128 digits_29 = digits_30 / 10;
|
||||
constexpr unsigned __int128 digits_28 = digits_29 / 10;
|
||||
constexpr unsigned __int128 digits_27 = digits_28 / 10;
|
||||
constexpr unsigned __int128 digits_26 = digits_27 / 10;
|
||||
constexpr unsigned __int128 digits_25 = digits_26 / 10;
|
||||
constexpr unsigned __int128 digits_24 = digits_25 / 10;
|
||||
constexpr unsigned __int128 digits_23 = digits_24 / 10;
|
||||
constexpr unsigned __int128 digits_22 = digits_23 / 10;
|
||||
constexpr unsigned __int128 digits_21 = digits_22 / 10;
|
||||
|
||||
return (x > digits_39) ? 39 :
|
||||
(x > digits_38) ? 38 :
|
||||
(x > digits_37) ? 37 :
|
||||
(x > digits_36) ? 36 :
|
||||
(x > digits_35) ? 35 :
|
||||
(x > digits_34) ? 34 :
|
||||
(x > digits_33) ? 33 :
|
||||
(x > digits_32) ? 32 :
|
||||
(x > digits_31) ? 31 :
|
||||
(x > digits_30) ? 30 :
|
||||
(x > digits_29) ? 29 :
|
||||
(x > digits_28) ? 28 :
|
||||
(x > digits_27) ? 27 :
|
||||
(x > digits_26) ? 26 :
|
||||
(x > digits_25) ? 25 :
|
||||
(x > digits_24) ? 24 :
|
||||
(x > digits_23) ? 23 :
|
||||
(x > digits_22) ? 22 :
|
||||
(x > digits_21) ? 21 :
|
||||
(x > powers_of_10[19]) ? 20 :
|
||||
(x > powers_of_10[18]) ? 19 :
|
||||
(x > powers_of_10[17]) ? 18 :
|
||||
(x > powers_of_10[16]) ? 17 :
|
||||
(x > powers_of_10[15]) ? 16 :
|
||||
(x > powers_of_10[14]) ? 15 :
|
||||
(x > powers_of_10[13]) ? 14 :
|
||||
(x > powers_of_10[12]) ? 13 :
|
||||
(x > powers_of_10[11]) ? 12 :
|
||||
(x > powers_of_10[10]) ? 11 :
|
||||
(x > powers_of_10[9]) ? 10 :
|
||||
(x > powers_of_10[8]) ? 9 :
|
||||
(x > powers_of_10[7]) ? 8 :
|
||||
(x > powers_of_10[6]) ? 7 :
|
||||
(x > powers_of_10[5]) ? 6 :
|
||||
(x > powers_of_10[4]) ? 5 :
|
||||
(x > powers_of_10[3]) ? 4 :
|
||||
(x > powers_of_10[2]) ? 3 :
|
||||
(x > powers_of_10[1]) ? 2 :
|
||||
(x > powers_of_10[0]) ? 1 : 0;
|
||||
}
|
||||
#endif // 128-bit support
|
||||
|
||||
}}} // Namespace boost::charconv::detail
|
||||
|
||||
#endif // BOOST_CHARCONV_DETAIL_INTEGER_SEARCH_TREES_HPP
|
||||
49
include/boost/charconv/detail/is_constant_evaluated.hpp
Normal file
49
include/boost/charconv/detail/is_constant_evaluated.hpp
Normal file
@@ -0,0 +1,49 @@
|
||||
// Copyright John Maddock 2011-2021.
|
||||
// Copyright Matt Borland 2023.
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_CHARCONV_TOOLS_IS_CONSTANT_EVALUATED_HPP
|
||||
#define BOOST_CHARCONV_TOOLS_IS_CONSTANT_EVALUATED_HPP
|
||||
|
||||
#include <boost/charconv/config.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
#ifdef __cpp_lib_is_constant_evaluated
|
||||
# define BOOST_CHARCONV_HAS_IS_CONSTANT_EVALUATED
|
||||
#endif
|
||||
|
||||
#ifdef __has_builtin
|
||||
# if __has_builtin(__builtin_is_constant_evaluated) && !defined(BOOST_NO_CXX14_CONSTEXPR)
|
||||
# define BOOST_CHARCONV_HAS_BUILTIN_IS_CONSTANT_EVALUATED
|
||||
# endif
|
||||
#endif
|
||||
|
||||
//
|
||||
// MSVC also supports __builtin_is_constant_evaluated if it's recent enough:
|
||||
//
|
||||
#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 192528326)
|
||||
# define BOOST_CHARCONV_HAS_BUILTIN_IS_CONSTANT_EVALUATED
|
||||
#endif
|
||||
|
||||
//
|
||||
// As does GCC-9:
|
||||
//
|
||||
#if !defined(BOOST_NO_CXX14_CONSTEXPR) && (__GNUC__ >= 9) && !defined(BOOST_CHARCONV_HAS_BUILTIN_IS_CONSTANT_EVALUATED)
|
||||
# define BOOST_CHARCONV_HAS_BUILTIN_IS_CONSTANT_EVALUATED
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_CHARCONV_HAS_IS_CONSTANT_EVALUATED) && !defined(BOOST_NO_CXX14_CONSTEXPR)
|
||||
# define BOOST_CHARCONV_IS_CONSTANT_EVALUATED(x) std::is_constant_evaluated()
|
||||
#elif defined(BOOST_CHARCONV_HAS_BUILTIN_IS_CONSTANT_EVALUATED)
|
||||
# define BOOST_CHARCONV_IS_CONSTANT_EVALUATED(x) __builtin_is_constant_evaluated()
|
||||
#elif !defined(BOOST_NO_CXX14_CONSTEXPR) && (__GNUC__ >= 6)
|
||||
# define BOOST_CHARCONV_IS_CONSTANT_EVALUATED(x) __builtin_constant_p(x)
|
||||
# define BOOST_CHARCONV_USING_BUILTIN_CONSTANT_P
|
||||
#else
|
||||
# define BOOST_CHARCONV_IS_CONSTANT_EVALUATED(x) false
|
||||
# define BOOST_CHARCONV_NO_CONSTEXPR_DETECTION
|
||||
#endif
|
||||
|
||||
#endif // BOOST_CHARCONV_TOOLS_IS_CONSTANT_EVALUATED_HPP
|
||||
78
include/boost/charconv/detail/memcpy.hpp
Normal file
78
include/boost/charconv/detail/memcpy.hpp
Normal file
@@ -0,0 +1,78 @@
|
||||
// Copyright 2023 Matt Borland
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#ifndef BOOST_CHARCONV_DETAIL_MEMCPY_HPP
|
||||
#define BOOST_CHARCONV_DETAIL_MEMCPY_HPP
|
||||
|
||||
#include <boost/charconv/detail/is_constant_evaluated.hpp>
|
||||
#include <cstring>
|
||||
#include <cstdint>
|
||||
|
||||
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89689
|
||||
// GCC 10 added checks for length of memcpy which yields the following warning (converted to error with -Werror)
|
||||
// /usr/include/x86_64-linux-gnu/bits/string_fortified.h:34:33: error:
|
||||
// ‘void* __builtin___memcpy_chk(void*, const void*, long unsigned int, long unsigned int)’ specified size between
|
||||
// 18446744071562067968 and 18446744073709551615 exceeds maximum object size 9223372036854775807 [-Werror=stringop-overflow=]
|
||||
//
|
||||
// memcpy is defined as taking a size_t for the count and the largest count this will recieve is the number of digits
|
||||
// in a 128-bit int (39) so we can safely ignore
|
||||
#if __GNUC__ >= 10
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wstringop-overflow"
|
||||
# define BOOST_CHARCONV_STRINGOP_OVERFLOW_DISABLED
|
||||
#endif
|
||||
|
||||
namespace boost { namespace charconv { namespace detail {
|
||||
|
||||
#if !defined(BOOST_CHARCONV_NO_CONSTEXPR_DETECTION) && defined(BOOST_CXX14_CONSTEXPR)
|
||||
|
||||
#define BOOST_CHARCONV_CONSTEXPR constexpr
|
||||
|
||||
constexpr char* memcpy(char* dest, const char* src, std::size_t count)
|
||||
{
|
||||
if (BOOST_CHARCONV_IS_CONSTANT_EVALUATED(count))
|
||||
{
|
||||
for (std::size_t i = 0; i < count; ++i)
|
||||
{
|
||||
*(dest + i) = *(src + i);
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Workaround for GCC-11 because it does not honor GCC diagnostic ignored
|
||||
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53431
|
||||
// Hopefully the optimizer turns this into memcpy
|
||||
#if __GNUC__ == 11
|
||||
for (std::size_t i = 0; i < count; ++i)
|
||||
{
|
||||
*(dest + i) = *(src + i);
|
||||
}
|
||||
|
||||
return dest;
|
||||
#else
|
||||
return static_cast<char*>(std::memcpy(dest, src, count));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#else // Either not C++14 or no way of telling if we are in a constexpr context
|
||||
|
||||
#define BOOST_CHARCONV_CONSTEXPR
|
||||
|
||||
inline void* memcpy(void* dest, const void* src, std::size_t count)
|
||||
{
|
||||
return std::memcpy(dest, src, count);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}}} // Namespace boost::charconv::detail
|
||||
|
||||
#ifdef BOOST_CHARCONV_STRINGOP_OVERFLOW_DISABLED
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif // BOOST_CHARCONV_DETAIL_MEMCPY_HPP
|
||||
@@ -6,6 +6,7 @@
|
||||
#ifndef BOOST_CHARCONV_FROM_CHARS_HPP_INCLUDED
|
||||
#define BOOST_CHARCONV_FROM_CHARS_HPP_INCLUDED
|
||||
|
||||
#include <boost/charconv/detail/apply_sign.hpp>
|
||||
#include <boost/charconv/config.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <type_traits>
|
||||
@@ -67,18 +68,6 @@ constexpr unsigned char digit_from_char(char val) noexcept
|
||||
return uchar_values[static_cast<std::size_t>(val)];
|
||||
}
|
||||
|
||||
template <typename Integer, typename std::enable_if<std::is_signed<Integer>::value, bool>::type = true>
|
||||
constexpr Integer apply_sign(Integer val) noexcept
|
||||
{
|
||||
return -val;
|
||||
}
|
||||
|
||||
template <typename Integer, typename std::enable_if<std::is_unsigned<Integer>::value, bool>::type = true>
|
||||
constexpr Integer apply_sign(Integer val) noexcept
|
||||
{
|
||||
return val;
|
||||
}
|
||||
|
||||
template <typename Integer>
|
||||
BOOST_CXX14_CONSTEXPR boost::charconv::from_chars_result from_chars_integer_impl(const char* first, const char* last, Integer& value, int base) noexcept
|
||||
{
|
||||
|
||||
@@ -1,12 +1,26 @@
|
||||
// Copyright 2022 Peter Dimov
|
||||
// Copyright 2023 Matt Borland
|
||||
// Copyright 2023 Junekey Jeon
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#ifndef BOOST_CHARCONV_TO_CHARS_HPP_INCLUDED
|
||||
#define BOOST_CHARCONV_TO_CHARS_HPP_INCLUDED
|
||||
|
||||
#include <boost/charconv/detail/apply_sign.hpp>
|
||||
#include <boost/charconv/detail/integer_search_trees.hpp>
|
||||
#include <boost/charconv/detail/integer_conversion.hpp>
|
||||
#include <boost/charconv/detail/memcpy.hpp>
|
||||
#include <boost/charconv/config.hpp>
|
||||
#include <type_traits>
|
||||
#include <array>
|
||||
#include <limits>
|
||||
#include <utility>
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <cerrno>
|
||||
#include <cstdint>
|
||||
#include <climits>
|
||||
|
||||
namespace boost { namespace charconv {
|
||||
|
||||
@@ -15,19 +29,346 @@ namespace boost { namespace charconv {
|
||||
struct to_chars_result
|
||||
{
|
||||
char* ptr;
|
||||
|
||||
// Values:
|
||||
// 0 = no error
|
||||
// EINVAL = invalid_argument
|
||||
// ERANGE = result_out_of_range
|
||||
int ec;
|
||||
friend bool operator==(const to_chars_result& lhs, const to_chars_result& rhs)
|
||||
|
||||
constexpr friend bool operator==(const to_chars_result& lhs, const to_chars_result& rhs) noexcept
|
||||
{
|
||||
return lhs.ptr == rhs.ptr && lhs.ec == rhs.ec;
|
||||
}
|
||||
|
||||
friend bool operator!=(const to_chars_result& lhs, const to_chars_result& rhs)
|
||||
constexpr friend bool operator!=(const to_chars_result& lhs, const to_chars_result& rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
};
|
||||
|
||||
BOOST_CHARCONV_DECL to_chars_result to_chars(char* first, char* last, int value, int base = 10);
|
||||
namespace detail {
|
||||
|
||||
static constexpr char radix_table[] = {
|
||||
'0', '0', '0', '1', '0', '2', '0', '3', '0', '4',
|
||||
'0', '5', '0', '6', '0', '7', '0', '8', '0', '9',
|
||||
'1', '0', '1', '1', '1', '2', '1', '3', '1', '4',
|
||||
'1', '5', '1', '6', '1', '7', '1', '8', '1', '9',
|
||||
'2', '0', '2', '1', '2', '2', '2', '3', '2', '4',
|
||||
'2', '5', '2', '6', '2', '7', '2', '8', '2', '9',
|
||||
'3', '0', '3', '1', '3', '2', '3', '3', '3', '4',
|
||||
'3', '5', '3', '6', '3', '7', '3', '8', '3', '9',
|
||||
'4', '0', '4', '1', '4', '2', '4', '3', '4', '4',
|
||||
'4', '5', '4', '6', '4', '7', '4', '8', '4', '9',
|
||||
'5', '0', '5', '1', '5', '2', '5', '3', '5', '4',
|
||||
'5', '5', '5', '6', '5', '7', '5', '8', '5', '9',
|
||||
'6', '0', '6', '1', '6', '2', '6', '3', '6', '4',
|
||||
'6', '5', '6', '6', '6', '7', '6', '8', '6', '9',
|
||||
'7', '0', '7', '1', '7', '2', '7', '3', '7', '4',
|
||||
'7', '5', '7', '6', '7', '7', '7', '8', '7', '9',
|
||||
'8', '0', '8', '1', '8', '2', '8', '3', '8', '4',
|
||||
'8', '5', '8', '6', '8', '7', '8', '8', '8', '9',
|
||||
'9', '0', '9', '1', '9', '2', '9', '3', '9', '4',
|
||||
'9', '5', '9', '6', '9', '7', '9', '8', '9', '9'
|
||||
};
|
||||
|
||||
static constexpr char digit_table[] = {
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
|
||||
'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
|
||||
'u', 'v', 'w', 'x', 'y', 'z'
|
||||
};
|
||||
|
||||
// See: https://jk-jeon.github.io/posts/2022/02/jeaiii-algorithm/
|
||||
// https://arxiv.org/abs/2101.11408
|
||||
BOOST_CHARCONV_CONSTEXPR char* decompose32(std::uint32_t value, char* buffer) noexcept
|
||||
{
|
||||
constexpr auto mask = (std::uint64_t(1) << 57) - 1;
|
||||
auto y = value * std::uint64_t(1441151881);
|
||||
|
||||
for (std::size_t i {}; i < 10; i += 2)
|
||||
{
|
||||
boost::charconv::detail::memcpy(buffer + i, radix_table + static_cast<std::size_t>(y >> 57) * 2, 2);
|
||||
y &= mask;
|
||||
y *= 100;
|
||||
}
|
||||
|
||||
return buffer + 10;
|
||||
}
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4127)
|
||||
#endif
|
||||
|
||||
template <typename Integer>
|
||||
BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars_integer_impl(char* first, char* last, Integer value) noexcept
|
||||
{
|
||||
using Unsigned_Integer = typename std::make_unsigned<Integer>::type;
|
||||
Unsigned_Integer unsigned_value {};
|
||||
|
||||
char buffer[10] {};
|
||||
int converted_value_digits {};
|
||||
const std::ptrdiff_t user_buffer_size = last - first;
|
||||
BOOST_ATTRIBUTE_UNUSED bool is_negative = false;
|
||||
|
||||
if (!(first <= last))
|
||||
{
|
||||
return {last, EINVAL};
|
||||
}
|
||||
|
||||
// Strip the sign from the value and apply at the end after parsing if the type is signed
|
||||
BOOST_IF_CONSTEXPR (std::is_signed<Integer>::value)
|
||||
{
|
||||
if (value < 0)
|
||||
{
|
||||
is_negative = true;
|
||||
unsigned_value = apply_sign(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned_value = value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned_value = value;
|
||||
}
|
||||
|
||||
// If the type is less than 32 bits we can use this without change
|
||||
// If the type is greater than 32 bits we use a binary search tree to figure out how many digits
|
||||
// are present and then decompose the value into two (or more) std::uint32_t of known length so that we
|
||||
// don't have the issue of removing leading zeros from the least significant digits
|
||||
|
||||
// Yields: warning C4127: conditional expression is constant becuase first half of the expression is constant
|
||||
// but we need to short circuit to avoid UB on the second half
|
||||
if (std::numeric_limits<Integer>::digits <= std::numeric_limits<std::uint32_t>::digits ||
|
||||
unsigned_value <= static_cast<Unsigned_Integer>((std::numeric_limits<std::uint32_t>::max)()))
|
||||
{
|
||||
const auto converted_value = static_cast<std::uint32_t>(unsigned_value);
|
||||
converted_value_digits = num_digits(converted_value);
|
||||
|
||||
if (converted_value_digits > user_buffer_size)
|
||||
{
|
||||
return {last, EOVERFLOW};
|
||||
}
|
||||
|
||||
decompose32(converted_value, buffer);
|
||||
|
||||
if (is_negative)
|
||||
{
|
||||
*first++ = '-';
|
||||
}
|
||||
|
||||
boost::charconv::detail::memcpy(first, buffer + (sizeof(buffer) - converted_value_digits), converted_value_digits);
|
||||
}
|
||||
else if (std::numeric_limits<Integer>::digits <= std::numeric_limits<std::uint64_t>::digits ||
|
||||
static_cast<std::uint64_t>(unsigned_value) <= (std::numeric_limits<std::uint64_t>::max)())
|
||||
{
|
||||
auto converted_value = static_cast<std::uint64_t>(unsigned_value);
|
||||
converted_value_digits = num_digits(converted_value);
|
||||
|
||||
if (converted_value_digits > user_buffer_size)
|
||||
{
|
||||
return {last, EOVERFLOW};
|
||||
}
|
||||
|
||||
if (is_negative)
|
||||
{
|
||||
*first++ = '-';
|
||||
}
|
||||
|
||||
// Only store 9 digits in each to avoid overflow
|
||||
if (num_digits(converted_value) <= 18)
|
||||
{
|
||||
const auto x = static_cast<std::uint32_t>(converted_value / UINT64_C(1000000000));
|
||||
const auto y = static_cast<std::uint32_t>(converted_value % UINT64_C(1000000000));
|
||||
const int first_value_chars = num_digits(x);
|
||||
|
||||
decompose32(x, buffer);
|
||||
boost::charconv::detail::memcpy(first, buffer + (sizeof(buffer) - first_value_chars), first_value_chars);
|
||||
|
||||
decompose32(y, buffer);
|
||||
boost::charconv::detail::memcpy(first + first_value_chars, buffer + 1, sizeof(buffer) - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto x = static_cast<std::uint32_t>(converted_value / UINT64_C(100000000000));
|
||||
converted_value -= x * UINT64_C(100000000000);
|
||||
const auto y = static_cast<std::uint32_t>(converted_value / UINT64_C(100));
|
||||
const auto z = static_cast<std::uint32_t>(converted_value % UINT64_C(100));
|
||||
|
||||
if (converted_value_digits == 19)
|
||||
{
|
||||
decompose32(x, buffer);
|
||||
boost::charconv::detail::memcpy(first, buffer + 2, sizeof(buffer) - 2);
|
||||
|
||||
decompose32(y, buffer);
|
||||
boost::charconv::detail::memcpy(first + 8, buffer + 1, sizeof(buffer) - 1);
|
||||
|
||||
decompose32(z, buffer);
|
||||
boost::charconv::detail::memcpy(first + 17, buffer + 8, 2);
|
||||
}
|
||||
else // 20
|
||||
{
|
||||
decompose32(x, buffer);
|
||||
boost::charconv::detail::memcpy(first, buffer + 1, sizeof(buffer) - 1);
|
||||
|
||||
decompose32(y, buffer);
|
||||
boost::charconv::detail::memcpy(first + 9, buffer + 1, sizeof(buffer) - 1);
|
||||
|
||||
decompose32(z, buffer);
|
||||
boost::charconv::detail::memcpy(first + 18, buffer + 8, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
// unsigned __128 requires 4 shifts
|
||||
// Could just recursivly call the uint64_t twice and then compose 2x 64 bits
|
||||
else if (static_cast<unsigned __int128>(value) <= (std::numeric_limits<unsigned __int128>::max)())
|
||||
#endif
|
||||
else
|
||||
{
|
||||
BOOST_CHARCONV_ASSERT_MSG(sizeof(Integer) < 1, "Your type is unsupported. Use a built-in integral type");
|
||||
}
|
||||
|
||||
return {first + converted_value_digits, 0};
|
||||
}
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
// All other bases
|
||||
// Use a simple lookup table to put together the Integer in character form
|
||||
template <typename Integer>
|
||||
BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars_integer_impl(char* first, char* last, Integer value, int base) noexcept
|
||||
{
|
||||
BOOST_CHARCONV_ASSERT_MSG(base >= 2 && base <= 36, "Base must be between 2 and 36 (inclusive)");
|
||||
|
||||
using Unsigned_Integer = typename std::make_unsigned<Integer>::type;
|
||||
|
||||
const std::ptrdiff_t output_length = last - first;
|
||||
|
||||
if (!(first <= last))
|
||||
{
|
||||
return {last, EINVAL};
|
||||
}
|
||||
|
||||
if (value == 0)
|
||||
{
|
||||
*first++ = '0';
|
||||
return {first, 0};
|
||||
}
|
||||
|
||||
Unsigned_Integer unsigned_value {};
|
||||
const auto unsigned_base = static_cast<Unsigned_Integer>(base);
|
||||
|
||||
BOOST_IF_CONSTEXPR (std::is_signed<Integer>::value)
|
||||
{
|
||||
if (value < 0)
|
||||
{
|
||||
*first++ = '-';
|
||||
unsigned_value = apply_sign(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned_value = value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned_value = value;
|
||||
}
|
||||
|
||||
constexpr Unsigned_Integer zero = 48U; // Char for '0'
|
||||
constexpr auto buffer_size = sizeof(Unsigned_Integer) * CHAR_BIT;
|
||||
char buffer[buffer_size] {};
|
||||
const char* buffer_end = buffer + buffer_size;
|
||||
char* end = buffer + buffer_size - 1;
|
||||
|
||||
// Work from LSB to MSB
|
||||
switch (base)
|
||||
{
|
||||
case 2:
|
||||
while (unsigned_value != 0)
|
||||
{
|
||||
*end-- = static_cast<char>(zero + (unsigned_value & 1U)); // 1<<1 - 1
|
||||
unsigned_value >>= 1U;
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
while (unsigned_value != 0)
|
||||
{
|
||||
*end-- = static_cast<char>(zero + (unsigned_value & 3U)); // 1<<2 - 1
|
||||
unsigned_value >>= 2U;
|
||||
}
|
||||
break;
|
||||
|
||||
case 8:
|
||||
while (unsigned_value != 0)
|
||||
{
|
||||
*end-- = static_cast<char>(zero + (unsigned_value & 7U)); // 1<<3 - 1
|
||||
unsigned_value >>= 3U;
|
||||
}
|
||||
break;
|
||||
|
||||
case 16:
|
||||
while (unsigned_value != 0)
|
||||
{
|
||||
*end-- = digit_table[unsigned_value & 15U]; // 1<<4 - 1
|
||||
unsigned_value >>= 4U;
|
||||
}
|
||||
break;
|
||||
|
||||
case 32:
|
||||
while (unsigned_value != 0)
|
||||
{
|
||||
*end-- = digit_table[unsigned_value & 31U]; // 1<<5 - 1
|
||||
unsigned_value >>= 5U;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
while (unsigned_value != 0)
|
||||
{
|
||||
*end-- = digit_table[unsigned_value % unsigned_base];
|
||||
unsigned_value /= unsigned_base;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
const std::ptrdiff_t num_chars = buffer_end - end - 1;
|
||||
|
||||
if (num_chars > output_length)
|
||||
{
|
||||
return {last, EOVERFLOW};
|
||||
}
|
||||
|
||||
boost::charconv::detail::memcpy(first, buffer + (buffer_size - num_chars), num_chars);
|
||||
|
||||
return {first + num_chars, 0};
|
||||
}
|
||||
|
||||
} // Namespace detail
|
||||
|
||||
template <typename Integer, typename std::enable_if<std::is_integral<Integer>::value, bool>::type = true>
|
||||
BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, Integer value, int base = 10) noexcept
|
||||
{
|
||||
if (base == 10)
|
||||
{
|
||||
return detail::to_chars_integer_impl(first, last, value);
|
||||
}
|
||||
|
||||
return detail::to_chars_integer_impl(first, last, value, base);
|
||||
}
|
||||
|
||||
template <>
|
||||
BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars<bool>(char* first, char* last, bool value, int base) noexcept = delete;
|
||||
|
||||
// TODO: Not correct, but need to make MSVC happy while working on integers
|
||||
BOOST_CHARCONV_DECL to_chars_result to_chars(char* first, char* last, float value) noexcept;
|
||||
|
||||
} // namespace charconv
|
||||
} // namespace boost
|
||||
|
||||
@@ -7,8 +7,9 @@
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
boost::charconv::to_chars_result boost::charconv::to_chars(char* first, char* last, int value, int /*base*/)
|
||||
|
||||
boost::charconv::to_chars_result boost::charconv::to_chars(char* first, char* last, float value) noexcept
|
||||
{
|
||||
std::snprintf( first, last - first - 1, "%d", value );
|
||||
return { first + std::strlen( first ), 0 };
|
||||
std::snprintf(first, last - first - 1, "%f", value);
|
||||
return {first + std::strlen(first), 0};
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# Copyright 2022 Peter Dimov
|
||||
# Copyright 2023 Matt Borland
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
@@ -20,4 +21,5 @@ run quick.cpp ;
|
||||
run from_chars.cpp ;
|
||||
run to_chars.cpp ;
|
||||
run roundtrip.cpp ;
|
||||
run from_chars_STL_comp.cpp : : : [ requires cxx17_std_apply ] ;
|
||||
run from_chars_STL_comp.cpp : : : [ requires cxx17_hdr_charconv ] ;
|
||||
run to_chars_integer_STL_comp.cpp : : : [ requires cxx17_hdr_charconv ] ;
|
||||
|
||||
@@ -5,25 +5,241 @@
|
||||
|
||||
#include <boost/charconv.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <type_traits>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <cerrno>
|
||||
|
||||
template <typename T>
|
||||
void specific_value_tests(T value)
|
||||
{
|
||||
char buffer[64] {};
|
||||
auto r = boost::charconv::to_chars(buffer, buffer + sizeof(buffer) - 1, value);
|
||||
BOOST_TEST_EQ(r.ec, 0);
|
||||
std::string value_string = std::to_string(value);
|
||||
BOOST_TEST_CSTR_EQ(buffer, value_string.c_str());
|
||||
}
|
||||
|
||||
void off_by_one_tests(int value)
|
||||
{
|
||||
char buffer[64] {};
|
||||
auto r = boost::charconv::to_chars(buffer, buffer + sizeof(buffer) - 1, value);
|
||||
BOOST_TEST_EQ(r.ec, 0);
|
||||
std::string value_string = std::to_string(value);
|
||||
BOOST_TEST_CSTR_EQ(buffer, value_string.c_str());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void base_thirtytwo_tests()
|
||||
{
|
||||
char buffer1[64] {};
|
||||
T v1 = static_cast<T>(42);
|
||||
auto r1 = boost::charconv::to_chars(buffer1, buffer1 + sizeof(buffer1) - 1, v1, 32);
|
||||
BOOST_TEST_EQ(r1.ec, 0);
|
||||
BOOST_TEST_CSTR_EQ(buffer1, "1a");
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void base_sixteen_tests()
|
||||
{
|
||||
char buffer1[64] {};
|
||||
T v1 = static_cast<T>(42);
|
||||
auto r1 = boost::charconv::to_chars(buffer1, buffer1 + sizeof(buffer1) - 1, v1, 16);
|
||||
BOOST_TEST_EQ(r1.ec, 0);
|
||||
BOOST_TEST_CSTR_EQ(buffer1, "2a");
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void base_eight_tests()
|
||||
{
|
||||
char buffer1[64] {};
|
||||
T v1 = static_cast<T>(42);
|
||||
auto r1 = boost::charconv::to_chars(buffer1, buffer1 + sizeof(buffer1) - 1, v1, 8);
|
||||
BOOST_TEST_EQ(r1.ec, 0);
|
||||
BOOST_TEST_CSTR_EQ(buffer1, "52");
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void base_four_tests()
|
||||
{
|
||||
char buffer1[64] {};
|
||||
T v1 = static_cast<T>(42);
|
||||
auto r1 = boost::charconv::to_chars(buffer1, buffer1 + sizeof(buffer1) - 1, v1, 4);
|
||||
BOOST_TEST_EQ(r1.ec, 0);
|
||||
BOOST_TEST_CSTR_EQ(buffer1, "222");
|
||||
}
|
||||
|
||||
// Tests the generic implementation
|
||||
template <typename T>
|
||||
void base_30_tests()
|
||||
{
|
||||
char buffer1[64] {};
|
||||
T v1 = static_cast<T>(1234);
|
||||
auto r1 = boost::charconv::to_chars(buffer1, buffer1 + sizeof(buffer1) - 1, v1, 30);
|
||||
BOOST_TEST_EQ(r1.ec, 0);
|
||||
BOOST_TEST_CSTR_EQ(buffer1, "1b4");
|
||||
|
||||
char buffer2[64] {};
|
||||
T v2 = static_cast<T>(-4321);
|
||||
auto r2 = boost::charconv::to_chars(buffer2, buffer2 + sizeof(buffer2) - 1, v2, 30);
|
||||
BOOST_TEST_EQ(r2.ec, 0);
|
||||
BOOST_TEST_CSTR_EQ(buffer2, "-4o1");
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void overflow_tests()
|
||||
{
|
||||
char buffer1[2] {};
|
||||
T v1 = static_cast<T>(250);
|
||||
auto r1 = boost::charconv::to_chars(buffer1, buffer1 + sizeof(buffer1) - 1, v1);
|
||||
BOOST_TEST_EQ(r1.ec, EOVERFLOW);
|
||||
|
||||
char buffer2[3] {};
|
||||
T v2 = static_cast<T>(12341234);
|
||||
auto r2 = boost::charconv::to_chars(buffer2, buffer2 + sizeof(buffer2) - 1, v2);
|
||||
BOOST_TEST_EQ(r2.ec, EOVERFLOW);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void base_two_tests()
|
||||
{
|
||||
char buffer1[64] {};
|
||||
T v1 = static_cast<T>(42);
|
||||
auto r1 = boost::charconv::to_chars(buffer1, buffer1 + sizeof(buffer1) - 1, v1, 2);
|
||||
BOOST_TEST_EQ(r1.ec, 0);
|
||||
BOOST_TEST_CSTR_EQ(buffer1, "101010");
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void sixty_four_bit_tests()
|
||||
{
|
||||
char buffer1[64] {};
|
||||
T v1 = static_cast<T>(-1234);
|
||||
auto r1 = boost::charconv::to_chars(buffer1, buffer1 + sizeof(buffer1) - 1, v1);
|
||||
BOOST_TEST_EQ(r1.ec, 0);
|
||||
BOOST_TEST_CSTR_EQ(buffer1, "-1234");
|
||||
|
||||
char buffer2[64] {};
|
||||
T v2 = static_cast<T>(1234123412341234LL);
|
||||
auto r2 = boost::charconv::to_chars(buffer2, buffer2 + sizeof(buffer2) - 1, v2);
|
||||
BOOST_TEST_EQ(r2.ec, 0);
|
||||
BOOST_TEST_CSTR_EQ(buffer2, "1234123412341234");
|
||||
}
|
||||
|
||||
template <>
|
||||
void sixty_four_bit_tests<std::uint64_t>()
|
||||
{
|
||||
char buffer1[64] {};
|
||||
std::uint64_t v1 = (std::numeric_limits<std::uint64_t>::max)();
|
||||
auto r1 = boost::charconv::to_chars(buffer1, buffer1 + sizeof(buffer1) - 1, v1);
|
||||
BOOST_TEST_EQ(r1.ec, 0);
|
||||
BOOST_TEST_CSTR_EQ(buffer1, "18446744073709551615");
|
||||
|
||||
// Cutting this value in half would overflow a 32 bit unsigned for the back 10 digits
|
||||
char buffer2[64] {};
|
||||
std::uint64_t v2 = UINT64_C(9999999999999999999);
|
||||
auto r2 = boost::charconv::to_chars(buffer2, buffer2 + sizeof(buffer2) - 1, v2);
|
||||
BOOST_TEST_EQ(r2.ec, 0);
|
||||
BOOST_TEST_CSTR_EQ(buffer2, "9999999999999999999");
|
||||
|
||||
// Account for zeros in the back half of the split
|
||||
char buffer3[64] {};
|
||||
std::uint64_t v3 = UINT64_C(10000000000000000000);
|
||||
auto r3 = boost::charconv::to_chars(buffer3, buffer3 + sizeof(buffer3) - 1, v3);
|
||||
BOOST_TEST_EQ(r3.ec, 0);
|
||||
BOOST_TEST_CSTR_EQ(buffer3, "10000000000000000000");
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void negative_vals_test()
|
||||
{
|
||||
char buffer1[10] {};
|
||||
T v = -4321;
|
||||
auto r1 = boost::charconv::to_chars(buffer1, buffer1 + sizeof(buffer1) - 1, v);
|
||||
BOOST_TEST_EQ(r1.ec, 0);
|
||||
BOOST_TEST_CSTR_EQ(buffer1, "-4321");
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void simple_test()
|
||||
{
|
||||
char buffer1[64] {};
|
||||
T v = 34;
|
||||
auto r1 = boost::charconv::to_chars(buffer1, buffer1 + sizeof(buffer1) - 1, v);
|
||||
BOOST_TEST_EQ(r1.ec, 0);
|
||||
BOOST_TEST_CSTR_EQ(buffer1, "34");
|
||||
|
||||
boost::charconv::to_chars_result r {r1.ptr, r1.ec};
|
||||
BOOST_TEST(r1 == r);
|
||||
|
||||
char buffer2[64] {};
|
||||
T v2 = 12;
|
||||
auto r2 = boost::charconv::to_chars(buffer2, buffer2 + sizeof(buffer2) - 1, v2);
|
||||
BOOST_TEST(r1 != r2);
|
||||
BOOST_TEST_EQ(r2.ec, 0);
|
||||
BOOST_TEST_CSTR_EQ(buffer2, "12");
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
char buffer[32] = {};
|
||||
|
||||
simple_test<char>();
|
||||
simple_test<signed char>();
|
||||
simple_test<unsigned char>();
|
||||
simple_test<short>();
|
||||
simple_test<unsigned short>();
|
||||
simple_test<int>();
|
||||
simple_test<unsigned>();
|
||||
simple_test<long>();
|
||||
simple_test<unsigned long>();
|
||||
simple_test<long long>();
|
||||
simple_test<unsigned long long>();
|
||||
simple_test<std::int32_t>();
|
||||
simple_test<std::uint64_t>();
|
||||
|
||||
int v = 1048576;
|
||||
auto r = boost::charconv::to_chars( buffer, buffer + sizeof( buffer ) - 1, v );
|
||||
negative_vals_test<int>();
|
||||
negative_vals_test<long>();
|
||||
|
||||
BOOST_TEST_EQ(r.ec, 0) && BOOST_TEST_CSTR_EQ(buffer, "1048576");
|
||||
BOOST_TEST(r == r);
|
||||
sixty_four_bit_tests<long long>();
|
||||
sixty_four_bit_tests<std::uint64_t>();
|
||||
|
||||
boost::charconv::to_chars_result r2 {r.ptr, 0};
|
||||
BOOST_TEST(r == r2);
|
||||
// Tests for every specialized base
|
||||
base_two_tests<int>();
|
||||
base_two_tests<unsigned>();
|
||||
|
||||
char buffer2[32] = {};
|
||||
base_four_tests<int>();
|
||||
base_four_tests<unsigned>();
|
||||
|
||||
auto r3 = boost::charconv::to_chars(buffer2, buffer2 + sizeof(buffer) - 1, v);
|
||||
BOOST_TEST(r != r3);
|
||||
base_eight_tests<int>();
|
||||
base_eight_tests<unsigned>();
|
||||
|
||||
base_sixteen_tests<int>();
|
||||
base_sixteen_tests<unsigned>();
|
||||
|
||||
base_thirtytwo_tests<int>();
|
||||
base_thirtytwo_tests<unsigned>();
|
||||
|
||||
// The generic impl
|
||||
base_30_tests<int>();
|
||||
base_30_tests<long>();
|
||||
|
||||
overflow_tests<int>();
|
||||
|
||||
// Resulted in off by one errors from random number generation
|
||||
// Consistently one larger with 10 digit numbers
|
||||
off_by_one_tests(1159137169);
|
||||
off_by_one_tests(-1321793318);
|
||||
off_by_one_tests(2140634902);
|
||||
|
||||
// If we compensate by one these fail
|
||||
off_by_one_tests(1038882992);
|
||||
off_by_one_tests(-1065658613);
|
||||
off_by_one_tests(-1027205339);
|
||||
|
||||
// Fails in CI at the time - Likely overflow when converting to positive
|
||||
specific_value_tests<short>(-32768);
|
||||
specific_value_tests(-7061872404794389355L);
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
209
test/to_chars_integer_STL_comp.cpp
Normal file
209
test/to_chars_integer_STL_comp.cpp
Normal file
@@ -0,0 +1,209 @@
|
||||
// Copyright 2023 Matt Borland
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#if !defined(BOOST_NO_CXX17_HDR_CHARCONV) && (!defined(__clang_major__) || (defined(__clang_major__) && __clang_major__ > 7))
|
||||
|
||||
#include <boost/charconv.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <charconv>
|
||||
#include <type_traits>
|
||||
#include <limits>
|
||||
#include <cstring>
|
||||
#include <cstdint>
|
||||
#include <cerrno>
|
||||
#include <utility>
|
||||
#include <system_error>
|
||||
#include <random>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
template <typename T>
|
||||
void stress_test_worker()
|
||||
{
|
||||
std::random_device rd;
|
||||
std::mt19937_64 gen(rd());
|
||||
std::uniform_int_distribution<T> dist((std::numeric_limits<T>::min)(), (std::numeric_limits<T>::max)());
|
||||
|
||||
std::mt19937_64 base_gen(rd());
|
||||
std::uniform_int_distribution<int> base_dist(2, 36);
|
||||
|
||||
for (std::size_t i = 0; i < 100'000'000; ++i)
|
||||
{
|
||||
char buffer_stl[128] {};
|
||||
char buffer_boost[128] {};
|
||||
|
||||
T v = dist(gen);
|
||||
int base = base_dist(base_gen);
|
||||
|
||||
auto r_stl = std::to_chars(buffer_stl, buffer_stl + sizeof(buffer_stl) - 1, v, base);
|
||||
auto r_boost = boost::charconv::to_chars(buffer_boost, buffer_boost + sizeof(buffer_boost) - 1, v, base);
|
||||
|
||||
BOOST_TEST_EQ(static_cast<std::ptrdiff_t>(r_stl.ptr - buffer_stl), static_cast<std::ptrdiff_t>(r_boost.ptr - buffer_boost));
|
||||
BOOST_TEST_CSTR_EQ(buffer_stl, buffer_boost);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void stress_test()
|
||||
{
|
||||
auto num_threads = std::thread::hardware_concurrency();
|
||||
std::vector<std::thread> thread_manager(num_threads);
|
||||
|
||||
for (std::size_t i = 0; i < num_threads; ++i)
|
||||
{
|
||||
thread_manager.emplace_back(std::thread(stress_test_worker<T>));
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < thread_manager.size(); ++i)
|
||||
{
|
||||
if (thread_manager[i].joinable())
|
||||
{
|
||||
thread_manager[i].join();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, int base = 10>
|
||||
void random_tests()
|
||||
{
|
||||
std::mt19937_64 gen(42);
|
||||
std::uniform_int_distribution<T> dist((std::numeric_limits<T>::min)(), (std::numeric_limits<T>::max)());
|
||||
|
||||
for (std::size_t i = 0; i < 100'000; ++i)
|
||||
{
|
||||
char buffer_stl[128] {};
|
||||
char buffer_boost[128] {};
|
||||
|
||||
T v = dist(gen);
|
||||
|
||||
auto r_stl = std::to_chars(buffer_stl, buffer_stl + sizeof(buffer_stl) - 1, v, base);
|
||||
auto r_boost = boost::charconv::to_chars(buffer_boost, buffer_boost + sizeof(buffer_boost) - 1, v, base);
|
||||
|
||||
BOOST_TEST_EQ(static_cast<std::ptrdiff_t>(r_stl.ptr - buffer_stl), static_cast<std::ptrdiff_t>(r_boost.ptr - buffer_boost));
|
||||
BOOST_TEST_CSTR_EQ(buffer_stl, buffer_boost);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void test()
|
||||
{
|
||||
// Signed 0
|
||||
char buffer1_stl[64] {};
|
||||
char buffer1_boost[64] {};
|
||||
T v1 = static_cast<T>(-0);
|
||||
auto r1_stl = std::to_chars(buffer1_stl, buffer1_stl + sizeof(buffer1_stl) - 1, v1);
|
||||
auto r1_boost = boost::charconv::to_chars(buffer1_boost, buffer1_boost + sizeof(buffer1_boost) - 1, v1);
|
||||
BOOST_TEST_EQ(r1_stl.ptr, buffer1_stl + 1);
|
||||
BOOST_TEST_EQ(r1_boost.ptr, buffer1_boost + 1);
|
||||
BOOST_TEST_CSTR_EQ(buffer1_stl, "0");
|
||||
BOOST_TEST_CSTR_EQ(buffer1_boost, "0");
|
||||
|
||||
// Binary
|
||||
char buffer2_stl[64] {};
|
||||
char buffer2_boost[64] {};
|
||||
T v2 = static_cast<T>(42);
|
||||
auto r2_stl = std::to_chars(buffer2_stl, buffer2_stl + sizeof(buffer2_stl) - 1, v2, 2);
|
||||
auto r2_boost = boost::charconv::to_chars(buffer2_boost, buffer2_boost + sizeof(buffer2_boost) - 1, v2, 2);
|
||||
BOOST_TEST_EQ(r2_stl.ptr, buffer2_stl + 6);
|
||||
BOOST_TEST_EQ(r2_boost.ptr, buffer2_boost + 6);
|
||||
BOOST_TEST_CSTR_EQ(buffer2_stl, "101010");
|
||||
BOOST_TEST_CSTR_EQ(buffer2_boost, "101010");
|
||||
|
||||
// Base 10
|
||||
char buffer3_stl[64] {};
|
||||
char buffer3_boost[64] {};
|
||||
T v3 = static_cast<T>(120);
|
||||
auto r3_stl = std::to_chars(buffer3_stl, buffer3_stl + sizeof(buffer3_stl) - 1, v3);
|
||||
auto r3_boost = boost::charconv::to_chars(buffer3_boost, buffer3_boost + sizeof(buffer3_boost) - 1, v3);
|
||||
BOOST_TEST_EQ(r3_stl.ptr, buffer3_stl + 3);
|
||||
BOOST_TEST_EQ(r3_boost.ptr, buffer3_boost + 3);
|
||||
BOOST_TEST_CSTR_EQ(buffer3_stl, "120");
|
||||
BOOST_TEST_CSTR_EQ(buffer3_boost, "120");
|
||||
|
||||
// Hexadecimal
|
||||
char buffer4_stl[64] {};
|
||||
char buffer4_boost[64] {};
|
||||
T v4 = static_cast<T>(44);
|
||||
auto r4_stl = std::to_chars(buffer4_stl, buffer4_stl + sizeof(buffer4_stl) - 1, v4, 16);
|
||||
auto r4_boost = boost::charconv::to_chars(buffer4_boost, buffer4_boost + sizeof(buffer4_boost) - 1, v4, 16);
|
||||
BOOST_TEST_EQ(r4_stl.ptr, buffer4_stl + 2);
|
||||
BOOST_TEST_EQ(r4_boost.ptr, buffer4_boost + 2);
|
||||
BOOST_TEST_CSTR_EQ(buffer4_stl, "2c");
|
||||
BOOST_TEST_CSTR_EQ(buffer4_boost, "2c");
|
||||
|
||||
// Base 28
|
||||
char buffer5_stl[64] {};
|
||||
char buffer5_boost[64] {};
|
||||
T v5 = static_cast<T>(100);
|
||||
auto r5_stl = std::to_chars(buffer5_stl, buffer5_stl + sizeof(buffer5_stl) - 1, v5, 28);
|
||||
auto r5_boost = boost::charconv::to_chars(buffer5_boost, buffer5_boost + sizeof(buffer5_boost) - 1, v5, 28);
|
||||
BOOST_TEST_EQ(r5_stl.ptr, buffer5_stl + 2);
|
||||
BOOST_TEST_EQ(r5_boost.ptr, buffer5_boost + 2);
|
||||
BOOST_TEST_CSTR_EQ(buffer5_stl, "3g");
|
||||
BOOST_TEST_CSTR_EQ(buffer5_boost, "3g");
|
||||
|
||||
// Overflow
|
||||
char buffer6_stl[1] {};
|
||||
char buffer6_boost[1] {};
|
||||
T v6 = static_cast<T>(100);
|
||||
auto r6_stl = std::to_chars(buffer6_stl, buffer6_stl + sizeof(buffer6_stl) - 1, v6);
|
||||
auto r6_boost = boost::charconv::to_chars(buffer6_boost, buffer6_boost + sizeof(buffer6_boost) - 1, v6);
|
||||
BOOST_TEST_EQ(r6_stl.ptr, r6_stl.ptr);
|
||||
BOOST_TEST_EQ(r6_boost.ptr, r6_boost.ptr);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test<char>();
|
||||
test<signed char>();
|
||||
test<unsigned char>();
|
||||
test<short>();
|
||||
test<unsigned short>();
|
||||
test<int>();
|
||||
test<unsigned>();
|
||||
test<long>();
|
||||
test<unsigned long>();
|
||||
test<long long>();
|
||||
test<unsigned long long>();
|
||||
|
||||
// Specialized bases
|
||||
random_tests<int, 2>();
|
||||
random_tests<int, 4>();
|
||||
random_tests<int, 8>();
|
||||
random_tests<int, 16>();
|
||||
random_tests<int, 32>();
|
||||
|
||||
#ifndef _MSC_VER // MSVC does not allow for 8-bit ints in std::uniform_int_distribution
|
||||
random_tests<std::int8_t, 10>();
|
||||
random_tests<std::uint8_t, 10>();
|
||||
#endif
|
||||
|
||||
random_tests<std::int16_t, 10>();
|
||||
random_tests<std::uint16_t, 10>();
|
||||
random_tests<std::int32_t, 10>();
|
||||
random_tests<std::uint32_t, 10>();
|
||||
random_tests<std::int64_t, 10>();
|
||||
random_tests<std::uint64_t, 10>();
|
||||
|
||||
// Generic implementation
|
||||
random_tests<int, 23>();
|
||||
|
||||
// Stress tests are disabled for CI
|
||||
#ifdef BOOST_CHARCONV_STRESS_TEST
|
||||
stress_test<int>();
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user