// -*- c++ -*-

/*
 * Jakelib2 - General purpose C++ library
 * Copyright (C) 2001 Florian Wolff  (florian@@donuz.de)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * $Id: WildCardFilter.h,v 1.6 2003/09/13 08:46:07 florian Exp $
 */

#ifndef INCLUDE_JAKELIB2_IO_WILDCARDFILTER_H
# define INCLUDE_JAKELIB2_IO_WILDCARDFILTER_H
#include "FilenameFilter.h"

namespace jakelib {
  namespace util {
    class ArrayList;
  }
  namespace io {
    class File;

    /**
     * \c WildCardFilter implements a simple wild card filename filter.
     *
     * The following wild card characters are supported:
     * - "\c *" Stands for an arbitrary number of arbitrary characters
     * - "\c ?" Stands for exactly one arbitrary character
     * - "\c [abc]" Stands for exactly one character out of \c abc
     * - "\c {abc,def,ghi}" Stands for a number of comma-separated alternative
     *       strings.
     *
     * \b Examples:
     * - "\c *.txt" Accepts all filenames that end with "\c .txt"
     * - "\c file[123]" Accepts "\c file1", "\c file2" and "\c file3"
     * - "\c *A*" Accepts all filenames that contain at least one "\c A"
     * - "\c *.{cpp,c,h}" Accepts all filenames that end with "\c .cpp",
     *       "\c .c" or "\c .h".
     *
     * @class WildCardFilter
     * @version $Id: WildCardFilter.h,v 1.6 2003/09/13 08:46:07 florian Exp $
     * @author Florian 'Overflo' Wolff (florian@@donuz.de)
     */
    class WildCardFilter : public jakelib::lang::Object, 
                           public FilenameFilter
    {
    public:

      /**
       * Creates a new \c WildCardFilter with the given search
       * pattern. (See above for a description of valid wild cards.)
       */
      WildCardFilter(jakelib::lang::String *pattern);

      ~WildCardFilter();

      /**
       * This method determines whether or not a given file should be included
       * in a directory listing.
       *
       * @param dir  The \c File instance for the directory being read.
       *             Totally ignored in this sub-class.
       * @param name The name of the file to test.
       *
       * @return \c true if the file should be included in the list,
       *         \c false otherwise.
       */
      jboolean accept(File *dir, jakelib::lang::String *name);

      /**
       * Returns a short description of this filename filter.
       */
      jakelib::lang::String *toString();

      /**
       * Frees all resources. Don't use the \c WildCardFilter afterwards!
       */
      virtual void destroy();
 
    protected:
        
      /** The wildcard pattern. */
      jakelib::lang::String *pattern;

      /** A pattern can consist of a number of tokens out of these types: */
      typedef enum {
        /** A certain string */              
        STRING,
        /** A number of characters to choose from */
        CHARACTER,
        /** The questionmark token: exactly one arbitrary character */
        QUESTIONMARK,
        /** The asterisk token: arbitrary number of characters */
        ASTERISK,
        /** A number of alternative strings, e.g. "\c {abc.def.ghi}" */
        ALTERNATIVES
      } TOKEN_TYPE;
      
      /** This data type holds one pattern token. */
      typedef struct {
        /** Type of token */
        TOKEN_TYPE type;
        /** If type is \c STRING this is this very string;
            if type is \c CHARACTER this is a string containing the
            allowed characters. Unused otherwise. */
        jakelib::lang::String *str;
        /** If type is \c ALTERNATIVES this is the list of alternative
            strings. */
        jakelib::util::ArrayList *alternatives;
      } TOKEN;
  
      /** Array containing the tokens */
      TOKEN *tokens;

      /** Number of tokens in \c tokens */
      int length;

      /**
       * Used to recursively match filename against pattern.
       *
       * @param input      The whole input string (= the filename)
       * @param inputPos   Position within the input string
       * @param patternPos Position within the \c tokens array
       */
      jboolean matches(jakelib::lang::String *input,
                       int inputPos,
                       int patternPos);

      JAKELIB_DECLARE_CLASS(WildCardFilter);
    };
  }
}
#endif

