+/*
+syncer -- stateful file/device data syncer.
+Copyright (C) 2015-2016 Sergey Matveev <stargrave@stargrave.org>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+package main
+
+import (
+ "fmt"
+ "strconv"
+)
+
+const (
+ BufLine = 80
+ CharChanged = byte('%')
+ CharUnchanged = byte('.')
+)
+
+type Printer struct {
+ i int64
+ total int64
+ changed int64
+ frmt string
+ bufSize int
+ outBuf []byte
+}
+
+func NewPrinter(total int64) *Printer {
+ p := Printer{total: total}
+ maxLen := len(fmt.Sprintf("%d", total))
+ p.frmt = "%" + strconv.Itoa(maxLen) + "d/%d %02d%% %s\n"
+ p.bufSize = BufLine - (2*maxLen + 6)
+ p.outBuf = make([]byte, 0, p.bufSize)
+ return &p
+}
+
+func (p *Printer) Changed() {
+ p.i++
+ p.changed++
+ p.outBuf = append(p.outBuf, CharChanged)
+ p.Output()
+}
+
+func (p *Printer) Unchanged() {
+ p.i++
+ p.outBuf = append(p.outBuf, CharUnchanged)
+ p.Output()
+}
+
+func (p *Printer) Output() {
+ if !(len(p.outBuf) == p.bufSize || p.i == p.total) {
+ return
+ }
+ fmt.Printf(p.frmt, p.i, p.total, 100*p.changed/p.i, string(p.outBuf))
+ p.outBuf = p.outBuf[:0]
+}