{"id":29460775,"url":"https://github.com/rphii/so","last_synced_at":"2025-07-14T02:38:11.990Z","repository":{"id":304053811,"uuid":"1017635217","full_name":"rphii/so","owner":"rphii","description":"Small String Optimized and Dynamically Allocatable String","archived":false,"fork":false,"pushed_at":"2025-07-11T00:07:45.000Z","size":15,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-07-11T03:24:27.073Z","etag":null,"topics":["c","dynamic-string","heap","sso","stack-string","str","string","string-object","string-space-optimization","substring","substrings"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rphii.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-07-10T21:08:59.000Z","updated_at":"2025-07-11T00:07:48.000Z","dependencies_parsed_at":"2025-07-11T03:24:54.996Z","dependency_job_id":"602c9fa4-a78f-4e4a-9ec7-1e73c31b4855","html_url":"https://github.com/rphii/so","commit_stats":null,"previous_names":["rphii/so"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/rphii/so","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rphii%2Fso","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rphii%2Fso/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rphii%2Fso/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rphii%2Fso/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rphii","download_url":"https://codeload.github.com/rphii/so/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rphii%2Fso/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265233753,"owners_count":23731825,"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":["c","dynamic-string","heap","sso","stack-string","str","string","string-object","string-space-optimization","substring","substrings"],"created_at":"2025-07-14T02:38:11.445Z","updated_at":"2025-07-14T02:38:11.948Z","avatar_url":"https://github.com/rphii.png","language":"C","readme":"# 🧵 So - String Object \n\nSmall String Optimized and Dynamically Allocatable String in C.\n\n## 🛠️ Installation\n\n```sh\ngit clone https://github.com/rphii/so \u0026\u0026 cd so\nsetup build \u0026\u0026 meson install -C build\n```\n\nInstallation features:\n- `librphiiso` the `So` library\n- [man](man) pages *(WIP)*\n- [tests](examples) using meson\n\n## ✨ Features\n\n*\\*Byte counts are assuming a 64 bit machine/architecture.*\n\n1. Any substring has a footprint of 16 bytes\n2. Any program-lifetime / data-segment string has a footprint of 16 bytes\n3. Operations on the stack, if length is \u003c=15 bytes *(operations without dynamically allocating!)*\n4. Dynamically resizable to a heap string, with a maximum length of 2^56-1\n\nNotes:\n\n- Endian doesn't matter (we need to know it to compile / set up TWO structs, and after that it doesn't matter)\n- Doesn't matter if machine/architecture is 64 bits or not, it still works (it should! XD)\n- Strings are not 0-terminated. Appropriate functions/macros for printing and other opterations shall be provided\n- Automatically converts any (sub-) string into a dynamic one, if manipulated\n\n## 🔌 API\n\n*Things that are not linked are planned but not yet implemented.*\n\n| part | description | .h | .c |\n| --- | --- |--- | ---|\n| [`so-core.md`](md/so-core.md) | core string | [so.h](src/so.h) | [so.c](src/so.c) |\n| [`so-cmp.md`](md/so-cmp.md) | comparison | [so-cmp.h](src/so-cmp.h) | [so-cmp.c](src/so-cmp.c) |\n| `so-find.md` | find within | [so-find.h](src/so-find.h) | [so-find.c](src/so-find.c) |\n| `so-count.md` | count things | | |\n| `so-split.md` | split into parts | | |\n| `so-splice.md` | splice repeatedly | | |\n| `so-as.md` | string to type conversion | | |\n| `so-uc.md` | utf8 + unicode conversions | | |\n| `so-fx.md` | formatting (bold, it, ul, rgb) | | |\n| `so-env.md` | environment variables | | |\n| `so-trim.md` | trimming | [so-trim.h](src/so-trim.h) | [so-trim.c](src/so-trim.c) |\n| `so-path.md` | handling as path | | |\n| `so-print.md` | printing | [so-print.h](src/so-print.h) | [so-print.c](src/so-print.c) |\n| [`so-input.md`](md/so-input.md) | user input | [so-input.h](src/so-input.h) | [so-input.c](src/so-input.c) |\n\n## ⚙️ How does it work?\n\n*\\*Explanations assuming a 64 bit machine/architecture.*\n\n### Memoy Layout\n\nConsolidating the `so.h` header, we find the main `So` struct:\n\n```c\ntypedef struct So {\n    union {\n        So_Stack stack;\n        So_Ref ref;\n    };\n} So;\n```\n\n#### `So_Ref`\n\nThis struct is the real heavy-lifter. Without it we could not do much! It's use cases are:\n\n- Allows detection if in stack-mode\n- Allows detection if in heap-mode\n- Holds potential heap pointer reference\n- Holds program-lifetime / data-segment string\n- Acts as a substring / reference to substring *(the starting pointer!)* within another string\n- ..and therefore holds a string length\n\n```\n    [64-bits|64-bits]\n    [str ptr|length ]\n```\n\n#### `So_Stack`\n\nThis struct is only used for short modified strings, \u003c=15 bytes, that do not yet hold a heap-reference.\nSo, modifications of short strings up to 15 bytes are dynamic-allocation-free!\n\n- Allows detection if in stack-mode\n- Allows detection if in heap-mode\n- Holds modifiable strings of up to 15 characters\n\n```\n    [120-bits |8-bits]\n    [stack buf|length]\n```\n\nNote that this struct shares the same memory footprint as the previous one, hence why `So` combines them with a `union`.\n\n### Detecting the modes\n\nThis is where I illustrate the *actual use* of the previously described memory footprints.\n\n#### `is_stack`\n\nDetection if we're in stack mode or not is really simple - we set length to any number above 1 (and less than 120/8 = 15).\n\n```\n    // So_Stack : used as such\n    [120-bits |7-bits|1-bit ]\n    [stack buf|length|unused]\n```\n\n- If length is \u003e0 we're in stack mode!\n\n#### `is_heap`\n\nDetection happens through setting one bit.\n\n```\n    // So_Ref : used as such\n    [64-bits|56-bits|7-bits|1-bit  ]\n    [str ptr|length |unused|is_heap]\n```\n\n- If that single bit is set, we're in heap mode!\n\n#### The rest\n\nIf none of the previous two modes apply, we're in either of the following, equally-acting modes:\n\n- Program-lifetime / data-segment string\n- Substring of another string\n\n### The heap\n\nThe heap is yet another struct with 16 bytes!\n\n```\n    [64-bits|64-bits ]\n    [str ptr|capacity]\n```\n\nWe don't need the information of the actual heap length within here, BECAUSE\nwe're using the `So_Ref` struct as soon as we rely on the heap, where we have\nthe length (of up to 2^56-1) !\n\n```\n    // So_Heap :\n    [64-bits|64-bits ]\n    [str ptr|capacity]\n    \u003c---+---\u003e\n        | \n        +(heap str ptr is returned to So_Ref :\n        |  \n        |  // So_Ref : used as such\n        |  [64-bits|56-bits|7-bits|1-bit  ]\n        \\-\u003e[str ptr|length |unused|is_heap]\n```\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frphii%2Fso","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frphii%2Fso","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frphii%2Fso/lists"}