github.com/mitranim/gg@v0.1.17/buf.go (about)

     1  package gg
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"strconv"
     7  	"unicode/utf8"
     8  )
     9  
    10  /*
    11  Short for "buffer". Simpler, cleaner, more usable alternative to
    12  `strings.Builder` and `bytes.Buffer`.
    13  */
    14  type Buf []byte
    15  
    16  var (
    17  	_ = fmt.Stringer(Zero[Buf]())
    18  	_ = AppenderTo(Zero[Buf]())
    19  	_ = io.Writer(Zero[*Buf]())
    20  	_ = io.StringWriter(Zero[*Buf]())
    21  )
    22  
    23  /*
    24  Free cast to a string. Mutation of the original buffer affects the resulting
    25  string.
    26  */
    27  func (self Buf) String() string { return ToString(self) }
    28  
    29  /*
    30  Implement `AppenderTo`. Appends its own content to the given buffer.
    31  If the given buffer has no capacity, returns itself.
    32  */
    33  func (self Buf) AppendTo(val []byte) []byte {
    34  	if !(cap(val) > 0) {
    35  		return self
    36  	}
    37  	return append(val, self...)
    38  }
    39  
    40  /*
    41  Implement `io.StringWriter`, appending the input to the buffer.
    42  The error is always nil and may be ignored.
    43  */
    44  func (self *Buf) WriteString(val string) (int, error) {
    45  	*self = append(*self, val...)
    46  	return len(val), nil
    47  }
    48  
    49  /*
    50  Implement `io.Writer`, appending the input to the buffer.
    51  The error is always nil and may be ignored.
    52  */
    53  func (self *Buf) Write(val []byte) (int, error) {
    54  	*self = append(*self, val...)
    55  	return len(val), nil
    56  }
    57  
    58  // Appends the given string. Mutates the receiver.
    59  func (self *Buf) AppendString(val string) { *self = append(*self, val...) }
    60  
    61  // Appends the given string N times. Mutates the receiver.
    62  func (self *Buf) AppendStringN(val string, count int) {
    63  	if len(val) > 0 {
    64  		for count > 0 {
    65  			count--
    66  			self.AppendString(val)
    67  		}
    68  	}
    69  }
    70  
    71  // Appends `Indent`. Mutates the receiver.
    72  func (self *Buf) AppendIndent() { self.AppendString(Indent) }
    73  
    74  // Appends `Indent` N times. Mutates the receiver.
    75  func (self *Buf) AppendIndents(lvl int) { self.AppendStringN(Indent, lvl) }
    76  
    77  // Appends the given bytes. Mutates the receiver.
    78  func (self *Buf) AppendBytes(val []byte) { *self = append(*self, val...) }
    79  
    80  // Appends the given byte. Mutates the receiver.
    81  func (self *Buf) AppendByte(val byte) { *self = append(*self, val) }
    82  
    83  // Appends the given rune. Mutates the receiver.
    84  func (self *Buf) AppendRune(val rune) { *self = utf8.AppendRune(*self, val) }
    85  
    86  // Appends the given rune N times. Mutates the receiver.
    87  func (self *Buf) AppendRuneN(val rune, count int) {
    88  	for count > 0 {
    89  		count--
    90  		self.AppendRune(val)
    91  	}
    92  }
    93  
    94  // Appends a single space. Mutates the receiver.
    95  func (self *Buf) AppendSpace() { self.AppendByte(' ') }
    96  
    97  // Appends a space N times. Mutates the receiver.
    98  func (self *Buf) AppendSpaces(count int) { self.AppendByteN(' ', count) }
    99  
   100  // Appends the given byte N times. Mutates the receiver.
   101  func (self *Buf) AppendByteN(val byte, count int) {
   102  	for count > 0 {
   103  		count--
   104  		self.AppendByte(val)
   105  	}
   106  }
   107  
   108  // Appends `Newline`. Mutates the receiver.
   109  func (self *Buf) AppendNewline() { self.AppendString(Newline) }
   110  
   111  /*
   112  If the buffer is non-empty and doesn't end with a newline, appends a newline.
   113  Otherwise does nothing. Uses `HasNewlineSuffix`. Mutates the receiver.
   114  */
   115  func (self *Buf) AppendNewlineOpt() {
   116  	if self.Len() > 0 && !HasNewlineSuffix(*self) {
   117  		self.AppendNewline()
   118  	}
   119  }
   120  
   121  // Appends `Newline` N times. Mutates the receiver.
   122  func (self *Buf) AppendNewlines(count int) { self.AppendStringN(Newline, count) }
   123  
   124  /*
   125  Appends text representation of the numeric value of the given byte in base 16.
   126  Always uses exactly 2 characters, for consistent width, which is the common
   127  convention for printing binary data. Mutates the receiver.
   128  */
   129  func (self *Buf) AppendByteHex(val byte) {
   130  	if val < 16 {
   131  		self.AppendByte('0')
   132  	}
   133  	*self = strconv.AppendUint(*self, uint64(val), 16)
   134  }
   135  
   136  // Appends text representation of the input. Mutates the receiver.
   137  func (self *Buf) AppendUint(val uint) {
   138  	*self = strconv.AppendUint(*self, uint64(val), 10)
   139  }
   140  
   141  // Appends text representation of the input. Mutates the receiver.
   142  func (self *Buf) AppendUint64(val uint64) {
   143  	*self = strconv.AppendUint(*self, val, 10)
   144  }
   145  
   146  /*
   147  Appends text representation of the input in base 16. Mutates the receiver.
   148  Also see `.AppendByteHex`.
   149  */
   150  func (self *Buf) AppendUint64Hex(val uint64) {
   151  	*self = strconv.AppendUint(*self, val, 16)
   152  }
   153  
   154  // Appends text representation of the input. Mutates the receiver.
   155  func (self *Buf) AppendInt(val int) {
   156  	*self = strconv.AppendInt(*self, int64(val), 10)
   157  }
   158  
   159  // Appends text representation of the input. Mutates the receiver.
   160  func (self *Buf) AppendInt64(val int64) {
   161  	*self = strconv.AppendInt(*self, val, 10)
   162  }
   163  
   164  // Appends text representation of the input. Mutates the receiver.
   165  func (self *Buf) AppendFloat32(val float32) {
   166  	*self = strconv.AppendFloat(*self, float64(val), 'f', -1, 32)
   167  }
   168  
   169  // Appends text representation of the input. Mutates the receiver.
   170  func (self *Buf) AppendFloat64(val float64) {
   171  	*self = strconv.AppendFloat(*self, val, 'f', -1, 64)
   172  }
   173  
   174  // Appends text representation of the input. Mutates the receiver.
   175  func (self *Buf) AppendBool(val bool) { *self = strconv.AppendBool(*self, val) }
   176  
   177  /*
   178  Appends the string representation of the given error. If the input is nil, this
   179  is a nop. Mutates the receiver.
   180  */
   181  func (self *Buf) AppendError(val error) {
   182  	if val == nil {
   183  		return
   184  	}
   185  
   186  	impl, _ := val.(AppenderTo)
   187  	if impl != nil {
   188  		*self = impl.AppendTo(*self)
   189  		return
   190  	}
   191  
   192  	self.AppendString(val.Error())
   193  }
   194  
   195  /*
   196  Appends the text representation of the input, using the `AppendTo` function.
   197  Mutates the receiver.
   198  */
   199  func (self *Buf) AppendAny(val any) { *self = AppendTo(*self, val) }
   200  
   201  // Like `(*Buf).AppendAny` but variadic. TODO better name.
   202  func (self *Buf) AppendAnys(val ...any) {
   203  	for _, val := range val {
   204  		self.AppendAny(val)
   205  	}
   206  }
   207  
   208  /*
   209  Like `(*Buf).AppendAnys` but ensures a trailing newline in the appended content,
   210  similarly to `fmt.Println`. As a special case, if the buffer was empty and the
   211  appended content is empty, no newline is appended. TODO better name.
   212  */
   213  func (self *Buf) AppendAnysln(val ...any) {
   214  	start := self.Len()
   215  	self.AppendAnys(val...)
   216  	end := self.Len()
   217  
   218  	if end > start {
   219  		self.AppendNewlineOpt()
   220  	} else if end > 0 {
   221  		self.AppendNewline()
   222  	}
   223  }
   224  
   225  /*
   226  Appends the text representation of the input, using the `AppendGoString`
   227  function. Mutates the receiver.
   228  */
   229  func (self *Buf) AppendGoString(val any) { *self = AppendGoString(*self, val) }
   230  
   231  // Shortcut for appending a formatted string.
   232  func (self *Buf) Fprintf(pat string, arg ...any) {
   233  	_, _ = fmt.Fprintf(self, pat, NoEscUnsafe(arg)...)
   234  }
   235  
   236  // Shortcut for appending a formatted string with an idempotent trailing newline.
   237  func (self *Buf) Fprintlnf(pat string, arg ...any) {
   238  	prev := self.Len()
   239  	self.Fprintf(pat, arg...)
   240  	if self.Len() > prev {
   241  		self.AppendNewlineOpt()
   242  	}
   243  }
   244  
   245  // Same as `len(buf)`.
   246  func (self Buf) Len() int { return len(self) }
   247  
   248  // Replaces the buffer with the given slice.
   249  func (self *Buf) Reset(src []byte) { *self = src }
   250  
   251  // Increases the buffer's length by N zero values. Mutates the receiver.
   252  func (self *Buf) GrowLen(size int) { *self = GrowLen(*self, size) }
   253  
   254  /*
   255  Increases the buffer's capacity sufficiently to accommodate N additional
   256  elements. Mutates the receiver.
   257  */
   258  func (self *Buf) GrowCap(size int) { *self = GrowCap(*self, size) }
   259  
   260  /*
   261  Reduces the current length to the given size. If the current length is already
   262  shorter, it's unaffected.
   263  */
   264  func (self *Buf) TruncLen(size int) { *self = TruncLen(*self, size) }
   265  
   266  /*
   267  Truncates the buffer's length, preserving the capacity. Does not modify the
   268  content. Mutates the receiver.
   269  */
   270  func (self *Buf) Clear() {
   271  	if self != nil {
   272  		*self = (*self)[:0]
   273  	}
   274  }