/*
 * ctype routines
 * Bart 2002/7
 * ASCII-only: Nickle is in the C locale
 */

namespace Ctype {

    public bool isascii(int ch) 
	/*
	 * As with C ctype.h, things outside the ASCII range
	 * are not handled here.  Unlike C ctype.h, we handle
	 * this case cleanly.
	 */
    {
	return ch >= 0 && ch <= 127;
    }
    
    /* The characteristic vector of sets of Latin-1 chars. */
    public typedef bool[256] charset;

    public charset make_charset(bool(int) cfun) 
	/*
	 * Make a characteristic vector from a characteristic function. 
	 */
    {
	charset result;
	for (int i = 0; i < dim(result); i++)
	    result[i] = cfun(i);
	return result;
    }

    public bool member(charset v, int ch) 
	/*
	 * Test whether a particular char is in a charset. 
	 */
    {
	return ch >= 0 && ch < dim(v) && v[ch];
    }


    /*
     * Now this machinery is used to implement the standard
     * C ctype.h tests in the obvious fasion.
     */


    public bool isupper(int ch) 
	/*
	 * Return whether 'ch' is uppercase.
	 */
    {
	static bool cfun(int ch) {
	    return (ch >= 'A' && ch <= 'Z' ||
		    ch >= 'À' && ch <= 'Þ');
	}
	static charset v = make_charset(cfun);
	return member(v, ch);
    }

    public bool islower(int ch) 
	/*
	 * Return whether 'ch' is lowercase.
	 */
    {
	static bool cfun(int ch) {
	    return (ch >= 'a' && ch <= 'z' ||
		    ch >= 'à' && ch <= 'þ');
	}
	static charset v = make_charset(cfun);
	return member(v, ch);
    }

    public bool isdigit(int ch) 
	/*
	 * Return whether 'ch' is a digit
	 */
    {
	static bool cfun(int ch) {
	    return ch >= '0' && ch <= '9';
	}
	static charset v = make_charset(cfun);
	return member(v, ch);
    }

    public bool isblank(int ch) 
	/*
	 * Return whether 'ch' is a space or tab
	 */
    {
	return ch == ' ' || ch == '\t';
    }

    public bool iscntrl(int ch)
	/*
	 * Return whether 'ch' is a control character
	 */
    {
	static bool cfun(int ch) {
	    return ch >= 0 && ch <= 31;
	}
	static charset v = make_charset(cfun);
	return member(v, ch);
    }

    public bool isgraph(int ch) 
	/*
	 * Return whether 'ch' is a visible character
	 */	
    {
	static bool cfun(int ch) {
	    return (ch > ' ' && ch < 127 ||
		    ch >= 'À' && ch <= 'þ');
	}
	static charset v = make_charset(cfun);
	return member(v, ch);
    }

    public bool isprint(int ch) 
	/*
	 * Return whether 'ch' is a printable character
	 */	
    {
	static bool cfun(int ch) {
	    return (ch >= ' ' && ch < 127 ||
		    ch >= 'À' && ch <= 'þ');
	}
	static charset v = make_charset(cfun);
	return member(v, ch);
    }
	
    public bool isspace(int ch)
	/*
	 * Return whether 'ch' is whitespace
	 */	
    {
	static bool cfun(int ch) {
	       int[*] sc = {' ', '\f', '\n', '\r', '\t', '\v'};
	       for (int i = 0; i < dim(sc); i++)
	           if (ch == sc[i])
		       return true;
	       return false;
	}
	static charset v = make_charset(cfun);
	return member(v, ch);
    }

    public bool isalpha(int ch) 
	/*
	 * Return whether 'ch' is a latin letter
	 */	
    {
	static bool cfun(int ch) {
	    return islower(ch) || isupper(ch);
	}
	static charset v = make_charset(cfun);
	return member(v, ch);
    }

    public bool isalnum(int ch)
	/*
	 * Return whether 'ch' is a letter or digit
	 */
    {
	static bool cfun(int ch) {
	    return isalpha(ch) || isdigit(ch);
	}
	static charset v = make_charset(cfun);
	return member(v, ch);
    }
    
    public bool ispunct(int ch)
	/*
	 * Return whether 'ch' is punctuation
	 */
    {
	static bool cfun(int ch) {
	    return isgraph(ch) && !isalnum(ch);
	}
	static charset v = make_charset(cfun);
	return member(v, ch);
    }

    public int tolower(int ch) 
	/*
	 * If 'ch' is upper case, return the lower case version
	 * else return 'ch'
	 */
    {
	if (isupper(ch))
	    return ch - 'A' + 'a';
	return ch;
    }

    public int toupper(int ch) 
	/*
	 * If 'ch' is lower case, return the upper case version
	 * else return 'ch'
	 */
    {
	if (islower(ch))
	    return ch - 'a' + 'A';
	return ch;
    }

    public bool isxdigit(int ch) 
	/*
	 * Return whether 'ch' is a hexidecimal digit
	 */
    {
	static bool cfun(int ch) {
	    if (isdigit(ch))
		return true;
	    int chl = tolower(ch);
	    return chl >= 'a' && chl <= 'f';
	}
	static charset v = make_charset(cfun);
	return member(v, ch);
    }
}

