Loading ...
Sorry, an error occurred while loading the content.

Re: Why C? If so how is the best way to have simple lists ?

Expand Messages
  • Marko Mahnič
    ... I think it would be hard to create a generic type-safe container library in C. I only see two options: rewrite container manipulation code for every type
    Message 1 of 20 , Jul 28, 2013
    • 0 Attachment
      > But it does not get the task done I talked about: type safe container
      > like stuff.

      I think it would be hard to create a generic type-safe container library in C. I only see two options: rewrite container manipulation code for every type of object (as is done in Vim) or define the container code as a set of preprocessor macros. In both cases a lot of code is duplicated either by the programmer or by the compiler. Also a lot of code in Vim relies on linked lists so it would be a huge and error-prone task to change all that.

      A solution compatible with the current state of Vim would be to use helpers for various containers. A helper for the linked list would look like:

      struct ListHelper
      {
      void** list_head_ptr;
      void** list_tail_ptr;
      int offset_of_next;
      int offset_of_prev;
      };

      void
      _lsthlpr_add_head(self, item)
      ListHelper* self;
      void* item;
      {
      void *pit = *self->list_head_ptr;
      *self->list_head_ptr = item;
      *(void**)((char*)item + self->offset_of_next) = pit; /* item->next = pit */
      if (self->list_tail_ptr && ! *self->list_tail_ptr)
      *self->list_tail_ptr = pit;
      }

      A list of Node structures along with it's helper would be initialized as:

      struct Node
      {
      Node* next;
      int data;
      };
      Node* my_nodes;
      ListHelper my_node_list;
      my_node_list.list_head_ptr = &my_nodes;
      my_node_list.list_tail_ptr = NULL; // we only use the forward pointer
      my_node_list.offset_of_next = offsetof(Node, next);
      my_node_list.offset_of_prev = -1; // reverse pointer doesn't exist

      Node* pnode = createNode();
      _lsthlpr_add_head(&my_node_list, pnode);

      You can still traverse the list in a type-safe way through my_nodes. The manipulation of the list through the list helper is type unsafe.

      If you feel it is absolutely necessary, a kind of run-time type safety could be achieved by adding a typeid member to the beginning of every structure that would be used in a container. The typeid for a structure would be set in a 'constructor' like createNode(). The same typeid would also be set in the helper during initialization. The helper methods would compare the value from the element to the value of the container.

      A more complex implementation of the ListHelper is in the file puls_st.c starting around line 108. It's not exactly C (without some preprocessing) but it will give you an idea.

      http://code.google.com/r/markomahnic-vim-popuplist/source/browse/src/puls_st.c?name=vim-popuplist

      A use example is in puls_st.c around line 2466 (_txmfac_init).

      http://code.google.com/r/markomahnic-vim-popuplist/source/browse/src/popuplst.c?name=vim-popuplist

      Marko

      --
      --
      You received this message from the "vim_dev" maillist.
      Do not top-post! Type your reply below the text you are replying to.
      For more information, visit http://www.vim.org/maillist.php

      ---
      You received this message because you are subscribed to the Google Groups "vim_dev" group.
      To unsubscribe from this group and stop receiving emails from it, send an email to vim_dev+unsubscribe@....
      For more options, visit https://groups.google.com/groups/opt_out.
    • Charles Campbell
      ... I use some macros... (outofmem() can be removed; it checks if the returned pointer is null, isses the failure message if so, and terminates). These four
      Message 2 of 20 , Jul 29, 2013
      • 0 Attachment
        David Larson wrote:
        > On Saturday, June 8, 2013 2:48:39 PM UTC-7, Bram Moolenaar wrote:
        >> There are no options. Vim is written in C and I see no reason to
        >>
        >> change. Perhaps, when Zimbu is "ready" I might consider rewriting some
        >>
        >> pieces in Zimbu, but that's going to take several years during which no
        >>
        >> bugs will be fixed and no new features will be added. For a similar
        >>
        >> reason Elvis no longer exists...
        > Aack! Don't do that! We want VIM to stay alive. I personally am not willing to see no advancement in VIM for several years just so that it can be ported to Zimbu. (Perhaps that was your point...)
        >
        > It seems somewhat safe to me if the file names were changed from .c to .cpp. That would allow us to leverage basic libraries and simple OOP. We can steer clear of the more esoteric and tricky features of the language.
        >
        I use some macros... (outofmem() can be removed; it checks if the
        returned pointer is null, isses the failure message if so, and
        terminates). These four macros presume that there are "nxt" and "prv"
        pointers in the structure for linking.

        #define double_link(structure,head,tail,fail_msg)
        { \
        structure *newstr; \
        newstr= (structure *)
        malloc(sizeof(structure)); \
        outofmem((void *)
        newstr,"%s\n",fail_msg); \
        if(tail) (tail)->nxt=
        newstr; \
        else head =
        newstr; \
        newstr->prv= tail; \
        newstr->nxt= (structure *)
        NULL; \
        tail = newstr; \
        }
        #define delete_double_link(structure,str,head,tail)
        { \
        structure *old=
        str; \
        if(old) { \
        if(old->prv) old->prv->nxt=
        old->nxt; \
        else head =
        old->nxt; \
        if(old->nxt) old->nxt->prv=
        old->prv; \
        else tail =
        old->prv; \
        free((char *)
        old); \
        } \
        }
        #define only_double_link(structure,newstr,head,tail)
        { \
        if(tail) (tail)->nxt=
        newstr; \
        else head =
        newstr; \
        newstr->prv= tail; \
        newstr->nxt= (structure *)
        NULL; \
        tail = newstr; \
        }
        #define only_delete_double_link(structure,str,head,tail)
        { \
        structure *old=
        str; \
        if(old) { \
        if(old->prv) old->prv->nxt=
        old->nxt; \
        else head =
        old->nxt; \
        if(old->nxt) old->nxt->prv=
        old->prv; \
        else tail =
        old->prv; \
        } \
        }

        Typical use:

        struct ABC_str {
        double something;
        struct ABC_str *nxt;
        struct ABC_str *prv;
        } *abchd= NULL, *abctl= NULL;

        double_link(struct ABC_str, abchd,abctl,"failed while attempting to
        double-link an ABC_str");

        struct ABC_str *abc;
        delete_double_link(struct ABC_str,abc,abchd,abctl);

        Regards,
        Chip Campbell

        --
        --
        You received this message from the "vim_dev" maillist.
        Do not top-post! Type your reply below the text you are replying to.
        For more information, visit http://www.vim.org/maillist.php

        ---
        You received this message because you are subscribed to the Google Groups "vim_dev" group.
        To unsubscribe from this group and stop receiving emails from it, send an email to vim_dev+unsubscribe@....
        For more options, visit https://groups.google.com/groups/opt_out.
      Your message has been successfully submitted and would be delivered to recipients shortly.