#ifdef __GNUC__
#pragma implementation
#endif

#include "CharSet.h"

void CharSet::clear()
{
    register _CharSetWord *p = words;
    for (register int i = _CHARSETWORDS; --i >= 0; ) *p++ = 0;
}

void CharSet::set(int ch)
{
    if (ch < 0 || ch > UCHAR_MAX) return;
    char_to_word(ch) |= 1 << bit_in_word(ch);
}

void CharSet::add(char *p, register int len)
{
    while (--len >= 0) set((unsigned char)*p++);
}

void CharSet::clear(int ch)
{
    if (ch < 0 || ch > UCHAR_MAX) return;
    char_to_word(ch) &= ~(1 << bit_in_word(ch));
}

void CharSet::put(register streambuf *sb, int flags) const
{
    int inverted = 0;
    int also_minus = 0;  // Need to emit '-' last.
    sb->sputc('\[');
    for (register int i = 0; i <= UCHAR_MAX; i++)
	if (test(i) != inverted) {
	    if (i == '-') {
		also_minus = 1;
		continue;
	    }
	    sb->sputc((unsigned char)i);
	    int j = i+1;
	    while (j <= UCHAR_MAX && (test(j) != inverted)) j++;
	    // j is first char after i not in set.
	    if (j-1 == '-') { // '-' cannot be end of range.
		also_minus = 1;
		j--;
	    }
	    if (j == i+1) ; // Do nothing
	    else {
		// Don't emit - if range is just two chars.
		if (j >= i+3) sb->sputc('-');
		sb->sputc((unsigned char)(j-1)); // put end of range
	    }
	    i = j; // Skipping j.
	}
    if (also_minus)
	sb->sputc('-');
    sb->sputc(']');
}

ostream& operator<<(ostream& s, const CharSet& cs)
{
    if (s.opfx()) {
	streambuf *sbuf = s.rdbuf();
	cs.put(sbuf, 2);
    }
    return s;
}

void Charset::printon(ostream &s) const
{
    s << *(CharSet*)this;
}
