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