Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

C template

Name: Anonymous 2011-12-19 12:05

Does this qualify for a template?

utility_stack.h
#ifndef __UTILITY_STACK_H
#define __UTILITY_STACK_H

#include <stddef.h>
#include <stdlib.h>

#define UTILITY_STACK_RESIZE_FACTOR (0.70)

#define utility_stack(type)                     \
  struct {                                      \
    type * base;                                \
    type * read;                                \
    type * end;                                 \
  }

#define utility_stack_init(stack)                       \
  ({                                                    \
    typeof(stack) __s = (stack);                        \
                                                        \
    __s->base = NULL;                                   \
    __s->read = __s->base;                              \
    __s->end  = __s->base + 0;                          \
  })

#define utility_stack_clear(stack)                      \
  ({                                                    \
    typeof(stack) __s = (stack);                        \
                                                        \
    free(__s->base);                                    \
  })

#define utility_stack_push(stack, element)                              \
  ({                                                                    \
    typeof(stack) __s = (stack);                                        \
    typeof(element) __e = (element);                                    \
                                                                        \
    if (__s->read == __s->end) {                                        \
      ptrdiff_t __read_offset = (__s->read - __s->base);                \
      ptrdiff_t __size = (__s->end - __s->base);                        \
                                                                        \
      __s->base = realloc(__s->base,                                    \
                          ((size_t)                                     \
                           ((UTILITY_STACK_RESIZE_FACTOR + 1) *         \
                            __size) + 1) *                              \
                          sizeof(*__s->base));                          \
                                                                        \
      __s->read = __s->base + __read_offset;                            \
      __s->end  = __s->base +                                           \
        (size_t) ((UTILITY_STACK_RESIZE_FACTOR + 1) *                   \
                  __size) + 1;                                          \
    }                                                                   \
                                                                        \
    *__s->read++ = __e;                                                 \
  })

#define utility_stack_pop(stack)                \
  ({                                            \
    typeof(stack) __s = (stack);                \
                                                \
    __s->read == __s->base ?                    \
      (typeof(*__s->read)) NULL :               \
      *--__s->read;                             \
  })

#define utility_stack_size(stack)               \
  ({                                            \
    typeof(stack) __s = (stack);                \
                                                \
    (size_t) (__s->read - __s->base);           \
  })

#define utility_stack_contains(stack, candidate, eq)    \
  ({                                                    \
    int __in = 0;                                       \
                                                        \
    typeof(stack) __s = (stack);                        \
    typeof(candidate) __c = (candidate);                \
    typeof(__s->read) __r = __s->read;                  \
                                                        \
    while (__s->base < __r)                             \
      if (eq(__c, *--__r)) {                            \
        __in = 1;                                       \
        break;                                          \
      }                                                 \
                                                        \
    __in;                                               \
  })

#endif /* __UTILITY_STACK_H */


Example usage:
#include <stdio.h>
#include <string.h>

#include "utility_stack.h"

#define str_eq(a, b) (strcmp(a, b) == 0)

int main (int argc, char ** argv) {
  utility_stack(char *) s;
  utility_stack_init(&s);

  while (--argc)
    utility_stack_push(&s, *++argv);

  if (utility_stack_contains(&s, "/prog/", str_eq))
    puts("/prog/ found on stack!");

  while (utility_stack_size(&s))
    printf("%s\n", utility_stack_pop(&s));

  utility_stack_clear(&s);

  return 0;
}

Name: Anonymous 2011-12-19 12:32

>>1

This code seems good. I've got a library of small pseudo-templates for many data structures as well, it works wonders.

Let me give you a number of hints.

1. Don't use __UTILITY_STACK_H as header guard, any symbol beginning with __ is standards-reserved (this also applies to the field names in the structure);
2. Relying in the same identifier for the "methods" of your template is not a good thing in C, specially because you might decide to move your code to a function (and overloading in C is not supported). An alternative approach is to separate the template in a declaration macro (DECLARE_STACK), which declares the structure and the functions, and a definition macro (DEFINE_STACK), which defines the functions. (This is exactly the same as explicitly instantiating a template.) You can then use the type name to build proper symbol names for yoyr methods (for example, intstack_push) by pasting them with the preprocessor;
3. If you're using C99, I'd also suggest you to create inline functions instead of macros. This will give you an extra degree of type safety and flexibility, specially when debugging;
4. If you intend to create extra "templates" using this scheme, you might also benefit a little from some type traits macros (as it is done in Sepples). The objective is to insulate a number of common type properties (such as the comparison function used) from every template/data structure which uses them.

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List