Annotation of win32/development/msvcee/cord/cordbscs.cpp, revision 1.1
1.1 ! paf 1: /*
! 2: * Copyright (c) 1993-1994 by Xerox Corporation. All rights reserved.
! 3: *
! 4: * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
! 5: * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
! 6: *
! 7: * Permission is hereby granted to use or copy this program
! 8: * for any purpose, provided the above notices are retained on all copies.
! 9: * Permission to modify the code and to distribute modified code is granted,
! 10: * provided the above notices are retained, and a notice that the code was
! 11: * modified is included with the above copyright notice.
! 12: *
! 13: * Author: Hans-J. Boehm (boehm@parc.xerox.com)
! 14: */
! 15: /* Boehm, October 3, 1994 5:19 pm PDT */
! 16: # include "cord.h"
! 17: # include <stdlib.h>
! 18: # include <stdio.h>
! 19: # include <string.h>
! 20:
! 21: /* An implementation of the cord primitives. These are the only */
! 22: /* Functions that understand the representation. We perform only */
! 23: /* minimal checks on arguments to these functions. Out of bounds */
! 24: /* arguments to the iteration functions may result in client functions */
! 25: /* invoked on garbage data. In most cases, client functions should be */
! 26: /* programmed defensively enough that this does not result in memory */
! 27: /* smashes. */
! 28:
! 29: #define GC_NEW(s) 0
! 30: #define GC_MALLOC_ATOMIC(s) 0
! 31:
! 32: typedef void (* oom_fn)(void);
! 33:
! 34: oom_fn CORD_oom_fn = (oom_fn) 0;
! 35:
! 36: # define OUT_OF_MEMORY { if (CORD_oom_fn != (oom_fn) 0) (*CORD_oom_fn)(); \
! 37: ABORT("Out of memory\n"); }
! 38: # define ABORT(msg) { fprintf(stderr, "%s\n", msg); abort(); }
! 39:
! 40: typedef unsigned long word;
! 41:
! 42: typedef union {
! 43: struct Concatenation {
! 44: char null;
! 45: char header;
! 46: char depth; /* concatenation nesting depth. */
! 47: unsigned char left_len;
! 48: /* Length of left child if it is sufficiently */
! 49: /* short; 0 otherwise. */
! 50: # define MAX_LEFT_LEN 255
! 51: word len;
! 52: CORD left; /* length(left) > 0 */
! 53: CORD right; /* length(right) > 0 */
! 54: } concatenation;
! 55: struct Function {
! 56: char null;
! 57: char header;
! 58: char depth; /* always 0 */
! 59: char left_len; /* always 0 */
! 60: word len;
! 61: CORD_fn fn;
! 62: void * client_data;
! 63: } function;
! 64: struct Generic {
! 65: char null;
! 66: char header;
! 67: char depth;
! 68: char left_len;
! 69: word len;
! 70: } generic;
! 71: char string[1];
! 72: } CordRep;
! 73:
! 74: # define CONCAT_HDR 1
! 75:
! 76: # define FN_HDR 4
! 77: # define SUBSTR_HDR 6
! 78: /* Substring nodes are a special case of function nodes. */
! 79: /* The client_data field is known to point to a substr_args */
! 80: /* structure, and the function is either CORD_apply_access_fn */
! 81: /* or CORD_index_access_fn. */
! 82:
! 83: /* The following may be applied only to function and concatenation nodes: */
! 84: #define IS_CONCATENATION(s) (((CordRep *)s)->generic.header == CONCAT_HDR)
! 85:
! 86: #define IS_FUNCTION(s) ((((CordRep *)s)->generic.header & FN_HDR) != 0)
! 87:
! 88: #define IS_SUBSTR(s) (((CordRep *)s)->generic.header == SUBSTR_HDR)
! 89:
! 90: #define LEN(s) (((CordRep *)s) -> generic.len)
! 91: #define DEPTH(s) (((CordRep *)s) -> generic.depth)
! 92: #define GEN_LEN(s) (CORD_IS_STRING(s) ? strlen(s) : LEN(s))
! 93:
! 94: #define LEFT_LEN(c) ((c) -> left_len != 0? \
! 95: (c) -> left_len \
! 96: : (CORD_IS_STRING(D((c) -> left)) ? \
! 97: (c) -> len - GEN_LEN(D((c) -> right)) \
! 98: : LEN(D((c) -> left))))
! 99:
! 100: #define SHORT_LIMIT (sizeof(CordRep) - 1)
! 101: /* Cords shorter than this are C strings */
! 102:
! 103: /* paf: using knowledge of interal structure to speedup */
! 104: char CORD_nul_func(size_t i, void * client_data);
! 105:
! 106: size_t CORD_len(CORD x)
! 107: {
! 108: if (x == 0) {
! 109: return(0);
! 110: } else {
! 111: return(GEN_LEN(x));
! 112: }
! 113: }
! 114:
! 115: struct substr_args {
! 116: CordRep * sa_cord;
! 117: size_t sa_index;
! 118: };
! 119:
! 120: char CORD_index_access_fn(size_t i, void * client_data)
! 121: {
! 122: register struct substr_args *descr = (struct substr_args *)client_data;
! 123:
! 124: return(((char *)(descr->sa_cord))[i + descr->sa_index]);
! 125: }
! 126:
! 127: char CORD_apply_access_fn(size_t i, void * client_data)
! 128: {
! 129: register struct substr_args *descr = (struct substr_args *)client_data;
! 130: register CordRep::Function * fn_cord = &(descr->sa_cord->function);
! 131:
! 132: return((*(fn_cord->fn))(i + descr->sa_index, fn_cord->client_data));
! 133: }
! 134:
! 135:
! 136: # define SUBSTR_LIMIT (10 * SHORT_LIMIT)
! 137: /* Substrings of function nodes and flat strings shorter than */
! 138: /* this are flat strings. Othewise we use a functional */
! 139: /* representation, which is significantly slower to access. */
! 140:
! 141:
! 142: /* See cord.h for definition. We assume i is in range. */
! 143: int CORD_iter5(DEBUGHELPER *pHelper, CORD x, size_t i, CORD_iter_fn f1,
! 144: CORD_batched_iter_fn f2, void * client_data)
! 145: {
! 146: int result;
! 147: if (x == 0) return(0);
! 148: if (CORD_IS_STRING(x)) {
! 149: register const char* p = x+i;
! 150:
! 151: if (*p == '\0') ABORT("2nd arg to CORD_iter5 too big");
! 152: if (f2 != CORD_NO_FN) {
! 153: return((*f2)(p, client_data));
! 154: } else {
! 155: while (*p) {
! 156: if (result=(*f1)(*p, client_data))
! 157: return result;
! 158: p++;
! 159: }
! 160: return(0);
! 161: }
! 162: } else if (IS_CONCATENATION(x)) {
! 163: register CordRep::Concatenation * conc = &(((CordRep *)x) -> concatenation);
! 164: if (i > 0) {
! 165: register size_t left_len = LEFT_LEN(conc);
! 166:
! 167: if (i >= left_len) {
! 168: return(CORD_iter5(pHelper, D(conc -> right), i - left_len, f1, f2,
! 169: client_data));
! 170: }
! 171: }
! 172: result=CORD_iter5(pHelper, D(conc -> left), i, f1, f2, client_data);
! 173: if (result) return result;
! 174: return(CORD_iter5(pHelper, D(conc -> right), 0, f1, f2, client_data));
! 175: } else /* function */ {
! 176: register CordRep::Function * f = &(((CordRep *)x) -> function);
! 177: register size_t j;
! 178: register size_t lim = f -> len;
! 179:
! 180: for (j = i; j < lim; j++) {
! 181: if (result=(*f1)((*(f -> fn))(j, f -> client_data), client_data))
! 182: return result;
! 183: }
! 184: return(0);
! 185: }
! 186: }
E-mail: