Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
孙龙
/
kaopu-server
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
b7d67be7
authored
Nov 27, 2019
by
huangchengyi
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
1.0
parent
26483060
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
2200 additions
and
1 deletions
internal/logic/common.go
internal/logic/common.go
View file @
b7d67be7
package
logic
import
"time"
import
(
"archive/zip"
"bytes"
"crypto/md5"
"crypto/sha1"
"encoding/base64"
"encoding/binary"
"encoding/csv"
"encoding/hex"
"encoding/json"
"fmt"
"hash/crc32"
"html"
"io"
"io/ioutil"
"math"
"math/rand"
"net"
"net/url"
"os"
"os/exec"
"path/filepath"
"reflect"
"runtime"
"strconv"
"strings"
"syscall"
"time"
"unicode"
"unicode/utf8"
)
//////////// Date/Time Functions ////////////
// Time time()
func
getTimeStamp
()(
timestamp
int64
)
{
return
time
.
Now
()
.
Unix
()
}
// Strtotime strtotime()
// Strtotime("02/01/2006 15:04:05", "02/01/2016 15:04:05") == 1451747045
// Strtotime("3 04 PM", "8 41 PM") == -62167144740
func
Strtotime
(
format
,
strtime
string
)
(
int64
,
error
)
{
t
,
err
:=
time
.
Parse
(
format
,
strtime
)
if
err
!=
nil
{
return
0
,
err
}
return
t
.
Unix
(),
nil
}
// Date date()
// Date("02/01/2006 15:04:05 PM", 1524799394)
func
Date
(
format
string
,
timestamp
int64
)
string
{
return
time
.
Unix
(
timestamp
,
0
)
.
Format
(
format
)
}
// Checkdate checkdate()
// Validate a Gregorian date
func
Checkdate
(
month
,
day
,
year
int
)
bool
{
if
month
<
1
||
month
>
12
||
day
<
1
||
day
>
31
||
year
<
1
||
year
>
32767
{
return
false
}
switch
month
{
case
4
,
6
,
9
,
11
:
if
day
>
30
{
return
false
}
case
2
:
// leap year
if
year
%
4
==
0
&&
(
year
%
100
!=
0
||
year
%
400
==
0
)
{
if
day
>
29
{
return
false
}
}
else
if
day
>
28
{
return
false
}
}
return
true
}
// Sleep sleep()
func
Sleep
(
t
int64
)
{
time
.
Sleep
(
time
.
Duration
(
t
)
*
time
.
Second
)
}
// Usleep usleep()
func
Usleep
(
t
int64
)
{
time
.
Sleep
(
time
.
Duration
(
t
)
*
time
.
Microsecond
)
}
//////////// String Functions ////////////
// Strpos strpos()
func
Strpos
(
haystack
,
needle
string
,
offset
int
)
int
{
length
:=
len
(
haystack
)
if
length
==
0
||
offset
>
length
||
-
offset
>
length
{
return
-
1
}
if
offset
<
0
{
offset
+=
length
}
pos
:=
strings
.
Index
(
haystack
[
offset
:
],
needle
)
if
pos
==
-
1
{
return
-
1
}
return
pos
+
offset
}
// Stripos stripos()
func
Stripos
(
haystack
,
needle
string
,
offset
int
)
int
{
length
:=
len
(
haystack
)
if
length
==
0
||
offset
>
length
||
-
offset
>
length
{
return
-
1
}
haystack
=
haystack
[
offset
:
]
if
offset
<
0
{
offset
+=
length
}
pos
:=
strings
.
Index
(
strings
.
ToLower
(
haystack
),
strings
.
ToLower
(
needle
))
if
pos
==
-
1
{
return
-
1
}
return
pos
+
offset
}
// Strrpos strrpos()
func
Strrpos
(
haystack
,
needle
string
,
offset
int
)
int
{
pos
,
length
:=
0
,
len
(
haystack
)
if
length
==
0
||
offset
>
length
||
-
offset
>
length
{
return
-
1
}
if
offset
<
0
{
haystack
=
haystack
[
:
offset
+
length
+
1
]
}
else
{
haystack
=
haystack
[
offset
:
]
}
pos
=
strings
.
LastIndex
(
haystack
,
needle
)
if
offset
>
0
&&
pos
!=
-
1
{
pos
+=
offset
}
return
pos
}
// Strripos strripos()
func
Strripos
(
haystack
,
needle
string
,
offset
int
)
int
{
pos
,
length
:=
0
,
len
(
haystack
)
if
length
==
0
||
offset
>
length
||
-
offset
>
length
{
return
-
1
}
if
offset
<
0
{
haystack
=
haystack
[
:
offset
+
length
+
1
]
}
else
{
haystack
=
haystack
[
offset
:
]
}
pos
=
strings
.
LastIndex
(
strings
.
ToLower
(
haystack
),
strings
.
ToLower
(
needle
))
if
offset
>
0
&&
pos
!=
-
1
{
pos
+=
offset
}
return
pos
}
// StrReplace str_replace()
func
StrReplace
(
search
,
replace
,
subject
string
,
count
int
)
string
{
return
strings
.
Replace
(
subject
,
search
,
replace
,
count
)
}
// Strtoupper strtoupper()
func
Strtoupper
(
str
string
)
string
{
return
strings
.
ToUpper
(
str
)
}
// Strtolower strtolower()
func
Strtolower
(
str
string
)
string
{
return
strings
.
ToLower
(
str
)
}
// Ucfirst ucfirst()
func
Ucfirst
(
str
string
)
string
{
for
_
,
v
:=
range
str
{
u
:=
string
(
unicode
.
ToUpper
(
v
))
return
u
+
str
[
len
(
u
)
:
]
}
return
""
}
// Lcfirst lcfirst()
func
Lcfirst
(
str
string
)
string
{
for
_
,
v
:=
range
str
{
u
:=
string
(
unicode
.
ToLower
(
v
))
return
u
+
str
[
len
(
u
)
:
]
}
return
""
}
// Ucwords ucwords()
func
Ucwords
(
str
string
)
string
{
return
strings
.
Title
(
str
)
}
// Substr substr()
func
Substr
(
str
string
,
start
uint
,
length
int
)
string
{
if
start
<
0
||
length
<
-
1
{
return
str
}
switch
{
case
length
==
-
1
:
return
str
[
start
:
]
case
length
==
0
:
return
""
}
end
:=
int
(
start
)
+
length
if
end
>
len
(
str
)
{
end
=
len
(
str
)
}
return
str
[
start
:
end
]
}
// Strrev strrev()
func
Strrev
(
str
string
)
string
{
runes
:=
[]
rune
(
str
)
for
i
,
j
:=
0
,
len
(
runes
)
-
1
;
i
<
j
;
i
,
j
=
i
+
1
,
j
-
1
{
runes
[
i
],
runes
[
j
]
=
runes
[
j
],
runes
[
i
]
}
return
string
(
runes
)
}
// ParseStr parse_str()
// f1=m&f2=n -> map[f1:m f2:n]
// f[a]=m&f[b]=n -> map[f:map[a:m b:n]]
// f[a][a]=m&f[a][b]=n -> map[f:map[a:map[a:m b:n]]]
// f[]=m&f[]=n -> map[f:[m n]]
// f[a][]=m&f[a][]=n -> map[f:map[a:[m n]]]
// f[][]=m&f[][]=n -> map[f:[map[]]] // Currently does not support nested slice.
// f=m&f[a]=n -> error // This is not the same as PHP.
// a .[[b=c -> map[a___[b:c]
func
ParseStr
(
encodedString
string
,
result
map
[
string
]
interface
{})
error
{
// build nested map.
var
build
func
(
map
[
string
]
interface
{},
[]
string
,
interface
{})
error
build
=
func
(
result
map
[
string
]
interface
{},
keys
[]
string
,
value
interface
{})
error
{
length
:=
len
(
keys
)
// trim ',"
key
:=
strings
.
Trim
(
keys
[
0
],
"'
\"
"
)
if
length
==
1
{
result
[
key
]
=
value
return
nil
}
// The end is slice. like f[], f[a][]
if
keys
[
1
]
==
""
&&
length
==
2
{
// todo nested slice
if
key
==
""
{
return
nil
}
val
,
ok
:=
result
[
key
]
if
!
ok
{
result
[
key
]
=
[]
interface
{}{
value
}
return
nil
}
children
,
ok
:=
val
.
([]
interface
{})
if
!
ok
{
return
fmt
.
Errorf
(
"expected type '[]interface{}' for key '%s', but got '%T'"
,
key
,
val
)
}
result
[
key
]
=
append
(
children
,
value
)
return
nil
}
// The end is slice + map. like f[][a]
if
keys
[
1
]
==
""
&&
length
>
2
&&
keys
[
2
]
!=
""
{
val
,
ok
:=
result
[
key
]
if
!
ok
{
result
[
key
]
=
[]
interface
{}{}
val
=
result
[
key
]
}
children
,
ok
:=
val
.
([]
interface
{})
if
!
ok
{
return
fmt
.
Errorf
(
"expected type '[]interface{}' for key '%s', but got '%T'"
,
key
,
val
)
}
if
l
:=
len
(
children
);
l
>
0
{
if
child
,
ok
:=
children
[
l
-
1
]
.
(
map
[
string
]
interface
{});
ok
{
if
_
,
ok
:=
child
[
keys
[
2
]];
!
ok
{
_
=
build
(
child
,
keys
[
2
:
],
value
)
return
nil
}
}
}
child
:=
map
[
string
]
interface
{}{}
_
=
build
(
child
,
keys
[
2
:
],
value
)
result
[
key
]
=
append
(
children
,
child
)
return
nil
}
// map. like f[a], f[a][b]
val
,
ok
:=
result
[
key
]
if
!
ok
{
result
[
key
]
=
map
[
string
]
interface
{}{}
val
=
result
[
key
]
}
children
,
ok
:=
val
.
(
map
[
string
]
interface
{})
if
!
ok
{
return
fmt
.
Errorf
(
"expected type 'map[string]interface{}' for key '%s', but got '%T'"
,
key
,
val
)
}
return
build
(
children
,
keys
[
1
:
],
value
)
}
// split encodedString.
parts
:=
strings
.
Split
(
encodedString
,
"&"
)
for
_
,
part
:=
range
parts
{
pos
:=
strings
.
Index
(
part
,
"="
)
if
pos
<=
0
{
continue
}
key
,
err
:=
url
.
QueryUnescape
(
part
[
:
pos
])
if
err
!=
nil
{
return
err
}
for
key
[
0
]
==
' '
{
key
=
key
[
1
:
]
}
if
key
==
""
||
key
[
0
]
==
'['
{
continue
}
value
,
err
:=
url
.
QueryUnescape
(
part
[
pos
+
1
:
])
if
err
!=
nil
{
return
err
}
// split into multiple keys
var
keys
[]
string
left
:=
0
for
i
,
k
:=
range
key
{
if
k
==
'['
&&
left
==
0
{
left
=
i
}
else
if
k
==
']'
{
if
left
>
0
{
if
len
(
keys
)
==
0
{
keys
=
append
(
keys
,
key
[
:
left
])
}
keys
=
append
(
keys
,
key
[
left
+
1
:
i
])
left
=
0
if
i
+
1
<
len
(
key
)
&&
key
[
i
+
1
]
!=
'['
{
break
}
}
}
}
if
len
(
keys
)
==
0
{
keys
=
append
(
keys
,
key
)
}
// first key
first
:=
""
for
i
,
chr
:=
range
keys
[
0
]
{
if
chr
==
' '
||
chr
==
'.'
||
chr
==
'['
{
first
+=
"_"
}
else
{
first
+=
string
(
chr
)
}
if
chr
==
'['
{
first
+=
keys
[
0
][
i
+
1
:
]
break
}
}
keys
[
0
]
=
first
// build nested map
if
err
:=
build
(
result
,
keys
,
value
);
err
!=
nil
{
return
err
}
}
return
nil
}
// NumberFormat number_format()
// decimals: Sets the number of decimal points.
// decPoint: Sets the separator for the decimal point.
// thousandsSep: Sets the thousands separator.
func
NumberFormat
(
number
float64
,
decimals
uint
,
decPoint
,
thousandsSep
string
)
string
{
neg
:=
false
if
number
<
0
{
number
=
-
number
neg
=
true
}
dec
:=
int
(
decimals
)
// Will round off
str
:=
fmt
.
Sprintf
(
"%."
+
strconv
.
Itoa
(
dec
)
+
"F"
,
number
)
prefix
,
suffix
:=
""
,
""
if
dec
>
0
{
prefix
=
str
[
:
len
(
str
)
-
(
dec
+
1
)]
suffix
=
str
[
len
(
str
)
-
dec
:
]
}
else
{
prefix
=
str
}
sep
:=
[]
byte
(
thousandsSep
)
n
,
l1
,
l2
:=
0
,
len
(
prefix
),
len
(
sep
)
// thousands sep num
c
:=
(
l1
-
1
)
/
3
tmp
:=
make
([]
byte
,
l2
*
c
+
l1
)
pos
:=
len
(
tmp
)
-
1
for
i
:=
l1
-
1
;
i
>=
0
;
i
,
n
,
pos
=
i
-
1
,
n
+
1
,
pos
-
1
{
if
l2
>
0
&&
n
>
0
&&
n
%
3
==
0
{
for
j
:=
range
sep
{
tmp
[
pos
]
=
sep
[
l2
-
j
-
1
]
pos
--
}
}
tmp
[
pos
]
=
prefix
[
i
]
}
s
:=
string
(
tmp
)
if
dec
>
0
{
s
+=
decPoint
+
suffix
}
if
neg
{
s
=
"-"
+
s
}
return
s
}
// ChunkSplit chunk_split()
func
ChunkSplit
(
body
string
,
chunklen
uint
,
end
string
)
string
{
if
end
==
""
{
end
=
"
\r\n
"
}
runes
,
erunes
:=
[]
rune
(
body
),
[]
rune
(
end
)
l
:=
uint
(
len
(
runes
))
if
l
<=
1
||
l
<
chunklen
{
return
body
+
end
}
ns
:=
make
([]
rune
,
0
,
len
(
runes
)
+
len
(
erunes
))
var
i
uint
for
i
=
0
;
i
<
l
;
i
+=
chunklen
{
if
i
+
chunklen
>
l
{
ns
=
append
(
ns
,
runes
[
i
:
]
...
)
}
else
{
ns
=
append
(
ns
,
runes
[
i
:
i
+
chunklen
]
...
)
}
ns
=
append
(
ns
,
erunes
...
)
}
return
string
(
ns
)
}
// StrWordCount str_word_count()
func
StrWordCount
(
str
string
)
[]
string
{
return
strings
.
Fields
(
str
)
}
// Wordwrap wordwrap()
func
Wordwrap
(
str
string
,
width
uint
,
br
string
,
cut
bool
)
string
{
strlen
:=
len
(
str
)
brlen
:=
len
(
br
)
linelen
:=
int
(
width
)
if
strlen
==
0
{
return
""
}
if
brlen
==
0
{
panic
(
"break string cannot be empty"
)
}
if
linelen
==
0
&&
cut
{
panic
(
"can't force cut when width is zero"
)
}
current
,
laststart
,
lastspace
:=
0
,
0
,
0
var
ns
[]
byte
for
current
=
0
;
current
<
strlen
;
current
++
{
if
str
[
current
]
==
br
[
0
]
&&
current
+
brlen
<
strlen
&&
str
[
current
:
current
+
brlen
]
==
br
{
ns
=
append
(
ns
,
str
[
laststart
:
current
+
brlen
]
...
)
current
+=
brlen
-
1
lastspace
=
current
+
1
laststart
=
lastspace
}
else
if
str
[
current
]
==
' '
{
if
current
-
laststart
>=
linelen
{
ns
=
append
(
ns
,
str
[
laststart
:
current
]
...
)
ns
=
append
(
ns
,
br
[
:
]
...
)
laststart
=
current
+
1
}
lastspace
=
current
}
else
if
current
-
laststart
>=
linelen
&&
cut
&&
laststart
>=
lastspace
{
ns
=
append
(
ns
,
str
[
laststart
:
current
]
...
)
ns
=
append
(
ns
,
br
[
:
]
...
)
laststart
=
current
lastspace
=
current
}
else
if
current
-
laststart
>=
linelen
&&
laststart
<
lastspace
{
ns
=
append
(
ns
,
str
[
laststart
:
lastspace
]
...
)
ns
=
append
(
ns
,
br
[
:
]
...
)
lastspace
++
laststart
=
lastspace
}
}
if
laststart
!=
current
{
ns
=
append
(
ns
,
str
[
laststart
:
current
]
...
)
}
return
string
(
ns
)
}
// Strlen strlen()
func
Strlen
(
str
string
)
int
{
return
len
(
str
)
}
// MbStrlen mb_strlen()
func
MbStrlen
(
str
string
)
int
{
return
utf8
.
RuneCountInString
(
str
)
}
// StrRepeat str_repeat()
func
StrRepeat
(
input
string
,
multiplier
int
)
string
{
return
strings
.
Repeat
(
input
,
multiplier
)
}
// Strstr strstr()
func
Strstr
(
haystack
string
,
needle
string
)
string
{
if
needle
==
""
{
return
""
}
idx
:=
strings
.
Index
(
haystack
,
needle
)
if
idx
==
-
1
{
return
""
}
return
haystack
[
idx
+
len
([]
byte
(
needle
))
-
1
:
]
}
// Strtr strtr()
//
// If the parameter length is 1, type is: map[string]string
// Strtr("baab", map[string]string{"ab": "01"}) will return "ba01"
// If the parameter length is 2, type is: string, string
// Strtr("baab", "ab", "01") will return "1001", a => 0; b => 1.
func
Strtr
(
haystack
string
,
params
...
interface
{})
string
{
ac
:=
len
(
params
)
if
ac
==
1
{
pairs
:=
params
[
0
]
.
(
map
[
string
]
string
)
length
:=
len
(
pairs
)
if
length
==
0
{
return
haystack
}
oldnew
:=
make
([]
string
,
length
*
2
)
for
o
,
n
:=
range
pairs
{
if
o
==
""
{
return
haystack
}
oldnew
=
append
(
oldnew
,
o
,
n
)
}
return
strings
.
NewReplacer
(
oldnew
...
)
.
Replace
(
haystack
)
}
else
if
ac
==
2
{
from
:=
params
[
0
]
.
(
string
)
to
:=
params
[
1
]
.
(
string
)
trlen
,
lt
:=
len
(
from
),
len
(
to
)
if
trlen
>
lt
{
trlen
=
lt
}
if
trlen
==
0
{
return
haystack
}
str
:=
make
([]
uint8
,
len
(
haystack
))
var
xlat
[
256
]
uint8
var
i
int
var
j
uint8
if
trlen
==
1
{
for
i
=
0
;
i
<
len
(
haystack
);
i
++
{
if
haystack
[
i
]
==
from
[
0
]
{
str
[
i
]
=
to
[
0
]
}
else
{
str
[
i
]
=
haystack
[
i
]
}
}
return
string
(
str
)
}
// trlen != 1
for
{
xlat
[
j
]
=
j
if
j
++
;
j
==
0
{
break
}
}
for
i
=
0
;
i
<
trlen
;
i
++
{
xlat
[
from
[
i
]]
=
to
[
i
]
}
for
i
=
0
;
i
<
len
(
haystack
);
i
++
{
str
[
i
]
=
xlat
[
haystack
[
i
]]
}
return
string
(
str
)
}
return
haystack
}
// StrShuffle str_shuffle()
func
StrShuffle
(
str
string
)
string
{
runes
:=
[]
rune
(
str
)
r
:=
rand
.
New
(
rand
.
NewSource
(
time
.
Now
()
.
UnixNano
()))
s
:=
make
([]
rune
,
len
(
runes
))
for
i
,
v
:=
range
r
.
Perm
(
len
(
runes
))
{
s
[
i
]
=
runes
[
v
]
}
return
string
(
s
)
}
// Trim trim()
func
Trim
(
str
string
,
characterMask
...
string
)
string
{
if
len
(
characterMask
)
==
0
{
return
strings
.
TrimSpace
(
str
)
}
return
strings
.
Trim
(
str
,
characterMask
[
0
])
}
// Ltrim ltrim()
func
Ltrim
(
str
string
,
characterMask
...
string
)
string
{
if
len
(
characterMask
)
==
0
{
return
strings
.
TrimLeftFunc
(
str
,
unicode
.
IsSpace
)
}
return
strings
.
TrimLeft
(
str
,
characterMask
[
0
])
}
// Rtrim rtrim()
func
Rtrim
(
str
string
,
characterMask
...
string
)
string
{
if
len
(
characterMask
)
==
0
{
return
strings
.
TrimRightFunc
(
str
,
unicode
.
IsSpace
)
}
return
strings
.
TrimRight
(
str
,
characterMask
[
0
])
}
// Explode explode()
func
Explode
(
delimiter
,
str
string
)
[]
string
{
return
strings
.
Split
(
str
,
delimiter
)
}
// Chr chr()
func
Chr
(
ascii
int
)
string
{
return
string
(
ascii
)
}
// Ord ord()
func
Ord
(
char
string
)
int
{
r
,
_
:=
utf8
.
DecodeRune
([]
byte
(
char
))
return
int
(
r
)
}
// Nl2br nl2br()
// \n\r, \r\n, \r, \n
func
Nl2br
(
str
string
,
isXhtml
bool
)
string
{
r
,
n
,
runes
:=
'\r'
,
'\n'
,
[]
rune
(
str
)
var
br
[]
byte
if
isXhtml
{
br
=
[]
byte
(
"<br />"
)
}
else
{
br
=
[]
byte
(
"<br>"
)
}
skip
:=
false
length
:=
len
(
runes
)
var
buf
bytes
.
Buffer
for
i
,
v
:=
range
runes
{
if
skip
{
skip
=
false
continue
}
switch
v
{
case
n
,
r
:
if
(
i
+
1
<
length
)
&&
(
v
==
r
&&
runes
[
i
+
1
]
==
n
)
||
(
v
==
n
&&
runes
[
i
+
1
]
==
r
)
{
buf
.
Write
(
br
)
skip
=
true
continue
}
buf
.
Write
(
br
)
default
:
buf
.
WriteRune
(
v
)
}
}
return
buf
.
String
()
}
// JSONDecode json_decode()
func
JSONDecode
(
data
[]
byte
,
val
interface
{})
error
{
return
json
.
Unmarshal
(
data
,
val
)
}
// JSONEncode json_encode()
func
JSONEncode
(
val
interface
{})
([]
byte
,
error
)
{
return
json
.
Marshal
(
val
)
}
// Addslashes addslashes()
func
Addslashes
(
str
string
)
string
{
var
buf
bytes
.
Buffer
for
_
,
char
:=
range
str
{
switch
char
{
case
'\'
'
,
'"'
,
'\\'
:
buf
.
WriteRune
(
'\\'
)
}
buf
.
WriteRune
(
char
)
}
return
buf
.
String
()
}
// Stripslashes stripslashes()
func
Stripslashes
(
str
string
)
string
{
var
buf
bytes
.
Buffer
l
,
skip
:=
len
(
str
),
false
for
i
,
char
:=
range
str
{
if
skip
{
skip
=
false
}
else
if
char
==
'\\'
{
if
i
+
1
<
l
&&
str
[
i
+
1
]
==
'\\'
{
skip
=
true
}
continue
}
buf
.
WriteRune
(
char
)
}
return
buf
.
String
()
}
// Quotemeta quotemeta()
func
Quotemeta
(
str
string
)
string
{
var
buf
bytes
.
Buffer
for
_
,
char
:=
range
str
{
switch
char
{
case
'.'
,
'+'
,
'\\'
,
'('
,
'$'
,
')'
,
'['
,
'^'
,
']'
,
'*'
,
'?'
:
buf
.
WriteRune
(
'\\'
)
}
buf
.
WriteRune
(
char
)
}
return
buf
.
String
()
}
// Htmlentities htmlentities()
func
Htmlentities
(
str
string
)
string
{
return
html
.
EscapeString
(
str
)
}
// HTMLEntityDecode html_entity_decode()
func
HTMLEntityDecode
(
str
string
)
string
{
return
html
.
UnescapeString
(
str
)
}
// Md5 md5()
func
Md5
(
str
string
)
string
{
hash
:=
md5
.
New
()
hash
.
Write
([]
byte
(
str
))
return
hex
.
EncodeToString
(
hash
.
Sum
(
nil
))
}
// Md5File md5_file()
func
Md5File
(
path
string
)
(
string
,
error
)
{
data
,
err
:=
ioutil
.
ReadFile
(
path
)
if
err
!=
nil
{
return
""
,
err
}
hash
:=
md5
.
New
()
hash
.
Write
([]
byte
(
data
))
return
hex
.
EncodeToString
(
hash
.
Sum
(
nil
)),
nil
}
// Sha1 sha1()
func
Sha1
(
str
string
)
string
{
hash
:=
sha1
.
New
()
hash
.
Write
([]
byte
(
str
))
return
hex
.
EncodeToString
(
hash
.
Sum
(
nil
))
}
// Sha1File sha1_file()
func
Sha1File
(
path
string
)
(
string
,
error
)
{
data
,
err
:=
ioutil
.
ReadFile
(
path
)
if
err
!=
nil
{
return
""
,
err
}
hash
:=
sha1
.
New
()
hash
.
Write
([]
byte
(
data
))
return
hex
.
EncodeToString
(
hash
.
Sum
(
nil
)),
nil
}
// Crc32 crc32()
func
Crc32
(
str
string
)
uint32
{
return
crc32
.
ChecksumIEEE
([]
byte
(
str
))
}
// Levenshtein levenshtein()
// costIns: Defines the cost of insertion.
// costRep: Defines the cost of replacement.
// costDel: Defines the cost of deletion.
func
Levenshtein
(
str1
,
str2
string
,
costIns
,
costRep
,
costDel
int
)
int
{
var
maxLen
=
255
l1
:=
len
(
str1
)
l2
:=
len
(
str2
)
if
l1
==
0
{
return
l2
*
costIns
}
if
l2
==
0
{
return
l1
*
costDel
}
if
l1
>
maxLen
||
l2
>
maxLen
{
return
-
1
}
p1
:=
make
([]
int
,
l2
+
1
)
p2
:=
make
([]
int
,
l2
+
1
)
var
c0
,
c1
,
c2
int
var
i1
,
i2
int
for
i2
:=
0
;
i2
<=
l2
;
i2
++
{
p1
[
i2
]
=
i2
*
costIns
}
for
i1
=
0
;
i1
<
l1
;
i1
++
{
p2
[
0
]
=
p1
[
0
]
+
costDel
for
i2
=
0
;
i2
<
l2
;
i2
++
{
if
str1
[
i1
]
==
str2
[
i2
]
{
c0
=
p1
[
i2
]
}
else
{
c0
=
p1
[
i2
]
+
costRep
}
c1
=
p1
[
i2
+
1
]
+
costDel
if
c1
<
c0
{
c0
=
c1
}
c2
=
p2
[
i2
]
+
costIns
if
c2
<
c0
{
c0
=
c2
}
p2
[
i2
+
1
]
=
c0
}
tmp
:=
p1
p1
=
p2
p2
=
tmp
}
c0
=
p1
[
l2
]
return
c0
}
// SimilarText similar_text()
func
SimilarText
(
first
,
second
string
,
percent
*
float64
)
int
{
var
similarText
func
(
string
,
string
,
int
,
int
)
int
similarText
=
func
(
str1
,
str2
string
,
len1
,
len2
int
)
int
{
var
sum
,
max
int
pos1
,
pos2
:=
0
,
0
// Find the longest segment of the same section in two strings
for
i
:=
0
;
i
<
len1
;
i
++
{
for
j
:=
0
;
j
<
len2
;
j
++
{
for
l
:=
0
;
(
i
+
l
<
len1
)
&&
(
j
+
l
<
len2
)
&&
(
str1
[
i
+
l
]
==
str2
[
j
+
l
]);
l
++
{
if
l
+
1
>
max
{
max
=
l
+
1
pos1
=
i
pos2
=
j
}
}
}
}
if
sum
=
max
;
sum
>
0
{
if
pos1
>
0
&&
pos2
>
0
{
sum
+=
similarText
(
str1
,
str2
,
pos1
,
pos2
)
}
if
(
pos1
+
max
<
len1
)
&&
(
pos2
+
max
<
len2
)
{
s1
:=
[]
byte
(
str1
)
s2
:=
[]
byte
(
str2
)
sum
+=
similarText
(
string
(
s1
[
pos1
+
max
:
]),
string
(
s2
[
pos2
+
max
:
]),
len1
-
pos1
-
max
,
len2
-
pos2
-
max
)
}
}
return
sum
}
l1
,
l2
:=
len
(
first
),
len
(
second
)
if
l1
+
l2
==
0
{
return
0
}
sim
:=
similarText
(
first
,
second
,
l1
,
l2
)
if
percent
!=
nil
{
*
percent
=
float64
(
sim
*
200
)
/
float64
(
l1
+
l2
)
}
return
sim
}
// Soundex soundex()
// Calculate the soundex key of a string.
func
Soundex
(
str
string
)
string
{
if
str
==
""
{
panic
(
"str: cannot be an empty string"
)
}
table
:=
[
26
]
rune
{
// A, B, C, D
'0'
,
'1'
,
'2'
,
'3'
,
// E, F, G
'0'
,
'1'
,
'2'
,
// H
'0'
,
// I, J, K, L, M, N
'0'
,
'2'
,
'2'
,
'4'
,
'5'
,
'5'
,
// O, P, Q, R, S, T
'0'
,
'1'
,
'2'
,
'6'
,
'2'
,
'3'
,
// U, V
'0'
,
'1'
,
// W, X
'0'
,
'2'
,
// Y, Z
'0'
,
'2'
,
}
last
,
code
,
small
:=
-
1
,
0
,
0
sd
:=
make
([]
rune
,
4
)
// build soundex string
for
i
:=
0
;
i
<
len
(
str
)
&&
small
<
4
;
i
++
{
// ToUpper
char
:=
str
[
i
]
if
char
<
'\u007F'
&&
'a'
<=
char
&&
char
<=
'z'
{
code
=
int
(
char
-
'a'
+
'A'
)
}
else
{
code
=
int
(
char
)
}
if
code
>=
'A'
&&
code
<=
'Z'
{
if
small
==
0
{
sd
[
small
]
=
rune
(
code
)
small
++
last
=
int
(
table
[
code
-
'A'
])
}
else
{
code
=
int
(
table
[
code
-
'A'
])
if
code
!=
last
{
if
code
!=
0
{
sd
[
small
]
=
rune
(
code
)
small
++
}
last
=
code
}
}
}
}
// pad with "0"
for
;
small
<
4
;
small
++
{
sd
[
small
]
=
'0'
}
return
string
(
sd
)
}
//////////// URL Functions ////////////
// ParseURL parse_url()
// Parse a URL and return its components
// -1: all; 1: scheme; 2: host; 4: port; 8: user; 16: pass; 32: path; 64: query; 128: fragment
func
ParseURL
(
str
string
,
component
int
)
(
map
[
string
]
string
,
error
)
{
u
,
err
:=
url
.
Parse
(
str
)
if
err
!=
nil
{
return
nil
,
err
}
if
component
==
-
1
{
component
=
1
|
2
|
4
|
8
|
16
|
32
|
64
|
128
}
var
components
=
make
(
map
[
string
]
string
)
if
(
component
&
1
)
==
1
{
components
[
"scheme"
]
=
u
.
Scheme
}
if
(
component
&
2
)
==
2
{
components
[
"host"
]
=
u
.
Hostname
()
}
if
(
component
&
4
)
==
4
{
components
[
"port"
]
=
u
.
Port
()
}
if
(
component
&
8
)
==
8
{
components
[
"user"
]
=
u
.
User
.
Username
()
}
if
(
component
&
16
)
==
16
{
components
[
"pass"
],
_
=
u
.
User
.
Password
()
}
if
(
component
&
32
)
==
32
{
components
[
"path"
]
=
u
.
Path
}
if
(
component
&
64
)
==
64
{
components
[
"query"
]
=
u
.
RawQuery
}
if
(
component
&
128
)
==
128
{
components
[
"fragment"
]
=
u
.
Fragment
}
return
components
,
nil
}
// URLEncode urlencode()
func
URLEncode
(
str
string
)
string
{
return
url
.
QueryEscape
(
str
)
}
// URLDecode urldecode()
func
URLDecode
(
str
string
)
(
string
,
error
)
{
return
url
.
QueryUnescape
(
str
)
}
// Rawurlencode rawurlencode()
func
Rawurlencode
(
str
string
)
string
{
return
strings
.
Replace
(
url
.
QueryEscape
(
str
),
"+"
,
"%20"
,
-
1
)
}
// Rawurldecode rawurldecode()
func
Rawurldecode
(
str
string
)
(
string
,
error
)
{
return
url
.
QueryUnescape
(
strings
.
Replace
(
str
,
"%20"
,
"+"
,
-
1
))
}
// HTTPBuildQuery http_build_query()
func
HTTPBuildQuery
(
queryData
url
.
Values
)
string
{
return
queryData
.
Encode
()
}
// Base64Encode base64_encode()
func
Base64Encode
(
str
string
)
string
{
return
base64
.
StdEncoding
.
EncodeToString
([]
byte
(
str
))
}
// Base64Decode base64_decode()
func
Base64Decode
(
str
string
)
(
string
,
error
)
{
switch
len
(
str
)
%
4
{
case
2
:
str
+=
"=="
case
3
:
str
+=
"="
}
data
,
err
:=
base64
.
StdEncoding
.
DecodeString
(
str
)
if
err
!=
nil
{
return
""
,
err
}
return
string
(
data
),
nil
}
//////////// Array(Slice/Map) Functions ////////////
// ArrayFill array_fill()
func
ArrayFill
(
startIndex
int
,
num
uint
,
value
interface
{})
map
[
int
]
interface
{}
{
m
:=
make
(
map
[
int
]
interface
{})
var
i
uint
for
i
=
0
;
i
<
num
;
i
++
{
m
[
startIndex
]
=
value
startIndex
++
}
return
m
}
// ArrayFlip array_flip()
func
ArrayFlip
(
m
map
[
interface
{}]
interface
{})
map
[
interface
{}]
interface
{}
{
n
:=
make
(
map
[
interface
{}]
interface
{})
for
i
,
v
:=
range
m
{
n
[
v
]
=
i
}
return
n
}
// ArrayKeys array_keys()
func
ArrayKeys
(
elements
map
[
interface
{}]
interface
{})
[]
interface
{}
{
i
,
keys
:=
0
,
make
([]
interface
{},
len
(
elements
))
for
key
:=
range
elements
{
keys
[
i
]
=
key
i
++
}
return
keys
}
// ArrayValues array_values()
func
ArrayValues
(
elements
map
[
interface
{}]
interface
{})
[]
interface
{}
{
i
,
vals
:=
0
,
make
([]
interface
{},
len
(
elements
))
for
_
,
val
:=
range
elements
{
vals
[
i
]
=
val
i
++
}
return
vals
}
// ArrayMerge array_merge()
func
ArrayMerge
(
ss
...
[]
interface
{})
[]
interface
{}
{
n
:=
0
for
_
,
v
:=
range
ss
{
n
+=
len
(
v
)
}
s
:=
make
([]
interface
{},
0
,
n
)
for
_
,
v
:=
range
ss
{
s
=
append
(
s
,
v
...
)
}
return
s
}
// ArrayChunk array_chunk()
func
ArrayChunk
(
s
[]
interface
{},
size
int
)
[][]
interface
{}
{
if
size
<
1
{
panic
(
"size: cannot be less than 1"
)
}
length
:=
len
(
s
)
chunks
:=
int
(
math
.
Ceil
(
float64
(
length
)
/
float64
(
size
)))
var
n
[][]
interface
{}
for
i
,
end
:=
0
,
0
;
chunks
>
0
;
chunks
--
{
end
=
(
i
+
1
)
*
size
if
end
>
length
{
end
=
length
}
n
=
append
(
n
,
s
[
i
*
size
:
end
])
i
++
}
return
n
}
// ArrayPad array_pad()
func
ArrayPad
(
s
[]
interface
{},
size
int
,
val
interface
{})
[]
interface
{}
{
if
size
==
0
||
(
size
>
0
&&
size
<
len
(
s
))
||
(
size
<
0
&&
size
>
-
len
(
s
))
{
return
s
}
n
:=
size
if
size
<
0
{
n
=
-
size
}
n
-=
len
(
s
)
tmp
:=
make
([]
interface
{},
n
)
for
i
:=
0
;
i
<
n
;
i
++
{
tmp
[
i
]
=
val
}
if
size
>
0
{
return
append
(
s
,
tmp
...
)
}
return
append
(
tmp
,
s
...
)
}
// ArraySlice array_slice()
func
ArraySlice
(
s
[]
interface
{},
offset
,
length
uint
)
[]
interface
{}
{
if
offset
>
uint
(
len
(
s
))
{
panic
(
"offset: the offset is less than the length of s"
)
}
end
:=
offset
+
length
if
end
<
uint
(
len
(
s
))
{
return
s
[
offset
:
end
]
}
return
s
[
offset
:
]
}
// ArrayRand array_rand()
func
ArrayRand
(
elements
[]
interface
{})
[]
interface
{}
{
r
:=
rand
.
New
(
rand
.
NewSource
(
time
.
Now
()
.
UnixNano
()))
n
:=
make
([]
interface
{},
len
(
elements
))
for
i
,
v
:=
range
r
.
Perm
(
len
(
elements
))
{
n
[
i
]
=
elements
[
v
]
}
return
n
}
// ArrayColumn array_column()
func
ArrayColumn
(
input
map
[
string
]
map
[
string
]
interface
{},
columnKey
string
)
[]
interface
{}
{
columns
:=
make
([]
interface
{},
0
,
len
(
input
))
for
_
,
val
:=
range
input
{
if
v
,
ok
:=
val
[
columnKey
];
ok
{
columns
=
append
(
columns
,
v
)
}
}
return
columns
}
// ArrayPush array_push()
// Push one or more elements onto the end of slice
func
ArrayPush
(
s
*
[]
interface
{},
elements
...
interface
{})
int
{
*
s
=
append
(
*
s
,
elements
...
)
return
len
(
*
s
)
}
// ArrayPop array_pop()
// Pop the element off the end of slice
func
ArrayPop
(
s
*
[]
interface
{})
interface
{}
{
if
len
(
*
s
)
==
0
{
return
nil
}
ep
:=
len
(
*
s
)
-
1
e
:=
(
*
s
)[
ep
]
*
s
=
(
*
s
)[
:
ep
]
return
e
}
// ArrayUnshift array_unshift()
// Prepend one or more elements to the beginning of a slice
func
ArrayUnshift
(
s
*
[]
interface
{},
elements
...
interface
{})
int
{
*
s
=
append
(
elements
,
*
s
...
)
return
len
(
*
s
)
}
// ArrayShift array_shift()
// Shift an element off the beginning of slice
func
ArrayShift
(
s
*
[]
interface
{})
interface
{}
{
if
len
(
*
s
)
==
0
{
return
nil
}
f
:=
(
*
s
)[
0
]
*
s
=
(
*
s
)[
1
:
]
return
f
}
// ArrayKeyExists array_key_exists()
func
ArrayKeyExists
(
key
interface
{},
m
map
[
interface
{}]
interface
{})
bool
{
_
,
ok
:=
m
[
key
]
return
ok
}
// ArrayCombine array_combine()
func
ArrayCombine
(
s1
,
s2
[]
interface
{})
map
[
interface
{}]
interface
{}
{
if
len
(
s1
)
!=
len
(
s2
)
{
panic
(
"the number of elements for each slice isn't equal"
)
}
m
:=
make
(
map
[
interface
{}]
interface
{},
len
(
s1
))
for
i
,
v
:=
range
s1
{
m
[
v
]
=
s2
[
i
]
}
return
m
}
// ArrayReverse array_reverse()
func
ArrayReverse
(
s
[]
interface
{})
[]
interface
{}
{
for
i
,
j
:=
0
,
len
(
s
)
-
1
;
i
<
j
;
i
,
j
=
i
+
1
,
j
-
1
{
s
[
i
],
s
[
j
]
=
s
[
j
],
s
[
i
]
}
return
s
}
// Implode implode()
func
Implode
(
glue
string
,
pieces
[]
string
)
string
{
var
buf
bytes
.
Buffer
l
:=
len
(
pieces
)
for
_
,
str
:=
range
pieces
{
buf
.
WriteString
(
str
)
if
l
--
;
l
>
0
{
buf
.
WriteString
(
glue
)
}
}
return
buf
.
String
()
}
// InArray in_array()
// haystack supported types: slice, array or map
func
InArray
(
needle
interface
{},
haystack
interface
{})
bool
{
val
:=
reflect
.
ValueOf
(
haystack
)
switch
val
.
Kind
()
{
case
reflect
.
Slice
,
reflect
.
Array
:
for
i
:=
0
;
i
<
val
.
Len
();
i
++
{
if
reflect
.
DeepEqual
(
needle
,
val
.
Index
(
i
)
.
Interface
())
{
return
true
}
}
case
reflect
.
Map
:
for
_
,
k
:=
range
val
.
MapKeys
()
{
if
reflect
.
DeepEqual
(
needle
,
val
.
MapIndex
(
k
)
.
Interface
())
{
return
true
}
}
default
:
panic
(
"haystack: haystack type muset be slice, array or map"
)
}
return
false
}
//////////// Mathematical Functions ////////////
// Abs abs()
func
Abs
(
number
float64
)
float64
{
return
math
.
Abs
(
number
)
}
// Rand rand()
// Range: [0, 2147483647]
func
Rand
(
min
,
max
int
)
int
{
if
min
>
max
{
panic
(
"min: min cannot be greater than max"
)
}
// PHP: getrandmax()
if
int31
:=
1
<<
31
-
1
;
max
>
int31
{
panic
(
"max: max can not be greater than "
+
strconv
.
Itoa
(
int31
))
}
if
min
==
max
{
return
min
}
r
:=
rand
.
New
(
rand
.
NewSource
(
time
.
Now
()
.
UnixNano
()))
return
r
.
Intn
(
max
+
1
-
min
)
+
min
}
// Round round()
func
Round
(
value
float64
)
float64
{
return
math
.
Floor
(
value
+
0.5
)
}
// Floor floor()
func
Floor
(
value
float64
)
float64
{
return
math
.
Floor
(
value
)
}
// Ceil ceil()
func
Ceil
(
value
float64
)
float64
{
return
math
.
Ceil
(
value
)
}
// Pi pi()
func
Pi
()
float64
{
return
math
.
Pi
}
// Max max()
func
Max
(
nums
...
float64
)
float64
{
if
len
(
nums
)
<
2
{
panic
(
"nums: the nums length is less than 2"
)
}
max
:=
nums
[
0
]
for
i
:=
1
;
i
<
len
(
nums
);
i
++
{
max
=
math
.
Max
(
max
,
nums
[
i
])
}
return
max
}
// Min min()
func
Min
(
nums
...
float64
)
float64
{
if
len
(
nums
)
<
2
{
panic
(
"nums: the nums length is less than 2"
)
}
min
:=
nums
[
0
]
for
i
:=
1
;
i
<
len
(
nums
);
i
++
{
min
=
math
.
Min
(
min
,
nums
[
i
])
}
return
min
}
// Decbin decbin()
func
Decbin
(
number
int64
)
string
{
return
strconv
.
FormatInt
(
number
,
2
)
}
// Bindec bindec()
func
Bindec
(
str
string
)
(
string
,
error
)
{
i
,
err
:=
strconv
.
ParseInt
(
str
,
2
,
0
)
if
err
!=
nil
{
return
""
,
err
}
return
strconv
.
FormatInt
(
i
,
10
),
nil
}
// Hex2bin hex2bin()
func
Hex2bin
(
data
string
)
(
string
,
error
)
{
i
,
err
:=
strconv
.
ParseInt
(
data
,
16
,
0
)
if
err
!=
nil
{
return
""
,
err
}
return
strconv
.
FormatInt
(
i
,
2
),
nil
}
// Bin2hex bin2hex()
func
Bin2hex
(
str
string
)
(
string
,
error
)
{
i
,
err
:=
strconv
.
ParseInt
(
str
,
2
,
0
)
if
err
!=
nil
{
return
""
,
err
}
return
strconv
.
FormatInt
(
i
,
16
),
nil
}
// Dechex dechex()
func
Dechex
(
number
int64
)
string
{
return
strconv
.
FormatInt
(
number
,
16
)
}
// Hexdec hexdec()
func
Hexdec
(
str
string
)
(
int64
,
error
)
{
return
strconv
.
ParseInt
(
str
,
16
,
0
)
}
// Decoct decoct()
func
Decoct
(
number
int64
)
string
{
return
strconv
.
FormatInt
(
number
,
8
)
}
// Octdec Octdec()
func
Octdec
(
str
string
)
(
int64
,
error
)
{
return
strconv
.
ParseInt
(
str
,
8
,
0
)
}
// BaseConvert base_convert()
func
BaseConvert
(
number
string
,
frombase
,
tobase
int
)
(
string
,
error
)
{
i
,
err
:=
strconv
.
ParseInt
(
number
,
frombase
,
0
)
if
err
!=
nil
{
return
""
,
err
}
return
strconv
.
FormatInt
(
i
,
tobase
),
nil
}
// IsNan is_nan()
func
IsNan
(
val
float64
)
bool
{
return
math
.
IsNaN
(
val
)
}
//////////// Directory/Filesystem Functions ////////////
// Stat stat()
func
Stat
(
filename
string
)
(
os
.
FileInfo
,
error
)
{
return
os
.
Stat
(
filename
)
}
// Pathinfo pathinfo()
// -1: all; 1: dirname; 2: basename; 4: extension; 8: filename
// Usage:
// Pathinfo("/home/go/path/src/php2go/php2go.go", 1|2|4|8)
func
Pathinfo
(
path
string
,
options
int
)
map
[
string
]
string
{
if
options
==
-
1
{
options
=
1
|
2
|
4
|
8
}
info
:=
make
(
map
[
string
]
string
)
if
(
options
&
1
)
==
1
{
info
[
"dirname"
]
=
filepath
.
Dir
(
path
)
}
if
(
options
&
2
)
==
2
{
info
[
"basename"
]
=
filepath
.
Base
(
path
)
}
if
((
options
&
4
)
==
4
)
||
((
options
&
8
)
==
8
)
{
basename
:=
""
if
(
options
&
2
)
==
2
{
basename
,
_
=
info
[
"basename"
]
}
else
{
basename
=
filepath
.
Base
(
path
)
}
p
:=
strings
.
LastIndex
(
basename
,
"."
)
filename
,
extension
:=
""
,
""
if
p
>
0
{
filename
,
extension
=
basename
[
:
p
],
basename
[
p
+
1
:
]
}
else
if
p
==
-
1
{
filename
=
basename
}
else
if
p
==
0
{
extension
=
basename
[
p
+
1
:
]
}
if
(
options
&
4
)
==
4
{
info
[
"extension"
]
=
extension
}
if
(
options
&
8
)
==
8
{
info
[
"filename"
]
=
filename
}
}
return
info
}
// FileExists file_exists()
func
FileExists
(
filename
string
)
bool
{
_
,
err
:=
os
.
Stat
(
filename
)
if
err
!=
nil
&&
os
.
IsNotExist
(
err
)
{
return
false
}
return
true
}
// IsFile is_file()
func
IsFile
(
filename
string
)
bool
{
_
,
err
:=
os
.
Stat
(
filename
)
if
err
!=
nil
&&
os
.
IsNotExist
(
err
)
{
return
false
}
return
true
}
// IsDir is_dir()
func
IsDir
(
filename
string
)
(
bool
,
error
)
{
fd
,
err
:=
os
.
Stat
(
filename
)
if
err
!=
nil
{
return
false
,
err
}
fm
:=
fd
.
Mode
()
return
fm
.
IsDir
(),
nil
}
// FileSize filesize()
func
FileSize
(
filename
string
)
(
int64
,
error
)
{
info
,
err
:=
os
.
Stat
(
filename
)
if
err
!=
nil
&&
os
.
IsNotExist
(
err
)
{
return
0
,
err
}
return
info
.
Size
(),
nil
}
// FilePutContents file_put_contents()
func
FilePutContents
(
filename
string
,
data
string
,
mode
os
.
FileMode
)
error
{
return
ioutil
.
WriteFile
(
filename
,
[]
byte
(
data
),
mode
)
}
// FileGetContents file_get_contents()
func
FileGetContents
(
filename
string
)
(
string
,
error
)
{
data
,
err
:=
ioutil
.
ReadFile
(
filename
)
return
string
(
data
),
err
}
// Unlink unlink()
func
Unlink
(
filename
string
)
error
{
return
os
.
Remove
(
filename
)
}
// Delete delete()
func
Delete
(
filename
string
)
error
{
return
os
.
Remove
(
filename
)
}
// Copy copy()
func
Copy
(
source
,
dest
string
)
(
bool
,
error
)
{
fd1
,
err
:=
os
.
Open
(
source
)
if
err
!=
nil
{
return
false
,
err
}
defer
fd1
.
Close
()
fd2
,
err
:=
os
.
OpenFile
(
dest
,
os
.
O_WRONLY
|
os
.
O_CREATE
,
0644
)
if
err
!=
nil
{
return
false
,
err
}
defer
fd2
.
Close
()
_
,
e
:=
io
.
Copy
(
fd2
,
fd1
)
if
e
!=
nil
{
return
false
,
e
}
return
true
,
nil
}
// IsReadable is_readable()
func
IsReadable
(
filename
string
)
bool
{
_
,
err
:=
syscall
.
Open
(
filename
,
syscall
.
O_RDONLY
,
0
)
if
err
!=
nil
{
return
false
}
return
true
}
// IsWriteable is_writeable()
func
IsWriteable
(
filename
string
)
bool
{
_
,
err
:=
syscall
.
Open
(
filename
,
syscall
.
O_WRONLY
,
0
)
if
err
!=
nil
{
return
false
}
return
true
}
// Rename rename()
func
Rename
(
oldname
,
newname
string
)
error
{
return
os
.
Rename
(
oldname
,
newname
)
}
// Touch touch()
func
Touch
(
filename
string
)
(
bool
,
error
)
{
fd
,
err
:=
os
.
OpenFile
(
filename
,
os
.
O_RDONLY
|
os
.
O_CREATE
,
0666
)
if
err
!=
nil
{
return
false
,
err
}
fd
.
Close
()
return
true
,
nil
}
// Mkdir mkdir()
func
Mkdir
(
filename
string
,
mode
os
.
FileMode
)
error
{
return
os
.
Mkdir
(
filename
,
mode
)
}
// Getcwd getcwd()
func
Getcwd
()
(
string
,
error
)
{
dir
,
err
:=
os
.
Getwd
()
return
dir
,
err
}
// Realpath realpath()
func
Realpath
(
path
string
)
(
string
,
error
)
{
return
filepath
.
Abs
(
path
)
}
// Basename basename()
func
Basename
(
path
string
)
string
{
return
filepath
.
Base
(
path
)
}
// Chmod chmod()
func
Chmod
(
filename
string
,
mode
os
.
FileMode
)
bool
{
return
os
.
Chmod
(
filename
,
mode
)
==
nil
}
// Chown chown()
func
Chown
(
filename
string
,
uid
,
gid
int
)
bool
{
return
os
.
Chown
(
filename
,
uid
,
gid
)
==
nil
}
// Fclose fclose()
func
Fclose
(
handle
*
os
.
File
)
error
{
return
handle
.
Close
()
}
// Filemtime filemtime()
func
Filemtime
(
filename
string
)
(
int64
,
error
)
{
fd
,
err
:=
os
.
Open
(
filename
)
if
err
!=
nil
{
return
0
,
err
}
defer
fd
.
Close
()
fileinfo
,
err
:=
fd
.
Stat
()
if
err
!=
nil
{
return
0
,
err
}
return
fileinfo
.
ModTime
()
.
Unix
(),
nil
}
// Fgetcsv fgetcsv()
func
Fgetcsv
(
handle
*
os
.
File
,
length
int
,
delimiter
rune
)
([][]
string
,
error
)
{
reader
:=
csv
.
NewReader
(
handle
)
reader
.
Comma
=
delimiter
// TODO length limit
return
reader
.
ReadAll
()
}
// Glob glob()
func
Glob
(
pattern
string
)
([]
string
,
error
)
{
return
filepath
.
Glob
(
pattern
)
}
//////////// Variable handling Functions ////////////
// Empty empty()
func
Empty
(
val
interface
{})
bool
{
if
val
==
nil
{
return
true
}
v
:=
reflect
.
ValueOf
(
val
)
switch
v
.
Kind
()
{
case
reflect
.
String
,
reflect
.
Array
:
return
v
.
Len
()
==
0
case
reflect
.
Map
,
reflect
.
Slice
:
return
v
.
Len
()
==
0
||
v
.
IsNil
()
case
reflect
.
Bool
:
return
!
v
.
Bool
()
case
reflect
.
Int
,
reflect
.
Int8
,
reflect
.
Int16
,
reflect
.
Int32
,
reflect
.
Int64
:
return
v
.
Int
()
==
0
case
reflect
.
Uint
,
reflect
.
Uint8
,
reflect
.
Uint16
,
reflect
.
Uint32
,
reflect
.
Uint64
,
reflect
.
Uintptr
:
return
v
.
Uint
()
==
0
case
reflect
.
Float32
,
reflect
.
Float64
:
return
v
.
Float
()
==
0
case
reflect
.
Interface
,
reflect
.
Ptr
:
return
v
.
IsNil
()
}
return
reflect
.
DeepEqual
(
val
,
reflect
.
Zero
(
v
.
Type
())
.
Interface
())
}
// IsNumeric is_numeric()
// Numeric strings consist of optional sign, any number of digits, optional decimal part and optional exponential part.
// Thus +0123.45e6 is a valid numeric value.
// In PHP hexadecimal (e.g. 0xf4c3b00c) is not supported, but IsNumeric is supported.
func
IsNumeric
(
val
interface
{})
bool
{
switch
val
.
(
type
)
{
case
int
,
int8
,
int16
,
int32
,
int64
,
uint
,
uint8
,
uint16
,
uint32
,
uint64
:
return
true
case
float32
,
float64
,
complex64
,
complex128
:
return
true
case
string
:
str
:=
val
.
(
string
)
if
str
==
""
{
return
false
}
// Trim any whitespace
str
=
strings
.
TrimSpace
(
str
)
if
str
[
0
]
==
'-'
||
str
[
0
]
==
'+'
{
if
len
(
str
)
==
1
{
return
false
}
str
=
str
[
1
:
]
}
// hex
if
len
(
str
)
>
2
&&
str
[
0
]
==
'0'
&&
(
str
[
1
]
==
'x'
||
str
[
1
]
==
'X'
)
{
for
_
,
h
:=
range
str
[
2
:
]
{
if
!
((
h
>=
'0'
&&
h
<=
'9'
)
||
(
h
>=
'a'
&&
h
<=
'f'
)
||
(
h
>=
'A'
&&
h
<=
'F'
))
{
return
false
}
}
return
true
}
// 0-9, Point, Scientific
p
,
s
,
l
:=
0
,
0
,
len
(
str
)
for
i
,
v
:=
range
str
{
if
v
==
'.'
{
// Point
if
p
>
0
||
s
>
0
||
i
+
1
==
l
{
return
false
}
p
=
i
}
else
if
v
==
'e'
||
v
==
'E'
{
// Scientific
if
i
==
0
||
s
>
0
||
i
+
1
==
l
{
return
false
}
s
=
i
}
else
if
v
<
'0'
||
v
>
'9'
{
return
false
}
}
return
true
}
return
false
}
//////////// Program execution Functions ////////////
// Exec exec()
// returnVar, 0: succ; 1: fail
// Return the last line from the result of the command.
// command format eg:
// "ls -a"
// "/bin/bash -c \"ls -a\""
func
Exec
(
command
string
,
output
*
[]
string
,
returnVar
*
int
)
string
{
q
:=
rune
(
0
)
parts
:=
strings
.
FieldsFunc
(
command
,
func
(
r
rune
)
bool
{
switch
{
case
r
==
q
:
q
=
rune
(
0
)
return
false
case
q
!=
rune
(
0
)
:
return
false
case
unicode
.
In
(
r
,
unicode
.
Quotation_Mark
)
:
q
=
r
return
false
default
:
return
unicode
.
IsSpace
(
r
)
}
})
// remove the " and ' on both sides
for
i
,
v
:=
range
parts
{
f
,
l
:=
v
[
0
],
len
(
v
)
if
l
>=
2
&&
(
f
==
'"'
||
f
==
'\'
'
)
{
parts
[
i
]
=
v
[
1
:
l
-
1
]
}
}
cmd
:=
exec
.
Command
(
parts
[
0
],
parts
[
1
:
]
...
)
out
,
err
:=
cmd
.
CombinedOutput
()
if
err
!=
nil
{
*
returnVar
=
1
return
""
}
*
returnVar
=
0
*
output
=
strings
.
Split
(
strings
.
TrimRight
(
string
(
out
),
"
\n
"
),
"
\n
"
)
if
l
:=
len
(
*
output
);
l
>
0
{
return
(
*
output
)[
l
-
1
]
}
return
""
}
// System system()
// returnVar, 0: succ; 1: fail
// Returns the last line of the command output on success, and "" on failure.
func
System
(
command
string
,
returnVar
*
int
)
string
{
*
returnVar
=
0
var
stdBuf
bytes
.
Buffer
var
err
,
err1
,
err2
,
err3
error
// split command
q
:=
rune
(
0
)
parts
:=
strings
.
FieldsFunc
(
command
,
func
(
r
rune
)
bool
{
switch
{
case
r
==
q
:
q
=
rune
(
0
)
return
false
case
q
!=
rune
(
0
)
:
return
false
case
unicode
.
In
(
r
,
unicode
.
Quotation_Mark
)
:
q
=
r
return
false
default
:
return
unicode
.
IsSpace
(
r
)
}
})
// remove the " and ' on both sides
for
i
,
v
:=
range
parts
{
f
,
l
:=
v
[
0
],
len
(
v
)
if
l
>=
2
&&
(
f
==
'"'
||
f
==
'\'
'
)
{
parts
[
i
]
=
v
[
1
:
l
-
1
]
}
}
cmd
:=
exec
.
Command
(
parts
[
0
],
parts
[
1
:
]
...
)
stdoutIn
,
_
:=
cmd
.
StdoutPipe
()
stderrIn
,
_
:=
cmd
.
StderrPipe
()
stdout
:=
io
.
MultiWriter
(
os
.
Stdout
,
&
stdBuf
)
stderr
:=
io
.
MultiWriter
(
os
.
Stderr
,
&
stdBuf
)
err
=
cmd
.
Start
()
if
err
!=
nil
{
*
returnVar
=
1
return
""
}
go
func
()
{
_
,
err1
=
io
.
Copy
(
stdout
,
stdoutIn
)
}()
go
func
()
{
_
,
err2
=
io
.
Copy
(
stderr
,
stderrIn
)
}()
err3
=
cmd
.
Wait
()
if
err1
!=
nil
||
err2
!=
nil
||
err3
!=
nil
{
if
err1
!=
nil
{
fmt
.
Println
(
err1
)
}
if
err2
!=
nil
{
fmt
.
Println
(
err2
)
}
if
err3
!=
nil
{
fmt
.
Println
(
err3
)
}
*
returnVar
=
1
return
""
}
if
output
:=
strings
.
TrimRight
(
stdBuf
.
String
(),
"
\n
"
);
output
!=
""
{
pos
:=
strings
.
LastIndex
(
output
,
"
\n
"
)
if
pos
==
-
1
{
return
output
}
return
output
[
pos
+
1
:
]
}
return
""
}
// Passthru passthru()
// returnVar, 0: succ; 1: fail
func
Passthru
(
command
string
,
returnVar
*
int
)
{
q
:=
rune
(
0
)
parts
:=
strings
.
FieldsFunc
(
command
,
func
(
r
rune
)
bool
{
switch
{
case
r
==
q
:
q
=
rune
(
0
)
return
false
case
q
!=
rune
(
0
)
:
return
false
case
unicode
.
In
(
r
,
unicode
.
Quotation_Mark
)
:
q
=
r
return
false
default
:
return
unicode
.
IsSpace
(
r
)
}
})
// remove the " and ' on both sides
for
i
,
v
:=
range
parts
{
f
,
l
:=
v
[
0
],
len
(
v
)
if
l
>=
2
&&
(
f
==
'"'
||
f
==
'\'
'
)
{
parts
[
i
]
=
v
[
1
:
l
-
1
]
}
}
cmd
:=
exec
.
Command
(
parts
[
0
],
parts
[
1
:
]
...
)
cmd
.
Stdout
=
os
.
Stdout
cmd
.
Stderr
=
os
.
Stderr
err
:=
cmd
.
Run
()
if
err
!=
nil
{
*
returnVar
=
1
fmt
.
Println
(
err
)
}
else
{
*
returnVar
=
0
}
}
//////////// Network Functions ////////////
// Gethostname gethostname()
func
Gethostname
()
(
string
,
error
)
{
return
os
.
Hostname
()
}
// Gethostbyname gethostbyname()
// Get the IPv4 address corresponding to a given Internet host name
func
Gethostbyname
(
hostname
string
)
(
string
,
error
)
{
ips
,
err
:=
net
.
LookupIP
(
hostname
)
if
ips
!=
nil
{
for
_
,
v
:=
range
ips
{
if
v
.
To4
()
!=
nil
{
return
v
.
String
(),
nil
}
}
return
""
,
nil
}
return
""
,
err
}
// Gethostbynamel gethostbynamel()
// Get a list of IPv4 addresses corresponding to a given Internet host name
func
Gethostbynamel
(
hostname
string
)
([]
string
,
error
)
{
ips
,
err
:=
net
.
LookupIP
(
hostname
)
if
ips
!=
nil
{
var
ipstrs
[]
string
for
_
,
v
:=
range
ips
{
if
v
.
To4
()
!=
nil
{
ipstrs
=
append
(
ipstrs
,
v
.
String
())
}
}
return
ipstrs
,
nil
}
return
nil
,
err
}
// Gethostbyaddr gethostbyaddr()
// Get the Internet host name corresponding to a given IP address
func
Gethostbyaddr
(
ipAddress
string
)
(
string
,
error
)
{
names
,
err
:=
net
.
LookupAddr
(
ipAddress
)
if
names
!=
nil
{
return
strings
.
TrimRight
(
names
[
0
],
"."
),
nil
}
return
""
,
err
}
// IP2long ip2long()
// IPv4
func
IP2long
(
ipAddress
string
)
uint32
{
ip
:=
net
.
ParseIP
(
ipAddress
)
if
ip
==
nil
{
return
0
}
return
binary
.
BigEndian
.
Uint32
(
ip
.
To4
())
}
// Long2ip long2ip()
// IPv4
func
Long2ip
(
properAddress
uint32
)
string
{
ipByte
:=
make
([]
byte
,
4
)
binary
.
BigEndian
.
PutUint32
(
ipByte
,
properAddress
)
ip
:=
net
.
IP
(
ipByte
)
return
ip
.
String
()
}
//////////// Misc. Functions ////////////
// Echo echo
func
Echo
(
args
...
interface
{})
{
fmt
.
Print
(
args
...
)
}
// Uniqid uniqid()
func
Uniqid
(
prefix
string
)
string
{
now
:=
time
.
Now
()
return
fmt
.
Sprintf
(
"%s%08x%05x"
,
prefix
,
now
.
Unix
(),
now
.
UnixNano
()
%
0x100000
)
}
// Exit exit()
func
Exit
(
status
int
)
{
os
.
Exit
(
status
)
}
// Die die()
func
Die
(
status
int
)
{
os
.
Exit
(
status
)
}
// Getenv getenv()
func
Getenv
(
varname
string
)
string
{
return
os
.
Getenv
(
varname
)
}
// Putenv putenv()
// The setting, like "FOO=BAR"
func
Putenv
(
setting
string
)
error
{
s
:=
strings
.
Split
(
setting
,
"="
)
if
len
(
s
)
!=
2
{
panic
(
"setting: invalid"
)
}
return
os
.
Setenv
(
s
[
0
],
s
[
1
])
}
// MemoryGetUsage memory_get_usage()
// return in bytes
func
MemoryGetUsage
(
realUsage
bool
)
uint64
{
stat
:=
new
(
runtime
.
MemStats
)
runtime
.
ReadMemStats
(
stat
)
return
stat
.
Alloc
}
// VersionCompare version_compare()
// The possible operators are: <, lt, <=, le, >, gt, >=, ge, ==, =, eq, !=, <>, ne respectively.
// special version strings these are handled in the following order,
// (any string not found) < dev < alpha = a < beta = b < RC = rc < # < pl = p
// Usage:
// VersionCompare("1.2.3-alpha", "1.2.3RC7", '>=')
// VersionCompare("1.2.3-beta", "1.2.3pl", 'lt')
// VersionCompare("1.1_dev", "1.2any", 'eq')
func
VersionCompare
(
version1
,
version2
,
operator
string
)
bool
{
var
vcompare
func
(
string
,
string
)
int
var
canonicalize
func
(
string
)
string
var
special
func
(
string
,
string
)
int
// version compare
vcompare
=
func
(
origV1
,
origV2
string
)
int
{
if
origV1
==
""
||
origV2
==
""
{
if
origV1
==
""
&&
origV2
==
""
{
return
0
}
if
origV1
==
""
{
return
-
1
}
return
1
}
ver1
,
ver2
,
compare
:=
""
,
""
,
0
if
origV1
[
0
]
==
'#'
{
ver1
=
origV1
}
else
{
ver1
=
canonicalize
(
origV1
)
}
if
origV2
[
0
]
==
'#'
{
ver2
=
origV2
}
else
{
ver2
=
canonicalize
(
origV2
)
}
n1
,
n2
:=
0
,
0
for
{
p1
,
p2
:=
""
,
""
n1
=
strings
.
IndexByte
(
ver1
,
'.'
)
if
n1
==
-
1
{
p1
,
ver1
=
ver1
[
:
],
""
}
else
{
p1
,
ver1
=
ver1
[
:
n1
],
ver1
[
n1
+
1
:
]
}
n2
=
strings
.
IndexByte
(
ver2
,
'.'
)
if
n2
==
-
1
{
p2
,
ver2
=
ver2
,
""
}
else
{
p2
,
ver2
=
ver2
[
:
n2
],
ver2
[
n2
+
1
:
]
}
if
(
p1
[
0
]
>=
'0'
&&
p1
[
0
]
<=
'9'
)
&&
(
p2
[
0
]
>=
'0'
&&
p2
[
0
]
<=
'9'
)
{
// all is digit
l1
,
_
:=
strconv
.
Atoi
(
p1
)
l2
,
_
:=
strconv
.
Atoi
(
p2
)
if
l1
>
l2
{
compare
=
1
}
else
if
l1
==
l2
{
compare
=
0
}
else
{
compare
=
-
1
}
}
else
if
!
(
p1
[
0
]
>=
'0'
&&
p1
[
0
]
<=
'9'
)
&&
!
(
p2
[
0
]
>=
'0'
&&
p2
[
0
]
<=
'9'
)
{
// all digit
compare
=
special
(
p1
,
p2
)
}
else
{
// part is digit
if
p1
[
0
]
>=
'0'
&&
p1
[
0
]
<=
'9'
{
// is digit
compare
=
special
(
"#N#"
,
p2
)
}
else
{
compare
=
special
(
p1
,
"#N#"
)
}
}
if
compare
!=
0
||
n1
==
-
1
||
n2
==
-
1
{
break
}
}
if
compare
==
0
{
if
ver1
!=
""
{
if
ver1
[
0
]
>=
'0'
&&
ver1
[
0
]
<=
'9'
{
compare
=
1
}
else
{
compare
=
vcompare
(
ver1
,
"#N#"
)
}
}
else
if
ver2
!=
""
{
if
ver2
[
0
]
>=
'0'
&&
ver2
[
0
]
<=
'9'
{
compare
=
-
1
}
else
{
compare
=
vcompare
(
"#N#"
,
ver2
)
}
}
}
return
compare
}
// canonicalize
canonicalize
=
func
(
version
string
)
string
{
ver
:=
[]
byte
(
version
)
l
:=
len
(
ver
)
if
l
==
0
{
return
""
}
var
buf
=
make
([]
byte
,
l
*
2
)
j
:=
0
for
i
,
v
:=
range
ver
{
next
:=
uint8
(
0
)
if
i
+
1
<
l
{
// Have the next one
next
=
ver
[
i
+
1
]
}
if
v
==
'-'
||
v
==
'_'
||
v
==
'+'
{
// replace '-', '_', '+' to '.'
if
j
>
0
&&
buf
[
j
-
1
]
!=
'.'
{
buf
[
j
]
=
'.'
j
++
}
}
else
if
(
next
>
0
)
&&
(
!
(
next
>=
'0'
&&
next
<=
'9'
)
&&
(
v
>=
'0'
&&
v
<=
'9'
))
||
(
!
(
v
>=
'0'
&&
v
<=
'9'
)
&&
(
next
>=
'0'
&&
next
<=
'9'
))
{
// Insert '.' before and after a non-digit
buf
[
j
]
=
v
j
++
if
v
!=
'.'
&&
next
!=
'.'
{
buf
[
j
]
=
'.'
j
++
}
continue
}
else
if
!
((
v
>=
'0'
&&
v
<=
'9'
)
||
(
v
>=
'a'
&&
v
<=
'z'
)
||
(
v
>=
'A'
&&
v
<=
'Z'
))
{
// Non-letters and numbers
if
j
>
0
&&
buf
[
j
-
1
]
!=
'.'
{
buf
[
j
]
=
'.'
j
++
}
}
else
{
buf
[
j
]
=
v
j
++
}
}
return
string
(
buf
[
:
j
])
}
// compare special version forms
special
=
func
(
form1
,
form2
string
)
int
{
found1
,
found2
,
len1
,
len2
:=
-
1
,
-
1
,
len
(
form1
),
len
(
form2
)
// (Any string not found) < dev < alpha = a < beta = b < RC = rc < # < pl = p
forms
:=
map
[
string
]
int
{
"dev"
:
0
,
"alpha"
:
1
,
"a"
:
1
,
"beta"
:
2
,
"b"
:
2
,
"RC"
:
3
,
"rc"
:
3
,
"#"
:
4
,
"pl"
:
5
,
"p"
:
5
,
}
for
name
,
order
:=
range
forms
{
if
len1
<
len
(
name
)
{
continue
}
if
strings
.
Compare
(
form1
[
:
len
(
name
)],
name
)
==
0
{
found1
=
order
break
}
}
for
name
,
order
:=
range
forms
{
if
len2
<
len
(
name
)
{
continue
}
if
strings
.
Compare
(
form2
[
:
len
(
name
)],
name
)
==
0
{
found2
=
order
break
}
}
if
found1
==
found2
{
return
0
}
else
if
found1
>
found2
{
return
1
}
else
{
return
-
1
}
}
compare
:=
vcompare
(
version1
,
version2
)
switch
operator
{
case
"<"
,
"lt"
:
return
compare
==
-
1
case
"<="
,
"le"
:
return
compare
!=
1
case
">"
,
"gt"
:
return
compare
==
1
case
">="
,
"ge"
:
return
compare
!=
-
1
case
"=="
,
"="
,
"eq"
:
return
compare
==
0
case
"!="
,
"<>"
,
"ne"
:
return
compare
!=
0
default
:
panic
(
"operator: invalid"
)
}
}
// ZipOpen zip_open()
func
ZipOpen
(
filename
string
)
(
*
zip
.
ReadCloser
,
error
)
{
return
zip
.
OpenReader
(
filename
)
}
// Pack pack()
func
Pack
(
order
binary
.
ByteOrder
,
data
interface
{})
(
string
,
error
)
{
buf
:=
new
(
bytes
.
Buffer
)
err
:=
binary
.
Write
(
buf
,
order
,
data
)
if
err
!=
nil
{
return
""
,
err
}
return
buf
.
String
(),
nil
}
// Unpack unpack()
func
Unpack
(
order
binary
.
ByteOrder
,
data
string
)
(
interface
{},
error
)
{
var
result
[]
byte
r
:=
bytes
.
NewReader
([]
byte
(
data
))
err
:=
binary
.
Read
(
r
,
order
,
&
result
)
if
err
!=
nil
{
return
nil
,
err
}
return
result
,
nil
}
// Ternary Ternary expression
// max := Ternary(a > b, a, b).(int)
func
Ternary
(
condition
bool
,
trueVal
,
falseVal
interface
{})
interface
{}
{
if
condition
{
return
trueVal
}
return
falseVal
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment