github.com/aldelo/common@v1.5.1/helper-other.go (about)

     1  package helper
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"runtime"
     7  	"strings"
     8  	"time"
     9  )
    10  
    11  /*
    12   * Copyright 2020-2023 Aldelo, LP
    13   *
    14   * Licensed under the Apache License, Version 2.0 (the "License");
    15   * you may not use this file except in compliance with the License.
    16   * You may obtain a copy of the License at
    17   *
    18   *     http://www.apache.org/licenses/LICENSE-2.0
    19   *
    20   * Unless required by applicable law or agreed to in writing, software
    21   * distributed under the License is distributed on an "AS IS" BASIS,
    22   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    23   * See the License for the specific language governing permissions and
    24   * limitations under the License.
    25   */
    26  
    27  // ================================================================================================================
    28  // Variadic Optional Value Helpers
    29  // ================================================================================================================
    30  
    31  // GetFirstOrDefault will select the first variadic value from paramValue,
    32  // if no paramValue variadic, then defaultValue is used as return value
    33  func GetFirstOrDefault(defaultValue interface{}, paramValue ...interface{}) interface{} {
    34  	if len(paramValue) > 0 {
    35  		return paramValue[0]
    36  	} else {
    37  		// returning default
    38  		return defaultValue
    39  	}
    40  }
    41  
    42  // GetFirstIntOrDefault will select the first variadic value from paramValue,
    43  // if no paramValue variadic, then defaultValue is used as return value
    44  func GetFirstIntOrDefault(defaultValue int, paramValue ...int) int {
    45  	if len(paramValue) > 0 {
    46  		return paramValue[0]
    47  	} else {
    48  		// returning default
    49  		return defaultValue
    50  	}
    51  }
    52  
    53  // GetFirstInt64OrDefault will select the first variadic value from paramValue,
    54  // if no paramValue variadic, then defaultValue is used as return value
    55  func GetFirstInt64OrDefault(defaultValue int64, paramValue ...int64) int64 {
    56  	if len(paramValue) > 0 {
    57  		return paramValue[0]
    58  	} else {
    59  		// returning default
    60  		return defaultValue
    61  	}
    62  }
    63  
    64  // GetFirstStringOrDefault will select the first variadic value from paramValue,
    65  // if no paramValue variadic, then defaultValue is used as return value
    66  func GetFirstStringOrDefault(defaultValue string, paramValue ...string) string {
    67  	if len(paramValue) > 0 {
    68  		return paramValue[0]
    69  	} else {
    70  		// returning default
    71  		return defaultValue
    72  	}
    73  }
    74  
    75  // GetFirstBoolOrDefault will select the first variadic value from paramValue,
    76  // if no paramValue variadic, then defaultValue is used as return value
    77  func GetFirstBoolOrDefault(defaultValue bool, paramValue ...bool) bool {
    78  	if len(paramValue) > 0 {
    79  		return paramValue[0]
    80  	} else {
    81  		// returning default
    82  		return defaultValue
    83  	}
    84  }
    85  
    86  // GetFirstFloat32OrDefault will select the first variadic value from paramValue,
    87  // if no paramValue variadic, then defaultValue is used as return value
    88  func GetFirstFloat32OrDefault(defaultValue float32, paramValue ...float32) float32 {
    89  	if len(paramValue) > 0 {
    90  		return paramValue[0]
    91  	} else {
    92  		// returning default
    93  		return defaultValue
    94  	}
    95  }
    96  
    97  // GetFirstFloat64OrDefault will select the first variadic value from paramValue,
    98  // if no paramValue variadic, then defaultValue is used as return value
    99  func GetFirstFloat64OrDefault(defaultValue float64, paramValue ...float64) float64 {
   100  	if len(paramValue) > 0 {
   101  		return paramValue[0]
   102  	} else {
   103  		// returning default
   104  		return defaultValue
   105  	}
   106  }
   107  
   108  // GetFirstTimeOrDefault will select the first variadic value from paramValue,
   109  // if no paramValue variadic, then defaultValue is used as return value
   110  func GetFirstTimeOrDefault(defaultValue time.Time, paramValue ...time.Time) time.Time {
   111  	if len(paramValue) > 0 {
   112  		return paramValue[0]
   113  	} else {
   114  		// returning default
   115  		return defaultValue
   116  	}
   117  }
   118  
   119  // GetFirstByteOrDefault will select the first variadic value from paramValue,
   120  // if no paramValue variadic, then defaultValue is used as return value
   121  func GetFirstByteOrDefault(defaultValue byte, paramValue ...byte) byte {
   122  	if len(paramValue) > 0 {
   123  		return paramValue[0]
   124  	} else {
   125  		// returning default
   126  		return defaultValue
   127  	}
   128  }
   129  
   130  // ================================================================================================================
   131  // slice helpers
   132  // ================================================================================================================
   133  
   134  // IntSliceContains checks if value is contained within the intSlice
   135  func IntSliceContains(intSlice *[]int, value int) bool {
   136  	if intSlice == nil {
   137  		return false
   138  	} else {
   139  		for _, v := range *intSlice {
   140  			if v == value {
   141  				return true
   142  			}
   143  		}
   144  
   145  		return false
   146  	}
   147  }
   148  
   149  // StringSliceContains checks if value is contained within the strSlice
   150  func StringSliceContains(strSlice *[]string, value string) bool {
   151  	if strSlice == nil {
   152  		return false
   153  	} else {
   154  		for _, v := range *strSlice {
   155  			if strings.ToLower(v) == strings.ToLower(value) {
   156  				return true
   157  			}
   158  		}
   159  
   160  		return false
   161  	}
   162  }
   163  
   164  // StringSliceExtractUnique returns unique string slice elements
   165  func StringSliceExtractUnique(strSlice []string) (result []string) {
   166  	if strSlice == nil {
   167  		return []string{}
   168  	} else if len(strSlice) <= 1 {
   169  		return strSlice
   170  	} else {
   171  		for _, v := range strSlice {
   172  			if !StringSliceContains(&result, v) {
   173  				result = append(result, v)
   174  			}
   175  		}
   176  
   177  		return result
   178  	}
   179  }
   180  
   181  // SliceSeekElement returns the first filterFunc input object's true response
   182  // note: use SliceObjectToSliceInterface to convert slice of objects to slice of interface before passing to slice parameter
   183  func SliceSeekElement(slice []interface{}, filterFunc func(input interface{}, filter ...interface{}) bool, filterParam ...interface{}) interface{} {
   184  	if len(slice) == 0 {
   185  		return nil
   186  	}
   187  
   188  	if filterFunc == nil {
   189  		return nil
   190  	}
   191  
   192  	if len(filterParam) == 0 {
   193  		return nil
   194  	}
   195  
   196  	for _, v := range slice {
   197  		if filterFunc(v, filterParam...) {
   198  			// found
   199  			return v
   200  		}
   201  	}
   202  
   203  	// not found
   204  	return nil
   205  }
   206  
   207  // SliceDeleteElement accepts slice (value type or pointer type, primitive or complex struct),
   208  // removes element by index position removalIndex,
   209  // and returns the reassembled result slice without the removed element
   210  //
   211  // note: this method does not preserve element ordering, this is in order to achieve faster call performance
   212  //
   213  // removalIndex = positive number indicates element removal index position (0-based index)
   214  //
   215  //	  negative number indicates element removal index from right,
   216  //		-1 = last element to remove; -2 = second to the last to remove, and so on
   217  //	  positive / negative number out of bound = returns original slice unchanged
   218  //
   219  // if resultSlice is nil, then no slice remain
   220  func SliceDeleteElement(slice interface{}, removalIndex int) (resultSlice interface{}) {
   221  	sliceObj := reflect.ValueOf(slice)
   222  
   223  	if sliceObj.Kind() == reflect.Ptr {
   224  		sliceObj = sliceObj.Elem()
   225  	}
   226  
   227  	if sliceObj.Kind() != reflect.Slice {
   228  		return nil
   229  	}
   230  
   231  	if removalIndex < 0 {
   232  		removalIndex = sliceObj.Len() - AbsInt(removalIndex)
   233  
   234  		if removalIndex < 0 {
   235  			return slice
   236  		}
   237  	}
   238  
   239  	if removalIndex > sliceObj.Len()-1 {
   240  		return slice
   241  	}
   242  
   243  	rm := sliceObj.Index(removalIndex)
   244  	last := sliceObj.Index(sliceObj.Len() - 1)
   245  
   246  	if rm.CanSet() {
   247  		rm.Set(last)
   248  	} else {
   249  		return slice
   250  	}
   251  
   252  	return sliceObj.Slice(0, sliceObj.Len()-1).Interface()
   253  }
   254  
   255  // ================================================================================================================
   256  // console helpers
   257  // ================================================================================================================
   258  
   259  // ConsolePromptAndAnswer is a helper to prompt a message and then scan a response in console
   260  func ConsolePromptAndAnswer(prompt string, replyLowercase bool, autoTrim ...bool) string {
   261  	fmt.Print(prompt)
   262  
   263  	answer := ""
   264  
   265  	if _, e := fmt.Scanln(&answer); e != nil {
   266  		answer = ""
   267  		fmt.Println()
   268  	} else {
   269  		answer = RightTrimLF(answer)
   270  
   271  		if replyLowercase {
   272  			answer = strings.ToLower(answer)
   273  		}
   274  
   275  		if len(autoTrim) > 0 {
   276  			if autoTrim[0] {
   277  				answer = Trim(answer)
   278  			}
   279  		}
   280  
   281  		fmt.Println()
   282  	}
   283  
   284  	return answer
   285  }
   286  
   287  // ConsolePromptAndAnswerBool is a helper to prompt a message and then scan a response in console
   288  func ConsolePromptAndAnswerBool(prompt string, defaultTrue ...bool) bool {
   289  	fmt.Print(prompt)
   290  
   291  	answer := ""
   292  	result := false
   293  	defVal := false
   294  
   295  	if len(defaultTrue) > 0 {
   296  		if defaultTrue[0] {
   297  			defVal = true
   298  		}
   299  	}
   300  
   301  	if _, e := fmt.Scanln(&answer); e != nil {
   302  		fmt.Println()
   303  		return defVal
   304  	} else {
   305  		answer = RightTrimLF(answer)
   306  
   307  		if LenTrim(answer) > 0 {
   308  			result, _ = ParseBool(answer)
   309  		} else {
   310  			result = defVal
   311  		}
   312  
   313  		fmt.Println()
   314  	}
   315  
   316  	return result
   317  }
   318  
   319  // ConsolePromptAndAnswerInt is a helper to prompt a message and then scan a response in console
   320  func ConsolePromptAndAnswerInt(prompt string, preventNegative ...bool) int {
   321  	fmt.Print(prompt)
   322  
   323  	answer := ""
   324  	result := 0
   325  
   326  	if _, e := fmt.Scanln(&answer); e != nil {
   327  		fmt.Println()
   328  		return 0
   329  	} else {
   330  		answer = RightTrimLF(answer)
   331  		result, _ = ParseInt32(answer)
   332  
   333  		if result < 0 {
   334  			if len(preventNegative) > 0 {
   335  				if preventNegative[0] {
   336  					result = 0
   337  				}
   338  			}
   339  		}
   340  
   341  		fmt.Println()
   342  	}
   343  
   344  	return result
   345  }
   346  
   347  // ConsolePromptAndAnswerFloat64 is a helper to prompt a message and then scan a response in console
   348  func ConsolePromptAndAnswerFloat64(prompt string, preventNegative ...bool) float64 {
   349  	fmt.Print(prompt)
   350  
   351  	answer := ""
   352  	result := float64(0)
   353  
   354  	if _, e := fmt.Scanln(&answer); e != nil {
   355  		fmt.Println()
   356  		return 0
   357  	} else {
   358  		answer = RightTrimLF(answer)
   359  		result, _ = ParseFloat64(answer)
   360  
   361  		if result < 0 {
   362  			if len(preventNegative) > 0 {
   363  				if preventNegative[0] {
   364  					result = 0
   365  				}
   366  			}
   367  		}
   368  
   369  		fmt.Println()
   370  	}
   371  
   372  	return result
   373  }
   374  
   375  // ErrorMessage find the error cause time, file, code line number and error message
   376  func ErrorMessage(err error) string {
   377  
   378  	_, file, line, _ := runtime.Caller(1)
   379  	indexFunc := func(file string) string {
   380  		backup := "/" + file
   381  		lastSlashIndex := strings.LastIndex(backup, "/")
   382  		if lastSlashIndex < 0 {
   383  			return backup
   384  		}
   385  		secondLastSlashIndex := strings.LastIndex(backup[:lastSlashIndex], "/")
   386  		if secondLastSlashIndex < 0 {
   387  			return backup[lastSlashIndex+1:]
   388  		}
   389  		return backup[secondLastSlashIndex+1:]
   390  	}
   391  
   392  	logmessage := fmt.Sprintf("%v %v:%v:%v", time.Now().UTC().Format("2006-01-02 15:04:05.000"), indexFunc(file), line, err.Error())
   393  
   394  	return logmessage
   395  }