/* Common.h - functions that are commonly used. Includes * routines for managing singly linked lists, some basic * string manipulation stuff, and other stuff of the * short but useful nature. */ #ifndef COMMON_H /* Wrapper to avoid including this twice. */ #define COMMON_H /* Some stuff to support large files in Linux. */ #define _LARGEFILE_SOURCE 1 #ifndef _FILE_OFFSET_BITS #define _FILE_OFFSET_BITS 64 #endif #include #include #include #include #include #include #include #include #include #include #include #include #include /* Let's pretend C has a boolean type. */ #define TRUE 1 #define FALSE 0 #define boolean int #define bool char /* Some other type synonyms */ #define UBYTE unsigned char /* Wants to be unsigned 8 bits. */ #define BYTE signed char /* Wants to be signed 8 bits. */ #define UWORD unsigned short /* Wants to be unsigned 16 bits. */ #define WORD short /* Wants to be signed 16 bits. */ #define bits32 unsigned /* Wants to be unsigned 32 bits. */ #define bits16 unsigned short /* Wants to be unsigned 16 bits. */ #define BIGNUM 0x3fffffff /* A really big number */ /* Default size of directory path string buffers */ #define PATH_LEN 512 /* How big is this array? */ #define ArraySize(a) (sizeof(a)/sizeof((a)[0])) #define uglyf printf /* debugging printf */ #define uglyAbort errAbort /* debugging error abort. */ #define uglyOut stdout /* debugging fprintf target. */ void *needMem(size_t size); /* Need mem calls abort if the memory allocation fails. The memory * is initialized to zero. */ void *needLargeMem(size_t size); /* This calls abort if the memory allocation fails. The memory is * not initialized to zero. */ void *needLargeZeroedMem(long size); /* Request a large block of memory and zero it. */ void *needHugeMem(size_t size); /* No checking on size. Memory not initted to 0. */ void *needHugeZeroedMem(long size); /* Request a large block of memory and zero it. */ void *needMoreMem(void *old, size_t copySize, size_t newSize); /* Allocate a new buffer, copy old buffer to it, free old buffer. */ void *cloneMem(void *pt, size_t size); /* Allocate a new buffer of given size, and copy pt to it. */ #define CloneVar(pt) cloneMem(pt, sizeof((pt)[0])) /* Allocate copy of a structure. */ void *wantMem(size_t size); /* Want mem just calls malloc - no zeroing of memory, no * aborting if request fails. */ void freeMem(void *pt); /* Free memory will check for null before freeing. */ void freez(void *ppt); /* Pass address of pointer. Will free pointer and set it * to NULL. Typical use: * s = needMem(1024); * ... * freez(&s); */ #define AllocVar(pt) (pt = needMem(sizeof(*pt))) /* Shortcut to allocating a single variable on the heap and * assigning pointer to it. */ #define AllocArray(pt, size) (pt = needLargeZeroedMem(sizeof(*pt) * (size))) #define AllocA(type) needMem(sizeof(type)) /* Shortcut to allocating a variable on heap of a specific type. */ #define AllocN(type,count) ((type*)needLargeZeroedMem(sizeof(type) * (count))) /* Shortcut to allocating an array on the heap of a specific type. */ #define ExpandArray(array, oldCount, newCount) \ (array = needMoreMem((array), (oldCount)*sizeof((array)[0]), (newCount)*sizeof((array)[0]))) /* Expand size of dynamically allocated array. */ #define CopyArray(source, dest,count) memcpy(dest,source,(count)*sizeof(dest[0])) /* Copy count elements of array from source to dest. */ #define CloneArray(a, count) cloneMem(a, (count)*sizeof(a[0])) /* Make new dynamic array initialized with count elements of a */ void errAbort(char *format, ...); /* Abort function, with optional (printf formatted) error message. */ #define internalErr() errAbort("Internal error %s %d", __FILE__, __LINE__) /* Generic internal error message */ void warn(char *format, ...); /* Issue a warning message. */ void zeroBytes(void *vpt, int count); /* fill a specified area of memory with zeroes */ #define ZeroVar(v) zeroBytes(v, sizeof(*v)) void reverseBytes(char *bytes, long length); /* Reverse the order of the bytes. */ void reverseInts(int *a, int length); /* Reverse the order of the integer array. */ void reverseUnsigned(unsigned *a, int length); /* Reverse the order of the unsigned array. */ void swapBytes(char *a, char *b, int length); /* Swap buffers a and b. */ /* Some things to manage simple lists - structures that begin * with a pointer to the next element in the list. */ struct slList { struct slList *next; }; int slCount(void *list); /* Return # of elements in list. */ void *slElementFromIx(void *list, int ix); /* Return the ix'th element in list. Returns NULL * if no such element. */ int slIxFromElement(void *list, void *el); /* Return index of el in list. Returns -1 if not on list. */ void slSafeAddHead(void *listPt, void *node); /* Add new node to start of list. * Usage: * slSafeAddHead(&list, node); * where list and nodes are both pointers to structure * that begin with a next pointer. */ /* The macro below is faster. For some reason under * GNU C the braces below are ignored. This leads * to problems if slAddHead is a single statement * after an if/for/while. Either use slSafeAddHead * or enclose the slAddHead line in braces in these * situations. */ #define slAddHead(listPt, node) \ { \ (node)->next = *(listPt); \ *(listPt) = (node); \ } void slAddTail(void *listPt, void *node); /* Add new node to tail of list. * Usage: * slAddTail(&list, node); * where list and nodes are both pointers to structure * that begin with a next pointer. This is sometimes * convenient but relatively slow. For longer lists * it's better to slAddHead, and slReverse when done. */ void *slPopHead(void *listPt); /* Return head of list and remove it from list. (Fast) */ void *slPopTail(void *listPt); /* Return tail of list and remove it from list. (Not so fast) */ void *slCat(void *a, void *b); /* Return concatenation of lists a and b. * Example Usage: * struct slName *a = getNames("a"); * struct slName *b = getNames("b"); * struct slName *ab = slCat(a,b) */ void *slLastEl(void *list); /* Returns last element in list or NULL if none. */ void slReverse(void *listPt); /* Reverse order of a list. * Usage: * slReverse(&list); */ void slSort(void *pList, int (*compare )(const void *elem1, const void *elem2)); /* Sort a singly linked list with Qsort and a temporary array. * The arguments to the compare function in real, non-void, life * are pointers to pointers. */ void slUniqify(void *pList, int (*compare )(const void *elem1, const void *elem2), void (*free)()); /* Return sorted list with duplicates removed. * Compare should be same type of function as slSort's compare (taking * pointers to pointers to elements. Free should take a simple * pointer to dispose of duplicate element, and can be NULL. */ void slRemoveEl(void *pList, void *el); /* Remove element from singly linked list. Usage: * slRemove(&list, el); */ void slFreeList(void *listPt); /* Free all elements in list and set list pointer to null. * Usage: * slFreeList(&list); */ struct slName /* List of names. The name array is allocated to accommodate full name */ { struct slName *next; /* Next in list. */ char name[1]; /* Allocated at run time to length of string. */ }; struct slName *newSlName(char *name); /* Return a new name. */ int slNameCmp(const void *va, const void *vb); /* Compare two slNames. */ void slNameSort(struct slName **pList); /* Sort slName list. */ boolean slNameInList(struct slName *list, char *string); /* Return true if string is in name list */ void *slNameFind(void *list, char *string); /* Return first element of slName list (or any other list starting * with next/name fields) that matches string. */ char *slNameStore(struct slName **pList, char *string); /* Put string into list if it's not there already. * Return the version of string stored in list. */ struct slRef /* Singly linked list of generic references. */ { struct slRef *next; /* Next in list. */ void *val; /* A reference to something. */ }; struct slRef *refOnList(struct slRef *refList, void *val); /* Return ref if val is already on list, otherwise NULL. */ void refAdd(struct slRef **pRefList, void *val); /* Add reference to list. */ void refAddUnique(struct slRef **pRefList, void *val); /* Add reference to list if not already on list. */ void gentleFree(void *pt); /* check pointer for NULL before freeing. * (Actually plain old freeMem does that these days.) */ /******* Some stuff for processing strings. *******/ char *cloneStringZ(char *s, int size); /* Make a zero terminated copy of string in memory */ char *cloneString(char *s); /* Make copy of string in dynamic memory */ int differentWord(char *s1, char *s2); /* strcmp ignoring case - returns zero if strings are * the same (ignoring case) otherwise returns difference * between first non-matching characters. */ #define sameWord(a,b) (!differentWord(a,b)) /* Return TRUE if two strings are same ignoring case */ #define differentString(a,b) (strcmp(a,b)) /* Returns FALSE if two strings same. */ #define sameString(a,b) (strcmp(a,b)==0) /* Returns TRUE if two strings same. */ boolean startsWith(char *start,char *string); /* Returns TRUE if string begins with start. */ #define stringIn(needle, haystack) strstr(haystack, needle) /* Returns position of needle in haystack or NULL if it's not there. */ /* char *stringIn(char *needle, char *haystack); */ boolean endsWith(char *string, char *end); /* Returns TRUE if string ends with end. */ char lastChar(char *s); /* Return last character in string. */ boolean wildMatch(char *wildCard, char *string); /* does a case insensitive wild card match with a string. * * matches any string or no character. * ? matches any single character. * anything else etc must match the character exactly. */ char *memMatch(char *needle, int nLen, char *haystack, int hLen); /* Returns first place where needle (of nLen chars) matches * haystack (of hLen chars) */ void toUpperN(char *s, int n); /* Convert a section of memory to upper case. */ void toLowerN(char *s, int n); /* Convert a section of memory to lower case. */ void touppers(char *s); /* Convert entire string to upper case. */ void tolowers(char *s); /* Convert entire string to lower case */ void subChar(char *s, char oldChar, char newChar); /* Substitute newChar for oldChar throughout string s. */ void stripChar(char *s, char c); /* Remove all occurences of c from s. */ int countChars(char *s, char c); /* Return number of characters c in string s. */ int chopString(char *in, char *sep, char *outArray[], int outSize); /* int chopString(in, sep, outArray, outSize); */ /* This chops up the input string (cannabilizing it) * into an array of zero terminated strings in * outArray. It returns the number of strings. * If you pass in NULL for outArray, it will just * return the number of strings that it *would* * chop. */ extern char crLfChopper[]; extern char whiteSpaceChopper[]; /* Some handy predefined separators. */ int chopByWhite(char *in, char *outArray[], int outSize); /* Like chopString, but specialized for white space separators. */ #define chopLine(line, words) chopByWhite(line, words, ArraySize(words)) /* Chop line by white space. */ int chopByChar(char *in, char chopper, char *outArray[], int outSize); /* Chop based on a single character. */ #define chopTabs(string, words) chopByChar(string, '\t', words, ArraySize(words)) /* Chop string by tabs. */ #define chopCommas(string, words) chopByChar(string, ',', words, ArraySize(words)) /* Chop string by commas. */ char *skipLeadingSpaces(char *s); /* Return first non-white space */ char *skipToSpaces(char *s); /* Return first white space. */ void eraseTrailingSpaces(char *s); /* Replace trailing white space with zeroes. */ void eraseWhiteSpace(char *s); /* Remove white space from a string */ char *trimSpaces(char *s); /* Remove leading and trailing white space. */ char *firstWordInLine(char *line); /* Returns first word in line if any (white space separated). * Puts 0 in place of white space after word. */ char *lastWordInLine(char *line); /* Returns last word in line if any (white space separated). * Returns NULL if string is empty. Removes any terminating white space * from line. */ char *nextWord(char **pLine); /* Return next word in *pLine and advance *pLine to next * word. Returns NULL when no more words. */ int stringArrayIx(char *string, char *array[], int arraySize); /* Return index of string in array or -1 if not there. */ int ptArrayIx(void *pt, void *array, int arraySize); /* Return index of pt in array or -1 if not there. */ #define stringIx(string, array) stringArrayIx( (string), (array), ArraySize(array)) /* Some stuff that is left out of GNU .h files!? */ #ifndef SEEK_SET #define SEEK_SET 0 #endif #ifndef SEEK_CUR #define SEEK_CUR 1 #endif #ifndef SEEK_END #define SEEK_END 2 #endif void splitPath(char *path, char dir[256], char name[128], char extension[64]); /* Split a full path into components. The dir component will include the * trailing / if any. The extension component will include the starting * . if any. Pass in NULL for dir, name, or extension if you don't care about * that part. */ void chopSuffix(char *s); /* Remove suffix (last . in string and beyond) if any. */ void chopSuffixAt(char *s, char c); /* Remove end of string from last occurrence of char c. * chopSuffixAt(s, '.') is equivalent to regular chopSuffix. */ FILE *mustOpen(char *fileName, char *mode); /* Open a file - or squawk and die. */ void mustWrite(FILE *file, void *buf, size_t size); /* Write to file or squawk and die. */ #define writeOne(file, var) mustWrite((file), &(var), sizeof(var)) /* Write out one variable to file. */ void mustRead(FILE *file, void *buf, size_t size); /* Read from a file or squawk and die. */ #define mustReadOne(file, var) mustRead((file), &(var), sizeof(var)) /* Read one variable from file or die. */ #define readOne(file, var) (fread(&(var), sizeof(var), 1, (file)) == 1) /* Read one variable from file. Returns FALSE if can't do it. */ void writeString(FILE *f, char *s); /* Write a 255 or less character string to a file. * This will write the length of the string in the first * byte then the string itself. */ char *readString(FILE *f); /* Read a string (written with writeString) into * memory. freeMem the result when done. Returns * NULL at EOF. */ char *mustReadString(FILE *f); /* Read a string. Squawk and die at EOF or if any problem. */ boolean fastReadString(FILE *f, char buf[256]); /* Read a string into buffer, which must be long enough * to hold it. String is in 'writeString' format. * Returns FALSE at EOF. */ void carefulClose(FILE **pFile); /* Close file if open and null out handle to it. */ char *firstWordInFile(char *fileName, char *wordBuf, int wordBufSize); /* Read the first word in file into wordBuf. */ int roundingScale(int a, int p, int q); /* returns rounded a*p/q */ int intAbs(int a); /* Return integer absolute value */ #define logBase2(x)(log(x)/log(2)) /* return log base two of number */ #define round(a) ((int)((a)+0.5)) /* Round floating point val to nearest integer. */ #ifndef min #define min(a,b) ( (a) < (b) ? (a) : (b) ) /* Return min of a and b. */ #endif #ifndef max #define max(a,b) ( (a) > (b) ? (a) : (b) ) /* Return max of a and b. */ #endif int rangeIntersection(int start1, int end1, int start2, int end2); /* Return amount of bases two ranges intersect over, 0 or negative if no * intersection. */ bits32 byteSwap32(bits32 a); /* Swap from intel to sparc order of a 32 bit quantity. */ void removeReturns(char* dest, char* src); /* Removes the '\r' character from a string. * the source and destination strings can be the same, * if there are no threads */ int intExp(char *text); /* Convert text to integer expression and evaluate. * Throws if it finds a non-number. */ char* readLine(FILE* fh); /* Read a line of any size into dynamic memory, return null on EOF */ long fileSize(char *fileName); /* The size of a file. */ boolean fileExists(char *fileName); /* Does a file exist? */ char *strstrNoCase(char *haystack, char *needle); /* A case-insensitive strstr */ #endif /* COMMON_H */