Standard library-Fmt/format.go interpretation

Source: Internet
Author: User

Copyright: The Go Authors. All rights reserved.//Use of this source code are governed by a bsd-style//license so can be found in the license file. go/src/fmt/format.go//version 1.7package Fmtimport ("StrConv" "Unicode/utf8")//For conversion to const (Ldigits = " 0123456789abcdefx "udigits =" 0123456789ABCDEFX ")//used as a parameter to facilitate the reader to understand what the incoming parameter means const (signed = Trueunsigned = False)//used to record Whether the corresponding tag is specified in the placeholder//flags are placed in a separate structure to facilitate cleanup of type fmtflags struct {widpresent bool//Width value precpresent bool//precision value minus bool -Mark plus bool//+ Mark sharp BOOL//# Mark space bool//space Mark zero BOOL//0 mark//for special formats%+v and% #v , set the PLUSV/SHARPV flag separately. PLUSV BOOL//+VSHARPV BOOL//#v}//FMT is a primitive formatter used in functions such as Printf. It outputs the formatted result to a buffer, which must be specified separately. Type FMT struct {buf *buffer//*[]bytefmtflags//struct, defines many flags WID int//width PREC int//precision//intbuf enough to store binary format in t64intbuf [68]byte}//Reset All flags func (f *fmt) Clearflags () {f.fmtflags = fmtflags{}}//struct initialization (must provide buffer) func (f *fmt) init (BUF * Buffer{f.buf = Buff.clearflags ()}//writes data to buffer (writes only n bytes of padding character) func (f *fmt) writepadding (n int) {if n <= 0 {return}buf: = *f.buf  The capacity is determined first, if the capacity is insufficient, then the expansion oldlen: = Len (buf) Newlen: = Oldlen + nif newlen > Cap (BUF) {//default will double the capacity, but to ensure that the write//content can be accommodated, so +nbuf = make (buffer, Cap (BUF) *2+n) copy (buf, *f.buf)}//determines the character to write padbyte: = Byte (") if F.zero {padbyte = byte (' 0 ')}//start writing Paddin G: = buf[oldlen:newlen]for I: = range padding {padding[i] = padbyte}//buf may have been expanded (address changed), so write back *f.buf = buf[:newlen]}/ /write data to buffer (write byte slice, processing width padding simultaneously) func (f *fmt) pad (b []byte) {///If no width value, write directly if!f.widpresent | | f.wid = 0 {f.buf.write (b) retu The rn}//width value is measured in characters rather than bytes (without regard to the feelings of the Chinese characters). Width: = F.wid-utf8. Runecount (b) If!f.minus {//specified '-' tag, padding on left f.writepadding (width) f.buf.write (b)} else {//unspecified '-' tag, padding f.buf.write on the right side (b) F.writepadding (width)}}//writes data to the buffer (writes a string while processing the width padding) func (f *fmt) padstring (s string) {//If there is no width value, write directly if!f.widpresent | | F.wid = = 0 {f.buf.writestring (s) return}//the width value is in characters as a unit, not as a byte (without regard to the feelings of Chinese characters). Width: = F.wid-utf8. RUnecountinstring (s) if!f.minus {//specified '-' tag, padding on left f.writepadding (width) f.buf.writestring (s)} else {//unspecified '-' tag, fill F on right . buf. WriteString (s) f.writepadding (width)}}//writes data to buffer (Boolean value) func (f *fmt) Fmt_boolean (v bool) {if v {f.padstring ("true")} else {f.padstring ("false")}} Writes data to the buffer (writes Unicode code point)//Unicode code point format "U+FFFF", if the # tag is specified, the format is "U+ffff ' corresponding character '". Func (f *fmt) Fmt_unicode (U UInt64) {//temporary buffer, capacity 68 bytes, can be expanded if the capacity is insufficient. BUF: = f.intbuf[0:]//1, determine whether the capacity is sufficient//if no precision is specified, then the capacity is certainly sufficient, because even if the use of the% #U 1 to format,//the maximum required storage space is only 18 bytes ("U+ffffffffffffffff"), no More than 68. It is possible to exceed the capacity range only after specifying too large a precision, such as 100. So the next face of the capacity of the judgment, and precision is only related. The default precision is 4 (if the code point length is less than 4 bits, add a leading 0, such as u+0065, if the//code point length exceeds the precision value, the precision is ignored) Prec: = 4//If precision is specified, determines whether the formatted result will exceed the BUF range if f.precpresent &A mp;& F.prec > 4 {prec = f.prec//estimates the required storage space: "u+", Precision, "'", corresponding character, "'". Width: = 2 + prec + 2 + UTF8. Utfmax + 1if width > len (buf) {buf = make ([]byte, width)}}//start formatting//right-to-left formatting easier some i: = Len (BUF)//2, Process # Mark//At last add ' phase should be the character '. The premise is that the value must be within the Unicode code point range, and the character can print if F.sharP && u <= UTF8. Maxrune && StrConv. Isprint (Rune (U)) {i--buf[i] = ' \ ' i-= UTF8. Runelen (Rune (U)) utf8. Encoderune (buf[i:], Rune (U)) i--buf[i] = ' \ ' i--buf[i] = '}//3, Format u as a hexadecimal value. For u >= + {i--//OK BUF write subscript buf[i] = udigits[u&0xf]//With 1111 phase, get hexadecimal single digit, then check the table for the character. prec--//accuracy is used for a U >>= 4//drop hexadecimal single digit}i--//processing the last one-digit buf[ I] = udigits[u]prec--//4, processing precision information (add leading 0) for Prec > 0 {i--buf[i] = ' 0 ' prec--}//5, processing leading "u+". I--buf[i] = ' + ' i--buf[i] = ' U '//6, Processing width information (padding space) Oldzero: = F.zerof.zero = Falsef.pad (buf[i:]) F.zero = oldzero}//writes data to buffer (integer Number: Includes signed and unsigned, processing a binary conversion)//u: The integer to be formatted. Base: Binary. IsSigned: whether there are symbols. Digits: Binary conversion table//16 binary case determined by the digits parameter func (f *fmt) Fmt_integer (u uint64, base int, issigned bool, digits string) {//1, fixup parameter Number//If there is a sign, the negative numbers stored in U are changed to positive negative: = issigned && Int64 (U) < 0if negative {u =-u//equals-int64 (U), type conversion does not change value contents , so minus whichever is the same,-U saves one step conversion operation}//temporary buffer, capacity is 68 bytes, if the capacity is not enough, you canTo be expanded. BUF: = f.intbuf[0:]//2, determine if the capacity is sufficient if F.widpresent | | F.precpresent {//requires an additional 3 bytes to hold the signed "0x". In order to improve efficiency, the width and precision are added directly (in fact the width and precision overlap)//Because in most cases, the result of the addition is not too large, the width > len (buf) is very//less, it is seldom re-allocated memory, so this is only to ensure security. Conversely, if the correct width value is calculated using a judgment statement, the efficiency is reduced.  Width: = 3 + f.wid + f.precif width > len (buf) {buf = make ([]byte, width)}}//3, determine accuracy information//NOTE: There are two ways to add a leading 0 to an integer:%.3d or%08d,// If both of these are used, the 0 tag is ignored and the width is padded with spaces. The default precision is 0, and if precision is specified, the specified precision is used. Prec: = 0if f.precpresent {prec = f.prec//If the precision is specified as 0 and the value is also specified as 0, then there is no content and only spaces are populated. For example: FMT. Printf ("% #8. D", 0) if Prec = = 0 && U = = 0 {oldzero: = F.zerof.zero = Falsef.writepadding (f.wid) F.zero = Oldzeroretu rn}//If no precision is specified, but 0 marks and widths are specified,//the width value is converted to the precision value, and the leading 0 is handled by the precision processing function. } else if F.zero && f.widpresent {prec = f.wid//if a symbol bit is specified, leave a sign bit if negative | | f.plus | | f.space {prec--}}//from right to It's easier to format the left some I: = Len (BUF)//4, Start coding//using constants for division and modulo operations can be more efficient. The case order is sorted by usage frequency. Switch base {case 10:for u >= {i--//OK buffer write subscript Next: = u/10//Remove single digit//here used-and * for the remainder, and no use%, is not faster than%? Buf[i] = byte (' 0 ' + u-next*10)//Get single digit u = next}case 16:for u >= + {i--//OK buffer write subscript buf[i] = Dig ITS[U&AMP;0XF]//with 1111, gets the hexadecimal single digit and then checks the table for the character.  U >>= 4//drop hexadecimal single digit}case 8:for u >= 8 {i--//OK buffer write subscript buf[i] = byte (' 0 ' + U&AMP;7)//With 111, gets the single digit of octal and then converts to characters. U >>= 3//Discard octal single digit}case 2:for u >= 2 {i--//OK buffer write subscript buf[i] = byte (' 0 ' + u&1)//vs. 1, gets the single digit of the binary, and then converts to characters. U >>= 1//Drop binary single digit}default:panic ("Fmt:unknown base; Can ' t happen ")//Unknown carry system}i--//The last single digit has not been processed, here processing buf[i] = Digits[u]//All the decimal digits of the binary can look up the table to take the character. 5, processing precision information (add leading 0) for i > 0 && prec > Len (buf)-i {i--buf[i] = ' 0 '}//6, processing prefix: 0x, 0, etc. if f.sharp {switch base { Case 8:if buf[i]! = ' 0 ' {i--buf[i] = ' 0 '}case 16://based on the parameter digits to determine the capitalization: 0x, 0xi--buf[i] = digits[16]i--buf[i] = ' 0 '}}//7, Handler Number bit if negative {i--Buf[i] = '-'} else if f.plus {i--buf[i] = ' + '} else if f.space {i--buf[i] = '}//8, processing width information (padding spaces) Oldzero: = F.zerof.zero = Falsef.pad (buf[i:]) F.zero = oldzero}//truncates the string to the specified precision func (f *fmt) truncate (s string) string {if f.precpresent {n: = F.PRECF or I: = range S {n--if N < 0 {return S[:i]}}}return s}//writes data to buffer (string: processing width and precision information) func (f *fmt) fmt_s (s string) {s = f.tr Uncate (s) f.padstring (s)}//writes data to buffer (string/byte slice: hexadecimal format) func (f *fmt) FMT_SBX (s string, b []byte, digits string) {//1, calculated result length Gets the string or byte slice length to be processed long: = Len (b) if b = = Nil {length = Len (s)}//only handles content within the accuracy range if f.precpresent && F.prec < Leng th {length = f.prec}//each element (bytes) requires 2 bytes to store its hexadecimal encoding. Width: = 2 * Lengthif width > 0 {if f.space {//elements have spaces between them, so you need to add 0x or 0X before each element.  The hexadecimal encoding of each element is exactly 2 bytes, so multiply by 2,//Just 2 bytes more space per element to hold 0x or 0Xif f.sharp {width *= 2}//each element will be separated by a space width + = length- 1} else if F.sharp {//elements have no spaces between them, simply add a 0x or 0X at the beginning. width + = 2}} else {//element is empty, only spaces are filled with widths, for example: FMT. Printf ("%8x", "") if F.widpresent {F.WRItepadding (F.wid)}return}//2, processing "left" width information if f.widpresent && f.wid > Width &&!f.minus {f.writepadding ( F.wid-width)}//3, start encoding buf: = *f.buf//Add a leading 0x or 0X before the first element. If F.sharp {buf = append (buf, ' 0 ', digits[16])}//traverse individual elements (bytes) var c bytefor I: = 0; i < length; Add spaces between i++ {//elements, preceded by 0x or 0X for each element. If F.space && i > 0 {buf = append (buf, ") if F.sharp {buf = append (buf, ' 0 ', digits[16])}}//encode the current element if b! = Nil {c = B[i]} else {c = s[i]}buf = Append (buf, digits[c>>4], digits[c&0xf])}//because of append operation, the buffer may be extended *f.buf = b uf//4, handle "right" width information if f.widpresent && f.wid > Width && f.minus {f.writepadding (f.wid-width)}}//write data to buffer (string: Hex format) func (f *fmt) fmt_sx (s, digits string) {F.FMT_SBX (s, nil, digits)}//writes data to buffer (byte slice: hexadecimal format) func (f *fmt) fmt_bx (b []byte, digits string) {F.FMT_SBX ("", b, digits)}//writes data to buffer (string: With double quotes, not escaped)//If a # tag is specified and the string does not contain any control characters (except tab),//Returns an original string (with an inverted quotation mark). Func (f *fmt) Fmt_q (s string) {///1, processing precision information//truncates string to specified precision s = F.truncaTE (s)//2, start encode//Process # if F.sharp && StrConv. Canbackquote (s) {f.padstring ("'" + S + "'") return}//temporary buffer, storing temporary encoding result buf: = f.intbuf[:0]//encoding and processing width information if F.plus {//non-ASCII characters will be converted to Unicode code point F.pad (StrConv. Appendquotetoascii (buf, s))} else {//non-ASCII characters will output normally f.pad (StrConv. Appendquote (buf, s))}}//writes data to buffer (character)//If the character is not a valid Unicode encoding, write ' \ufffd ' func (f *fmt) Fmt_c (c UInt64) {r: = Rune (c)//exceeds Unicode range if C > UTF8. Maxrune {r = UTF8. runeerror}//temporary buffer buf: = f.intbuf[:0]//encode r w: = UTF8. Encoderune (Buf[:utf8. Utfmax], R)//writes the encoded result to the buffer F.pad (Buf[:w])}//writes the data to the buffer (character: with single quotation marks, not escaped)//writes ' \UFFFD ' func (f *fmt) If the character is not a valid Unicode encoding FMT_QC (c UInt64) {r: = Rune (c)//exceeds the Unicode range if C > UTF8. Maxrune {r = UTF8. runeerror}//temporary buffer buf: = f.intbuf[:0]//encode and process width information if F.plus {//non-ASCII characters will be converted to Unicode code point F.pad (StrConv. Appendquoterunetoascii (BUF, R))} else {//non-ASCII characters will be output f.pad normally (StrConv. Appendquoterune (BUF, R))}}//writes data to buffer (float64)//If the verb provided by the argument is a valid format delimiter, it can be in StrConv. Appendfloat in//converts it to a byte type incoming.Func (f *fmt) fmt_float (v float64, size int, verb rune, Prec int) {///1, Start encoding//"placeholder" in precision overrides the default precision in the parameter if F.precpresent {PREC = f.prec}//formatted numeric value, the result is written to a temporary buffer, and a space is reserved for the + number num: = StrConv. Appendfloat (F.intbuf[:1], V, byte (verb), prec, size)//2, processing symbol//If the conversion result is signed, remove the reserved space, otherwise the reserved space will be converted to + if num[1] = = '-' | | NUM[1] = = ' + ' {num = num[1:]} else {num[0] = ' + '}//if a space tag is specified and the + tag is not specified, the + is changed to a space. If F.space && num[0] = = ' + ' &&!f.plus {num[0] = '}//3, handling infinity and non-numbers//It does not look like a number, so it should not be filled with 0. If num[1] = = ' I ' | | NUM[1] = = ' N ' {oldzero: = F.zerof.zero = false//If no symbol is specified, remove the preceding symbol if num[1] = = ' N ' &&!f.space &&!f. Plus {num = num[1:]}f.pad (num) F.zero = oldzeroreturn}//4, after processing the fill write f.buf//specified + number | | The + sign is not specified and the result is not preceded by +. If F.plus | | NUM[0]! = ' + ' {//if left padding with 0, then we want the symbol to be in front of all 0. If F.zero && f.widpresent && f.wid > Len (num) {f.buf.writebyte (num[0])//write symbol f.writepadding (f . Wid-len (num))//Fill F.buf.write (num[1:])//write to the content other than the symbol Return}f.pad (NUM) return}//does not specify a + number, but the result is the + sign minus the + number. F.pad (num[1:])}

Standard library-fmt/format.go interpretation

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.