1228060Sbapt/* A set of byte positions.
2228060Sbapt   Copyright (C) 1989-1998, 2000, 2002 Free Software Foundation, Inc.
3228060Sbapt   Written by Douglas C. Schmidt <schmidt@ics.uci.edu>
4228060Sbapt   and Bruno Haible <bruno@clisp.org>.
5228060Sbapt
6228060Sbapt   This file is part of GNU GPERF.
7228060Sbapt
8228060Sbapt   GNU GPERF is free software; you can redistribute it and/or modify
9228060Sbapt   it under the terms of the GNU General Public License as published by
10228060Sbapt   the Free Software Foundation; either version 2, or (at your option)
11228060Sbapt   any later version.
12228060Sbapt
13228060Sbapt   GNU GPERF is distributed in the hope that it will be useful,
14228060Sbapt   but WITHOUT ANY WARRANTY; without even the implied warranty of
15228060Sbapt   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16228060Sbapt   GNU General Public License for more details.
17228060Sbapt
18228060Sbapt   You should have received a copy of the GNU General Public License
19228060Sbapt   along with this program; see the file COPYING.
20228060Sbapt   If not, write to the Free Software Foundation, Inc.,
21228060Sbapt   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
22228060Sbapt
23228060Sbapt/* Specification. */
24228060Sbapt#include "positions.h"
25228060Sbapt
26228060Sbapt#include <stdio.h>
27228060Sbapt#include <stdlib.h> /* declares exit() */
28228060Sbapt#include <string.h>
29228060Sbapt
30228060Sbapt/* ---------------------------- Class Positions ---------------------------- */
31228060Sbapt
32228060Sbapt/* Set operations.  Assumes the array is in reverse order.  */
33228060Sbapt
34228060Sbaptbool
35228060SbaptPositions::contains (int pos) const
36228060Sbapt{
37228060Sbapt  unsigned int count = _size;
38228060Sbapt  const int *p = _positions + _size - 1;
39228060Sbapt
40228060Sbapt  for (; count > 0; p--, count--)
41228060Sbapt    {
42228060Sbapt      if (*p == pos)
43228060Sbapt        return true;
44228060Sbapt      if (*p > pos)
45228060Sbapt        break;
46228060Sbapt    }
47228060Sbapt  return false;
48228060Sbapt}
49228060Sbapt
50228060Sbaptvoid
51228060SbaptPositions::add (int pos)
52228060Sbapt{
53228060Sbapt  set_useall (false);
54228060Sbapt
55228060Sbapt  unsigned int count = _size;
56228060Sbapt
57228060Sbapt  if (count == MAX_SIZE)
58228060Sbapt    {
59228060Sbapt      fprintf (stderr, "Positions::add internal error: overflow\n");
60228060Sbapt      exit (1);
61228060Sbapt    }
62228060Sbapt
63228060Sbapt  int *p = _positions + _size - 1;
64228060Sbapt
65228060Sbapt  for (; count > 0; p--, count--)
66228060Sbapt    {
67228060Sbapt      if (*p == pos)
68228060Sbapt        {
69228060Sbapt          fprintf (stderr, "Positions::add internal error: duplicate\n");
70228060Sbapt          exit (1);
71228060Sbapt        }
72228060Sbapt      if (*p > pos)
73228060Sbapt        break;
74228060Sbapt      p[1] = p[0];
75228060Sbapt    }
76228060Sbapt  p[1] = pos;
77228060Sbapt  _size++;
78228060Sbapt}
79228060Sbapt
80228060Sbaptvoid
81228060SbaptPositions::remove (int pos)
82228060Sbapt{
83228060Sbapt  set_useall (false);
84228060Sbapt
85228060Sbapt  unsigned int count = _size;
86228060Sbapt  if (count > 0)
87228060Sbapt    {
88228060Sbapt      int *p = _positions + _size - 1;
89228060Sbapt
90228060Sbapt      if (*p == pos)
91228060Sbapt        {
92228060Sbapt          _size--;
93228060Sbapt          return;
94228060Sbapt        }
95228060Sbapt      if (*p < pos)
96228060Sbapt        {
97228060Sbapt          int prev = *p;
98228060Sbapt
99228060Sbapt          for (;;)
100228060Sbapt            {
101228060Sbapt              p--;
102228060Sbapt              count--;
103228060Sbapt              if (count == 0)
104228060Sbapt                break;
105228060Sbapt              if (*p == pos)
106228060Sbapt                {
107228060Sbapt                  *p = prev;
108228060Sbapt                  _size--;
109228060Sbapt                  return;
110228060Sbapt                }
111228060Sbapt              if (*p > pos)
112228060Sbapt                break;
113228060Sbapt              int curr = *p;
114228060Sbapt              *p = prev;
115228060Sbapt              prev = curr;
116228060Sbapt            }
117228060Sbapt        }
118228060Sbapt    }
119228060Sbapt  fprintf (stderr, "Positions::remove internal error: not found\n");
120228060Sbapt  exit (1);
121228060Sbapt}
122228060Sbapt
123228060Sbapt/* Output in external syntax.  */
124228060Sbaptvoid
125228060SbaptPositions::print () const
126228060Sbapt{
127228060Sbapt  if (_useall)
128228060Sbapt    printf ("*");
129228060Sbapt  else
130228060Sbapt    {
131228060Sbapt      bool first = true;
132228060Sbapt      bool seen_LASTCHAR = false;
133228060Sbapt      unsigned int count = _size;
134228060Sbapt      const int *p = _positions + _size - 1;
135228060Sbapt
136228060Sbapt      for (; count > 0; p--)
137228060Sbapt        {
138228060Sbapt          count--;
139228060Sbapt          if (*p == LASTCHAR)
140228060Sbapt            seen_LASTCHAR = true;
141228060Sbapt          else
142228060Sbapt            {
143228060Sbapt              if (!first)
144228060Sbapt                printf (",");
145228060Sbapt              printf ("%d", *p + 1);
146228060Sbapt              if (count > 0 && p[-1] == *p + 1)
147228060Sbapt                {
148228060Sbapt                  printf ("-");
149228060Sbapt                  do
150228060Sbapt                    {
151228060Sbapt                      p--;
152228060Sbapt                      count--;
153228060Sbapt                    }
154228060Sbapt                  while (count > 0 && p[-1] == *p + 1);
155228060Sbapt                  printf ("%d", *p + 1);
156228060Sbapt                }
157228060Sbapt              first = false;
158228060Sbapt            }
159228060Sbapt        }
160228060Sbapt      if (seen_LASTCHAR)
161228060Sbapt        {
162228060Sbapt          if (!first)
163228060Sbapt            printf (",");
164228060Sbapt          printf ("$");
165228060Sbapt        }
166228060Sbapt    }
167228060Sbapt}
168228060Sbapt
169228060Sbapt/* ------------------------------------------------------------------------- */
170228060Sbapt
171228060Sbapt#ifndef __OPTIMIZE__
172228060Sbapt
173228060Sbapt#define INLINE /* not inline */
174228060Sbapt#include "positions.icc"
175228060Sbapt#undef INLINE
176228060Sbapt
177228060Sbapt#endif /* not defined __OPTIMIZE__ */
178