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 This program 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 3 of the License, or
11 (at your option) any later version.
12
13 This program 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. If not, see <http://www.gnu.org/licenses/>. */
20
21/* Specification. */
22#include "positions.h"
23
24#include <stdio.h>
25#include <stdlib.h> /* declares exit() */
26#include <string.h>
27
28/* ---------------------------- Class Positions ---------------------------- */
29
30/* Set operations. Assumes the array is in reverse order. */
31
32bool
33Positions::contains (int pos) const
34{
35 unsigned int count = _size;
36 const int *p = _positions + _size - 1;
37
38 for (; count > 0; p--, count--)
39 {
40 if (*p == pos)
41 return true;
42 if (*p > pos)
43 break;
44 }
45 return false;
46}
47
48void
49Positions::add (int pos)
50{
51 set_useall (false);
52
53 unsigned int count = _size;
54
55 if (count == MAX_SIZE)
56 {
57 fprintf (stderr, "Positions::add internal error: overflow\n");
58 exit (1);
59 }
60
61 int *p = _positions + _size - 1;
62
63 for (; count > 0; p--, count--)
64 {
65 if (*p == pos)
66 {
67 fprintf (stderr, "Positions::add internal error: duplicate\n");
68 exit (1);
69 }
70 if (*p > pos)
71 break;
72 p[1] = p[0];
73 }
74 p[1] = pos;
75 _size++;
76}
77
78void
79Positions::remove (int pos)
80{
81 set_useall (false);
82
83 unsigned int count = _size;
84 if (count > 0)
85 {
86 int *p = _positions + _size - 1;
87
88 if (*p == pos)
89 {
90 _size--;
91 return;
92 }
93 if (*p < pos)
94 {
95 int prev = *p;
96
97 for (;;)
98 {
99 p--;
100 count--;
101 if (count == 0)
102 break;
103 if (*p == pos)
104 {
105 *p = prev;
106 _size--;
107 return;
108 }
109 if (*p > pos)
110 break;
111 int curr = *p;
112 *p = prev;
113 prev = curr;
114 }
115 }
116 }
117 fprintf (stderr, "Positions::remove internal error: not found\n");
118 exit (1);
119}
120
121/* Output in external syntax. */
122void
123Positions::print () const
124{
125 if (_useall)
126 printf ("*");
127 else
128 {
129 bool first = true;
130 bool seen_LASTCHAR = false;
131 unsigned int count = _size;
132 const int *p = _positions + _size - 1;
133
134 for (; count > 0; p--)
135 {
136 count--;
137 if (*p == LASTCHAR)
138 seen_LASTCHAR = true;
139 else
140 {
141 if (!first)
142 printf (",");
143 printf ("%d", *p + 1);
144 if (count > 0 && p[-1] == *p + 1)
145 {
146 printf ("-");
147 do
148 {
149 p--;
150 count--;
151 }
152 while (count > 0 && p[-1] == *p + 1);
153 printf ("%d", *p + 1);
154 }
155 first = false;
156 }
157 }
158 if (seen_LASTCHAR)
159 {
160 if (!first)
161 printf (",");
162 printf ("$");
163 }
164 }
165}
166
167/* ------------------------------------------------------------------------- */
168
169#ifndef __OPTIMIZE__
170
171#define INLINE /* not inline */
172#include "positions.icc"
173#undef INLINE
174
175#endif /* not defined __OPTIMIZE__ */
176