Giter Site home page Giter Site logo

1.8: How to use list? about pupnp HOT 13 CLOSED

pupnp avatar pupnp commented on June 3, 2024
1.8: How to use list?

from pupnp.

Comments (13)

ukleinek avatar ukleinek commented on June 3, 2024 1

@v00d00: I'd let the _add routine take either only a single new item or a C array (+ a parameter for the length).

from pupnp.

mrjimenez avatar mrjimenez commented on June 3, 2024

Hi Ian,

I imagine you already know that, but for completeness, the relevant files are upnp/inc/TemplateSource.h and upnp/inc/TemplateInclude.h, where the methods are generated. And of course, upnp/inc/list.h, where the list implementation resides.

The "list" type used is a frozen version of the linux kernel list. I tried to keep the file as close as possible to the original, so that it would be easy to put patches and keep it up to date.

The clever mechanism in this list is that it can be a list of anything you want, it really does not care about the structure that you want to be in that list. All that matters is that this struct contains a "struct list head something" member anywhere inside it. And it is a pointer to this struct that you get back when you call the get method "const struct list_head *CLASS##get##MEMBER(const CLASS *p)". All you need to know is that there is a "member function" to retrieve that member object. The object returned is a pointer to a "struct list head". And that list is totally "struct agnostic". You can put anything on that list, as long as it has a field that is a "struct list head" (not a pointer, the struct itself).

To recover your original struct from the list, you must walk that list with the functions and macros of the "list.h" file. For example, two of the most useful macros:

/**

  • list_entry - get the struct for this entry
  • @ptr: the &struct list_head pointer.
  • @type: the type of the struct this is embedded in.
  • @member: the name of the list_struct within the struct.
    */
    #define list_entry(ptr, type, member) \
    container_of(ptr, type, member)

/**

  • list_for_each - iterate over a list
  • @pos: the &struct list_head to use as a loop cursor.
  • @Head: the head for your list.
    */
    #define list_for_each(pos, head) \
    for (pos = (head)->next; prefetch(pos->next), pos != (head); \
    pos = pos->next)

There are several macros there that do the necessary magic. The file list.h is worth a read.

Back when I put this list code in pupnp, the intention was to use something proven and practical and that was written in C, not C++. I think this list code is still used today to implement lots of things inside the linux kernel.

I hope I was clear, but if there are any doubts remaining, please ask.

Best regards,
Marcelo.

from pupnp.

whyman avatar whyman commented on June 3, 2024

I am probably doing something wrong but getting:

/usr/include/upnp-1.8/list.h:360:26: note: in definition of macro ‘list_entry’
  container_of(ptr, type, member)
                          ^~~~~~
/usr/include/upnp-1.8/list.h:360:2: error: ‘container_of’ was not declared in this scope
  container_of(ptr, type, member)
  ^

from pupnp.

mrjimenez avatar mrjimenez commented on June 3, 2024

You are doing it right. There is missing code that should be in an include file.

We must add it somewhere, maybe in list.h.

#undef offsetof
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

/**

  • container_of - cast a member of a structure out to the containing structure
  • @ptr: the pointer to the member.
  • @type: the type of the container struct this is embedded in.
  • @member: the name of the member within the struct.

*/
#define container_of(ptr, type, member) ({
const typeof( ((type *)0)->member ) *__mptr = (ptr);
(type *)( (char *)__mptr - offsetof(type,member) );})

from pupnp.

mrjimenez avatar mrjimenez commented on June 3, 2024

I have just committed a new version of list.h, please check.

Also, I did a rebase on the philipe44-master branch, it this is the one you are using, maybe you will want to delete it and fetch it again.

from pupnp.

ukleinek avatar ukleinek commented on June 3, 2024

My personal opinion is that exposing list_head in the upnp-API is wrong. Something like this is better to be kept internal. The list implementation changed since libupnp 1.6.x, and we have problems like
Debian Bug #884243 where programs started to use the upnp list implementation for their own use and so are harder to convert to libupnp 1.8.

from pupnp.

whyman avatar whyman commented on June 3, 2024

@mrjimenez thanks, I will try it later.

@ukleinek I do not see how we can avoid exposing some kind of list here?

from pupnp.

whyman avatar whyman commented on June 3, 2024

Hmm again probably doing something wrong here, but I cant seem to use this from C++.

I guess this needs an actual C compiler to work.

from pupnp.

whyman avatar whyman commented on June 3, 2024

I am still having troube here with 1.8.5

auto head = const_cast<list_head*>(UpnpFileInfo_get_ExtraHeadersList(fileInfo));
UpnpExtraHeaders* h = UpnpExtraHeaders_new();
UpnpExtraHeaders_strcpy_name(h, "example-header");
UpnpExtraHeaders_strcpy_value(h, "example-value");
UpnpExtraHeaders_set_resp(h, "lolcat");
UpnpExtraHeaders_add_to_list_node(h, head); // ?
// or
UpnpFileInfo_add_to_list_ExtraHeadersList(fileInfo, head); // ?

But nothing seems to be produced

Apolgies in advance...

from pupnp.

mrjimenez avatar mrjimenez commented on June 3, 2024

Hi Ian,

Your code is ok, I don't know why nothing is produced. Both add_to_list's are fine, I just don't have it in my mind right now how the structures are supposed to be used.

In fact, these templates were meant to be used in a C compiler, but there is nothing stopping you from using it from a C++ compiler.

Designing this API for a C++ compiler would in fact simplify things a lot by using real classes.

No need for apologies, if I can help somehow, please tell me.

Regards,
Marcelo.

from pupnp.

whyman avatar whyman commented on June 3, 2024

Working for me now... not sure why the above was giving me trouble... PEBKAC almost certainly.

Example of use for adding headers:

auto head = const_cast<list_head*>(UpnpFileInfo_get_ExtraHeadersList(fileInfo));
for (auto header : *headers) {
    UpnpExtraHeaders* h = UpnpExtraHeaders_new();
    UpnpExtraHeaders_set_resp(h, header);
    UpnpExtraHeaders_add_to_list_node(h, head);
}

Do not include a trailing CLRF or you will destroy the HTTP payload 👎

I wonder if we need to patch the const-ness? Perhaps make CLASS##_add_to_list_##MEMBER take a const value?

from pupnp.

whyman avatar whyman commented on June 3, 2024

And for tidiness consider making ExtraHTTPHeaders() in webserver.c call the UpnpExtraHeaders_add_to_list_node method rather using list_add directly

from pupnp.

mrjimenez avatar mrjimenez commented on June 3, 2024

I think they are both good ideas. If you have a patch I will happily accept it.

from pupnp.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.