split.go (4852B)
1 package render 2 3 import ( 4 "fmt" 5 "strings" 6 ) 7 8 func bookmark(values []string) []uint32 { 9 var c int 10 var bookmarks []uint32 = []uint32{0} 11 12 for _, v := range values { 13 c += len(v) + 1 14 bookmarks = append(bookmarks, uint32(c)) 15 } 16 return bookmarks 17 } 18 // 19 //func paginate(bookmarks []uint32, capacity uint32) ([][]uint32, error) { 20 // if len(bookmarks) == 0 { 21 // return nil, fmt.Errorf("empty bookmark array") 22 // } 23 // var c uint32 24 // var pages [][]uint32 25 // var prev uint32 26 // 27 // pages = append(pages, []uint32{}) 28 // currentPage := 0 29 // lookAhead := bookmarks[1:] 30 // 31 // for i, v := range lookAhead { 32 // lc := v - c 33 // if lc > capacity { 34 // c = prev 35 // if lc - c > capacity { 36 // return nil, fmt.Errorf("value at %v alone exceeds capacity", i) 37 // } 38 // currentPage += 1 39 // pages = append(pages, []uint32{}) 40 // } 41 // pages[currentPage] = append(pages[currentPage], bookmarks[i]) 42 // prev = v 43 // } 44 // 45 // pages[currentPage] = append(pages[currentPage], bookmarks[len(bookmarks)-1]) 46 // return pages, nil 47 //} 48 49 func isLast(cursor uint32, end uint32, capacity uint32) bool { 50 l := end - cursor 51 remaining := capacity 52 return l <= remaining 53 } 54 55 func paginate(bookmarks []uint32, capacity uint32, nextSize uint32, prevSize uint32) ([][]uint32, error) { 56 if len(bookmarks) == 0 { 57 return nil, fmt.Errorf("empty page array") 58 } 59 60 var pages [][]uint32 61 var c uint32 62 lastIndex := len(bookmarks) - 1 63 last := bookmarks[lastIndex] 64 var haveMore bool 65 66 if isLast(0, last, capacity) { 67 pages = append(pages, bookmarks) 68 return pages, nil 69 } 70 71 lookAhead := bookmarks[1:] 72 pages = append(pages, []uint32{}) 73 var i int 74 75 haveMore = true 76 for haveMore { 77 remaining := int(capacity) 78 if i > 0 { 79 remaining -= int(prevSize) 80 } 81 if remaining < 0 { 82 return nil, fmt.Errorf("underrun in item %v:%v (%v) index %v prevsize %v remain %v cap %v", bookmarks[i], lookAhead[i], lookAhead[i] - bookmarks[i], i, prevSize, remaining, capacity) 83 } 84 if isLast(c, last, uint32(remaining)) { 85 haveMore = false 86 } else { 87 remaining -= int(nextSize) 88 } 89 if remaining < 0 { 90 return nil, fmt.Errorf("underrun in item %v:%v (%v) index %v prevsize %v nextsize %v remain %v cap %v", bookmarks[i], lookAhead[i], lookAhead[i] - bookmarks[i], i, prevSize, nextSize, remaining, capacity) 91 } 92 93 var z int 94 currentPage := len(pages) - 1 95 for i < lastIndex { 96 logg.Tracef("have render", "bookmark", bookmarks[i], "lookahead", lookAhead[i], "diff", lookAhead[i] - bookmarks[i], "index", i, "prevsize", prevSize, "nextsize", nextSize, "remain", remaining, "capacity", capacity) 97 98 v := lookAhead[i] 99 delta := int((v - c) + 1) 100 if z == 0 { 101 if delta > remaining { 102 return nil, fmt.Errorf("single value at %v exceeds capacity", i) 103 } 104 } 105 z += delta 106 if z > remaining { 107 break 108 } 109 pages[currentPage] = append(pages[currentPage], bookmarks[i]) 110 c = v 111 i += 1 112 } 113 logg.Tracef("render more", "have", haveMore, "remain", remaining, "c", c, "last", last, "pages", pages) 114 115 if haveMore { 116 pages = append(pages, []uint32{}) 117 } 118 } 119 120 l := len(pages)-1 121 pages[l] = append(pages[l], last) 122 return pages, nil 123 } 124 125 func explode(values []string, pages [][]uint32) string { 126 s := strings.Join(values, "") 127 s += "\n" 128 sb := strings.Builder{} 129 130 var start uint32 131 var end uint32 132 var lastPage int 133 var z uint32 134 for i, page := range pages { 135 for _, c := range page { 136 if c == 0 { 137 continue 138 } 139 z += 1 140 if i != lastPage { 141 sb.WriteRune('\n') 142 } else if c > 0 { 143 sb.WriteByte(byte(0x00)) 144 } 145 end = c - z 146 v := s[start:end] 147 logg.Tracef("explode", "page", i, "part start", start, "part end", end, "part str", v) 148 v = s[start:end] 149 sb.WriteString(v) 150 start = end 151 } 152 lastPage = i 153 } 154 r := sb.String() 155 r = strings.TrimRight(r, "\n") 156 return r 157 } 158 159 // if lastCursor <= capacity { 160 // return pages, nil 161 // } 162 // 163 // var flatPages [][]uint32 164 // 165 // pages = append(pages, []uint32{}) 166 // for _, v := range bookmarks { 167 // for _, vv := range v { 168 // pages[0] = append(pages[0], vv) 169 // } 170 // } 171 // 172 // var c uint32 173 // var prev uint32 174 // currentPage := 0 175 // 176 // for i, page := range pages { 177 // var delta uint32 178 // if i == 0 { 179 // delta = nextSize 180 // } else if i == len(pages) - 1 { 181 // delta = prevSize 182 // } else { 183 // delta = nextSize + prevSize 184 // } 185 // remaining := capacity - delta 186 // log.Printf("processing page %v", page) 187 // lookAhead := page[1:] 188 // 189 // for j, v := range lookAhead { 190 // lc := v - c 191 // log.Printf("currentpage j %v lc %v v %v remain %v", j, lc, v, remaining) 192 // if lc > remaining { 193 // c = prev 194 // if lc - c > remaining { 195 // return nil, fmt.Errorf("value at page %v idx %v alone exceeds capacity", i, v) 196 // } 197 // currentPage += 1 198 // page = append(page, []uint32{}) 199 // } 200 // page[currentPage] = append(page[currentPage], page[j]) 201 // prev = v 202 // } 203 // } 204 // return page, nil 205 //}