using System;
using Microsoft.SPOT;

namespace CPF
{
    class Tokenizer
    {
        private static readonly byte[] _DEFAULT_DELIMITERS = System.Text.Encoding.UTF8.GetBytes(" \t\v\n\r\f");

        public Tokenizer() {
            _buffer = new ByteString();
            _token = new ByteString();
            _delimiters = new ByteString(_DEFAULT_DELIMITERS);
            _currentPosition = 0;
        }

        public Tokenizer(ByteString s)
        {
            _buffer = s;
            _token = new ByteString();
            _delimiters = new ByteString(_DEFAULT_DELIMITERS);
            _currentPosition = 0;
        }        

        public Tokenizer(ByteString s, ByteString delimiters)
        {
            _buffer = s;
            _token = new ByteString();
            _delimiters = delimiters;
            _currentPosition = 0;
        }

        // set string and delimiter
        public void Set(ByteString s, ByteString delimiters) 
        {
            _buffer = s;
            _delimiters = delimiters;
            _currentPosition = _buffer.Begin();
        }

        public void SetString(ByteString s) 
        {
            _buffer = s;
            _currentPosition = _buffer.Begin();
        }            
        
        public void SetDelimiter(ByteString delimiters) 
        {
            _delimiters = delimiters;
            _currentPosition = _buffer.Begin();
        }

        public void Next(ref ByteString token)
        {
            if (_buffer.Length != 0)
            {
                _token.Clear();                        // reset token string
                skipDelimiters();                      // skip leading delimiters

                // Append each char to token until delimiter
                while (_currentPosition != _buffer.End() && !isDelimiter(_buffer[_currentPosition]))
                    token.Append(_buffer[_currentPosition++]);
            }
            else
                token = null;                           // buffer is empty
        }

        private void skipDelimiters() 
        {
            while (_currentPosition != _buffer.End() && isDelimiter(_buffer[_currentPosition]))
                _currentPosition++;
        }

        private bool isDelimiter(byte ch)
        {
            int i = 0;
            while (ch != _delimiters[i] && i < _delimiters.Length) 
                i++;
            return (i != _delimiters.Length);
        }

        ByteString  _buffer;                                 // input string
        ByteString  _token;                                  // output string
        ByteString  _delimiters;                             // delimiter string
        int         _currentPosition;
    }
}
