Skip to content

Commit

Permalink
Reuse buffer for default encoder
Browse files Browse the repository at this point in the history
  • Loading branch information
nineinchnick committed Mar 21, 2021
1 parent e5792f9 commit d46de1d
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 34 deletions.
37 changes: 22 additions & 15 deletions encode.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package tblfmt

import (
"bufio"
"bytes"
"encoding/csv"
"encoding/json"
"fmt"
Expand Down Expand Up @@ -39,6 +40,9 @@ type TableEncoder struct {
// lineStyle is the table line style.
lineStyle LineStyle

// rowStyles is the table of row style.
rowStyles map[[4]rune]rowStyle

// formatter handles formatting values prior to output.
formatter Formatter

Expand Down Expand Up @@ -94,6 +98,7 @@ func NewTableEncoder(resultSet ResultSet, opts ...Option) (Encoder, error) {
border: 1,
tab: 8,
lineStyle: ASCIILineStyle(),
rowStyles: make(map[[4]rune]rowStyle),
formatter: NewEscapeFormatter(WithHeaderAlign(AlignCenter)),
summary: DefaultTableSummary(),
empty: &Value{
Expand All @@ -117,6 +122,7 @@ func NewTableEncoder(resultSet ResultSet, opts ...Option) (Encoder, error) {
enc.lineStyle.Wrap,
enc.lineStyle.End,
} {
enc.rowStyles[l] = enc.rowStyle(l)
for _, r := range l {
if r != 0 && runewidth.RuneWidth(r) != 1 {
return nil, ErrInvalidLineStyle
Expand Down Expand Up @@ -214,7 +220,7 @@ func (enc *TableEncoder) Encode(w io.Writer) error {

// draw end border
if enc.border >= 2 {
enc.divider(enc.rowStyle(enc.lineStyle.End))
enc.divider(enc.rowStyles[enc.lineStyle.End])
}
}

Expand All @@ -239,7 +245,7 @@ func (enc *TableEncoder) initBuffers() {
}

func (enc *TableEncoder) encodeVals(vals [][]*Value) error {
rs := enc.rowStyle(enc.lineStyle.Row)
rs := enc.rowStyles[enc.lineStyle.Row]
// print buffered vals
for i := 0; i < len(vals); i++ {
enc.row(vals[i], rs)
Expand Down Expand Up @@ -308,7 +314,7 @@ func (enc *TableEncoder) nextResults() ([][]*Value, error) {
func (enc *TableEncoder) calcWidth(vals [][]*Value) {
// calc offsets and widths for this batch of rows
var offset int
rs := enc.rowStyle(enc.lineStyle.Row)
rs := enc.rowStyles[enc.lineStyle.Row]
offset += runewidth.StringWidth(string(rs.left))
for i, h := range enc.headers {
if i != 0 {
Expand Down Expand Up @@ -339,7 +345,7 @@ func (enc *TableEncoder) calcWidth(vals [][]*Value) {
}

func (enc *TableEncoder) header() {
rs := enc.rowStyle(enc.lineStyle.Row)
rs := enc.rowStyles[enc.lineStyle.Row]

if enc.title != nil && enc.title.Width != 0 {
maxWidth := ((enc.tableWidth() - enc.title.Width) / 2) + enc.title.Width
Expand All @@ -348,20 +354,20 @@ func (enc *TableEncoder) header() {
}
// draw top border
if enc.border >= 2 && !enc.inline {
enc.divider(enc.rowStyle(enc.lineStyle.Top))
enc.divider(enc.rowStyles[enc.lineStyle.Top])
}

// draw the header row with top border style
if enc.inline {
rs = enc.rowStyle(enc.lineStyle.Top)
rs = enc.rowStyles[enc.lineStyle.Top]
}

// write header
enc.row(enc.headers, rs)

if !enc.inline {
// draw mid divider
enc.divider(enc.rowStyle(enc.lineStyle.Mid))
enc.divider(enc.rowStyles[enc.lineStyle.Mid])
}
}

Expand Down Expand Up @@ -400,14 +406,15 @@ func (enc TableEncoder) rowStyle(r [4]rune) rowStyle {
middle = string(r[2]) + spacer
}

return rowStyle{
rs := rowStyle{
left: []byte(left),
wrapper: []byte(string(enc.lineStyle.Wrap[1])),
middle: []byte(middle),
right: []byte(right + string(enc.newline)),
filler: []byte(filler),
filler: bytes.Repeat([]byte(filler), 8)[:len(filler)],
hasWrapping: runewidth.RuneWidth(enc.lineStyle.Row[1]) > 0,
}
return rs
}

// scanAndFormat scans and formats values from the result set.
Expand Down Expand Up @@ -449,7 +456,7 @@ func (enc *TableEncoder) divider(rs rowStyle) {

// tableWidth calculates total table width.
func (enc *TableEncoder) tableWidth() int {
rs := enc.rowStyle(enc.lineStyle.Mid)
rs := enc.rowStyles[enc.lineStyle.Mid]
width := runewidth.StringWidth(string(rs.left)) + runewidth.StringWidth(string(rs.right))

for i, w := range enc.maxWidths {
Expand Down Expand Up @@ -682,7 +689,7 @@ func (enc *ExpandedEncoder) Encode(w io.Writer) error {
}

func (enc *ExpandedEncoder) encodeVals(vals [][]*Value) error {
rs := enc.rowStyle(enc.lineStyle.Row)
rs := enc.rowStyles[enc.lineStyle.Row]
// print buffered vals
for i := 0; i < len(vals); i++ {
enc.record(i, vals[i], rs)
Expand All @@ -701,7 +708,7 @@ func (enc *ExpandedEncoder) encodeVals(vals [][]*Value) error {

// draw end border
if enc.border >= 2 && enc.scanCount != 0 {
enc.divider(enc.rowStyle(enc.lineStyle.End))
enc.divider(enc.rowStyles[enc.lineStyle.End])
}
return nil
}
Expand Down Expand Up @@ -732,7 +739,7 @@ func (enc *ExpandedEncoder) EncodeAll(w io.Writer) error {
}

func (enc *ExpandedEncoder) calcWidth(vals [][]*Value) {
rs := enc.rowStyle(enc.lineStyle.Row)
rs := enc.rowStyles[enc.lineStyle.Row]

offset := runewidth.StringWidth(string(rs.left))

Expand Down Expand Up @@ -770,9 +777,9 @@ func (enc *ExpandedEncoder) record(i int, vals []*Value, rs rowStyle) {
headerRS := rs
header := enc.recordHeader(i)
if enc.border != 0 {
headerRS = enc.rowStyle(enc.lineStyle.Top)
headerRS = enc.rowStyles[enc.lineStyle.Top]
if i != 0 {
headerRS = enc.rowStyle(enc.lineStyle.Mid)
headerRS = enc.rowStyles[enc.lineStyle.Mid]
}
}

Expand Down
27 changes: 16 additions & 11 deletions fmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ type EscapeFormatter struct {
// If nil, the standard encoding/json.Encoder will be used instead.
marshaler func(interface{}) ([]byte, error)

defaultMarshaler *json.Encoder
defaultMarshalerBuffer *bytes.Buffer

// prefix is indent prefix used by the JSON encoder when Marshaler is nil.
prefix string

Expand Down Expand Up @@ -79,11 +82,15 @@ type EscapeFormatter struct {
// values.
func NewEscapeFormatter(opts ...EscapeFormatterOption) *EscapeFormatter {
f := &EscapeFormatter{
mask: "%d",
timeFormat: time.RFC3339Nano,
indent: " ",
valuesPool: newValuesPool(),
mask: "%d",
timeFormat: time.RFC3339Nano,
indent: " ",
valuesPool: newValuesPool(),
defaultMarshalerBuffer: new(bytes.Buffer),
}
f.defaultMarshaler = json.NewEncoder(f.defaultMarshalerBuffer)
f.defaultMarshaler.SetIndent(f.prefix, f.indent)
f.defaultMarshaler.SetEscapeHTML(f.escapeHTML)
f.Configure(opts...)
return f
}
Expand Down Expand Up @@ -288,17 +295,15 @@ func (f *EscapeFormatter) Format(vals []interface{}) ([]*Value, error) {
res[i] = f.valuesPool.newRaw(buf)
} else {
// json encode
buf := new(bytes.Buffer)
enc := json.NewEncoder(buf)
enc.SetIndent(f.prefix, f.indent)
enc.SetEscapeHTML(f.escapeHTML)
if err := enc.Encode(v); err != nil {
// TODO reuse buffer and reset it before every use
f.defaultMarshalerBuffer.Reset()
if err := f.defaultMarshaler.Encode(v); err != nil {
return nil, err
}
if f.escapeJSON {
res[i] = f.valuesPool.newRaw(bytes.TrimSpace(buf.Bytes()))
res[i] = f.valuesPool.newRaw(bytes.TrimSpace(f.defaultMarshalerBuffer.Bytes()))
} else {
res[i] = f.valuesPool.formatBytes(bytes.TrimSpace(buf.Bytes()), f.invalid, f.invalidWidth, false)
res[i] = f.valuesPool.formatBytes(bytes.TrimSpace(f.defaultMarshalerBuffer.Bytes()), f.invalid, f.invalidWidth, false)
res[i].Raw = true
}
}
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module github.com/xo/tblfmt

require (
github.com/mattn/go-runewidth v0.0.9
github.com/mattn/go-runewidth v0.0.10
github.com/nathan-fiscaletti/consolesize-go v0.0.0-20210105204122-a87d9f614b9d
)

Expand Down
6 changes: 4 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.10 h1:CoZ3S2P7pvtP45xOtBw+/mDL2z0RKI576gSkzRRpdGg=
github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
github.com/nathan-fiscaletti/consolesize-go v0.0.0-20210105204122-a87d9f614b9d h1:PQW4Aqovdqc9efHl9EVA+bhKmuZ4ME1HvSYYDvaDiK0=
github.com/nathan-fiscaletti/consolesize-go v0.0.0-20210105204122-a87d9f614b9d/go.mod h1:cxIIfNMTwff8f/ZvRouvWYF6wOoO7nj99neWSx2q/Es=
github.com/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY=
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
10 changes: 5 additions & 5 deletions util.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,10 +114,10 @@ func repeat(w io.Writer, b []byte, c int) []byte {
w.Write(b[:c])
return b
}
nb := b[:cap(b)]
for len(nb) < c {
nb = append(nb, nb...)
b = b[:cap(b)]
for len(b) < c {
b = append(b, b...)
}
w.Write(nb[:c])
return nb[:len(b)]
w.Write(b[:c])
return b[:1]
}

0 comments on commit d46de1d

Please sign in to comment.