| 
									
										
										
										
											2021-09-11 20:12:47 +01:00
										 |  |  | package fastpath | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"unsafe" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-13 12:29:08 +01:00
										 |  |  | // allocate these just once | 
					
						
							|  |  |  | var ( | 
					
						
							| 
									
										
										
										
											2022-05-08 19:49:45 +02:00
										 |  |  | 	dot    = []byte(dotStr) | 
					
						
							|  |  |  | 	dotStr = "." | 
					
						
							| 
									
										
										
										
											2021-11-13 12:29:08 +01:00
										 |  |  | ) | 
					
						
							| 
									
										
										
										
											2021-09-11 20:12:47 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | type Builder struct { | 
					
						
							| 
									
										
										
										
											2022-05-08 19:49:45 +02:00
										 |  |  | 	B   []byte // B is the underlying byte buffer | 
					
						
							|  |  |  | 	dd  int    // pos of last '..' appended to builder | 
					
						
							|  |  |  | 	abs bool   // abs stores whether path passed to first .Append() is absolute | 
					
						
							|  |  |  | 	set bool   // set stores whether b.abs has been set i.e. not first call to .Append() | 
					
						
							| 
									
										
										
										
											2021-09-11 20:12:47 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-08 19:49:45 +02:00
										 |  |  | // NewBuilder returns a new Builder object using the | 
					
						
							|  |  |  | // supplied byte slice as the underlying buffer | 
					
						
							| 
									
										
										
										
											2021-09-11 20:12:47 +01:00
										 |  |  | func NewBuilder(b []byte) Builder { | 
					
						
							|  |  |  | 	if b != nil { | 
					
						
							|  |  |  | 		b = b[:0] | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return Builder{ | 
					
						
							| 
									
										
										
										
											2021-11-13 12:29:08 +01:00
										 |  |  | 		B:  b, | 
					
						
							| 
									
										
										
										
											2021-09-11 20:12:47 +01:00
										 |  |  | 		dd: 0, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		abs: false, | 
					
						
							|  |  |  | 		set: false, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Reset resets the Builder object | 
					
						
							|  |  |  | func (b *Builder) Reset() { | 
					
						
							| 
									
										
										
										
											2021-11-13 12:29:08 +01:00
										 |  |  | 	b.B = b.B[:0] | 
					
						
							| 
									
										
										
										
											2021-09-11 20:12:47 +01:00
										 |  |  | 	b.dd = 0 | 
					
						
							|  |  |  | 	b.abs = false | 
					
						
							|  |  |  | 	b.set = false | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Len returns the number of accumulated bytes in the Builder | 
					
						
							|  |  |  | func (b *Builder) Len() int { | 
					
						
							| 
									
										
										
										
											2021-11-13 12:29:08 +01:00
										 |  |  | 	return len(b.B) | 
					
						
							| 
									
										
										
										
											2021-09-11 20:12:47 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Cap returns the capacity of the underlying Builder buffer | 
					
						
							|  |  |  | func (b *Builder) Cap() int { | 
					
						
							| 
									
										
										
										
											2021-11-13 12:29:08 +01:00
										 |  |  | 	return cap(b.B) | 
					
						
							| 
									
										
										
										
											2021-09-11 20:12:47 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Bytes returns the accumulated path bytes. | 
					
						
							|  |  |  | func (b *Builder) Bytes() []byte { | 
					
						
							| 
									
										
										
										
											2022-05-08 19:49:45 +02:00
										 |  |  | 	if len(b.B) < 1 { | 
					
						
							| 
									
										
										
										
											2021-09-11 20:12:47 +01:00
										 |  |  | 		return dot | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-11-13 12:29:08 +01:00
										 |  |  | 	return b.B | 
					
						
							| 
									
										
										
										
											2021-09-11 20:12:47 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // String returns the accumulated path string. | 
					
						
							|  |  |  | func (b *Builder) String() string { | 
					
						
							| 
									
										
										
										
											2022-05-08 19:49:45 +02:00
										 |  |  | 	if len(b.B) < 1 { | 
					
						
							| 
									
										
										
										
											2021-11-13 12:29:08 +01:00
										 |  |  | 		return dotStr | 
					
						
							| 
									
										
										
										
											2021-09-11 20:12:47 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-11-13 12:29:08 +01:00
										 |  |  | 	return string(b.B) | 
					
						
							| 
									
										
										
										
											2021-09-11 20:12:47 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // StringPtr returns a ptr to the accumulated path string. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // Please note the underlying byte slice for this string is | 
					
						
							|  |  |  | // tied to the builder, so any changes will result in the | 
					
						
							|  |  |  | // returned string changing. Consider using .String() if | 
					
						
							|  |  |  | // this is undesired behaviour. | 
					
						
							|  |  |  | func (b *Builder) StringPtr() string { | 
					
						
							| 
									
										
										
										
											2022-05-08 19:49:45 +02:00
										 |  |  | 	if len(b.B) < 1 { | 
					
						
							| 
									
										
										
										
											2021-11-13 12:29:08 +01:00
										 |  |  | 		return dotStr | 
					
						
							| 
									
										
										
										
											2021-09-11 20:12:47 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-11-13 12:29:08 +01:00
										 |  |  | 	return *(*string)(unsafe.Pointer(&b.B)) | 
					
						
							| 
									
										
										
										
											2021-09-11 20:12:47 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-13 12:29:08 +01:00
										 |  |  | // Absolute returns whether current path is absolute (not relative) | 
					
						
							| 
									
										
										
										
											2021-09-11 20:12:47 +01:00
										 |  |  | func (b *Builder) Absolute() bool { | 
					
						
							|  |  |  | 	return b.abs | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-13 12:29:08 +01:00
										 |  |  | // SetAbsolute converts the current path to / from absolute | 
					
						
							| 
									
										
										
										
											2021-09-11 20:12:47 +01:00
										 |  |  | func (b *Builder) SetAbsolute(val bool) { | 
					
						
							|  |  |  | 	if !b.set { | 
					
						
							|  |  |  | 		if val { | 
					
						
							| 
									
										
										
										
											2022-05-08 19:49:45 +02:00
										 |  |  | 			// .Append() has not been | 
					
						
							|  |  |  | 			// called, add a '/' and set abs | 
					
						
							|  |  |  | 			b.Guarantee(1) | 
					
						
							| 
									
										
										
										
											2021-09-11 20:12:47 +01:00
										 |  |  | 			b.appendByte('/') | 
					
						
							|  |  |  | 			b.abs = true | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Set as having been set | 
					
						
							|  |  |  | 		b.set = true | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if !val && b.abs { | 
					
						
							|  |  |  | 		// Already set and absolute. Update | 
					
						
							|  |  |  | 		b.abs = false | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// If not empty (i.e. not just '/'), | 
					
						
							|  |  |  | 		// then shift bytes 1 left | 
					
						
							| 
									
										
										
										
											2022-05-08 19:49:45 +02:00
										 |  |  | 		if len(b.B) > 1 { | 
					
						
							| 
									
										
										
										
											2021-11-13 12:29:08 +01:00
										 |  |  | 			copy(b.B, b.B[1:]) | 
					
						
							| 
									
										
										
										
											2021-09-11 20:12:47 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Truncate 1 byte. In the case of empty, | 
					
						
							|  |  |  | 		// i.e. just '/' then it will drop this | 
					
						
							|  |  |  | 		b.truncate(1) | 
					
						
							|  |  |  | 	} else if val && !b.abs { | 
					
						
							|  |  |  | 		// Already set but NOT abs. Update | 
					
						
							|  |  |  | 		b.abs = true | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Guarantee 1 byte available | 
					
						
							| 
									
										
										
										
											2022-05-08 19:49:45 +02:00
										 |  |  | 		b.Guarantee(1) | 
					
						
							| 
									
										
										
										
											2021-09-11 20:12:47 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// If empty, just append '/' | 
					
						
							| 
									
										
										
										
											2022-05-08 19:49:45 +02:00
										 |  |  | 		if len(b.B) < 1 { | 
					
						
							| 
									
										
										
										
											2021-09-11 20:12:47 +01:00
										 |  |  | 			b.appendByte('/') | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Increase length | 
					
						
							| 
									
										
										
										
											2022-05-08 19:49:45 +02:00
										 |  |  | 		l := len(b.B) | 
					
						
							| 
									
										
										
										
											2021-11-13 12:29:08 +01:00
										 |  |  | 		b.B = b.B[:l+1] | 
					
						
							| 
									
										
										
										
											2021-09-11 20:12:47 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// Shift bytes 1 right | 
					
						
							| 
									
										
										
										
											2021-11-13 12:29:08 +01:00
										 |  |  | 		copy(b.B[1:], b.B[:l]) | 
					
						
							| 
									
										
										
										
											2021-09-11 20:12:47 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// Set first byte '/' | 
					
						
							| 
									
										
										
										
											2021-11-13 12:29:08 +01:00
										 |  |  | 		b.B[0] = '/' | 
					
						
							| 
									
										
										
										
											2021-09-11 20:12:47 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Append adds and cleans the supplied path bytes to the | 
					
						
							|  |  |  | // builder's internal buffer, growing the buffer if necessary | 
					
						
							|  |  |  | // to accomodate the extra path length | 
					
						
							|  |  |  | func (b *Builder) Append(p []byte) { | 
					
						
							|  |  |  | 	b.AppendString(*(*string)(unsafe.Pointer(&p))) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // AppendString adds and cleans the supplied path string to the | 
					
						
							|  |  |  | // builder's internal buffer, growing the buffer if necessary | 
					
						
							|  |  |  | // to accomodate the extra path length | 
					
						
							|  |  |  | func (b *Builder) AppendString(path string) { | 
					
						
							|  |  |  | 	defer func() { | 
					
						
							| 
									
										
										
										
											2022-05-08 19:49:45 +02:00
										 |  |  | 		// If buffer is empty, and an absolute | 
					
						
							|  |  |  | 		// path, ensure it starts with a '/' | 
					
						
							|  |  |  | 		if len(b.B) < 1 && b.abs { | 
					
						
							| 
									
										
										
										
											2021-09-11 20:12:47 +01:00
										 |  |  | 			b.appendByte('/') | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Empty path, nothing to do | 
					
						
							|  |  |  | 	if len(path) == 0 { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Guarantee at least the total length | 
					
						
							|  |  |  | 	// of supplied path available in the buffer | 
					
						
							| 
									
										
										
										
											2022-05-08 19:49:45 +02:00
										 |  |  | 	b.Guarantee(len(path)) | 
					
						
							| 
									
										
										
										
											2021-09-11 20:12:47 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Try store if absolute | 
					
						
							|  |  |  | 	if !b.set { | 
					
						
							|  |  |  | 		b.abs = len(path) > 0 && path[0] == '/' | 
					
						
							|  |  |  | 		b.set = true | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	i := 0 | 
					
						
							|  |  |  | 	for i < len(path) { | 
					
						
							|  |  |  | 		switch { | 
					
						
							|  |  |  | 		// Empty path segment | 
					
						
							|  |  |  | 		case path[i] == '/': | 
					
						
							|  |  |  | 			i++ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Singular '.' path segment, treat as empty | 
					
						
							|  |  |  | 		case path[i] == '.' && (i+1 == len(path) || path[i+1] == '/'): | 
					
						
							|  |  |  | 			i++ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Backtrack segment | 
					
						
							|  |  |  | 		case path[i] == '.' && path[i+1] == '.' && (i+2 == len(path) || path[i+2] == '/'): | 
					
						
							|  |  |  | 			i += 2 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			switch { | 
					
						
							|  |  |  | 			// Check if it's possible to backtrack with | 
					
						
							|  |  |  | 			// our current state of the buffer. i.e. is | 
					
						
							|  |  |  | 			// our buffer length longer than the last | 
					
						
							|  |  |  | 			// '..' we placed? | 
					
						
							| 
									
										
										
										
											2022-05-08 19:49:45 +02:00
										 |  |  | 			case len(b.B) > b.dd: | 
					
						
							| 
									
										
										
										
											2021-09-11 20:12:47 +01:00
										 |  |  | 				b.backtrack() | 
					
						
							|  |  |  | 				// b.cp = b.lp | 
					
						
							|  |  |  | 				// b.lp = 0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// If we reached here, need to check if | 
					
						
							|  |  |  | 			// we can append '..' to the path buffer, | 
					
						
							|  |  |  | 			// which is ONLY when path is NOT absolute | 
					
						
							|  |  |  | 			case !b.abs: | 
					
						
							| 
									
										
										
										
											2022-05-08 19:49:45 +02:00
										 |  |  | 				if len(b.B) > 0 { | 
					
						
							| 
									
										
										
										
											2021-09-11 20:12:47 +01:00
										 |  |  | 					b.appendByte('/') | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				b.appendByte('.') | 
					
						
							|  |  |  | 				b.appendByte('.') | 
					
						
							| 
									
										
										
										
											2022-05-08 19:49:45 +02:00
										 |  |  | 				b.dd = len(b.B) | 
					
						
							| 
									
										
										
										
											2021-09-11 20:12:47 +01:00
										 |  |  | 				// b.lp = lp - 2 | 
					
						
							|  |  |  | 				// b.cp = b.dd | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		default: | 
					
						
							| 
									
										
										
										
											2022-05-08 19:49:45 +02:00
										 |  |  | 			if (b.abs && len(b.B) != 1) || (!b.abs && len(b.B) > 0) { | 
					
						
							| 
									
										
										
										
											2021-09-11 20:12:47 +01:00
										 |  |  | 				b.appendByte('/') | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			// b.lp = b.cp | 
					
						
							| 
									
										
										
										
											2022-05-08 19:49:45 +02:00
										 |  |  | 			// b.cp = len(b.B) | 
					
						
							| 
									
										
										
										
											2021-09-11 20:12:47 +01:00
										 |  |  | 			i += b.appendSlice(path[i:]) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Clean creates the shortest possible functional equivalent | 
					
						
							|  |  |  | // to the supplied path, resetting the builder before performing | 
					
						
							|  |  |  | // this operation. The builder object is NOT reset after return | 
					
						
							|  |  |  | func (b *Builder) Clean(path string) string { | 
					
						
							|  |  |  | 	b.Reset() | 
					
						
							|  |  |  | 	b.AppendString(path) | 
					
						
							|  |  |  | 	return b.String() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Join connects and cleans multiple paths, resetting the builder before | 
					
						
							|  |  |  | // performing this operation and returning the shortest possible combination | 
					
						
							|  |  |  | // of all the supplied paths. The builder object is NOT reset after return | 
					
						
							|  |  |  | func (b *Builder) Join(base string, paths ...string) string { | 
					
						
							|  |  |  | 	b.Reset() | 
					
						
							|  |  |  | 	b.AppendString(base) | 
					
						
							| 
									
										
										
										
											2022-05-08 19:49:45 +02:00
										 |  |  | 	size := len(base) | 
					
						
							|  |  |  | 	for i := 0; i < len(paths); i++ { | 
					
						
							|  |  |  | 		b.AppendString(paths[i]) | 
					
						
							|  |  |  | 		size += len(paths[i]) | 
					
						
							| 
									
										
										
										
											2021-09-11 20:12:47 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-05-08 19:49:45 +02:00
										 |  |  | 	if size < 1 { | 
					
						
							| 
									
										
										
										
											2021-09-11 20:12:47 +01:00
										 |  |  | 		return "" | 
					
						
							| 
									
										
										
										
											2022-05-08 19:49:45 +02:00
										 |  |  | 	} else if len(b.B) < 1 { | 
					
						
							|  |  |  | 		return dotStr | 
					
						
							| 
									
										
										
										
											2021-09-11 20:12:47 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-05-08 19:49:45 +02:00
										 |  |  | 	return string(b.B) | 
					
						
							| 
									
										
										
										
											2021-09-11 20:12:47 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Guarantee ensures there is at least the requested size | 
					
						
							| 
									
										
										
										
											2022-05-08 19:49:45 +02:00
										 |  |  | // free bytes available in the buffer, reallocating if necessary | 
					
						
							| 
									
										
										
										
											2021-09-11 20:12:47 +01:00
										 |  |  | func (b *Builder) Guarantee(size int) { | 
					
						
							| 
									
										
										
										
											2022-05-08 19:49:45 +02:00
										 |  |  | 	if size > cap(b.B)-len(b.B) { | 
					
						
							|  |  |  | 		nb := make([]byte, 2*cap(b.B)+size) | 
					
						
							|  |  |  | 		copy(nb, b.B) | 
					
						
							|  |  |  | 		b.B = nb[:len(b.B)] | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-09-11 20:12:47 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Truncate reduces the length of the buffer by the requested | 
					
						
							|  |  |  | // number of bytes. If the builder is set to absolute, the first | 
					
						
							|  |  |  | // byte (i.e. '/') will never be truncated | 
					
						
							|  |  |  | func (b *Builder) Truncate(size int) { | 
					
						
							|  |  |  | 	// If absolute and just '/', do nothing | 
					
						
							| 
									
										
										
										
											2022-05-08 19:49:45 +02:00
										 |  |  | 	if b.abs && len(b.B) == 1 { | 
					
						
							| 
									
										
										
										
											2021-09-11 20:12:47 +01:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Truncate requested bytes | 
					
						
							|  |  |  | 	b.truncate(size) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-08 19:49:45 +02:00
										 |  |  | // truncate reduces the length of the buffer by the requested | 
					
						
							|  |  |  | // size, no sanity checks are performed | 
					
						
							| 
									
										
										
										
											2021-09-11 20:12:47 +01:00
										 |  |  | func (b *Builder) truncate(size int) { | 
					
						
							| 
									
										
										
										
											2022-05-08 19:49:45 +02:00
										 |  |  | 	b.B = b.B[:len(b.B)-size] | 
					
						
							| 
									
										
										
										
											2021-09-11 20:12:47 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // appendByte appends the supplied byte to the end of | 
					
						
							|  |  |  | // the buffer. appending is achieved by continually reslicing the | 
					
						
							|  |  |  | // buffer and setting the next byte-at-index, this is safe as guarantee() | 
					
						
							|  |  |  | // will have been called beforehand | 
					
						
							|  |  |  | func (b *Builder) appendByte(c byte) { | 
					
						
							| 
									
										
										
										
											2022-05-08 19:49:45 +02:00
										 |  |  | 	b.B = b.B[:len(b.B)+1] | 
					
						
							|  |  |  | 	b.B[len(b.B)-1] = c | 
					
						
							| 
									
										
										
										
											2021-09-11 20:12:47 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // appendSlice appends the supplied string slice to | 
					
						
							|  |  |  | // the end of the buffer and returns the number of indices | 
					
						
							|  |  |  | // we were able to iterate before hitting a path separator '/'. | 
					
						
							|  |  |  | // appending is achieved by continually reslicing the buffer | 
					
						
							|  |  |  | // and setting the next byte-at-index, this is safe as guarantee() | 
					
						
							|  |  |  | // will have been called beforehand | 
					
						
							|  |  |  | func (b *Builder) appendSlice(slice string) int { | 
					
						
							|  |  |  | 	i := 0 | 
					
						
							|  |  |  | 	for i < len(slice) && slice[i] != '/' { | 
					
						
							| 
									
										
										
										
											2022-05-08 19:49:45 +02:00
										 |  |  | 		b.B = b.B[:len(b.B)+1] | 
					
						
							|  |  |  | 		b.B[len(b.B)-1] = slice[i] | 
					
						
							| 
									
										
										
										
											2021-09-11 20:12:47 +01:00
										 |  |  | 		i++ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return i | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // backtrack reduces the end of the buffer back to the last | 
					
						
							|  |  |  | // separating '/', or end of buffer | 
					
						
							|  |  |  | func (b *Builder) backtrack() { | 
					
						
							| 
									
										
										
										
											2022-05-08 19:49:45 +02:00
										 |  |  | 	b.B = b.B[:len(b.B)-1] | 
					
						
							| 
									
										
										
										
											2021-09-11 20:12:47 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-08 19:49:45 +02:00
										 |  |  | 	for len(b.B)-1 > b.dd && b.B[len(b.B)-1] != '/' { | 
					
						
							|  |  |  | 		b.B = b.B[:len(b.B)-1] | 
					
						
							| 
									
										
										
										
											2021-09-11 20:12:47 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-08 19:49:45 +02:00
										 |  |  | 	if len(b.B) > 0 { | 
					
						
							|  |  |  | 		b.B = b.B[:len(b.B)-1] | 
					
						
							| 
									
										
										
										
											2021-09-11 20:12:47 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | } |