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