Skip to content

Commit

Permalink
right/left pad
Browse files Browse the repository at this point in the history
  • Loading branch information
Rhymond committed Jul 18, 2017
1 parent 017a937 commit ce32d30
Show file tree
Hide file tree
Showing 5 changed files with 216 additions and 139 deletions.
23 changes: 15 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
# Go Left Pad
String left pad
# Go Pad
Optimized String Right/Left Pad

[![Go Report Card](https://goreportcard.com/badge/github.com/rhymond/go-left)](https://goreportcard.com/report/github.com/rhymond/go-left)
[![Coverage Status](https://coveralls.io/repos/github/Rhymond/go-money/badge.svg?branch=master)](https://coveralls.io/github/Rhymond/go-left?branch=master)
[![Build Status](https://travis-ci.org/Rhymond/go-money.svg?branch=master)](https://travis-ci.org/Rhymond/go-left)
[![GoDoc](https://godoc.org/github.com/Rhymond/go-money?status.svg)](https://godoc.org/github.com/Rhymond/go-left)
[![Go Report Card](https://goreportcard.com/badge/github.com/rhymond/gopad)](https://goreportcard.com/report/github.com/rhymond/gopad)
[![Coverage Status](https://coveralls.io/repos/github/Rhymond/go-money/badge.svg?branch=master)](https://coveralls.io/github/Rhymond/gopad?branch=master)
[![Build Status](https://travis-ci.org/Rhymond/go-money.svg?branch=master)](https://travis-ci.org/Rhymond/gopad)
[![GoDoc](https://godoc.org/github.com/Rhymond/go-money?status.svg)](https://godoc.org/github.com/Rhymond/gopad)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

Usage
-
```Go
import "github.com/rhymond/gopad"


gopad.Left("foo", 5) // " foo"
gopad.Right("foobar", 8) // "foobar "
gopad.Left("foobar", 6) // "foobar"
```
Contributing
-
Thank you for considering contributing!
Expand All @@ -18,4 +25,4 @@ License
-
The MIT License (MIT). Please see License File for more information.

[![forthebadge](http://forthebadge.com/images/badges/built-with-love.svg)](https://github.com/Rhymond/go-left)
[![forthebadge](http://forthebadge.com/images/badges/built-with-love.svg)](https://github.com/Rhymond/gopad)
39 changes: 0 additions & 39 deletions goleft.go

This file was deleted.

92 changes: 0 additions & 92 deletions goleft_test.go

This file was deleted.

61 changes: 61 additions & 0 deletions gopad.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package gopad

import (
"bytes"
"unicode/utf8"
)

var cache = []string{"", " ", " ", " ", " ", " ", " ", " ", " ", " "}

// pad pads out a string
// it uses given rune slice with
// first value or space by default for filling a space
// it has caching for common use cases
// and buffer for quicker concatenation
func pad(s string, l int, ch []rune, di bool) string {
l = l - utf8.RuneCountInString(s)

if l <= 0 {
return s
}

c := ' '
if len(ch) > 0 {
c = ch[0]
}

// Use cache if possible
if c == ' ' && l < 10 {
if di {
return s + cache[l]
}

return cache[l] + s
}

var b bytes.Buffer

if di {
b.WriteString(s)
}

for ; l != 0; l-- {
b.WriteRune(c)
}

if !di {
b.WriteString(s)
}

return b.String()
}

// Left pads out the lefthand-side of strings
func Left(s string, l int, ch ...rune) string {
return pad(s, l, ch, false)
}

// Right pads out the righthand-side of strings
func Right(s string, l int, ch ...rune) string {
return pad(s, l, ch, true)
}
140 changes: 140 additions & 0 deletions gopad_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
package gopad

import "testing"

func TestLeft(t *testing.T) {
ts := []struct {
s, expected string
}{
{Left("foobar", 6), "foobar"},
{Left("foobar", 5), "foobar"},
{Left("foobar", -1), "foobar"},
{Left("foobar", 6, '1'), "foobar"},
{Left("foobar", 5, '1'), "foobar"},
{Left("foobar", -1, '1'), "foobar"},
{Left("foobar", 8, ' '), " foobar"},
{Left("foobar", 8, '0'), "00foobar"},
{Left("0", 3, '1'), "110"},
{Left("true", 7), " true"},
{Left("", 2), " "},
{Left("foo", 5), " foo"},
{Left("foobar", 6), "foobar"},
{Left("1", 2, '0'), "01"},
{Left("好吗", 3, '你'), "你好吗"},
{Left("好吗", 5, '你'), "你你你好吗"},
{Left("1", 19, '0'), "0000000000000000001"},
{Left("foo", 2), "foo"},
{Left("foo", 3), "foo"},
{Left("foo", 4), " foo"},
{Left("foo", 5), " foo"},
{Left("foo", 12), " foo"},
{Left("foo", 13), " foo"},
{Left("foo", 2, ' '), "foo"},
{Left("foo", 3, ' '), "foo"},
{Left("foo", 4, ' '), " foo"},
{Left("foo", 5, ' '), " foo"},
{Left("foo", 12, ' '), " foo"},
{Left("foo", 13, ' '), " foo"},
{Left("1", 2, '0'), "01"},
{Left("1", 2, '-'), "-1"},
{Left("foo", 4, '*'), "*foo"},
{Left("foo", 5, '*'), "**foo"},
{Left("foo", 6, '*'), "***foo"},
{Left("foo", 7, '*'), "****foo"},
{Left("foo", 103, '*'), "****************************************************************************************************foo"},
}
for _, v := range ts {
if v.expected != v.s {
t.Errorf("Expected %s, actual %s", v.expected, v.s)
}
}
}

func TestRight(t *testing.T) {
ts := []struct {
s, expected string
}{
{Right("foobar", 6), "foobar"},
{Right("foobar", 5), "foobar"},
{Right("foobar", -1), "foobar"},
{Right("foobar", 6, '1'), "foobar"},
{Right("foobar", 5, '1'), "foobar"},
{Right("foobar", -1, '1'), "foobar"},
{Right("foobar", 8, ' '), "foobar "},
{Right("foobar", 8, '0'), "foobar00"},
{Right("0", 3, '1'), "011"},
{Right("true", 7), "true "},
{Right("", 2), " "},
{Right("foo", 5), "foo "},
{Right("foobar", 6), "foobar"},
{Right("1", 2, '0'), "10"},
{Right("好吗", 3, '你'), "好吗你"},
{Right("好吗", 5, '你'), "好吗你你你"},
{Right("1", 19, '0'), "1000000000000000000"},
{Right("foo", 2), "foo"},
{Right("foo", 3), "foo"},
{Right("foo", 4), "foo "},
{Right("foo", 5), "foo "},
{Right("foo", 12), "foo "},
{Right("foo", 13), "foo "},
{Right("foo", 2, ' '), "foo"},
{Right("foo", 3, ' '), "foo"},
{Right("foo", 4, ' '), "foo "},
{Right("foo", 5, ' '), "foo "},
{Right("foo", 12, ' '), "foo "},
{Right("foo", 13, ' '), "foo "},
{Right("1", 2, '0'), "10"},
{Right("1", 2, '-'), "1-"},
{Right("foo", 4, '*'), "foo*"},
{Right("foo", 5, '*'), "foo**"},
{Right("foo", 6, '*'), "foo***"},
{Right("foo", 7, '*'), "foo****"},
{Right("foo", 103, '*'), "foo****************************************************************************************************"},
}
for _, v := range ts {
if v.expected != v.s {
t.Errorf("Expected %s, actual %s", v.expected, v.s)
}
}
}

func BenchmarkPad(b *testing.B) {
for n := 0; n < b.N; n++ {
pad("foobar", 6, []rune{' '}, false)
pad("foobar", 5, []rune{' '}, true)
pad("foobar", -1, []rune{' '}, false)
pad("foobar", 6, []rune{'1'}, true)
pad("foobar", 5, []rune{'1'}, false)
pad("foobar", -1, []rune{' '}, true)
pad("foobar", 8, []rune{' '}, false)
pad("foobar", 8, []rune{'0'}, true)
pad("0", 3, []rune{'1'}, false)
pad("true", 7, []rune{' '}, true)
pad("", 2, []rune{' '}, false)
pad("foo", 5, []rune{' '}, true)
pad("foobar", 6, []rune{' '}, false)
pad("1", 2, []rune{'0'}, true)
// pad("好吗", 3, []rune{'你'}, false)
// pad("好吗", 5, []rune{'你'}, true)
pad("1", 19, []rune{'0'}, false)
pad("foo", 2, []rune{'0'}, true)
pad("foo", 3, []rune{' '}, false)
pad("foo", 4, []rune{' '}, true)
pad("foo", 5, []rune{' '}, false)
pad("foo", 12, []rune{' '}, true)
pad("foo", 13, []rune{' '}, false)
pad("foo", 2, []rune{' '}, true)
pad("foo", 3, []rune{' '}, false)
pad("foo", 4, []rune{' '}, true)
pad("foo", 5, []rune{' '}, false)
pad("foo", 12, []rune{' '}, true)
pad("foo", 13, []rune{' '}, false)
pad("1", 2, []rune{'0'}, true)
pad("1", 2, []rune{'-'}, false)
pad("foo", 4, []rune{'*'}, true)
pad("foo", 5, []rune{'*'}, false)
pad("foo", 6, []rune{'*'}, true)
pad("foo", 7, []rune{'*'}, false)
pad("foo", 103, []rune{'*'}, true)
}
}

0 comments on commit ce32d30

Please sign in to comment.