package common
import (
"bufio"
"bytes"
"context"
"errors"
"fmt"
"log"
"net/url"
"os"
"os/exec"
"path"
"path/filepath"
"reflect"
"runtime"
"strconv"
"strings"
"time"
)
var (
Timeout = 3 * time .Second
ErrTimeout = errors .New ("command timed out" )
)
type Invoker interface {
Command (string , ...string ) ([]byte , error )
CommandWithContext (context .Context , string , ...string ) ([]byte , error )
}
type Invoke struct {}
func (i Invoke ) Command (name string , arg ...string ) ([]byte , error ) {
ctx , cancel := context .WithTimeout (context .Background (), Timeout )
defer cancel ()
return i .CommandWithContext (ctx , name , arg ...)
}
func (i Invoke ) CommandWithContext (ctx context .Context , name string , arg ...string ) ([]byte , error ) {
cmd := exec .CommandContext (ctx , name , arg ...)
var buf bytes .Buffer
cmd .Stdout = &buf
cmd .Stderr = &buf
if err := cmd .Start (); err != nil {
return buf .Bytes (), err
}
if err := cmd .Wait (); err != nil {
return buf .Bytes (), err
}
return buf .Bytes (), nil
}
type FakeInvoke struct {
Suffix string
Error error
}
func (i FakeInvoke ) Command (name string , arg ...string ) ([]byte , error ) {
if i .Error != nil {
return []byte {}, i .Error
}
arch := runtime .GOOS
commandName := filepath .Base (name )
fname := strings .Join (append ([]string {commandName }, arg ...), "" )
fname = url .QueryEscape (fname )
fpath := path .Join ("testdata" , arch , fname )
if i .Suffix != "" {
fpath += "_" + i .Suffix
}
if PathExists (fpath ) {
return os .ReadFile (fpath )
}
return []byte {}, fmt .Errorf ("could not find testdata: %s" , fpath )
}
func (i FakeInvoke ) CommandWithContext (ctx context .Context , name string , arg ...string ) ([]byte , error ) {
return i .Command (name , arg ...)
}
var ErrNotImplementedError = errors .New ("not implemented yet" )
func ReadFile (filename string ) (string , error ) {
content , err := os .ReadFile (filename )
if err != nil {
return "" , err
}
return string (content ), nil
}
func ReadLines (filename string ) ([]string , error ) {
return ReadLinesOffsetN (filename , 0 , -1 )
}
func ReadLinesOffsetN (filename string , offset uint , n int ) ([]string , error ) {
f , err := os .Open (filename )
if err != nil {
return []string {"" }, err
}
defer func (f *os .File ) {
err := f .Close ()
if err != nil {
log .Fatalln (err )
}
}(f )
var ret []string
r := bufio .NewReader (f )
for i := 0 ; i < n +int (offset ) || n < 0 ; i ++ {
line , err := r .ReadString ('\n' )
if err != nil {
break
}
if i < int (offset ) {
continue
}
ret = append (ret , strings .Trim (line , "\n" ))
}
return ret , nil
}
func IntToString (orig []int8 ) string {
ret := make ([]byte , len (orig ))
size := -1
for i , o := range orig {
if o == 0 {
size = i
break
}
ret [i ] = byte (o )
}
if size == -1 {
size = len (orig )
}
return string (ret [0 :size ])
}
func UintToString (orig []uint8 ) string {
ret := make ([]byte , len (orig ))
size := -1
for i , o := range orig {
if o == 0 {
size = i
break
}
ret [i ] = byte (o )
}
if size == -1 {
size = len (orig )
}
return string (ret [0 :size ])
}
func ByteToString (orig []byte ) string {
n := -1
l := -1
for i , b := range orig {
if l == -1 && b == 0 {
continue
}
if l == -1 {
l = i
}
if b == 0 {
break
}
n = i + 1
}
if n == -1 {
return string (orig )
}
return string (orig [l :n ])
}
func ReadInts (filename string ) ([]int64 , error ) {
f , err := os .Open (filename )
if err != nil {
return []int64 {}, err
}
defer func (f *os .File ) {
err := f .Close ()
if err != nil {
log .Fatalln (err )
}
}(f )
var ret []int64
r := bufio .NewReader (f )
line , err := r .ReadString ('\n' )
if err != nil {
return []int64 {}, err
}
i , err := strconv .ParseInt (strings .Trim (line , "\n" ), 10 , 32 )
if err != nil {
return []int64 {}, err
}
ret = append (ret , i )
return ret , nil
}
func HexToUint32 (hex string ) uint32 {
vv , _ := strconv .ParseUint (hex , 16 , 32 )
return uint32 (vv )
}
func mustParseInt32(val string ) int32 {
vv , _ := strconv .ParseInt (val , 10 , 32 )
return int32 (vv )
}
func mustParseUint64(val string ) uint64 {
vv , _ := strconv .ParseInt (val , 10 , 64 )
return uint64 (vv )
}
func mustParseFloat64(val string ) float64 {
vv , _ := strconv .ParseFloat (val , 64 )
return vv
}
func StringsHas (target []string , src string ) bool {
for _ , t := range target {
if strings .TrimSpace (t ) == src {
return true
}
}
return false
}
func StringsContains (target []string , src string ) bool {
for _ , t := range target {
if strings .Contains (t , src ) {
return true
}
}
return false
}
func IntContains (target []int , src int ) bool {
for _ , t := range target {
if src == t {
return true
}
}
return false
}
func attributes(m interface {}) map [string ]reflect .Type {
typ := reflect .TypeOf (m )
if typ .Kind () == reflect .Ptr {
typ = typ .Elem ()
}
attrs := make (map [string ]reflect .Type )
if typ .Kind () != reflect .Struct {
return nil
}
for i := 0 ; i < typ .NumField (); i ++ {
p := typ .Field (i )
if !p .Anonymous {
attrs [p .Name ] = p .Type
}
}
return attrs
}
func PathExists (filename string ) bool {
if _ , err := os .Stat (filename ); err == nil {
return true
}
return false
}
func GetEnv (key , dfault string , combineWith ...string ) string {
value := os .Getenv (key )
if value == "" {
value = dfault
}
switch len (combineWith ) {
case 0 :
return value
case 1 :
return filepath .Join (value , combineWith [0 ])
default :
all := make ([]string , len (combineWith )+1 )
all [0 ] = value
copy (all [1 :], combineWith )
return filepath .Join (all ...)
}
}
func HostProc (combineWith ...string ) string {
return GetEnv ("HOST_PROC" , "/proc" , combineWith ...)
}
func HostSys (combineWith ...string ) string {
return GetEnv ("HOST_SYS" , "/sys" , combineWith ...)
}
func HostEtc (combineWith ...string ) string {
return GetEnv ("HOST_ETC" , "/etc" , combineWith ...)
}
func HostVar (combineWith ...string ) string {
return GetEnv ("HOST_VAR" , "/var" , combineWith ...)
}
func HostRun (combineWith ...string ) string {
return GetEnv ("HOST_RUN" , "/run" , combineWith ...)
}
func HostDev (combineWith ...string ) string {
return GetEnv ("HOST_DEV" , "/dev" , combineWith ...)
}
func getSysctrlEnv(env []string ) []string {
foundLC := false
for i , line := range env {
if strings .HasPrefix (line , "LC_ALL" ) {
env [i ] = "LC_ALL=C"
foundLC = true
}
}
if !foundLC {
env = append (env , "LC_ALL=C" )
}
return env
}
The pages are generated with Golds v0.6.7 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds .