package reflux import "strings" // pathIter 在不分配内存的前提下遍历路径片段。 // // reflux 现有的 expandPath 会对每个片段做 strings.Split 并 append 到一个新切片, // Get("Address","City") 这样一次调用就要分配 4 次(2 次 Split 的结果切片 + // append 扩容 2 次)。pathIter 只做字符串切片(sub-slice 不分配)。 type pathIter struct { parts []string // one 用于"路径只有一个字符串"的场景(Set/Delete 的 key 参数)。 // 走这条分支可以避免临时构造 []string{key} 带来的堆分配。 one string isOne bool i int // 当前处理到第几个片段 off int // 在当前片段内部的字节偏移 n int // 已经产出的段数 limit int // 最多产出多少段, -1 表示不限制 } func newPathIter(parts []string) pathIter { return pathIter{parts: parts, limit: -1} } func (it *pathIter) numParts() int { if it.isOne { return 1 } return len(it.parts) } func (it *pathIter) partAt(i int) string { if it.isOne { return it.one } return it.parts[i] } // next 返回下一个非空路径段。空段(连续点号、前后缀点号)会被跳过, // 与 reflux expandPath 忽略空字符串的行为一致。 func (it *pathIter) next() (string, bool) { if it.limit >= 0 && it.n >= it.limit { return "", false } for it.i < it.numParts() { s := it.partAt(it.i) if it.off >= len(s) { it.i++ it.off = 0 continue } rest := s[it.off:] if j := strings.IndexByte(rest, '.'); j >= 0 { it.off += j + 1 if j == 0 { continue // 空段, 跳过 } it.n++ return rest[:j], true } it.i++ it.off = 0 it.n++ return rest, true } return "", false } func parseIndex(s string) (int, bool) { if len(s) == 0 || len(s) > 18 { return 0, false } neg := false i := 0 if s[0] == '-' { neg = true i = 1 if len(s) == 1 { return 0, false } } n := 0 for ; i < len(s); i++ { c := s[i] if c < '0' || c > '9' { return 0, false } n = n*10 + int(c-'0') } if neg { n = -n } return n, true } // splitLastStr 是 splitLast 的单字符串版本, 避免为了调用 splitLast 而临时 // 构造一个 []string(那会带来一次堆分配 —— Set 的热路径上不可接受)。 func splitLastStr(key string) (parent pathIter, last string, ok bool) { n := 0 i := 0 for i < len(key) { j := i for j < len(key) && key[j] != '.' { j++ } if j > i { last = key[i:j] n++ } i = j + 1 } if n == 0 { return pathIter{}, "", false } return pathIter{one: key, isOne: true, limit: n - 1}, last, true }