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

Pages: 1-

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:06

No.

Name: Anonymous 2011-12-19 12:09

>>2
What's missing?

Name: Anonymous 2011-12-19 12:11

>>3
maintability

Name: Anonymous 2011-12-19 12:13

>>2
This is basically how they're done in Java.

Name: Anonymous 2011-12-19 12:15

>>4
Funny joke, templates in SEPPLES aren't maintainable.

Name: Anonymous 2011-12-19 12:18

>>5
Really?

Name: Anonymous 2011-12-19 12:28

>>7
Generics in Java are just syntactic sugar.

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.

Name: Anonymous 2011-12-19 12:37

>>9
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
That's what I originally did, but it didn't cooperate well with pointers.

Thanks for the pointers though.

Name: Anonymous 2011-12-19 12:41

Perfect example as to why C is so useless, everyone has to implement basic features themselves, usually breaking something or causing some bugs in the process.

Name: Anonymous 2011-12-19 12:50

>>11
If you only tackle problems other people have already solved, stick with Java, python, perl, and ruby. Faggot.

Name: Anonymous 2011-12-19 13:06

>>12
Are you angry, is that why you forgot your \`\`FAGGOT QUOTES\'\'?

Name: Anonymous 2011-12-19 13:25

>>13
Why would I be angry? I don't depend on you to make coding decisions. I count that as a huge win for the day, finding this out.

Name: Anonymous 2011-12-20 4:53

I like it!

Two things:

1. You don't need to use __s as a variable name unless you really want to. Since it it is in its own {scope}, you don't need to worry about the name conflicting with other variables where the macro is used.

2. Since it is all written in macros, you can't use recursion, and you can't call functions (macros) that will eventually call the calling function. You can still do everything you could do anyways using other methods though, like using a stack to simulate a function call stack.

Name: Anonymous 2011-12-20 5:14

>>12

If you think you're solving problems that other people haven't already solved a thousand times, you don't understand what you're doing nor what other people have done in the past.

Name: Anonymous 2011-12-20 5:56

>>16

that was mean. take it back.

Name: Anonymous 2011-12-20 8:24

>>12,14,16
YHBT

Name: Anonymous 2011-12-20 9:34

So, is naming a variable __s directly violating the standard?

Name: Anonymous 2011-12-20 10:06

ENTERPRISE QUALITY PREPROCESSOR ABUSE

FrozenVoid would be proud

Name: Anonymous 2011-12-20 10:13

This is ok but really should be based on a universal queuestacklistarray that can be disguised as a stack if that's what one desires

Name: Anonymous 2011-12-20 10:23

>>20
Sepples was actually invented because ENTERPRISE QUALITY PREPROCESSOR ABUSE was not enough.

Name: Anonymous 2011-12-20 10:24

>>20,22
FrozenVoid would not be proud, he would squirm at the sight of this OO-like abstraction.

Name: Anonymous 2011-12-20 10:24

>>21
You mean an array deque?

Name: Anonymous 2011-12-20 10:25

>>22
They didn't have GNU extensions back then.

Name: Anonymous 2011-12-20 12:50

>>23
FrozenVoid would not be proud, he would squeak like the faggot furry he is at the sight of this OO-like abstraction.
FTFY

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