Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Generic Linked List Library (similar to C++ STL list) - version 1.0

72 views
Skip to first unread message

Amit

unread,
Nov 13, 2022, 3:40:29 AM11/13/22
to

Generic Linked List Library (similar to C++ STL list) - version 1.0

The code is below:

-----------------------------
generic_linked_list_library.c
-----------------------------

/*
* License: This file has been released under APACHE LICENSE, VERSION 2.0.
* The license details can be found here:
https://www.apache.org/licenses/LICENSE-2.0
*/

#include <stdlib.h>
#include <string.h>

#include "generic_linked_list_library.h"

struct generic_linked_list_container
*init_generic_linked_list_container(before_deleting_data_callback_function
func)
{

struct generic_linked_list_container *gllc_ptr = malloc(sizeof(*gllc_ptr));

if (!gllc_ptr)
return NULL;

gllc_ptr->first = NULL;
gllc_ptr->last = NULL;
gllc_ptr->bdd_callback_func = func;
gllc_ptr->total_number_of_nodes = 0;

return gllc_ptr;

} // end of init_generic_linked_list_container

int add_new_node_to_end(struct generic_linked_list_container
*gllc_ptr, void *data, long data_len)
{

struct linked_list_node *lln = NULL;
struct node_data *nddt = NULL;

if (!data)
return ARG_DATA_IS_NULL;

if (data_len <= 0)
return DATA_LEN_IS_INVALID;

lln = malloc(sizeof(*lln));
if (!lln) {
return NO_MEMORY;
}

nddt = malloc(sizeof(*nddt));
if (!nddt) {
free(lln);
return NO_MEMORY;
}

nddt->data = malloc((size_t)(data_len));
if (!nddt->data) {
free(nddt);
free(lln);
return NO_MEMORY;
}

nddt->data_len = data_len;
memmove(nddt->data, data, (size_t)(nddt->data_len));

lln->nd_ptr = nddt;
lln->next = NULL;

if (gllc_ptr->total_number_of_nodes == 0) {
gllc_ptr->first = lln;
gllc_ptr->last = lln;
} else {
gllc_ptr->last->next = lln;
}

gllc_ptr->total_number_of_nodes = gllc_ptr->total_number_of_nodes + 1;

return GLLL_SUCCESS;

} // end of add_new_node_to_end

struct node_data *remove_front_node_and_get_data(struct
generic_linked_list_container *gllc_ptr)
{

struct linked_list_node *lln_ptr = NULL;
struct node_data *nddt = NULL;

lln_ptr = remove_front_node(gllc_ptr);
if (!lln_ptr)
return NULL;

nddt = lln_ptr->nd_ptr;

free(lln_ptr);

return nddt;

} // end of remove_front_node_and_get_data

struct linked_list_node *remove_front_node(struct
generic_linked_list_container *gllc_ptr)
{

struct linked_list_node *lln_ptr = NULL;

if (gllc_ptr->total_number_of_nodes == 0)
return NULL;

lln_ptr = gllc_ptr->first;

if (gllc_ptr->total_number_of_nodes == 1) {
gllc_ptr->first = NULL;
gllc_ptr->last = NULL;
} else {
gllc_ptr->first = gllc_ptr->first->next;
}

gllc_ptr->total_number_of_nodes = gllc_ptr->total_number_of_nodes - 1;

lln_ptr->next = NULL;

return lln_ptr;

} // end of remove_front_node

void delete_front_node(struct generic_linked_list_container *gllc_ptr)
{

struct linked_list_node *lln_ptr = NULL;
struct node_data *nddt = NULL;

lln_ptr = remove_front_node(gllc_ptr);
if (!lln_ptr)
return;

nddt = lln_ptr->nd_ptr;

if (gllc_ptr->bdd_callback_func)
gllc_ptr->bdd_callback_func(nddt);

free(nddt);
free(lln_ptr);

return;

} // end of delete_front_node

-----------------------------
generic_linked_list_library.h
-----------------------------

/*
* License: This file has been released under APACHE LICENSE, VERSION 2.0.
* The license details can be found here:
https://www.apache.org/licenses/LICENSE-2.0
*/

#ifndef _GENERIC_LINKED_LIST_LIBRARY_H_
#define _GENERIC_LINKED_LIST_LIBRARY_H_

#define GLLL_SUCCESS 0 // everything happened successfully
#define ARG_DATA_IS_NULL -1 // 'data' argument is NULL
#define DATA_LEN_IS_INVALID -2 // 'data_len' argument is <= 0
#define NO_MEMORY -3 // no memory available

struct node_data
{
void *data;
long data_len;
};

struct linked_list_node
{
struct node_data *nd_ptr;
struct linked_list_node *next;
};

typedef void (*before_deleting_data_callback_function)(struct node_data *);

struct generic_linked_list_container
{
struct linked_list_node *first;
struct linked_list_node *last;
before_deleting_data_callback_function bdd_callback_func;
long total_number_of_nodes;
};

struct generic_linked_list_container
*init_generic_linked_list_container(before_deleting_data_callback_function
func);
int add_new_node_to_end(struct generic_linked_list_container
*gllc_ptr, void *data, long data_len);
struct node_data *remove_front_node_and_get_data(struct
generic_linked_list_container *gllc_ptr);
struct linked_list_node *remove_front_node(struct
generic_linked_list_container *gllc_ptr);
void delete_front_node(struct generic_linked_list_container *gllc_ptr);

#endif

---- End of code ----

Ben Bacarisse

unread,
Nov 13, 2022, 8:17:59 AM11/13/22
to
Amit <amitchou...@gmail.com> writes:

> Generic Linked List Library (similar to C++ STL list) - version 1.0

I'm not sure what you want from posting this. I'm going to assume you
want some comments on the code.

My main objection is the you force copying of the user's data when it's
often useful to have lists that share data. You could provide both an
'add' and an 'add_copy' function, but since copying the data is simple,
you could just leave it up to the caller.

A second issue if that you return what is essentially a private
structure when returning data. Surely you should simply return the data
pointer itself? The user can't so anything useful with a struct
node_data, can they?

A third design issue is that you expose the definition of struct
generic_linked_list_container to the user. This should be an 'opaque'
type visible only to the implementation.

Finally, why only add to end and remove from front? A generic list
should support add to front and remove from end as well as a more
general mechanism to insert and remove data at any position.

> struct generic_linked_list_container
> *init_generic_linked_list_container(before_deleting_data_callback_function
> func)

It's all very well having long explanatory names (though I am not a fan)
but they should all start with some common prefix to indicate that they
are all related functions. Something like gll_<whatever> for example.

> int add_new_node_to_end(struct generic_linked_list_container
> *gllc_ptr, void *data, long data_len)

size_t data_len would be more standard.

> lln = malloc(sizeof(*lln));
> if (!lln) {
> return NO_MEMORY;
> }
>
> nddt = malloc(sizeof(*nddt));
> if (!nddt) {
> free(lln);
> return NO_MEMORY;
> }

I would try to avoid doing to allocations here. It's not trivial to
arrange, but it can be done in modern C.

> nddt->data = malloc((size_t)(data_len));
> if (!nddt->data) {
> free(nddt);
> free(lln);
> return NO_MEMORY;
> }
>
> nddt->data_len = data_len;
> memmove(nddt->data, data, (size_t)(nddt->data_len));

There's no need to use memmove here. A plain memcpy will be fine. The
source and destination can't possibly overlap.

> lln->nd_ptr = nddt;
> lln->next = NULL;
>
> if (gllc_ptr->total_number_of_nodes == 0) {
> gllc_ptr->first = lln;
> gllc_ptr->last = lln;
> } else {
> gllc_ptr->last->next = lln;
> }
>
> gllc_ptr->total_number_of_nodes = gllc_ptr->total_number_of_nodes + 1;

I'd shorten that:

gllc_ptr->total_number_of_nodes += 1;

or

++gllc_ptr->total_number_of_nodes;

> return GLLL_SUCCESS;
>
> } // end of add_new_node_to_end

--
Ben.

Amit

unread,
Nov 13, 2022, 8:46:51 AM11/13/22
to

On Sun, Nov 13, 2022, 6:48 PM Ben Bacarisse <ben.u...@bsb.me.uk> wrote:
Amit <amitchou...@gmail.com> writes:

> Generic Linked List Library (similar to C++ STL list) - version 1.0

I'm not sure what you want from posting this. I'm going to assume you
want some comments on the code.


Hi Ben,

Thanks for the review. This code is not complete yet, that's why I called it version 1.0.

I am actually implementing C++ STL in C.

I am also writing code for Java string functions in C to augment C string library functions. I am also introducing some string functions of my own.

I started to do this to make programming in C easier.

May be, these things might have already been done earlier but I am not sure.

The main idea of sending the code to this group was to let C people know that things like this (C++ STL in C) exist and they can use it.

I am not sending my code for review.

I will send this kind of code later also but if many people object then I will not send it.

Next time, I will mention why I am sending it.

Regards,
Amit

Chris M. Thomasson

unread,
Nov 13, 2022, 3:58:18 PM11/13/22
to
On 11/13/2022 12:40 AM, Amit wrote:
>
> Generic Linked List Library (similar to C++ STL list) - version 1.0
>
> The code is below:
>
> -----------------------------
> generic_linked_list_library.c
> -----------------------------
>
> /*
> * License: This file has been released under APACHE LICENSE, VERSION 2.0.
> * The license details can be found here:
> https://www.apache.org/licenses/LICENSE-2.0
> */
>
> #include <stdlib.h>
> #include <string.h>
>
> #include "generic_linked_list_library.h"
>
> struct generic_linked_list_container
> *init_generic_linked_list_container(before_deleting_data_callback_function
> func)
> {
>
> struct generic_linked_list_container *gllc_ptr = malloc(sizeof(*gllc_ptr));
[...]

Fwiw, I prefer intrusive containers when possible.

Ben Bacarisse

unread,
Nov 13, 2022, 9:47:43 PM11/13/22
to
Amit <amitchou...@gmail.com> writes:

> I am not sending my code for review.

I see.

> I will send this kind of code later also but if many people object
> then I will not send it.
>
> Next time, I will mention why I am sending it.

So I'm not sure why you posted the code. If you want people to know of
the software's existence (so that it might be used), then you should
post a link to the documentation.

--
Ben.

Amit

unread,
Nov 14, 2022, 12:19:02 AM11/14/22
to
> So I'm not sure why you posted the code. If you want people to know of
> the software's existence (so that it might be used), then you should
> post a link to the documentation.

Didn't understand why you said to post an external link to documentation.

In my opinion, the documentation and code should go together.

Next time, I will include the documentation in the code itself.

Amit

Öö Tiib

unread,
Nov 14, 2022, 3:39:09 AM11/14/22
to
If you want to hear about other such C container effort then maybe read that:
<https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1625.pdf>

In general better post your external project that you hope to be useful as link to
public repo. Like for example github.

Then people know that it will be there, can put their issues directly to issue
management of it and if interested about particular version of it can share
the link to others. Only novice goes to search and copy-paste code from some
forum post. Very rare novice knows where Usenet is, most posts time out fast
on Usenet servers and whatever code looks like garbage in google groups
archives.

Documentation in particular is usually easier to read as formatted and structured
differently than source code for example as markdown (*.md) files. Push those
also to repo, do not try to integrate everything to source code. You may have
different opinion now but don't be surprised if that opinion does change.

Amit

unread,
Nov 14, 2022, 4:14:29 AM11/14/22
to
I totally agree with you.

But actually, I am not very serious about all this. I just code in my free time whatever I want to code.

Even if people don't use my code, its fine. They may not copy my code from this forum and that's too fine with me.

I just sent the code here so that in case some people are interested then they can use it.

If no one uses it, then that is also fine with me.

Amit

Chris M. Thomasson

unread,
Nov 14, 2022, 4:33:05 AM11/14/22
to
Imvho, one "benefit" of an intrusive container is that no malloc/free is
needed in the guts of the linked list logic. No memory management. That
aspect is totally left up to the user of the abstract intrusive linked
list impl. Nice from a lib writers point of view... ;^)

Po Lu

unread,
Nov 14, 2022, 4:47:17 AM11/14/22
to
"Chris M. Thomasson" <chris.m.t...@gmail.com> writes:

> Imvho, one "benefit" of an intrusive container is that no malloc/free
> is needed in the guts of the linked list logic. No memory
> management.

Indeed. Especially when your program has its own malloc (or
replacement, i.e. the Memory Pool System.)

Amit

unread,
Nov 14, 2022, 5:07:48 AM11/14/22
to
My goal is to make my library easy to use (just like Java/C++). That's why I have removed the burden of memory allocation, etc. from the user. In C++, when the user uses C++ STL list, the user doesn't have to bother about memory allocation, etc. I am trying to achieve similar functionality.

Amit

Ben Bacarisse

unread,
Nov 14, 2022, 7:25:38 AM11/14/22
to
Amit <amitchou...@gmail.com> writes:

>> So I'm not sure why you posted the code. If you want people to know of
>> the software's existence (so that it might be used), then you should
>> post a link to the documentation.
>
> Didn't understand why you said to post an external link to
> documentation.
>
> In my opinion, the documentation and code should go together.

Sure, but if you post the code, people are likely to review it and you
have said you don't want that. Posting just documentation would be OK,
but you'll still likely get reviews of the design and interface.
Posting just a link would make it less likely that anyone would review
it whist letting people know it's there. That seems to be more in line
with what you want.

> Next time, I will include the documentation in the code itself.

But make sure to say that you don't want a code review or people will
waste their time making comments and suggestions.

--
Ben.

Amit

unread,
Nov 14, 2022, 9:25:24 AM11/14/22
to
I will be sending code in this group but I will mention that please don't review.

If many people have issues with it, then please let me know. In that case, I will not send the code.

Amit

Andrey Tarasevich

unread,
Nov 14, 2022, 11:57:50 AM11/14/22
to
On 11/13/2022 12:40 AM, Amit wrote:
>
> Generic Linked List Library (similar to C++ STL list) - version 1.0
>

And what exactly is the purpose of separating each list node into three
(three!) independently allocated elements? Why not a monolithic node
through, say, struct hack/flexible array member at the end? And if you
for some reason wanted to avoid flexible members, then... why three
instead of, say, two? What was the purpose of separating `struct
linked_list_node` and `struct node_data` from each other?

--
Best regards,
Andrey

Keith Thompson

unread,
Nov 14, 2022, 12:04:00 PM11/14/22
to
Amit <amitchou...@gmail.com> writes:
[...]
> I will be sending code in this group but I will mention that please
> don't review.
>
> If many people have issues with it, then please let me know. In that
> case, I will not send the code.

This is a discussion group, not a write-only code repository.

You're welcome to post here, but don't want people to discuss what you
post I don't see the point.

--
Keith Thompson (The_Other_Keith) Keith.S.T...@gmail.com
Working, but not speaking, for XCOM Labs
void Void(void) { Void(); } /* The recursive call of the void */

Keith Thompson

unread,
Nov 14, 2022, 12:16:44 PM11/14/22
to
Keith Thompson <Keith.S.T...@gmail.com> writes:
> Amit <amitchou...@gmail.com> writes:
> [...]
>> I will be sending code in this group but I will mention that please
>> don't review.
>>
>> If many people have issues with it, then please let me know. In that
>> case, I will not send the code.
>
> This is a discussion group, not a write-only code repository.
>
> You're welcome to post here, but don't want people to discuss what you
> post I don't see the point.

Sorry, I dropped a couple of words.

You're welcome to post here, but *if you* don't want people to discuss
0 new messages