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