| 1 | /* |
| 2 | * Utility functions for handling cvecs |
| 3 | * This file is #included by regcomp.c. |
| 4 | * |
| 5 | * Copyright (c) 1998, 1999 Henry Spencer. All rights reserved. |
| 6 | * |
| 7 | * Development of this software was funded, in part, by Cray Research Inc., |
| 8 | * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics |
| 9 | * Corporation, none of whom are responsible for the results. The author |
| 10 | * thanks all of them. |
| 11 | * |
| 12 | * Redistribution and use in source and binary forms -- with or without |
| 13 | * modification -- are permitted for any purpose, provided that |
| 14 | * redistributions in source form retain this entire copyright notice and |
| 15 | * indicate the origin and nature of any modifications. |
| 16 | * |
| 17 | * I'd appreciate being given credit for this package in the documentation |
| 18 | * of software which uses it, but that is not a requirement. |
| 19 | * |
| 20 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, |
| 21 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY |
| 22 | * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL |
| 23 | * HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| 24 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| 25 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
| 26 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| 27 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
| 28 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
| 29 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 30 | * |
| 31 | * src/backend/regex/regc_cvec.c |
| 32 | * |
| 33 | */ |
| 34 | |
| 35 | /* |
| 36 | * Notes: |
| 37 | * Only (selected) functions in _this_ file should treat the chr arrays |
| 38 | * of a cvec as non-constant. |
| 39 | */ |
| 40 | |
| 41 | /* |
| 42 | * newcvec - allocate a new cvec |
| 43 | */ |
| 44 | static struct cvec * |
| 45 | newcvec(int nchrs, /* to hold this many chrs... */ |
| 46 | int nranges) /* ... and this many ranges */ |
| 47 | { |
| 48 | size_t nc = (size_t) nchrs + (size_t) nranges * 2; |
| 49 | size_t n = sizeof(struct cvec) + nc * sizeof(chr); |
| 50 | struct cvec *cv = (struct cvec *) MALLOC(n); |
| 51 | |
| 52 | if (cv == NULL) |
| 53 | return NULL; |
| 54 | cv->chrspace = nchrs; |
| 55 | cv->chrs = (chr *) (((char *) cv) + sizeof(struct cvec)); |
| 56 | cv->ranges = cv->chrs + nchrs; |
| 57 | cv->rangespace = nranges; |
| 58 | return clearcvec(cv); |
| 59 | } |
| 60 | |
| 61 | /* |
| 62 | * clearcvec - clear a possibly-new cvec |
| 63 | * Returns pointer as convenience. |
| 64 | */ |
| 65 | static struct cvec * |
| 66 | clearcvec(struct cvec *cv) |
| 67 | { |
| 68 | assert(cv != NULL); |
| 69 | cv->nchrs = 0; |
| 70 | cv->nranges = 0; |
| 71 | cv->cclasscode = -1; |
| 72 | return cv; |
| 73 | } |
| 74 | |
| 75 | /* |
| 76 | * addchr - add a chr to a cvec |
| 77 | */ |
| 78 | static void |
| 79 | addchr(struct cvec *cv, /* character vector */ |
| 80 | chr c) /* character to add */ |
| 81 | { |
| 82 | assert(cv->nchrs < cv->chrspace); |
| 83 | cv->chrs[cv->nchrs++] = c; |
| 84 | } |
| 85 | |
| 86 | /* |
| 87 | * addrange - add a range to a cvec |
| 88 | */ |
| 89 | static void |
| 90 | addrange(struct cvec *cv, /* character vector */ |
| 91 | chr from, /* first character of range */ |
| 92 | chr to) /* last character of range */ |
| 93 | { |
| 94 | assert(cv->nranges < cv->rangespace); |
| 95 | cv->ranges[cv->nranges * 2] = from; |
| 96 | cv->ranges[cv->nranges * 2 + 1] = to; |
| 97 | cv->nranges++; |
| 98 | } |
| 99 | |
| 100 | /* |
| 101 | * getcvec - get a transient cvec, initialized to empty |
| 102 | * |
| 103 | * The returned cvec is valid only until the next call of getcvec, which |
| 104 | * typically will recycle the space. Callers should *not* free the cvec |
| 105 | * explicitly; it will be cleaned up when the struct vars is destroyed. |
| 106 | * |
| 107 | * This is typically used while interpreting bracket expressions. In that |
| 108 | * usage the cvec is only needed momentarily until we build arcs from it, |
| 109 | * so transientness is a convenient behavior. |
| 110 | */ |
| 111 | static struct cvec * |
| 112 | getcvec(struct vars *v, /* context */ |
| 113 | int nchrs, /* to hold this many chrs... */ |
| 114 | int nranges) /* ... and this many ranges */ |
| 115 | { |
| 116 | /* recycle existing transient cvec if large enough */ |
| 117 | if (v->cv != NULL && nchrs <= v->cv->chrspace && |
| 118 | nranges <= v->cv->rangespace) |
| 119 | return clearcvec(v->cv); |
| 120 | |
| 121 | /* nope, make a new one */ |
| 122 | if (v->cv != NULL) |
| 123 | freecvec(v->cv); |
| 124 | v->cv = newcvec(nchrs, nranges); |
| 125 | if (v->cv == NULL) |
| 126 | ERR(REG_ESPACE); |
| 127 | |
| 128 | return v->cv; |
| 129 | } |
| 130 | |
| 131 | /* |
| 132 | * freecvec - free a cvec |
| 133 | */ |
| 134 | static void |
| 135 | freecvec(struct cvec *cv) |
| 136 | { |
| 137 | FREE(cv); |
| 138 | } |
| 139 | |