mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-11-02 16:52:25 -06:00 
			
		
		
		
	
		
			
	
	
		
			113 lines
		
	
	
	
		
			3.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
		
		
			
		
	
	
			113 lines
		
	
	
	
		
			3.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| 
								 | 
							
								package split
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								import (
							 | 
						||
| 
								 | 
							
									"strconv"
							 | 
						||
| 
								 | 
							
									"time"
							 | 
						||
| 
								 | 
							
									"unsafe"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									"codeberg.org/gruf/go-bytesize"
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// joinFunc will join given slice of elements, using the passed function to append each element at index
							 | 
						||
| 
								 | 
							
								// from the slice, forming a combined comma-space separated string. Passed size is for buffer preallocation.
							 | 
						||
| 
								 | 
							
								func JoinFunc[T any](slice []T, each func(buf []byte, value T) []byte, size int) string {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Move nil check
							 | 
						||
| 
								 | 
							
									// outside main loop.
							 | 
						||
| 
								 | 
							
									if each == nil {
							 | 
						||
| 
								 | 
							
										panic("nil func")
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Catch easiest case
							 | 
						||
| 
								 | 
							
									if len(slice) == 0 {
							 | 
						||
| 
								 | 
							
										return ""
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Preallocate string buffer (size + commas)
							 | 
						||
| 
								 | 
							
									buf := make([]byte, 0, size+len(slice)-1)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for _, value := range slice {
							 | 
						||
| 
								 | 
							
										// Append each item
							 | 
						||
| 
								 | 
							
										buf = each(buf, value)
							 | 
						||
| 
								 | 
							
										buf = append(buf, ',', ' ')
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Drop final comma-space
							 | 
						||
| 
								 | 
							
									buf = buf[:len(buf)-2]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Directly cast buf to string
							 | 
						||
| 
								 | 
							
									data := unsafe.SliceData(buf)
							 | 
						||
| 
								 | 
							
									return unsafe.String(data, len(buf))
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// JoinStrings will pass string slice to JoinFunc(), quoting where
							 | 
						||
| 
								 | 
							
								// necessary and combining into a single comma-space separated string.
							 | 
						||
| 
								 | 
							
								func JoinStrings[String ~string](slice []String) string {
							 | 
						||
| 
								 | 
							
									var size int
							 | 
						||
| 
								 | 
							
									for _, str := range slice {
							 | 
						||
| 
								 | 
							
										size += len(str)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									return JoinFunc(slice, func(buf []byte, value String) []byte {
							 | 
						||
| 
								 | 
							
										return appendQuote(buf, string(value))
							 | 
						||
| 
								 | 
							
									}, size)
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// JoinBools will pass bool slice to JoinFunc(), formatting
							 | 
						||
| 
								 | 
							
								// and combining into a single comma-space separated string.
							 | 
						||
| 
								 | 
							
								func JoinBools[Bool ~bool](slice []Bool) string {
							 | 
						||
| 
								 | 
							
									return JoinFunc(slice, func(buf []byte, value Bool) []byte {
							 | 
						||
| 
								 | 
							
										return strconv.AppendBool(buf, bool(value))
							 | 
						||
| 
								 | 
							
									}, len(slice)*5 /* len("false") */)
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// JoinInts will pass signed integer slice to JoinFunc(), formatting
							 | 
						||
| 
								 | 
							
								// and combining into a single comma-space separated string.
							 | 
						||
| 
								 | 
							
								func JoinInts[Int Signed](slice []Int) string {
							 | 
						||
| 
								 | 
							
									return JoinFunc(slice, func(buf []byte, value Int) []byte {
							 | 
						||
| 
								 | 
							
										return strconv.AppendInt(buf, int64(value), 10)
							 | 
						||
| 
								 | 
							
									}, len(slice)*20) // max signed int str len
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// JoinUints will pass unsigned integer slice to JoinFunc(),
							 | 
						||
| 
								 | 
							
								// formatting and combining into a single comma-space separated string.
							 | 
						||
| 
								 | 
							
								func JoinUints[Uint Unsigned](slice []Uint) string {
							 | 
						||
| 
								 | 
							
									return JoinFunc(slice, func(buf []byte, value Uint) []byte {
							 | 
						||
| 
								 | 
							
										return strconv.AppendUint(buf, uint64(value), 10)
							 | 
						||
| 
								 | 
							
									}, len(slice)*20) // max unsigned int str len
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// JoinFloats will pass float slice to JoinFunc(), formatting
							 | 
						||
| 
								 | 
							
								// and combining into a single comma-space separated string.
							 | 
						||
| 
								 | 
							
								func JoinFloats[Float_ Float](slice []Float_) string {
							 | 
						||
| 
								 | 
							
									bits := int(unsafe.Sizeof(Float_(0)) * 8) // param type bits
							 | 
						||
| 
								 | 
							
									return JoinFunc(slice, func(buf []byte, value Float_) []byte {
							 | 
						||
| 
								 | 
							
										return strconv.AppendFloat(buf, float64(value), 'g', -1, bits)
							 | 
						||
| 
								 | 
							
									}, len(slice)*20) // max signed int str len (it's a good guesstimate)
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// JoinSizes will pass byte size slice to JoinFunc(), formatting
							 | 
						||
| 
								 | 
							
								// and combining into a single comma-space separated string.
							 | 
						||
| 
								 | 
							
								func JoinSizes(slice []bytesize.Size) string {
							 | 
						||
| 
								 | 
							
									const iecLen = 7 // max IEC string length
							 | 
						||
| 
								 | 
							
									return JoinFunc(slice, func(buf []byte, value bytesize.Size) []byte {
							 | 
						||
| 
								 | 
							
										return value.AppendFormatIEC(buf)
							 | 
						||
| 
								 | 
							
									}, len(slice)*iecLen)
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// JoinDurations will pass duration slice to JoinFunc(), formatting
							 | 
						||
| 
								 | 
							
								// and combining into a single comma-space separated string.
							 | 
						||
| 
								 | 
							
								func JoinDurations(slice []time.Duration) string {
							 | 
						||
| 
								 | 
							
									const durLen = 10 // max duration string length
							 | 
						||
| 
								 | 
							
									return JoinFunc(slice, func(buf []byte, value time.Duration) []byte {
							 | 
						||
| 
								 | 
							
										return append(buf, value.String()...)
							 | 
						||
| 
								 | 
							
									}, len(slice)*durLen)
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// JoinTimes will pass time slice to JoinFunc(), formatting
							 | 
						||
| 
								 | 
							
								// and combining into a single comma-space separated string.
							 | 
						||
| 
								 | 
							
								func JoinTimes(slice []time.Time, format string) string {
							 | 
						||
| 
								 | 
							
									return JoinFunc(slice, func(buf []byte, value time.Time) []byte {
							 | 
						||
| 
								 | 
							
										return value.AppendFormat(buf, format)
							 | 
						||
| 
								 | 
							
									}, len(slice)*len(format))
							 | 
						||
| 
								 | 
							
								}
							 |