github.com/spi-ca/misc@v1.0.1/strutil/format.go (about)

     1  package strutil
     2  
     3  import (
     4  	"math"
     5  	"strings"
     6  )
     7  
     8  // FillBytes fill the destination byte array with the given pattern.
     9  func FillBytes(dst []byte, pattern []byte) {
    10  	for i := 0; i < len(dst); i++ {
    11  		dst[i] = pattern[i%len(pattern)]
    12  	}
    13  }
    14  
    15  // FillByte fills the destination byte array with a single byte.
    16  func FillByte(dst []byte, pattern byte) {
    17  	for i := 0; i < len(dst); i++ {
    18  		dst[i] = pattern
    19  	}
    20  }
    21  
    22  // StrPad method pads the input string with the padString until the resulting string reaches the given length
    23  func StrPad(input string, padLength int, padString string, rightPad bool) (output string) {
    24  	var (
    25  		inputLength     = len(input)
    26  		padStringLength = len(padString)
    27  	)
    28  	if inputLength >= padLength {
    29  		return input
    30  	}
    31  
    32  	var (
    33  		repeat  = int(math.Ceil(float64(1) + (float64(padLength-padStringLength))/float64(padStringLength)))
    34  		builder strings.Builder
    35  	)
    36  	builder.Grow(inputLength + padStringLength*repeat)
    37  	if rightPad {
    38  		builder.WriteString(input)
    39  		for i := 0; i < repeat; i++ {
    40  			builder.WriteString(padString)
    41  		}
    42  		output = builder.String()[:padLength]
    43  	} else {
    44  		for i := 0; i < repeat; i++ {
    45  			builder.WriteString(padString)
    46  		}
    47  		builder.WriteString(input)
    48  		output = builder.String()[builder.Len()-padLength:]
    49  	}
    50  
    51  	return
    52  }
    53  
    54  // StrPadSingle method pads the input string with a single character until the resulting string reaches the given length
    55  func StrPadSingle(input string, padLength int, pad byte, rightPad bool) (output string) {
    56  	var (
    57  		inputLength = len(input)
    58  	)
    59  	if inputLength >= padLength {
    60  		return input
    61  	}
    62  
    63  	var (
    64  		builder strings.Builder
    65  	)
    66  	builder.Grow(inputLength + padLength)
    67  	if rightPad {
    68  		builder.WriteString(input)
    69  		for i := 0; i < padLength; i++ {
    70  			builder.WriteByte(pad)
    71  		}
    72  		output = builder.String()[:padLength]
    73  	} else {
    74  		for i := 0; i < padLength; i++ {
    75  			builder.WriteByte(pad)
    76  		}
    77  		builder.WriteString(input)
    78  		output = builder.String()[builder.Len()-padLength:]
    79  	}
    80  
    81  	return
    82  }
    83  
    84  // BytesPad method pads the input byte array with the padData byte array until the resulting string reaches the given length
    85  func BytesPad(input []byte, padLength int, padData []byte, rightPad bool) (output []byte) {
    86  	var (
    87  		inputLength   = len(input)
    88  		padDataLength = len(padData)
    89  	)
    90  	if inputLength >= padLength {
    91  		output = make([]byte, inputLength)
    92  		copy(output, input)
    93  		return
    94  	}
    95  
    96  	var (
    97  		repeat            = int(math.Ceil(float64(1) + (float64(padLength-padDataLength))/float64(padDataLength)))
    98  		maxFillLength     = repeat * padDataLength
    99  		bufSize           = inputLength + repeat*padDataLength
   100  		padArea, fillArea []byte
   101  	)
   102  
   103  	output = make([]byte, bufSize)
   104  
   105  	if rightPad {
   106  		fillArea, padArea = output[0:inputLength], output[inputLength:bufSize]
   107  		output = output[:padLength]
   108  	} else {
   109  		fillArea, padArea = output[maxFillLength:bufSize], output[0:maxFillLength]
   110  		output = output[inputLength+maxFillLength-padLength:]
   111  	}
   112  
   113  	// copy data
   114  	copy(fillArea, input)
   115  	// fill pad
   116  	for i := 0; i < repeat; i++ {
   117  		copy(padArea[:padDataLength], padData)
   118  		padArea = padArea[padDataLength:]
   119  	}
   120  
   121  	return
   122  }
   123  
   124  // BytesPad method pads the input byte array with a single byte until the resulting string reaches the given length
   125  func BytesPadSingle(input []byte, padLength int, pad byte, rightPad bool) (output []byte) {
   126  	var (
   127  		inputLength = len(input)
   128  	)
   129  	if inputLength >= padLength {
   130  		output = make([]byte, inputLength)
   131  		copy(output, input)
   132  		return
   133  	}
   134  
   135  	var (
   136  		maxFillLength     = padLength
   137  		bufSize           = inputLength + padLength
   138  		padArea, fillArea []byte
   139  	)
   140  
   141  	output = make([]byte, bufSize)
   142  
   143  	if rightPad {
   144  		fillArea, padArea = output[0:inputLength], output[inputLength:bufSize]
   145  		output = output[:padLength]
   146  	} else {
   147  		fillArea, padArea = output[maxFillLength:bufSize], output[0:maxFillLength]
   148  		output = output[inputLength+maxFillLength-padLength:]
   149  	}
   150  
   151  	// copy data
   152  	copy(fillArea, input)
   153  	// fill pad
   154  	FillByte(padArea, pad)
   155  	return
   156  }
   157  
   158  // BytesUnPadSingle method removes a given pad character from both ends.
   159  func BytesUnPadSingle(input []byte, pad byte, rightPad bool, copyData bool) (output []byte) {
   160  	var (
   161  		limit  = len(input)
   162  		offset = 0
   163  	)
   164  	if rightPad {
   165  		for ; limit > offset; limit-- {
   166  			if input[limit-1] != pad {
   167  				break
   168  			}
   169  		}
   170  	} else {
   171  		for ; offset < limit; offset++ {
   172  			if input[offset] != pad {
   173  				break
   174  			}
   175  		}
   176  	}
   177  	if limit-offset < 1 {
   178  		return
   179  	}
   180  	if copyData {
   181  		output = make([]byte, limit-offset)
   182  		copy(output, input[offset:limit])
   183  	} else {
   184  		output = input[offset:limit]
   185  	}
   186  	return
   187  }