C语言接口与实现学习

C Interfaces and Implementations

简介: C语言接口与实现:创建可重用软件的技术 如今的程序员忙于应付大量关于API(Application Programming Interface)的信息。但是,大多数程序员都会在其所写的几乎每一个应用程序中使用API并实现API的库,只有少数程序员会创建或发布新的能广泛应用的API。
感受:
书中对atom,list,stack,hashtable,set,ring,exception等都作了探讨。看过这边书后,使用c编程的功力会大为提高(误。也许使用c++的朋友会认为这些c++的标准模板库都可以实现,因此对c封装这些不屑一顾。但是即使是c++程序员,我相信你看过本书后,就不会这么认为了,这些对写好c++代码也同样有好处。反正我是用STL后就变得很懒,什么数据结构都向STL靠,这可不是很好。网上有篇文章流传的很广,叫做《lua让我脸红》,为什么呢?因为lua编译器和虚拟机就是用纯c实现的。一个能把c写得如此优雅的人,你可以想到他写起c++来会怎么样。打开lua的源码,你会发现,一个全局变量都没有,代码非常简洁。lua编写就很有本书的思想。比如lua里面的字符串,全部都存在hashtable中,TSring存储的只是对hashtable的“引用”,比较字符串只需要比较地址就可以了。这个方法就是本书中的atom.

这本书还用setjmp,longjmp实现了一个c的异常机制,setjmp,longjmp在一般的c语言书中介绍的很少,看过之后,我对异常机制也有了更深的理解。

对于va_start,va_end这些函数,书中也有详细的讲解,如何封装成自己的format(如printf)函数。

有很多底层的函数,c标准库中的函数,本书都有实现,如itoa,还有字符串函数等。不要说这是重造轮子,这些有用得着的时候。

内存管理一向是大难题,对此,本书用两章内容探讨了自己封装内存管理函数,包括内存池的使用。

诸如此类的封装头直接上码:
ap.h

/* $Id$ */
#ifndef AP_INCLUDED
#define AP_INCLUDED
#include 
#include "fmt.h"
#define T AP_T
typedef struct T *T;
extern T AP_new    (long int n);
extern T AP_fromstr(const char *str, int base,
   char **end);
extern long int AP_toint(T x);
extern char    *AP_tostr(char *str, int size,
   int base, T x);
extern void     AP_fmt(int code, va_list_box *box,
   int put(int c, void *cl), void *cl,
   unsigned char flags[], int width, int precision);
extern void AP_free(T *z);
extern T AP_neg(T x);
extern T AP_add(T x, T y);
extern T AP_sub(T x, T y);
extern T AP_mul(T x, T y);
extern T AP_div(T x, T y);
extern T AP_mod(T x, T y);
extern T AP_pow(T x, T y, T p);
extern T    AP_addi(T x, long int y);
extern T    AP_subi(T x, long int y);
extern T    AP_muli(T x, long int y);
extern T    AP_divi(T x, long int y);
extern long AP_modi(T x, long int y);
extern T AP_lshift(T x, int s);
extern T AP_rshift(T x, int s);
extern int AP_cmp (T x, T y);
extern int AP_cmpi(T x, long int y);
#undef T
#endif

arena.h

/* $Id$ */
#ifndef ARENA_INCLUDED
#define ARENA_INCLUDED
#include "except.h"
#define T Arena_T
typedef struct T *T;
extern const Except_T Arena_NewFailed;
extern const Except_T Arena_Failed;
extern T    Arena_new    (void);
extern void Arena_dispose(T *ap);
extern void *Arena_alloc (T arena, long nbytes,
    const char *file, int line);
extern void *Arena_calloc(T arena, long count,
    long nbytes, const char *file, int line);
extern void  Arena_free  (T arena);
#undef T
#endif

arith.h

/* $Id$ */
extern int Arith_max(int x, int y);
extern int Arith_min(int x, int y);
extern int Arith_div(int x, int y);
extern int Arith_mod(int x, int y);
extern int Arith_ceiling(int x, int y);
extern int Arith_floor  (int x, int y);

array.h

/* $Id$ */
#ifndef ARRAY_INCLUDED
#define ARRAY_INCLUDED
#define T Array_T
typedef struct T *T;
extern T    Array_new (int length, int size);
extern void Array_free(T *array);
extern int Array_length(T array);
extern int Array_size  (T array);
extern void *Array_get(T array, int i);
extern void *Array_put(T array, int i, void *elem);
extern void Array_resize(T array, int length);
extern T    Array_copy  (T array, int length);
#undef T
#endif

arrayrep.h

/* $Id$ */
#ifndef ARRAYREP_INCLUDED
#define ARRAYREP_INCLUDED
#define T Array_T
struct T {
    int length;
    int size;
    char *array;
};
extern void ArrayRep_init(T array, int length,
    int size, void *ary);
#undef T
#endif

assert.h

/* $Id$ */
#undef assert
#ifdef NDEBUG
#define assert(e) ((void)0)
#else
#include "except.h"
extern void assert(int e);
#define assert(e) ((void)((e)||(RAISE(Assert_Failed),0)))
#endif

atom

/* $Id$ */
#ifndef ATOM_INCLUDED
#define ATOM_INCLUDED
extern       int   Atom_length(const char *str);
extern const char *Atom_new   (const char *str, int len);
extern const char *Atom_string(const char *str);
extern const char *Atom_int   (long n);
#endif

bit.h

/* $Id$ */
#ifndef BIT_INCLUDED
#define BIT_INCLUDED
#define T Bit_T
typedef struct T *T;
extern T   Bit_new   (int length);
extern int Bit_length(T set);
extern int Bit_count (T set);
extern void Bit_free(T *set);
extern int Bit_get(T set, int n);
extern int Bit_put(T set, int n, int bit);
extern void Bit_clear(T set, int lo, int hi);
extern void Bit_set  (T set, int lo, int hi);
extern void Bit_not  (T set, int lo, int hi);
extern int Bit_lt (T s, T t);
extern int Bit_eq (T s, T t);
extern int Bit_leq(T s, T t);
extern void Bit_map(T set,
    void apply(int n, int bit, void *cl), void *cl);
extern T Bit_union(T s, T t);
extern T Bit_inter(T s, T t);
extern T Bit_minus(T s, T t);
extern T Bit_diff (T s, T t);
#undef T
#endif

chan.h

/* $Id$ */
#ifndef CHAN_INCLUDED
#define CHAN_INCLUDED
#define T Chan_T
typedef struct T *T;
extern T   Chan_new    (void);
extern int Chan_send   (T c, const void *ptr, int size);
extern int Chan_receive(T c,       void *ptr, int size);
#undef T
#endif

except.h

/* $Id$ */
#ifndef EXCEPT_INCLUDED
#define EXCEPT_INCLUDED
#include 
#define T Except_T
typedef struct T {
    const char *reason;
} T;
typedef struct Except_Frame Except_Frame;
struct Except_Frame {
    Except_Frame *prev;
    jmp_buf env;
    const char *file;
    int line;
    const T *exception;
};
enum { Except_entered=0, Except_raised,
       Except_handled,   Except_finalized };
extern Except_Frame *Except_stack;
extern const Except_T Assert_Failed;
void Except_raise(const T *e, const char *file,int line);
#ifdef WIN32
#include 

extern int Except_index;
extern void Except_init(void);
extern void Except_push(Except_Frame *fp);
extern void Except_pop(void);
#endif
#ifdef WIN32
/* $Id$ */
#define RAISE(e) Except_raise(&(e), __FILE__, __LINE__)
#define RERAISE Except_raise(Except_frame.exception, \
    Except_frame.file, Except_frame.line)
#define RETURN switch (Except_pop(),0) default: return
#define TRY do { \
    volatile int Except_flag; \
    Except_Frame Except_frame; \
    if (Except_index == -1) \
        Except_init(); \
    Except_push(&Except_frame);  \
    Except_flag = setjmp(Except_frame.env); \
    if (Except_flag == Except_entered) {
#define EXCEPT(e) \
        if (Except_flag == Except_entered) Except_pop(); \
    } else if (Except_frame.exception == &(e)) { \
        Except_flag = Except_handled;
#define ELSE \
        if (Except_flag == Except_entered) Except_pop(); \
    } else { \
        Except_flag = Except_handled;
#define FINALLY \
        if (Except_flag == Except_entered) Except_pop(); \
    } { \
        if (Except_flag == Except_entered) \
            Except_flag = Except_finalized;
#define END_TRY \
        if (Except_flag == Except_entered) Except_pop(); \
        } if (Except_flag == Except_raised) RERAISE; \
} while (0)
#else
#define RAISE(e) Except_raise(&(e), __FILE__, __LINE__)
#define RERAISE Except_raise(Except_frame.exception, \
    Except_frame.file, Except_frame.line)
#define RETURN switch (Except_stack = Except_stack->prev,0) default: return
#define TRY do { \
    volatile int Except_flag; \
    Except_Frame Except_frame; \
    Except_frame.prev = Except_stack; \
    Except_stack = &Except_frame;  \
    Except_flag = setjmp(Except_frame.env); \
    if (Except_flag == Except_entered) {
#define EXCEPT(e) \
        if (Except_flag == Except_entered) Except_stack = Except_stack->prev; \
    } else if (Except_frame.exception == &(e)) { \
        Except_flag = Except_handled;
#define ELSE \
        if (Except_flag == Except_entered) Except_stack = Except_stack->prev; \
    } else { \
        Except_flag = Except_handled;
#define FINALLY \
        if (Except_flag == Except_entered) Except_stack = Except_stack->prev; \
    } { \
        if (Except_flag == Except_entered) \
            Except_flag = Except_finalized;
#define END_TRY \
        if (Except_flag == Except_entered) Except_stack = Except_stack->prev; \
        } if (Except_flag == Except_raised) RERAISE; \
} while (0)
#endif
#undef T
#endif

fmt.h

/* $Id$ */
#ifndef FMT_INCLUDED
#define FMT_INCLUDED
#include 
#include 
#include "except.h"
typedef struct va_list_box {
    va_list ap;
} va_list_box;
#define T Fmt_T
typedef void (*T)(int code, va_list_box *box,
    int put(int c, void *cl), void *cl,
    unsigned char flags[256], int width, int precision);
extern char *Fmt_flags;
extern const Except_T Fmt_Overflow;
extern void Fmt_fmt (int put(int c, void *cl), void *cl,
    const char *fmt, ...);
extern void Fmt_vfmt(int put(int c, void *cl), void *cl,
    const char *fmt, va_list_box *box);
extern void Fmt_print (const char *fmt, ...);
extern void Fmt_fprint(FILE *stream,
    const char *fmt, ...);
extern int Fmt_sfmt   (char *buf, int size,
    const char *fmt, ...);
extern int Fmt_vsfmt(char *buf, int size,
    const char *fmt, va_list_box *box);
extern char *Fmt_string (const char *fmt, ...);
extern char *Fmt_vstring(const char *fmt, va_list_box *box);
extern T Fmt_register(int code, T cvt);
extern void Fmt_putd(const char *str, int len,
    int put(int c, void *cl), void *cl,
    unsigned char flags[256], int width, int precision);
extern void Fmt_puts(const char *str, int len,
    int put(int c, void *cl), void *cl,
    unsigned char flags[256], int width, int precision);
#undef T
#endif

list.h

/* $Id$ */
#ifndef LIST_INCLUDED
#define LIST_INCLUDED
#define T List_T
typedef struct T *T;
struct T {
    T rest;
    void *first;
};
extern T      List_append (T list, T tail);
extern T      List_copy   (T list);
extern T      List_list   (void *x, ...);
extern T      List_pop    (T list, void **x);
extern T      List_push   (T list, void *x);
extern T      List_reverse(T list);
extern int    List_length (T list);
extern void   List_free   (T *list);
extern void   List_map    (T list,
    void apply(void **x, void *cl), void *cl);
extern void **List_toArray(T list, void *end);
#undef T
#endif

mem.h

/* $Id$ */
#ifndef MEM_INCLUDED
#define MEM_INCLUDED
#include "except.h"
extern const Except_T Mem_Failed;
extern void *Mem_alloc (long nbytes,
    const char *file, int line);
extern void *Mem_calloc(long count, long nbytes,
    const char *file, int line);
extern void Mem_free(void *ptr,
    const char *file, int line);
extern void *Mem_resize(void *ptr, long nbytes,
    const char *file, int line);
#define ALLOC(nbytes) \
    Mem_alloc((nbytes), __FILE__, __LINE__)
#define CALLOC(count, nbytes) \
    Mem_calloc((count), (nbytes), __FILE__, __LINE__)
#define  NEW(p) ((p) = ALLOC((long)sizeof *(p)))
#define NEW0(p) ((p) = CALLOC(1, (long)sizeof *(p)))
#define FREE(ptr) ((void)(Mem_free((ptr), \
    __FILE__, __LINE__), (ptr) = 0))
#define RESIZE(ptr, nbytes)     ((ptr) = Mem_resize((ptr), \
    (nbytes), __FILE__, __LINE__))
#endif

mp.h

/* $Id$ */
#ifndef MP_INCLUDED
#define MP_INCLUDED
#include 
#include 
#include "except.h"
#include "fmt.h"
#define T MP_T
typedef unsigned char *T;
extern const Except_T MP_Overflow;
extern const Except_T MP_Dividebyzero;
extern int MP_set(int n);
extern T MP_new(unsigned long u);
extern T MP_fromint (T z, long v);
extern T MP_fromintu(T z, unsigned long u);
extern unsigned long MP_tointu(T x);
extern          long MP_toint (T x);
extern T MP_cvt (int m, T z, T x);
extern T MP_cvtu(int m, T z, T x);
extern T MP_add (T z, T x, T y);
extern T MP_sub (T z, T x, T y);
extern T MP_mul (T z, T x, T y);
extern T MP_div (T z, T x, T y);
extern T MP_mod (T z, T x, T y);
extern T MP_neg (T z, T x);
extern T MP_addu(T z, T x, T y);
extern T MP_subu(T z, T x, T y);
extern T MP_mulu(T z, T x, T y);
extern T MP_divu(T z, T x, T y);
extern T MP_modu(T z, T x, T y);
extern T MP_mul2u(T z, T x, T y);
extern T MP_mul2 (T z, T x, T y);
extern T MP_addi (T z, T x, long y);
extern T MP_subi (T z, T x, long y);
extern T MP_muli (T z, T x, long y);
extern T MP_divi (T z, T x, long y);
extern T MP_addui(T z, T x, unsigned long y);
extern T MP_subui(T z, T x, unsigned long y);
extern T MP_mului(T z, T x, unsigned long y);
extern T MP_divui(T z, T x, unsigned long y);
extern          long MP_modi (T x,          long y);
extern unsigned long MP_modui(T x, unsigned long y);
extern int MP_cmp  (T x, T y);
extern int MP_cmpi (T x, long y);
extern int MP_cmpu (T x, T y);
extern int MP_cmpui(T x, unsigned long y);
extern T MP_and (T z, T x, T y);
extern T MP_or  (T z, T x, T y);
extern T MP_xor (T z, T x, T y);
extern T MP_not (T z, T x);
extern T MP_andi(T z, T x, unsigned long y);
extern T MP_ori (T z, T x, unsigned long y);
extern T MP_xori(T z, T x, unsigned long y);
extern T MP_lshift(T z, T x, int s);
extern T MP_rshift(T z, T x, int s);
extern T MP_ashift(T z, T x, int s);
extern T     MP_fromstr(T z, const char *str,
    int base, char **end);
extern char *MP_tostr  (char *str, int size,
    int base, T x);
extern void  MP_fmt    (int code, va_list_box *box,
    int put(int c, void *cl), void *cl,
    unsigned char flags[], int width, int precision);
extern void  MP_fmtu   (int code, va_list_box *box,
    int put(int c, void *cl), void *cl,
    unsigned char flags[], int width, int precision);
#undef T
#endif

ring.h

/* $Id$ */
#ifndef RING_INCLUDED
#define RING_INCLUDED
#define T Ring_T
typedef struct T *T;
extern T Ring_new (void);
extern T Ring_ring(void *x, ...);
extern void Ring_free  (T *ring);
extern int  Ring_length(T  ring);
extern void *Ring_get(T ring, int i);
extern void *Ring_put(T ring, int i, void *x);
extern void *Ring_add(T ring, int pos, void *x);
extern void *Ring_addlo(T ring, void *x);
extern void *Ring_addhi(T ring, void *x);
extern void *Ring_remove(T ring, int i);
extern void *Ring_remlo(T ring);
extern void *Ring_remhi(T ring);
extern void Ring_rotate(T ring, int n);
#undef T
#endif

sem.h

/* $Id$ */
#ifndef SEM_INCLUDED
#define SEM_INCLUDED
#define T Sem_T
typedef struct T {
    int count;
    void *queue;
} T;
#define LOCK(mutex) do { Sem_T *_yymutex = &(mutex); \
    Sem_wait(_yymutex);
#define END_LOCK Sem_signal(_yymutex); } while (0)
extern void Sem_init  (T *s, int count);
extern T   *Sem_new   (int count);
extern void Sem_wait  (T *s);
extern void Sem_signal(T *s);
#undef T
#endif

seq.h

/* $Id$ */
#ifndef SEQ_INCLUDED
#define SEQ_INCLUDED
#define T Seq_T
typedef struct T *T;
extern T Seq_new(int hint);
extern T Seq_seq(void *x, ...);
extern void Seq_free(T *seq);
extern int Seq_length(T seq);
extern void *Seq_get(T seq, int i);
extern void *Seq_put(T seq, int i, void *x);
extern void *Seq_addlo(T seq, void *x);
extern void *Seq_addhi(T seq, void *x);
extern void *Seq_remlo(T seq);
extern void *Seq_remhi(T seq);
#undef T
#endif

set.h

/* $Id$ */
#ifndef SET_INCLUDED
#define SET_INCLUDED
#define T Set_T
typedef struct T *T;
extern T    Set_new (int hint,
    int cmp(const void *x, const void *y),
    unsigned hash(const void *x));
extern void Set_free(T *set);
extern int   Set_length(T set);
extern int   Set_member(T set, const void *member);
extern void  Set_put   (T set, const void *member);
extern void *Set_remove(T set, const void *member);
extern void   Set_map    (T set,
    void apply(const void *member, void *cl), void *cl);
extern void **Set_toArray(T set, void *end);
extern T Set_union(T s, T t);
extern T Set_inter(T s, T t);
extern T Set_minus(T s, T t);
extern T Set_diff (T s, T t);
#undef T
#endif

stack.h

/* $Id$ */
#ifndef STACK_INCLUDED
#define STACK_INCLUDED
#define T Stack_T
typedef struct T *T;
extern T     Stack_new  (void);
extern int   Stack_empty(T stk);
extern void  Stack_push (T stk, void *x);
extern void *Stack_pop  (T stk);
extern void  Stack_free (T *stk);
#undef T
#endif

str.h

/* $Id$ */
#ifndef STR_INCLUDED
#define STR_INCLUDED
#include 
#include "fmt.h"
extern char *Str_sub(const char *s, int i, int j);
extern char *Str_dup(const char *s, int i, int j, int n);
extern char *Str_cat(const char *s1, int i1, int j1,
    const char *s2, int i2, int j2);
extern char *Str_catv   (const char *s, ...);
extern char *Str_reverse(const char *s, int i, int j);
extern char *Str_map    (const char *s, int i, int j,
    const char *from, const char *to);
extern int Str_pos(const char *s, int i);
extern int Str_len(const char *s, int i, int j);
extern int Str_cmp(const char *s1, int i1, int j1,
    const char *s2, int i2, int j2);
extern int Str_chr  (const char *s, int i, int j, int c);
extern int Str_rchr (const char *s, int i, int j, int c);
extern int Str_upto (const char *s, int i, int j,
    const char *set);
extern int Str_rupto(const char *s, int i, int j,
    const char *set);
extern int Str_find (const char *s, int i, int j,
    const char *str);
extern int Str_rfind(const char *s, int i, int j,
    const char *str);
extern int Str_any   (const char *s, int i,
    const char *set);
extern int Str_many  (const char *s, int i, int j,
    const char *set);
extern int Str_rmany (const char *s, int i, int j,
    const char *set);
extern int Str_match (const char *s, int i, int j,
    const char *str);
extern int Str_rmatch(const char *s, int i, int j,
    const char *str);
extern void Str_fmt(int code, va_list_box *box,
    int put(int c, void *cl), void *cl,
    unsigned char flags[], int width, int precision);
#undef T
#endif

table.h

/* $Id$ */
#ifndef TABLE_INCLUDED
#define TABLE_INCLUDED
#define T Table_T
typedef struct T *T;
extern T    Table_new (int hint,
    int cmp(const void *x, const void *y),
    unsigned hash(const void *key));
extern void Table_free(T *table);
extern int   Table_length(T table);
extern void *Table_put   (T table, const void *key,
    void *value);
extern void *Table_get   (T table, const void *key);
extern void *Table_remove(T table, const void *key);
extern void   Table_map    (T table,
    void apply(const void *key, void **value, void *cl),
    void *cl);
extern void **Table_toArray(T table, void *end);
#undef T
#endif

text.h

/* $Id$ */
#ifndef TEXT_INCLUDED
#define TEXT_INCLUDED
#include 
#include "fmt.h"
#define T Text_T
typedef struct T {
    int len;
    const char *str;
} T;
typedef struct Text_save_T *Text_save_T;
extern const T Text_cset;
extern const T Text_ascii;
extern const T Text_ucase;
extern const T Text_lcase;
extern const T Text_digits;
extern const T Text_null;
extern T     Text_put(const char *str);
extern char *Text_get(char *str, int size, T s);
extern T     Text_box(const char *str, int len);
extern T Text_sub(T s, int i, int j);
extern int Text_pos(T s, int i);
extern T Text_cat    (T s1, T s2);
extern T Text_dup    (T s, int n);
extern T Text_reverse(T s);
extern T Text_map(T s, const T *from, const T *to);
extern int Text_cmp(T s1, T s2);
extern int Text_chr  (T s, int i, int j, int c);
extern int Text_rchr (T s, int i, int j, int c);
extern int Text_upto (T s, int i, int j, T set);
extern int Text_rupto(T s, int i, int j, T set);
extern int Text_any  (T s, int i, T set);
extern int Text_many (T s, int i, int j, T set);
extern int Text_rmany(T s, int i, int j, T set);
extern int Text_find  (T s, int i, int j, T str);
extern int Text_rfind (T s, int i, int j, T str);
extern int Text_match (T s, int i, int j, T str);
extern int Text_rmatch(T s, int i, int j, T str);
extern void Text_fmt(int code, va_list_box *box,
    int put(int c, void *cl), void *cl,
    unsigned char flags[], int width, int precision);
extern Text_save_T Text_save(void);
extern void        Text_restore(Text_save_T *save);
#undef T
#endif

thread.h

/* $Id$ */
#ifndef THREAD_INCLUDED
#define THREAD_INCLUDED
#include "except.h"
#define T Thread_T
typedef struct T *T;
extern const Except_T Thread_Failed;
extern const Except_T Thread_Alerted;
extern int  Thread_init (int preempt, ...);
extern T    Thread_new  (int apply(void *),
                void *args, int nbytes, ...);
extern void Thread_exit (int code);
extern void Thread_alert(T t);
extern T    Thread_self (void);
extern int  Thread_join (T t);
extern void Thread_pause(void);
#undef T
#endif

xp.h

/* $Id$ */
#ifndef XP_INCLUDED
#define XP_INCLUDED
#define T XP_T
typedef unsigned char *T;
extern int XP_add(int n, T z, T x, T y, int carry);
extern int XP_sub(int n, T z, T x, T y, int borrow);
extern int XP_mul(T z, int n, T x, int m, T y);
extern int XP_div(int n, T q, T x, int m, T y, T r,T tmp);
extern int XP_sum     (int n, T z, T x, int y);
extern int XP_diff    (int n, T z, T x, int y);
extern int XP_product (int n, T z, T x, int y);
extern int XP_quotient(int n, T z, T x, int y);
extern int XP_neg(int n, T z, T x, int carry);
extern int XP_cmp(int n, T x, T y);
extern void XP_lshift(int n, T z, int m, T x,
    int s, int fill);
extern void XP_rshift(int n, T z, int m, T x,
    int s, int fill);
extern int           XP_length (int n, T x);
extern unsigned long XP_fromint(int n, T z,
    unsigned long u);
extern unsigned long XP_toint  (int n, T x);
extern int   XP_fromstr(int n, T z, const char *str,
    int base, char **end);
extern char *XP_tostr  (char *str, int size, int base,
    int n, T x);
#undef T
#endif

你可能感兴趣的:(C语言接口与实现学习)