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