aboutsummaryrefslogtreecommitdiff
path: root/lib/bytes
diff options
context:
space:
mode:
authorShulhan <ms@kilabit.info>2018-09-03 22:27:44 +0700
committerShulhan <ms@kilabit.info>2018-09-03 22:55:06 +0700
commitd3e6c2e902eb3a00c2dfdcde09bf35282ea63396 (patch)
tree63432c09e0dddb08942e7172f24666a811432bb5 /lib/bytes
parentaab053ef5c49bcc67f6de5477d9760ea4e3bf6ab (diff)
downloadpakakeh.go-d3e6c2e902eb3a00c2dfdcde09bf35282ea63396.tar.xz
Move all byte(s) related constant and functions from package text to bytes
Diffstat (limited to 'lib/bytes')
-rw-r--r--lib/bytes/bytes.go20
-rw-r--r--lib/bytes/bytes_test.go3
-rw-r--r--lib/bytes/is.go70
-rw-r--r--lib/bytes/json.go172
-rw-r--r--lib/bytes/random.go22
5 files changed, 284 insertions, 3 deletions
diff --git a/lib/bytes/bytes.go b/lib/bytes/bytes.go
index 549d82db..ad777180 100644
--- a/lib/bytes/bytes.go
+++ b/lib/bytes/bytes.go
@@ -2,13 +2,31 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Packages bytes contains common functions to manipulate slice of bytes.
+// Packages bytes provide a library for working with byte or slice of bytes.
package bytes
import (
"fmt"
)
+const (
+ // ASCIILetters contains list of lower and upper case characters in
+ // ASCII.
+ ASCIILetters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ // HexaLETTERS contains list of hexadecimal characters in upper cases.
+ HexaLETTERS = "0123456789ABCDEF"
+ // HexaLetters contains list of hexadecimal characters in lower and
+ // upper cases.
+ HexaLetters = "0123456789abcedfABCDEF"
+ // HexaLetters contains list of hexadecimal characters in lower cases.
+ Hexaletters = "0123456789abcedf"
+)
+
+var (
+ // ASCIISpaces contains list of white spaces in ASCII.
+ ASCIISpaces = []byte{'\t', '\n', '\v', '\f', '\r', ' '}
+)
+
//
// PrintHex will print each byte in slice as hexadecimal value into N column
// length.
diff --git a/lib/bytes/bytes_test.go b/lib/bytes/bytes_test.go
index d4fef2a6..50669c4f 100644
--- a/lib/bytes/bytes_test.go
+++ b/lib/bytes/bytes_test.go
@@ -5,7 +5,6 @@ import (
"testing"
"github.com/shuLhan/share/lib/test"
- libtext "github.com/shuLhan/share/lib/text"
)
func TestToLower(t *testing.T) {
@@ -35,7 +34,7 @@ func TestToLower(t *testing.T) {
}
}
-var randomInput256 = libtext.Random([]byte(libtext.HexaLetters), 256)
+var randomInput256 = Random([]byte(HexaLetters), 256)
func BenchmarkToLowerStd(b *testing.B) {
in := make([]byte, len(randomInput256))
diff --git a/lib/bytes/is.go b/lib/bytes/is.go
new file mode 100644
index 00000000..4ad06805
--- /dev/null
+++ b/lib/bytes/is.go
@@ -0,0 +1,70 @@
+// Copyright 2018, Shulhan <ms@kilabit.info>. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package bytes
+
+//
+// IsAlpha will return true if byte is ASCII alphabet character, otherwise
+// it will return false.
+//
+func IsAlpha(b byte) bool {
+ if (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') {
+ return true
+ }
+ return false
+}
+
+//
+// IsAlnum will return true if byte is ASCII alphanumeric character, otherwise
+// it will return false.
+//
+func IsAlnum(b byte) bool {
+ return IsAlpha(b) || IsDigit(b)
+}
+
+//
+// IsDigit will return true if byte is ASCII digit, otherwise it will return
+// false.
+//
+func IsDigit(b byte) bool {
+ if b >= '0' && b <= '9' {
+ return true
+ }
+ return false
+}
+
+//
+// IsDigits will return true if all bytes are ASCII digit, otherwise it will
+// return false.
+//
+func IsDigits(data []byte) bool {
+ for x := 0; x < len(data); x++ {
+ if !IsDigit(data[x]) {
+ return false
+ }
+ }
+ return true
+}
+
+//
+// IsHex will return true if byte is hexadecimal number, otherwise it will
+// return false.
+//
+func IsHex(b byte) bool {
+ if (b >= '1' && b <= '9') || (b >= 'a' && b <= 'f') || (b >= 'A' && b <= 'F') {
+ return true
+ }
+ return false
+}
+
+//
+// IsSpace will return true if byte is ASCII white spaces character,
+// otherwise it will return false.
+//
+func IsSpace(b byte) bool {
+ if b == '\t' || b == '\n' || b == '\v' || b == '\f' || b == '\r' || b == ' ' {
+ return true
+ }
+ return false
+}
diff --git a/lib/bytes/json.go b/lib/bytes/json.go
new file mode 100644
index 00000000..1a296a3b
--- /dev/null
+++ b/lib/bytes/json.go
@@ -0,0 +1,172 @@
+// Copyright 2018, Shulhan <ms@kilabit.info>. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package bytes
+
+import (
+ "bytes"
+ "fmt"
+ "strconv"
+)
+
+const (
+ errInvalidSyntax = "%s: invalid syntax at %d"
+)
+
+const (
+ bDoubleQuote = '"'
+ bRevSolidus = '\\'
+ bSolidus = '/'
+ bBackspace = '\b'
+ bFormFeed = '\f'
+ bLineFeed = '\n'
+ bCarReturn = '\r'
+ bTab = '\t'
+)
+
+//
+// JSONEscape escape the following character: `"` (quotation mark),
+// `\` (reverse solidus), `/` (solidus), `\b` (backspace), `\f` (formfeed),
+// `\n` (newline), `\r` (carriage return`), `\t` (horizontal tab), and control
+// character from 0 - 31.
+//
+// References:
+//
+// * https://tools.ietf.org/html/rfc7159#page-8
+//
+func JSONEscape(in []byte) []byte {
+ var buf bytes.Buffer
+
+ for x := 0; x < len(in); x++ {
+ if in[x] == bDoubleQuote || in[x] == bRevSolidus || in[x] == bSolidus {
+ buf.WriteByte(bRevSolidus)
+ buf.WriteByte(in[x])
+ continue
+ }
+ if in[x] == bBackspace {
+ buf.WriteByte(bRevSolidus)
+ buf.WriteByte('b')
+ continue
+ }
+ if in[x] == bFormFeed {
+ buf.WriteByte(bRevSolidus)
+ buf.WriteByte('f')
+ continue
+ }
+ if in[x] == bLineFeed {
+ buf.WriteByte(bRevSolidus)
+ buf.WriteByte('n')
+ continue
+ }
+ if in[x] == bCarReturn {
+ buf.WriteByte(bRevSolidus)
+ buf.WriteByte('r')
+ continue
+ }
+ if in[x] == bTab {
+ buf.WriteByte(bRevSolidus)
+ buf.WriteByte('t')
+ continue
+ }
+ if in[x] <= 31 {
+ buf.WriteString(fmt.Sprintf("\\u%04X", in[x]))
+ continue
+ }
+
+ buf.WriteByte(in[x])
+ }
+
+ return buf.Bytes()
+}
+
+//
+// JSONUnescape unescape JSON bytes, reversing what BytesJSONEscape do.
+//
+// If strict is true, any unknown control character will be returned as error.
+// For example, in string "\x", "x" is not valid control character, and the
+// function will return empty string and error.
+// If strict is false, it will return "x".
+//
+func JSONUnescape(in []byte, strict bool) ([]byte, error) {
+ var (
+ buf bytes.Buffer
+ uni bytes.Buffer
+ esc bool
+ )
+
+ for x := 0; x < len(in); x++ {
+ if esc {
+ if in[x] == 'u' {
+ uni.Reset()
+ x++
+
+ for y := 0; y < 4 && x < len(in); x++ {
+ uni.WriteByte(in[x])
+ y++
+ }
+
+ dec, err := strconv.ParseUint(uni.String(), 16, 32)
+ if err != nil {
+ return nil, err
+ }
+
+ if dec <= 31 {
+ buf.WriteByte(byte(dec))
+ } else {
+ buf.WriteRune(rune(dec))
+ }
+
+ esc = false
+ x--
+ continue
+ }
+ if in[x] == 't' {
+ buf.WriteByte(bTab)
+ esc = false
+ continue
+ }
+ if in[x] == 'r' {
+ buf.WriteByte(bCarReturn)
+ esc = false
+ continue
+ }
+ if in[x] == 'n' {
+ buf.WriteByte(bLineFeed)
+ esc = false
+ continue
+ }
+ if in[x] == 'f' {
+ buf.WriteByte(bFormFeed)
+ esc = false
+ continue
+ }
+ if in[x] == 'b' {
+ buf.WriteByte(bBackspace)
+ esc = false
+ continue
+ }
+ if in[x] == bDoubleQuote || in[x] == bRevSolidus || in[x] == bSolidus {
+ buf.WriteByte(in[x])
+ esc = false
+ continue
+ }
+
+ if strict {
+ err := fmt.Errorf(errInvalidSyntax, "BytesJSONUnescape", x)
+ return nil, err
+ }
+
+ buf.WriteByte(in[x])
+ esc = false
+ continue
+ }
+ if in[x] == bRevSolidus {
+ esc = true
+ continue
+ }
+ buf.WriteByte(in[x])
+ }
+
+ return buf.Bytes(), nil
+}
diff --git a/lib/bytes/random.go b/lib/bytes/random.go
new file mode 100644
index 00000000..73945788
--- /dev/null
+++ b/lib/bytes/random.go
@@ -0,0 +1,22 @@
+// Copyright 2018, Shulhan <ms@kilabit.info>. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package bytes
+
+import (
+ "math/rand"
+)
+
+//
+// Random generate random sequence of value from seed with fixed length.
+//
+// This function assume that random generator has been seeded.
+//
+func Random(seed []byte, n int) []byte {
+ b := make([]byte, n)
+ for x := 0; x < n; x++ {
+ b[x] = seed[rand.Intn(len(seed))]
+ }
+ return b
+}