From cacf57bd4a044185604faf7d45dce09df11fc9cc Mon Sep 17 00:00:00 2001 From: "marko.tikvic" Date: Wed, 3 Apr 2019 14:05:19 +0200 Subject: [PATCH] merging with /utility package --- default_values.go | 65 ++++++++++++ diff.go | 32 ++++++ file_util.go | 63 +++++++++++ http.go | 15 ++- int_util.go | 46 ++++++++ nullables.go | 309 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ string_util.go | 83 +++++++++++++++ 7 files changed, 611 insertions(+), 2 deletions(-) create mode 100644 default_values.go create mode 100644 diff.go create mode 100644 file_util.go create mode 100644 int_util.go create mode 100644 nullables.go create mode 100644 string_util.go diff --git a/default_values.go b/default_values.go new file mode 100644 index 0000000..d9b98b1 --- /dev/null +++ b/default_values.go @@ -0,0 +1,65 @@ +package util + +// IntOrDefault ... +func IntOrDefault(v *int) int { + if v != nil { + return *v + } + return 0 +} + +// Int32OrDefault ... +func Int32OrDefault(v *int32) int32 { + if v != nil { + return *v + } + return 0 +} + +// Int64OrDefault ... +func Int64OrDefault(v *int64) int64 { + if v != nil { + return *v + } + return 0 +} + +// Uint32OrDefault ... +func Uint32OrDefault(v *uint32) uint32 { + if v != nil { + return *v + } + return 0 +} + +// Uint64OrDefault ... +func Uint64OrDefault(v *uint64) uint64 { + if v != nil { + return *v + } + return 0 +} + +// StringOrDefault ... +func StringOrDefault(v *string) string { + if v != nil { + return *v + } + return "" +} + +// Float32OrDefault ... +func Float32OrDefault(v *float32) float32 { + if v != nil { + return *v + } + return 0.0 +} + +// Float64OrDefault ... +func Float64OrDefault(v *float64) float64 { + if v != nil { + return *v + } + return 0.0 +} diff --git a/diff.go b/diff.go new file mode 100644 index 0000000..c9ab90e --- /dev/null +++ b/diff.go @@ -0,0 +1,32 @@ +package util + +// Diff ... +func Diff(old, new []int64) (added, removed []int64) { + for i := range old { + isRemoved := true + for j := range new { + if old[i] == new[j] { + isRemoved = false + break + } + } + if isRemoved { + removed = append(removed, old[i]) + } + } + + for i := range new { + isAdded := true + for j := range old { + if new[i] == old[j] { + isAdded = false + break + } + } + if isAdded { + added = append(added, new[i]) + } + } + + return added, removed +} diff --git a/file_util.go b/file_util.go new file mode 100644 index 0000000..e856d7d --- /dev/null +++ b/file_util.go @@ -0,0 +1,63 @@ +package util + +import ( + "bytes" + "io" + "io/ioutil" + "os" + "strings" +) + +func ReadFileContent(path string) ([]byte, error) { + f, err := os.Open(path) + if err != nil { + return nil, err + } + defer f.Close() + + buf := &bytes.Buffer{} + if _, err = io.Copy(buf, f); err != nil { + return nil, err + } + + return buf.Bytes(), nil +} + +// ReadFileLines ... +func ReadFileLines(path string) ([]string, error) { + f, err := os.Open(path) + if err != nil { + return nil, err + } + defer f.Close() + + var s strings.Builder + + if _, err = io.Copy(&s, f); err != nil { + return nil, err + } + + lines := strings.Split(s.String(), "\n") + for i := range lines { + lines[i] = strings.TrimRight(lines[i], "\r\n") + } + + return lines, nil +} + +// LinesToFile ... +func LinesToFile(path string, lines []string) error { + content := "" + for _, l := range lines { + content += l + "\n" + } + + return ioutil.WriteFile(path, []byte(content), 0644) // drw-r--r-- +} + +// InsertLine ... +func InsertLine(lines *[]string, pos int64, l string) { + tail := append([]string{l}, (*lines)[pos:]...) + + *lines = append((*lines)[:pos], tail...) +} diff --git a/http.go b/http.go index fd425c5..2435465 100644 --- a/http.go +++ b/http.go @@ -58,12 +58,24 @@ func NotFoundHandlerFunc(w http.ResponseWriter, req *http.Request) { NotFound(w, req, fmt.Sprintf("Resource you requested was not found: %s", req.URL.String())) } +func SetContentType(w http.ResponseWriter, ctype string) { + w.Header().Set("Content-Type", ctype) +} + +func SetResponseStatus(w http.ResponseWriter, status int) { + w.WriteHeader(status) +} + +func WriteResponse(w http.ResponseWriter, content []byte) { + w.Write(content) +} + // SetDefaultHeaders set's default headers for an HTTP response. func SetDefaultHeaders(w http.ResponseWriter) { w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE, OPTIONS") w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization") - w.Header().Set("Content-Type", "application/json; charset=utf-8") + SetContentType(w, "application/json; charset=utf-8") } // GetLocale ... @@ -134,4 +146,3 @@ func Conflict(w http.ResponseWriter, r *http.Request, err string) { func InternalServerError(w http.ResponseWriter, r *http.Request, err string) { Error(w, r, http.StatusInternalServerError, err) } - diff --git a/int_util.go b/int_util.go new file mode 100644 index 0000000..14c59d3 --- /dev/null +++ b/int_util.go @@ -0,0 +1,46 @@ +package util + +import ( + "fmt" + "strconv" +) + +// ClampInt64 ... +func ClampInt64(v, min, max int64) int64 { + if v < min { + return min + } else if v > max { + return max + } + + return v +} + +// InRangeInt64 ... +func InRangeInt64(v, min, max int64) bool { + return (v >= min && v <= max) +} + +// StringToInt64 ... +func StringToInt64(s string) int64 { + i, _ := strconv.ParseInt(s, 10, 64) + return i +} + +// Int64ToString ... +func Int64ToString(i int64) string { + return fmt.Sprintf("%d", i) +} + +// BoolToInt64 ... +func BoolToInt64(b bool) int64 { + if b { + return 1 + } + return 0 +} + +// Int64ToBool ... +func Int64ToBool(i int64) bool { + return i != 0 +} diff --git a/nullables.go b/nullables.go new file mode 100644 index 0000000..c99385f --- /dev/null +++ b/nullables.go @@ -0,0 +1,309 @@ +package util + +import ( + "database/sql" + "database/sql/driver" + "encoding/json" + "fmt" + "time" +) + +// NullBool is a wrapper for sql.NullBool with added JSON (un)marshalling +type NullBool sql.NullBool + +// Scan ... +func (nb *NullBool) Scan(value interface{}) error { + var b sql.NullBool + if err := b.Scan(value); err != nil { + nb.Bool, nb.Valid = false, false + return err + } + nb.Bool, nb.Valid = b.Bool, b.Valid + return nil +} + +// Value ... +func (nb *NullBool) Value() (driver.Value, error) { + if !nb.Valid { + return nil, nil + } + return nb.Bool, nil +} + +// MarshalJSON ... +func (nb NullBool) MarshalJSON() ([]byte, error) { + if nb.Valid { + return json.Marshal(nb.Bool) + } + + return json.Marshal(nil) +} + +// UnmarshalJSON ... +func (nb *NullBool) UnmarshalJSON(b []byte) error { + var temp *bool + if err := json.Unmarshal(b, &temp); err != nil { + return err + } + if temp != nil { + nb.Valid = true + nb.Bool = *temp + } else { + nb.Valid = false + } + return nil +} + +// SQLCast ... +func (nb *NullBool) SQLCast() sql.NullBool { + return sql.NullBool(*nb) +} + +// NullString is a wrapper for sql.NullString with added JSON (un)marshalling +type NullString sql.NullString + +// Scan ... +func (ns *NullString) Scan(value interface{}) error { + var s sql.NullString + if err := s.Scan(value); err != nil { + ns.String, ns.Valid = "", false + return err + } + ns.String, ns.Valid = s.String, s.Valid + return nil +} + +// Value ... +func (ns *NullString) Value() (driver.Value, error) { + if !ns.Valid { + return nil, nil + } + return ns.String, nil +} + +// MarshalJSON ... +func (ns NullString) MarshalJSON() ([]byte, error) { + if ns.Valid { + return json.Marshal(ns.String) + } + return json.Marshal(nil) +} + +// UnmarshalJSON ... +func (ns *NullString) UnmarshalJSON(b []byte) error { + var temp *string + if err := json.Unmarshal(b, &temp); err != nil { + return err + } + if temp != nil { + ns.Valid = true + ns.String = *temp + } else { + ns.Valid = false + } + return nil +} + +// SQLCast ... +func (ns *NullString) SQLCast() sql.NullString { + return sql.NullString(*ns) +} + +// NullInt64 is a wrapper for sql.NullInt64 with added JSON (un)marshalling +type NullInt64 sql.NullInt64 + +// Scan ... +func (ni *NullInt64) Scan(value interface{}) error { + var i sql.NullInt64 + if err := i.Scan(value); err != nil { + ni.Int64, ni.Valid = 0, false + return err + } + ni.Int64, ni.Valid = i.Int64, i.Valid + return nil +} + +// Value ... +func (ni *NullInt64) Value() (driver.Value, error) { + if !ni.Valid { + return nil, nil + } + return ni.Int64, nil +} + +// MarshalJSON ... +func (ni NullInt64) MarshalJSON() ([]byte, error) { + if ni.Valid { + return json.Marshal(ni.Int64) + } + return json.Marshal(nil) +} + +// UnmarshalJSON ... +func (ni *NullInt64) UnmarshalJSON(b []byte) error { + var temp *int64 + if err := json.Unmarshal(b, &temp); err != nil { + return err + } + if temp != nil { + ni.Valid = true + ni.Int64 = *temp + } else { + ni.Valid = false + } + return nil +} + +// SQLCast ... +func (ni *NullInt64) SQLCast() sql.NullInt64 { + return sql.NullInt64(*ni) +} + +// NullFloat64 is a wrapper for sql.NullFloat64 with added JSON (un)marshalling +type NullFloat64 sql.NullFloat64 + +// Scan ... +func (nf *NullFloat64) Scan(value interface{}) error { + var f sql.NullFloat64 + if err := f.Scan(value); err != nil { + nf.Float64, nf.Valid = 0.0, false + return err + } + nf.Float64, nf.Valid = f.Float64, f.Valid + return nil +} + +// Value ... +func (nf *NullFloat64) Value() (driver.Value, error) { + if !nf.Valid { + return nil, nil + } + return nf.Float64, nil +} + +// MarshalJSON ... +func (nf NullFloat64) MarshalJSON() ([]byte, error) { + if nf.Valid { + return json.Marshal(nf.Float64) + } + return json.Marshal(nil) +} + +// UnmarshalJSON ... +func (nf *NullFloat64) UnmarshalJSON(b []byte) error { + var temp *float64 + if err := json.Unmarshal(b, &temp); err != nil { + return err + } + if temp != nil { + nf.Valid = true + nf.Float64 = *temp + } else { + nf.Valid = false + } + return nil +} + +// SQLCast ... +func (nf *NullFloat64) SQLCast() sql.NullFloat64 { + return sql.NullFloat64(*nf) +} + +// NullTime ... +type NullTime struct { + Time time.Time + Valid bool // Valid is true if Time is not NULL +} + +// Scan ... +func (nt *NullTime) Scan(value interface{}) (err error) { + if value == nil { + nt.Time, nt.Valid = time.Time{}, false + return + } + + switch v := value.(type) { + case time.Time: + nt.Time, nt.Valid = v, true + return + case []byte: + nt.Time, err = parseDateTime(string(v), time.UTC) + nt.Valid = (err == nil) + return + case string: + nt.Time, err = parseDateTime(v, time.UTC) + nt.Valid = (err == nil) + return + } + + nt.Valid = false + return fmt.Errorf("Can't convert %T to time.Time", value) +} + +// Value implements the driver Valuer interface. +func (nt NullTime) Value() (driver.Value, error) { + if !nt.Valid { + return nil, nil + } + return nt.Time, nil +} + +// MarshalJSON ... +func (nt NullTime) MarshalJSON() ([]byte, error) { + if nt.Valid { + format := nt.Time.Format("2006-01-02 15:04:05") + return json.Marshal(format) + } + return json.Marshal(nil) +} + +// UnmarshalJSON ... +func (nt *NullTime) UnmarshalJSON(b []byte) error { + var temp *time.Time + var t1 time.Time + var err error + + s1 := string(b) + s2 := s1[1 : len(s1)-1] + if s1 == "null" { + temp = nil + } else { + t1, err = time.Parse("2006-01-02 15:04:05", s2) + if err != nil { + return err + } + temp = &t1 + } + + if temp != nil { + nt.Valid = true + nt.Time = *temp + } else { + nt.Valid = false + } + return nil +} + +func parseDateTime(str string, loc *time.Location) (t time.Time, err error) { + base := "0000-00-00 00:00:00.0000000" + timeFormat := "2006-01-02 15:04:05.999999" + switch len(str) { + case 10, 19, 21, 22, 23, 24, 25, 26: // up to "YYYY-MM-DD HH:MM:SS.MMMMMM" + if str == base[:len(str)] { + return + } + t, err = time.Parse(timeFormat[:len(str)], str) + default: + err = fmt.Errorf("invalid time string: %s", str) + return + } + + // Adjust location + if err == nil && loc != time.UTC { + y, mo, d := t.Date() + h, mi, s := t.Clock() + t, err = time.Date(y, mo, d, h, mi, s, t.Nanosecond(), loc), nil + } + + return +} diff --git a/string_util.go b/string_util.go new file mode 100644 index 0000000..07f7155 --- /dev/null +++ b/string_util.go @@ -0,0 +1,83 @@ +package util + +import ( + "fmt" + "strings" +) + +// IsWrappedWith ... +func IsWrappedWith(src, begin, end string) bool { + return strings.HasPrefix(src, begin) && strings.HasSuffix(src, end) +} + +// ParseInt64Arr ... +func ParseInt64Arr(s, sep string) (arr []int64) { + s = strings.TrimSpace(s) + if s != "" { + parts := strings.Split(s, sep) + arr = make([]int64, len(parts)) + for i, p := range parts { + num := StringToInt64(p) + arr[i] = num + } + } + + return arr +} + +// Int64SliceToString ... +func Int64SliceToString(arr []int64) (s string) { + for i, num := range arr { + if i == 0 { + s += fmt.Sprintf("%d", num) + } else { + s += fmt.Sprintf(",%d", num) + } + } + + return s +} + +// CombineStrings ... +func CombineStrings(s1, s2, s3 string) string { + s1 = strings.TrimSpace(s1) + s2 = strings.TrimSpace(s2) + + if s1 != "" && s2 != "" { + s1 += s3 + s2 + } else { + s1 += s2 + } + + return s1 +} + +// ReplaceAny replaces any of the characters from patern found in s with r and returns a new resulting string. +func ReplaceAny(s, patern, r string) (n string) { + n = s + for _, c := range patern { + n = strings.Replace(n, string(c), r, -1) + } + return n +} + +func StringToBool(s string) bool { + s = strings.ToLower(s) + if s == "true" { + return true + } + return false +} + +func BoolToString(b bool) string { + return fmt.Sprintf("%b", b) +} + +func StringSliceContains(slice []string, s string) bool { + for i := range slice { + if slice[i] == s { + return true + } + } + return false +} -- 1.8.1.2