158314Sache/* A set of byte positions.
221308Sache   Copyright (C) 1989-1998, 2000, 2002 Free Software Foundation, Inc.
321308Sache   Written by Douglas C. Schmidt <schmidt@ics.uci.edu>
4165675Sache   and Bruno Haible <bruno@clisp.org>.
521308Sache
621308Sache   This file is part of GNU GPERF.
721308Sache
821308Sache   GNU GPERF is free software; you can redistribute it and/or modify
921308Sache   it under the terms of the GNU General Public License as published by
1021308Sache   the Free Software Foundation; either version 2, or (at your option)
1158314Sache   any later version.
1221308Sache
1321308Sache   GNU GPERF is distributed in the hope that it will be useful,
1421308Sache   but WITHOUT ANY WARRANTY; without even the implied warranty of
1521308Sache   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1621308Sache   GNU General Public License for more details.
1721308Sache
1821308Sache   You should have received a copy of the GNU General Public License
1921308Sache   along with this program; see the file COPYING.
2021308Sache   If not, write to the Free Software Foundation, Inc.,
2121308Sache   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
2258314Sache
2321308Sache/* Specification. */
2421308Sache#include "positions.h"
2521308Sache
2621308Sache#include <stdio.h>
2721308Sache#include <stdlib.h> /* declares exit() */
2821308Sache#include <string.h>
2921308Sache
3021308Sache/* ---------------------------- Class Positions ---------------------------- */
3121308Sache
3221308Sache/* Set operations.  Assumes the array is in reverse order.  */
3321308Sache
3421308Sachebool
3526497SachePositions::contains (int pos) const
3626497Sache{
3721308Sache  unsigned int count = _size;
3821308Sache  const int *p = _positions + _size - 1;
3921308Sache
4021308Sache  for (; count > 0; p--, count--)
4121308Sache    {
4221308Sache      if (*p == pos)
4326497Sache        return true;
4421308Sache      if (*p > pos)
4521308Sache        break;
4621308Sache    }
47119614Sache  return false;
4821308Sache}
4921308Sache
5021308Sachevoid
5121308SachePositions::add (int pos)
5221308Sache{
5321308Sache  set_useall (false);
5421308Sache
5521308Sache  unsigned int count = _size;
5658314Sache
5758314Sache  if (count == MAX_SIZE)
5858314Sache    {
5921308Sache      fprintf (stderr, "Positions::add internal error: overflow\n");
6021308Sache      exit (1);
6121308Sache    }
6221308Sache
63119614Sache  int *p = _positions + _size - 1;
64119614Sache
65119614Sache  for (; count > 0; p--, count--)
66119614Sache    {
67119614Sache      if (*p == pos)
6821308Sache        {
69119614Sache          fprintf (stderr, "Positions::add internal error: duplicate\n");
70136759Speter          exit (1);
71119614Sache        }
72119614Sache      if (*p > pos)
73119614Sache        break;
74119614Sache      p[1] = p[0];
75119614Sache    }
7621308Sache  p[1] = pos;
7758314Sache  _size++;
7821308Sache}
7921308Sache
80165675Sachevoid
81165675SachePositions::remove (int pos)
8221308Sache{
8321308Sache  set_useall (false);
84165675Sache
85165675Sache  unsigned int count = _size;
86165675Sache  if (count > 0)
87165675Sache    {
88165675Sache      int *p = _positions + _size - 1;
89165675Sache
90165675Sache      if (*p == pos)
91165675Sache        {
9221308Sache          _size--;
9321308Sache          return;
9421308Sache        }
9521308Sache      if (*p < pos)
9621308Sache        {
9721308Sache          int prev = *p;
9821308Sache
9921308Sache          for (;;)
10021308Sache            {
10121308Sache              p--;
10221308Sache              count--;
10321308Sache              if (count == 0)
10421308Sache                break;
10521308Sache              if (*p == pos)
10621308Sache                {
10721308Sache                  *p = prev;
10821308Sache                  _size--;
10921308Sache                  return;
11021308Sache                }
11121308Sache              if (*p > pos)
11221308Sache                break;
11321308Sache              int curr = *p;
11421308Sache              *p = prev;
11521308Sache              prev = curr;
11621308Sache            }
11721308Sache        }
11821308Sache    }
11921308Sache  fprintf (stderr, "Positions::remove internal error: not found\n");
12075409Sache  exit (1);
12121308Sache}
12221308Sache
12321308Sache/* Output in external syntax.  */
12421308Sachevoid
12521308SachePositions::print () const
12621308Sache{
127157188Sache  if (_useall)
12821308Sache    printf ("*");
12921308Sache  else
13021308Sache    {
13121308Sache      bool first = true;
13221308Sache      bool seen_LASTCHAR = false;
13321308Sache      unsigned int count = _size;
134157188Sache      const int *p = _positions + _size - 1;
13521308Sache
136157188Sache      for (; count > 0; p--)
137157188Sache        {
138157188Sache          count--;
139157188Sache          if (*p == LASTCHAR)
14021308Sache            seen_LASTCHAR = true;
14121308Sache          else
14221308Sache            {
143157188Sache              if (!first)
144165675Sache                printf (",");
145157188Sache              printf ("%d", *p + 1);
14621308Sache              if (count > 0 && p[-1] == *p + 1)
14721308Sache                {
14821308Sache                  printf ("-");
14921308Sache                  do
15021308Sache                    {
15121308Sache                      p--;
15221308Sache                      count--;
15321308Sache                    }
15421308Sache                  while (count > 0 && p[-1] == *p + 1);
15521308Sache                  printf ("%d", *p + 1);
15621308Sache                }
15721308Sache              first = false;
15821308Sache            }
15921308Sache        }
16021308Sache      if (seen_LASTCHAR)
16121308Sache        {
16221308Sache          if (!first)
16321308Sache            printf (",");
16421308Sache          printf ("$");
16521308Sache        }
16621308Sache    }
16721308Sache}
16875409Sache
16975409Sache/* ------------------------------------------------------------------------- */
17075409Sache
17121308Sache#ifndef __OPTIMIZE__
172165675Sache
17375409Sache#define INLINE /* not inline */
17421308Sache#include "positions.icc"
17521308Sache#undef INLINE
17621308Sache
17721308Sache#endif /* not defined __OPTIMIZE__ */
17821308Sache