{"id":23508748,"url":"https://github.com/lovasko/m_list","last_synced_at":"2025-09-07T07:40:14.980Z","repository":{"id":32341566,"uuid":"35917073","full_name":"lovasko/m_list","owner":"lovasko","description":"Linked List for C89","archived":false,"fork":false,"pushed_at":"2017-07-05T16:50:59.000Z","size":64,"stargazers_count":2,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-05-13T15:57:01.581Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lovasko.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-05-20T00:57:07.000Z","updated_at":"2017-07-05T15:41:23.000Z","dependencies_parsed_at":"2022-09-12T05:11:41.273Z","dependency_job_id":null,"html_url":"https://github.com/lovasko/m_list","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/lovasko/m_list","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lovasko%2Fm_list","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lovasko%2Fm_list/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lovasko%2Fm_list/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lovasko%2Fm_list/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lovasko","download_url":"https://codeload.github.com/lovasko/m_list/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lovasko%2Fm_list/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274010098,"owners_count":25206763,"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","status":"online","status_checked_at":"2025-09-07T02:00:09.463Z","response_time":67,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":[],"created_at":"2024-12-25T11:31:56.989Z","updated_at":"2025-09-07T07:40:14.919Z","avatar_url":"https://github.com/lovasko.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# m_list\nGeneral-purpose linked list implementation in the C89 language that runs on all\nPOSIX-compatible systems.\n\n## Features\n### Initialisation\nTo initialise a list, call the `m_list_init` function. \n\n### Access\nThe first and the last element of the list can be accessed with the\n`m_list_first` and `m_list_last` functions respectively. The _n_-th element of\nthe list can be accessed with the `n_list_nth` function. Once you have obtained\nthe `struct m_elem` entry, you can move to the previous or the next element\nwith `m_elem_prev` and `m_elem_next` functions. To obtain the actual data\nstored in the element, use the `m_elem_data` function.\n\n### Insertion\nTo append or prepend elements to the list, use `m_list_append` and\n`m_list_prepend` functions. To insert an element after another element that is\nalready in the list, use the `m_list_insert` function.\n\n### Length\nTo retrieve the length of the list, use the function `m_list_length`. The\nfunction operates in constant time.\n\n### Modification\nTo remove an element from the list, use the function `m_list_remove` or\n`m_list_remove_safe`. The difference between these two functions is that the\n`safe` variant verifies that the element selected for removal belongs to the\nspecified list.\nTo remove all elements, use `m_list_clear`.\n\n### Algorithms\n#### Map\nIn order to apply a certain function to all element data, the standard _map_\nfunction is provided under the name `m_list_map`. \n#### Join\nThe standard _join_ algorithm allows you to insert an element between every\nconsecutive pair of elements in the list. Note that this is a very powerful\nability when combined with shallow copies (hence the actual object exists only\nonce).\n\n### Deep/shallow copy\nIt is up to you to decide if the list element should point to already\nexisting data that you `mallloc`ed earlier or whether it should be copied to a\nseparate memory managed by the `m_list`. The decision is made in one of the  \n`m_list_append`, `m_list_prepend`, `m_list_insert` functions. Possible values\nare either `M_LIST_COPY_DEEP` for an internal copy of the memory, or\n`M_LIST_COPY_SHALLOW` for a pointer-copy only. The `size` argument (one before\nthe last) of the function can be ignored with value `0` in case of the shallow\ncopy.\n\n## Time and space complexity\nAll operations have `O(1)` space complexity, with the exception of\n`m_list_build_index` with space complexity of `O(n)`.\n| Operation                    | Time             |\n| ---------------------------- | ---------------- |\n| `m_elem_data`                | `O(1)`           |\n| `m_elem_next`                | `O(1)`           |\n| `m_elem_prev`                | `O(1)`           |\n| `m_list_append`              | `O(1)`           |\n| `m_list_build_index`         | `O(n)`           |\n| `m_list_copy`                | `O(n)`           |\n| `m_list_drop_index`          | `O(1)`           |\n| `m_list_equal`               | `O(n)`           |\n| `m_list_error_string`        | `O(1)`           |\n| `m_list_filter`              | `O(n)`           |\n| `m_list_find`                | `O(n)`           |\n| `m_list_first`               | `O(1)`           |\n| `m_list_generate`            | `O(n)`           |\n| `m_list_init`                | `O(n)`           |\n| `m_list_insert`              | `O(1)`           |\n| `m_list_is_empty`            | `O(1)`           |\n| `m_list_is_sorted`           | `O(n)`           |\n| `m_list_join`                | `O(n)`           |\n| `m_list_last`                | `O(1)`           |\n| `m_list_length`              | `O(1)`           |\n| `m_list_map2`                | `O(n)`           |\n| `m_list_map`                 | `O(n)`           |\n| `m_list_match_all`           | `O(n)`           |\n| `m_list_match_any`           | `O(n)`           |\n| `m_list_match_at_least`      | `O(n)`           |\n| `m_list_match_exactly`       | `O(n)`           |\n| `m_list_nth`                 | `O(1)` or `O(n)` |\n| `m_list_prepend`             | `O(1)`           |\n| `m_list_remove_all`          | `O(n)`           |\n| `m_list_remove_first`        | `O(1)`           |\n| `m_list_remove_last`         | `O(1)`           |\n| `m_list_remove_safe`         | `O(n)`           |\n| `m_list_remove`              | `O(1)`           |\n| `m_list_reverse`             | `O(n)`           |\n| `m_list_sort`                | `O(nlogn)`       |\n| `m_list_zip`                 | `O(n)`           |\nwhere `n` denotes the number of list elements.\n\n## Examples\n * [Sum of integers](examples/sum.md)\n * [Comma-separated words](examples/commas.md)\n * [Postfix calculator] (examples/calc.md)\n * [Fizz buzz] (examples/fizz_buzz.md)\n * [String palindrome test] (examples/palindrome.md)\n\n## Using m_list as other data structures\n### Stack\nBy using only a certain subset of the `m_list` API, it is possible to achieve\nthe functionality of the stack data structure. Since it is possible to\nmanipulate with both ends of a `m_list`, it is necessary to choose one end and\nbe consistent. This example will use the beginning of the list.\n#### top\nIn order to see what is on top of the stack, use the `m_list_first` function.\n#### pop\nTo remove the top value from the stack, use the `m_list_remove_first` function.\n#### push\nAdding to the stack is enabled by the `m_list_prepend` function.\n\n### Queue\nAs with the stack, it is necessary to choose a direction of usage of the list.\nThe queue in this example will retrieve elements from the beginning of the list\nand add new values to the end.\n#### peak\nTo see what will be the next dequeued element, use the `m_list_first` function.\n#### enqueue\nTo add elements to the queue, use the `m_list_append` function.\n#### dequeue\nTo retrieve elements from the queue, use the `m_list_remove_first` function.\n\n## Return codes\n### `M_LIST_OK`\nUsed by all algorithms and general-purpose functions in case of a successful\nrun of the function.\n\n### `M_LIST_TRUE`\nUsed by all predicates and some of the general-purpose functions to indicate\nthat the expected conditions were met.\n\n### `M_LIST_FALSE`\nUsed by all predicates and some of the general-purpose functions to indicate\nthat the expected conditions were _not_ met. It is important to note that this\nreturn code is _not_ an error, but a valid logic value.\n\n### `M_LIST_E_NULL`\nUsed by every function to indicate that one or more of the essential arguments\nwere `NULL`. Arguments such as `payload` can hold the value of `NULL`, since it\nmight be a valid value picked by the user.\n\n### `M_LIST_E_OUT_OF_BOUNDS`\nUsed by functions that expect an index or a count that relates to the elements.\nThis return codes indicates that the number supplied is larger than the length\nof the list.\n\n### `M_LIST_E_NOT_PRESENT`\nReturned by the `m_list_remove_safe` function in case that the element selected\nfor removal is not present in the list.\n\n### `M_LIST_E_UNKNOWN_COPY`\nReturned in case that the `copy` argument of a function is not one of the\nfollowing: `M_LIST_COPY_SHALLOW`, `M_LIST_COPY_DEEP`.\n\n### `M_LIST_E_UNKNOWN_LOCATION`\nReturned in case that the `loc` argument of a function is not one of the\nfollowing: `M_LIST_INSERT_BEFORE`, `M_LIST_INSERT_AFTER`.\n\n### `M_LIST_E_UNKNOWN_CODE`\nReturned by the `m_list_error_string` function, in case that the queries return\ncode does not exists.\n\n## Supported platforms\n * FreeBSD 10.0 with Clang 3.3\n * OS X 10.9 with Clang 3.5\n * Linux Gentoo 2.2 with Clang 3.6\n\nIf a platform does not appear to be in the previous list, it does not mean that\n`m_list` will not work in such environment. It only means that nobody tested\nit - you are encouraged to do so and report either success or failure.\n\n## Build \u0026 install\n```\n$ ninja\n$ sudo ./install.sh\n```\n\n## License\n2-clause BSD license. For more information please consult the\n[LICENSE](LICENSE.md) file. In the case that you need a different license, feel\nfree to contact me.\n\n## Author\nDaniel Lovasko (daniel.lovasko@gmail.com)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flovasko%2Fm_list","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flovasko%2Fm_list","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flovasko%2Fm_list/lists"}