{"id":17273817,"url":"https://github.com/chewxy/skiprope","last_synced_at":"2025-04-14T08:51:06.009Z","repository":{"id":57550225,"uuid":"107110978","full_name":"chewxy/skiprope","owner":"chewxy","description":"package skiprope is a rope-like data structure built on top of skiplists","archived":false,"fork":false,"pushed_at":"2017-12-02T20:28:18.000Z","size":51,"stargazers_count":27,"open_issues_count":4,"forks_count":4,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-27T22:22:18.324Z","etag":null,"topics":["data-structures","datastructure","golang","rope","rope-string"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chewxy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-10-16T10:07:59.000Z","updated_at":"2024-02-26T08:28:32.000Z","dependencies_parsed_at":"2022-09-10T06:10:51.145Z","dependency_job_id":null,"html_url":"https://github.com/chewxy/skiprope","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chewxy%2Fskiprope","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chewxy%2Fskiprope/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chewxy%2Fskiprope/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chewxy%2Fskiprope/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chewxy","download_url":"https://codeload.github.com/chewxy/skiprope/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248852079,"owners_count":21171837,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["data-structures","datastructure","golang","rope","rope-string"],"created_at":"2024-10-15T08:52:18.593Z","updated_at":"2025-04-14T08:51:05.975Z","avatar_url":"https://github.com/chewxy.png","language":"Go","readme":"# SkipRope [![GoDoc](https://godoc.org/github.com/chewxy/skiprope?status.svg)](https://godoc.org/github.com/chewxy/skiprope) [![Build Status](https://travis-ci.org/chewxy/skiprope.svg?branch=master)](https://travis-ci.org/chewxy/skiprope) [![Coverage Status](https://coveralls.io/repos/github/chewxy/skiprope/badge.svg?branch=master)](https://coveralls.io/github/chewxy/skiprope?branch=master) #\n\npackage `skiprope` is an implementation of the [rope](https://en.wikipedia.org/wiki/Rope_%28data_structure%29) data structure. It's not strictly a rope as per se. It's not built on top of a binary tree like most rope data structures are. \n\nInstead it's built on top of a [skip list](https://en.wikipedia.org/wiki/Skip_list).  This makes it more akin to a piece table than a true rope. \n\nThis library is quite complete as it is (it has all the functions and I need for my projects). However, any addition, corrections etc are welcome. Please see CONTRIBUTING.md for more information on how to contribute. \n\n# Installing #\n\nThis package is go-gettable: `go get -u github.com/chewxy/skiprope`. \n\nThis package is versioned with SemVer 2.0, and does not have any external dependencies except for testing (of which the fantastic [`assert`](https://github.com/stretchr/testify) package is used).\n\n# Usage #\n\n```\nr := skiprope.New()\nif err := r.Insert(0, \"Hello World! Hello, 世界\"); err != nil {\n\t// handle error\n}\nif err  := r.Insert(5, \"there \"); err != nil {\n\t// handle error\n}\nfmt.Println(r.String()) // \"Hello there World! Hello, 世界\"\n```\n\n# FAQ #\n\n## How do I keep track of row, col information? ##\n\nThe best way is to use a linebuffer data structure in conjunction with the `Rope`:\n\n```\ntype Foo struct{\n\t*skiprope.Rope\n\tlinebuf []int\n}\n```\n\nThe `linebuf` is essentially a list of offsets to a newline character. The main reason why I didn't add a `linebuf` slice into the `*Rope` data structure is because while it's a common thing to do, for a couple of my projects I didn't need it. The nature of Go's composable data structure and programs make it quite easy to add these things. A pro-tip is to extend the `Insert`, `InsertRunes` and `EraseAt` methods.\n\nI do not think it to be wise to add it to the core data structure.\n\n## When is `*Rope` going to implement `io.Writer` and `io.Reader`? ##\n\nThe main reason why I didn't do it was mostly because I didn't need it. However, I've been asked about this before. I personally don't have the bandwidth to do it.\n\nPlease send a pull request :)\n\n# Benchmarks #\n\nThere is a benchmark mini-program that is not required for the running, but here are the results:\n\n```\ngo test -run=^$ -bench=. -benchmem -cpuprofile=test.prof\nBenchmarkNaiveRandomInsert-8   \t   50000\t     37774 ns/op\t      15 B/op\t       0 allocs/op\nBenchmarkRopeRandomInsert-8    \t 3000000\t       407 ns/op\t      27 B/op\t       0 allocs/op\nBenchmarkERopeRandomInsert-8   \t 1000000\t      2143 ns/op\t    1161 B/op\t      25 allocs/op\nPASS\n```\n\n# Fuzz testing\n\nGuard against crashing for certain inputs by running fuzz tests. First, build the instrumented binaries for the tests and then run them.\n\n```\n$ go-fuzz-build github.com/chewxy/skiprope\n$ go-fuzz -bin=skiprope-fuzz.zip -workdir=workdir\n```\n\n# History, Development and Acknowledgements #\nThis package started its life as a textbook binary-tree data structure for another personal project of mine. Over time, I decided to add more and more optimizations to it. The original design had a split at every new-line character. \n\nI started by moving more and more things off the heap, and onto the stack. As I wondered how to incorporate a search structure using a skiplist, I stumbled onto a well developed library for C, [librope](https://github.com/josephg/librope).\n\nIt had everything I had wanted: a rope-like structure, using skiplists to find nodes, minimal allocations on heap, and a solution to my problem wrt keeping the skiplists off heap. The solution turned out to be to be the `skiplist` data structure, without a pointer. So I ended up adapting most of Joseph Gentle's algorithm. So this library owes most of its work to Joseph Gentle. \n\nHours before releasing this library, I had a consult by Egon Elbre, who gave good advice on whether just sticking with `[]rune` was a good idea. He managed to convince me that it isn't, so the first pull request was made to update this library to deal with `[]byte` instead. As a result, memory use went down 40B/op at the cost of an increase of about 30 ns/op. The number can be further shaved down with better optimizations.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchewxy%2Fskiprope","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchewxy%2Fskiprope","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchewxy%2Fskiprope/lists"}