Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
G
golang
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
go
golang
Commits
42d78506
Commit
42d78506
authored
Mar 27, 2008
by
Rob Pike
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Basic formatted I/O library plus one support lib.
SVN=113977
parent
d79b17e6
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
500 additions
and
0 deletions
+500
-0
fmt.go
src/lib/fmt.go
+484
-0
sys.go
src/lib/sys.go
+16
-0
No files found.
src/lib/fmt.go
0 → 100644
View file @
42d78506
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package
fmt
/*
f := fmt.New();
print f.d(1234).s("\n").str(); // create string, print it
f.d(-1234).s("\n").put(); // print string
f.ud(^0).putnl(); // print string with automatic newline
*/
import
sys
"sys"
export
Fmt
,
New
;
var
ldigits
[
16
]
byte
;
// BUG: should be constants
var
udigits
[
16
]
byte
;
// BUG: can they be strings? looks like trouble with buf[i] = digits[val];
var
inited
bool
;
var
pows10
[
160
]
double
;
type
Fmt
struct
{
buf
string
;
wid
int
;
wid_present
bool
;
prec
int
;
prec_present
bool
;
}
func
(
f
*
Fmt
)
clearflags
()
{
f
.
wid_present
=
false
;
f
.
prec_present
=
false
;
}
func
(
f
*
Fmt
)
clearbuf
()
{
f
.
buf
=
""
;
}
func
(
f
*
Fmt
)
init
()
{
f
.
clearbuf
();
f
.
clearflags
();
if
inited
{
return
;
}
var
i
byte
;
for
i
=
0
;
i
<
10
;
i
++
{
ldigits
[
i
]
=
'0'
+
i
;
udigits
[
i
]
=
'0'
+
i
;
}
for
i
=
0
;
i
<
6
;
i
++
{
ldigits
[
i
+
10
]
=
'a'
+
i
;
udigits
[
i
+
10
]
=
'A'
+
i
;
}
// BUG: should be done with initialization
var
p
double
=
1.0
;
for
i
=
0
;
i
<
160
;
i
++
{
// BUG: len(pows10)
pows10
[
i
]
=
p
;
p
*=
10.0
;
}
inited
=
true
;
}
func
New
()
*
Fmt
{
f
:=
new
(
Fmt
);
f
.
init
();
return
f
;
}
func
(
f
*
Fmt
)
str
()
string
{
s
:=
f
.
buf
;
f
.
clearbuf
();
f
.
clearflags
();
f
.
buf
=
""
;
return
s
;
}
func
(
f
*
Fmt
)
put
()
{
print
f
.
buf
;
f
.
clearbuf
();
f
.
clearflags
();
}
func
(
f
*
Fmt
)
putnl
()
{
print
f
.
buf
,
"
\n
"
;
f
.
clearbuf
();
f
.
clearflags
();
}
func
(
f
*
Fmt
)
wp
(
w
,
p
int
)
*
Fmt
{
f
.
wid_present
=
true
;
f
.
wid
=
w
;
f
.
prec_present
=
true
;
f
.
prec
=
p
;
return
f
;
}
func
(
f
*
Fmt
)
p
(
p
int
)
*
Fmt
{
f
.
prec_present
=
true
;
f
.
prec
=
p
;
return
f
;
}
func
(
f
*
Fmt
)
w
(
x
int
)
*
Fmt
{
f
.
wid_present
=
true
;
f
.
wid
=
x
;
return
f
;
}
// append s to buf, padded on left (w > 0) or right (w < 0)
// padding is in bytes, not characters (agrees with ANSIC C, not Plan 9 C)
func
(
f
*
Fmt
)
pad
(
s
string
)
{
if
f
.
wid_present
&&
f
.
wid
!=
0
{
left
:=
true
;
w
:=
f
.
wid
;
if
w
<
0
{
left
=
false
;
w
=
-
w
;
}
w
-=
len
(
s
);
if
w
>
0
{
if
w
>
64
{
// BUG: should be able to use a const
w
=
64
;
}
var
buf
[
64
]
byte
;
// BUG: should be able to allocate a size
for
i
:=
0
;
i
<
w
;
i
++
{
buf
[
i
]
=
' '
;
}
if
left
{
s
=
string
(
buf
)[
0
:
w
]
+
s
;
}
else
{
s
=
s
+
string
(
buf
)[
0
:
w
];
}
}
}
f
.
buf
=
f
.
buf
+
s
;
// BUG: += should work
}
// format val into buf, ending at buf[i]. (printing is easier right-to-left;
// that's why the bidi languages are right-to-left except for numbers. wait,
// never mind.) val is known to be unsigned. we could make things maybe
// marginally faster by splitting the 32-bit case out into a separate function
// but it's not worth the duplication, so val has 64 bits.
func
putint
(
buf
*
[
64
]
byte
,
i
int
,
base
,
val
uint64
,
digits
*
[
16
]
byte
)
int
{
for
val
>=
base
{
buf
[
i
]
=
digits
[
val
%
base
];
i
--
;
val
/=
base
;
}
buf
[
i
]
=
digits
[
val
];
return
i
-
1
;
}
// integer; interprets prec but not wid.
func
(
f
*
Fmt
)
integer
(
a
int64
,
base
uint
,
is_signed
bool
,
digits
*
[
16
]
byte
)
string
{
var
buf
[
64
]
byte
;
negative
:=
is_signed
&&
a
<
0
;
if
negative
{
a
=
-
a
;
}
i
:=
putint
(
&
buf
,
63
,
uint64
(
base
),
uint64
(
a
),
digits
);
if
f
.
prec_present
{
for
i
>
0
&&
f
.
prec
>
(
63
-
i
)
{
buf
[
i
]
=
'0'
;
i
--
;
}
}
if
negative
{
buf
[
i
]
=
'-'
;
i
--
;
}
return
string
(
buf
)[
i
+
1
:
64
];
}
// decimal
func
(
f
*
Fmt
)
d
(
a
int32
)
*
Fmt
{
f
.
pad
(
f
.
integer
(
int64
(
a
),
10
,
true
,
&
ldigits
));
f
.
clearflags
();
return
f
;
}
func
(
f
*
Fmt
)
D
(
a
int64
)
*
Fmt
{
f
.
pad
(
f
.
integer
(
a
,
10
,
true
,
&
ldigits
));
f
.
clearflags
();
return
f
;
}
// unsigned decimal
func
(
f
*
Fmt
)
ud
(
a
int32
)
*
Fmt
{
f
.
pad
(
f
.
integer
(
int64
(
uint32
(
a
)),
10
,
false
,
&
ldigits
));
f
.
clearflags
();
return
f
;
}
func
(
f
*
Fmt
)
uD
(
a
int64
)
*
Fmt
{
f
.
pad
(
f
.
integer
(
a
,
10
,
false
,
&
ldigits
));
f
.
clearflags
();
return
f
;
}
// hexdecimal
func
(
f
*
Fmt
)
x
(
a
int32
)
*
Fmt
{
f
.
pad
(
f
.
integer
(
int64
(
a
),
16
,
true
,
&
ldigits
));
f
.
clearflags
();
return
f
;
}
func
(
f
*
Fmt
)
X
(
a
int64
)
*
Fmt
{
f
.
pad
(
f
.
integer
(
a
,
16
,
true
,
&
ldigits
));
f
.
clearflags
();
return
f
;
}
// unsigned hexdecimal
func
(
f
*
Fmt
)
ux
(
a
int32
)
*
Fmt
{
f
.
pad
(
f
.
integer
(
int64
(
uint32
(
a
)),
16
,
false
,
&
ldigits
));
f
.
clearflags
();
return
f
;
}
func
(
f
*
Fmt
)
uX
(
a
int64
)
*
Fmt
{
f
.
pad
(
f
.
integer
(
a
,
16
,
false
,
&
ldigits
));
f
.
clearflags
();
return
f
;
}
// HEXADECIMAL
func
(
f
*
Fmt
)
Ux
(
a
int32
)
*
Fmt
{
f
.
pad
(
f
.
integer
(
int64
(
a
),
16
,
true
,
&
udigits
));
f
.
clearflags
();
return
f
;
}
func
(
f
*
Fmt
)
UX
(
a
int64
)
*
Fmt
{
f
.
pad
(
f
.
integer
(
a
,
16
,
true
,
&
udigits
));
f
.
clearflags
();
return
f
;
}
// unsigned HEXADECIMAL
func
(
f
*
Fmt
)
uUx
(
a
int32
)
*
Fmt
{
f
.
pad
(
f
.
integer
(
int64
(
uint32
(
a
)),
16
,
false
,
&
udigits
));
f
.
clearflags
();
return
f
;
}
func
(
f
*
Fmt
)
uUX
(
a
int64
)
*
Fmt
{
f
.
pad
(
f
.
integer
(
a
,
16
,
false
,
&
udigits
));
f
.
clearflags
();
return
f
;
}
// octal
func
(
f
*
Fmt
)
o
(
a
int32
)
*
Fmt
{
f
.
pad
(
f
.
integer
(
int64
(
a
),
8
,
true
,
&
ldigits
));
f
.
clearflags
();
return
f
;
}
func
(
f
*
Fmt
)
O
(
a
int64
)
*
Fmt
{
f
.
pad
(
f
.
integer
(
a
,
8
,
true
,
&
ldigits
));
f
.
clearflags
();
return
f
;
}
// unsigned octal
func
(
f
*
Fmt
)
uo
(
a
int32
)
*
Fmt
{
f
.
pad
(
f
.
integer
(
int64
(
uint32
(
a
)),
8
,
false
,
&
ldigits
));
f
.
clearflags
();
return
f
;
}
func
(
f
*
Fmt
)
uO
(
a
int64
)
*
Fmt
{
f
.
pad
(
f
.
integer
(
a
,
8
,
false
,
&
ldigits
));
f
.
clearflags
();
return
f
;
}
// binary
func
(
f
*
Fmt
)
b
(
a
int32
)
*
Fmt
{
f
.
pad
(
f
.
integer
(
int64
(
uint32
(
a
)),
2
,
false
,
&
ldigits
));
f
.
clearflags
();
return
f
;
}
func
(
f
*
Fmt
)
B
(
a
int64
)
*
Fmt
{
f
.
pad
(
f
.
integer
(
a
,
2
,
false
,
&
ldigits
));
f
.
clearflags
();
return
f
;
}
// character
func
(
f
*
Fmt
)
c
(
a
int
)
*
Fmt
{
f
.
pad
(
string
(
a
));
f
.
clearflags
();
return
f
;
}
// string
func
(
f
*
Fmt
)
s
(
s
string
)
*
Fmt
{
if
f
.
prec_present
{
if
f
.
prec
<
len
(
s
)
{
w
:=
f
.
prec
;
// BUG: can't use f.prec in slice
s
=
s
[
0
:
w
];
}
}
f
.
pad
(
s
);
f
.
clearflags
();
return
f
;
}
func
pow10
(
n
int
)
double
{
var
d
double
;
npows10
:=
160
;
// nelem(pows10); BUG: why not a const?
neg
:=
false
;
if
n
<
0
{
if
n
<
-
307
{
// DBL_MIN_10_EXP
return
0.
;
}
neg
=
true
;
n
=
-
n
;
}
else
if
n
>
308
{
// DBL_MAX_10_EXP
return
1.79769e+308
;
// HUGE_VAL
}
if
n
<
npows10
{
d
=
pows10
[
n
];
}
else
{
d
=
pows10
[
npows10
-
1
];
for
{
n
-=
npows10
-
1
;
if
n
<
npows10
{
d
*=
pows10
[
n
];
break
;
}
d
*=
pows10
[
npows10
-
1
];
}
}
if
neg
{
return
1
/
d
;
}
return
d
;
}
func
unpack
(
a
double
)
(
negative
bool
,
exp
int
,
num
double
)
{
neg
:=
a
<
0
;
if
neg
{
a
=
-
a
;
}
// find g,e such that a = g*10^e.
// guess 10-exponent using 2-exponent, then fine tune.
var
g
double
;
var
e2
int
;
e2
,
g
=
sys
.
frexp
(
a
);
e
:=
int
(
e2
*
.301029995663981
);
g
:=
a
*
pow10
(
-
e
);
for
g
<
1
{
e
--
;
g
=
a
*
pow10
(
-
e
);
}
for
g
>=
10
{
e
++
;
g
=
a
*
pow10
(
-
e
);
}
return
neg
,
e
,
g
;
}
// double
func
(
f
*
Fmt
)
E
(
a
double
)
*
Fmt
{
var
negative
bool
;
var
g
double
;
var
exp
int
;
negative
,
exp
,
g
=
unpack
(
a
);
prec
:=
6
;
if
f
.
prec_present
{
prec
=
f
.
prec
;
}
prec
++
;
// one digit left of decimal
// multiply by 10^prec to get decimal places; put decimal after first digit
g
*=
pow10
(
prec
);
s
:=
f
.
integer
(
int64
(
g
+
.5
),
10
,
true
,
&
ldigits
);
// get the digits into a string
s
=
s
[
0
:
1
]
+
"."
+
s
[
1
:
prec
];
// insert a decimal point
// print exponent with leading 0 if appropriate.
es
:=
New
()
.
p
(
2
)
.
integer
(
int64
(
exp
),
10
,
true
,
&
ldigits
);
if
exp
>
0
{
es
=
"+"
+
es
;
// BUG: should do this with a fmt flag
}
s
=
s
+
"e"
+
es
;
if
negative
{
s
=
"-"
+
s
;
}
f
.
pad
(
s
);
f
.
clearflags
();
return
f
;
}
// double
func
(
f
*
Fmt
)
F
(
a
double
)
*
Fmt
{
var
negative
bool
;
var
g
double
;
var
exp
int
;
negative
,
exp
,
g
=
unpack
(
a
);
if
exp
>
19
||
exp
<
-
19
{
// too big for this sloppy code
return
f
.
E
(
a
);
}
prec
:=
6
;
if
f
.
prec_present
{
prec
=
f
.
prec
;
}
// prec is number of digits after decimal point
s
:=
"NO"
;
if
exp
>=
0
{
g
*=
pow10
(
exp
);
gi
:=
int64
(
g
);
s
=
New
()
.
integer
(
gi
,
10
,
true
,
&
ldigits
);
s
=
s
+
"."
;
g
-=
double
(
gi
);
s
=
s
+
New
()
.
p
(
prec
)
.
integer
(
int64
(
g
*
pow10
(
prec
)
+
.5
),
10
,
true
,
&
ldigits
);
}
else
{
g
*=
pow10
(
prec
+
exp
);
s
=
"0."
+
New
()
.
p
(
prec
)
.
integer
(
int64
(
g
+
.5
),
10
,
true
,
&
ldigits
);
}
if
negative
{
s
=
"-"
+
s
;
}
f
.
pad
(
s
);
f
.
clearflags
();
return
f
;
}
// double
func
(
f
*
Fmt
)
G
(
a
double
)
*
Fmt
{
f1
:=
New
();
f2
:=
New
();
if
f
.
wid_present
{
f1
.
w
(
f
.
wid
);
f2
.
w
(
f
.
wid
);
}
if
f
.
prec_present
{
f1
.
p
(
f
.
prec
);
f2
.
p
(
f
.
prec
);
}
efmt
:=
f1
.
E
(
a
)
.
str
();
ffmt
:=
f2
.
F
(
a
)
.
str
();
// ffmt can return e in my bogus world; don't trim trailing 0s if so.
f_is_e
:=
false
;
for
i
:=
0
;
i
<
len
(
ffmt
);
i
++
{
if
ffmt
[
i
]
==
'e'
{
f_is_e
=
true
;
break
;
}
}
if
!
f_is_e
{
// strip trailing zeros
l
:=
len
(
ffmt
);
for
ffmt
[
l
-
1
]
==
'0'
{
l
--
;
}
ffmt
=
ffmt
[
0
:
l
];
}
if
len
(
efmt
)
<
len
(
ffmt
)
{
f
.
pad
(
efmt
);
}
else
{
f
.
pad
(
ffmt
);
}
f
.
clearflags
();
return
f
;
}
// float
func
(
x
*
Fmt
)
f
(
a
float
)
*
Fmt
{
return
x
.
F
(
double
(
a
));
}
// float
func
(
x
*
Fmt
)
e
(
a
float
)
*
Fmt
{
return
x
.
E
(
double
(
a
));
}
// float
func
(
x
*
Fmt
)
g
(
a
float
)
*
Fmt
{
return
x
.
G
(
double
(
a
));
}
src/lib/sys.go
0 → 100644
View file @
42d78506
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package
sys
func
modf
(
a
double
)
(
double
,
double
);
func
frexp
(
a
double
)
(
int
,
double
);
func
ldexp
(
double
,
int
)
double
;
func
Inf
(
n
int
)
double
;
func
NaN
()
double
;
func
isInf
(
arg
double
,
n
int
)
bool
;
export
modf
,
frexp
,
ldexp
export
NaN
,
isInf
,
Inf
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment