1/* A set of byte positions. 2 Copyright (C) 1989-1998, 2000, 2002 Free Software Foundation, Inc. 3 Written by Douglas C. Schmidt <schmidt@ics.uci.edu> 4 and Bruno Haible <bruno@clisp.org>. 5 6 This file is part of GNU GPERF. 7 8 GNU GPERF is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 2, or (at your option) 11 any later version. 12 13 GNU GPERF is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; see the file COPYING. 20 If not, write to the Free Software Foundation, Inc., 21 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ 22 23/* Specification. */ 24#include "positions.h" 25 26#include <stdio.h> 27#include <stdlib.h> /* declares exit() */ 28#include <string.h> 29 30/* ---------------------------- Class Positions ---------------------------- */ 31 32/* Set operations. Assumes the array is in reverse order. */ 33 34bool 35Positions::contains (int pos) const 36{ 37 unsigned int count = _size; 38 const int *p = _positions + _size - 1; 39 40 for (; count > 0; p--, count--) 41 { 42 if (*p == pos) 43 return true; 44 if (*p > pos) 45 break; 46 } 47 return false; 48} 49 50void 51Positions::add (int pos) 52{ 53 set_useall (false); 54 55 unsigned int count = _size; 56 57 if (count == MAX_SIZE) 58 { 59 fprintf (stderr, "Positions::add internal error: overflow\n"); 60 exit (1); 61 } 62 63 int *p = _positions + _size - 1; 64 65 for (; count > 0; p--, count--) 66 { 67 if (*p == pos) 68 { 69 fprintf (stderr, "Positions::add internal error: duplicate\n"); 70 exit (1); 71 } 72 if (*p > pos) 73 break; 74 p[1] = p[0]; 75 } 76 p[1] = pos; 77 _size++; 78} 79 80void 81Positions::remove (int pos) 82{ 83 set_useall (false); 84 85 unsigned int count = _size; 86 if (count > 0) 87 { 88 int *p = _positions + _size - 1; 89 90 if (*p == pos) 91 { 92 _size--; 93 return; 94 } 95 if (*p < pos) 96 { 97 int prev = *p; 98 99 for (;;) 100 { 101 p--; 102 count--; 103 if (count == 0) 104 break; 105 if (*p == pos) 106 { 107 *p = prev; 108 _size--; 109 return; 110 } 111 if (*p > pos) 112 break; 113 int curr = *p; 114 *p = prev; 115 prev = curr; 116 } 117 } 118 } 119 fprintf (stderr, "Positions::remove internal error: not found\n"); 120 exit (1); 121} 122 123/* Output in external syntax. */ 124void 125Positions::print () const 126{ 127 if (_useall) 128 printf ("*"); 129 else 130 { 131 bool first = true; 132 bool seen_LASTCHAR = false; 133 unsigned int count = _size; 134 const int *p = _positions + _size - 1; 135 136 for (; count > 0; p--) 137 { 138 count--; 139 if (*p == LASTCHAR) 140 seen_LASTCHAR = true; 141 else 142 { 143 if (!first) 144 printf (","); 145 printf ("%d", *p + 1); 146 if (count > 0 && p[-1] == *p + 1) 147 { 148 printf ("-"); 149 do 150 { 151 p--; 152 count--; 153 } 154 while (count > 0 && p[-1] == *p + 1); 155 printf ("%d", *p + 1); 156 } 157 first = false; 158 } 159 } 160 if (seen_LASTCHAR) 161 { 162 if (!first) 163 printf (","); 164 printf ("$"); 165 } 166 } 167} 168 169/* ------------------------------------------------------------------------- */ 170 171#ifndef __OPTIMIZE__ 172 173#define INLINE /* not inline */ 174#include "positions.icc" 175#undef INLINE 176 177#endif /* not defined __OPTIMIZE__ */ 178