/***************************************************************************
 $RCSfile$
 -------------------
 cvs         : $Id$
 begin       : Thu Apr 03 2003
 copyright   : (C) 2003 by Martin Preuss
 email       : martin@libchipcard.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                                                   *
 *                                                                         *
 ***************************************************************************/

#ifndef GWENHYWFAR_STRINGLIST_H
#define GWENHYWFAR_STRINGLIST_H

#include <gwenhywfar/gwenhywfarapi.h>

#include <gwenhywfar/buffer.h>


#ifdef __cplusplus
extern "C" {
#endif


typedef enum {
  /** case-insensitive, i.e. using strcasecmp(3). */
  GWEN_StringList_SortModeNoCase=0,
  /** case-sensitive, i.e. using strcmp(3). */
  GWEN_StringList_SortModeCase,
  /** handle string list entries as integers (-> correct sorting of ASCII
   * coded values like "10", "1") */
  GWEN_StringList_SortModeInt
}
GWEN_STRINGLIST_SORT_MODE;


typedef struct GWEN_STRINGLISTENTRYSTRUCT GWEN_STRINGLISTENTRY;


typedef struct GWEN_STRINGLISTSTRUCT GWEN_STRINGLIST;


GWENHYWFAR_API GWEN_STRINGLIST *GWEN_StringList_new(void);

GWENHYWFAR_API GWEN_STRINGLIST *GWEN_StringList_fromTabString(const char *s, int checkDup);
GWENHYWFAR_API int GWEN_StringList_toBuffer(const GWEN_STRINGLIST *sl, const char *delimiter, GWEN_BUFFER *outBuffer);

GWENHYWFAR_API void GWEN_StringList_free(GWEN_STRINGLIST *sl);
GWENHYWFAR_API
GWEN_STRINGLIST *GWEN_StringList_dup(const GWEN_STRINGLIST *sl);
GWENHYWFAR_API void GWEN_StringList_Clear(GWEN_STRINGLIST *sl);

/** Returns the number of elements in this list. */
GWENHYWFAR_API
unsigned int GWEN_StringList_Count(const GWEN_STRINGLIST *sl);

GWENHYWFAR_API GWEN_STRINGLISTENTRY *GWEN_StringListEntry_new(const char *s,
                                                              int take);
GWENHYWFAR_API void GWEN_StringListEntry_ReplaceString(GWEN_STRINGLISTENTRY *e,
                                                       const char *s,
                                                       int take);
GWENHYWFAR_API void GWEN_StringListEntry_free(GWEN_STRINGLISTENTRY *sl);
GWENHYWFAR_API void GWEN_StringList_AppendEntry(GWEN_STRINGLIST *sl,
                                                GWEN_STRINGLISTENTRY *se);
GWENHYWFAR_API void GWEN_StringList_RemoveEntry(GWEN_STRINGLIST *sl,
                                                GWEN_STRINGLISTENTRY *se);
GWENHYWFAR_API
GWEN_STRINGLISTENTRY *GWEN_StringList_FirstEntry(const GWEN_STRINGLIST *sl);
GWENHYWFAR_API
GWEN_STRINGLISTENTRY *GWEN_StringListEntry_Next(const GWEN_STRINGLISTENTRY *se);

GWENHYWFAR_API
const char *GWEN_StringListEntry_Data(const GWEN_STRINGLISTENTRY *se);

GWENHYWFAR_API
void GWEN_StringListEntry_SetData(GWEN_STRINGLISTENTRY *se,
                                  const char *s);

/**
 * Normally this group of functions ignores cases when comparing two strings.
 * You can change this behaviour here.
 * @param sl string list
 * @param i if 0 then cases are ignored
 */
GWENHYWFAR_API
void GWEN_StringList_SetSenseCase(GWEN_STRINGLIST *sl, int i);

/**
 * Normally this group of functions ignores reference counters on stringlist
 * entries when removing a string via @ref GWEN_StringList_RemoveString.
 * You can change this behaviour here.
 * @param sl string list
 * @param i if 0 then reference counters are honoured
 */
GWENHYWFAR_API
void GWEN_StringList_SetIgnoreRefCount(GWEN_STRINGLIST *sl, int i);

/**
 * Appends a string.
 * @return 0 if not appended, !=0 if appended
 * @param take if true then the StringList takes over ownership of the string
 * @param checkDouble if true the the string will only be appended if it
 * does not already exist
 */
GWENHYWFAR_API int GWEN_StringList_AppendString(GWEN_STRINGLIST *sl,
                                                const char *s,
                                                int take,
                                                int checkDouble);

/**
 * Inserts a string.
 * @return 0 if not inserted, !=0 if inserted
 * @param take if true then the StringList takes over ownership of the string
 * @param checkDouble if true the the string will only be appended if it
 * does not already exist
 */
GWENHYWFAR_API int GWEN_StringList_InsertString(GWEN_STRINGLIST *sl,
                                                const char *s,
                                                int take,
                                                int checkDouble);

/**
 * Removes a given string from the stringlist.
 * @return 0 if not found, !=0 if found and removed
 */
GWENHYWFAR_API int GWEN_StringList_RemoveString(GWEN_STRINGLIST *sl,
                                                const char *s);

/**
 * Removes the first string from the stringlist (if any).
 */
GWENHYWFAR_API void GWEN_StringList_RemoveFirstString(GWEN_STRINGLIST *sl);


/**
 * Append duplicates of the entries in the source list to the destination list.
 * The source list is not modified.
 */
GWENHYWFAR_API void GWEN_StringList_AppendStringList(GWEN_STRINGLIST *slDest,
                                                     const GWEN_STRINGLIST *slSource,
                                                     int checkDouble);


/**
 * Checks whether the given string already exists within in the
 * string list.
 * @return !=0 if found, 0 otherwise
 */
GWENHYWFAR_API int GWEN_StringList_HasString(const GWEN_STRINGLIST *sl,
                                             const char *s);

/**
 * Returns the position of the given string within the stringlist.
 *
 * @return position, -1 if not found
 */
GWENHYWFAR_API int GWEN_StringList_GetStringPos(const GWEN_STRINGLIST *sl, const char *s);


/**
 * Returns the first stringlist entry which contains the given string
 * @return string list entry containing the given string, NULL otherwise
 */
GWENHYWFAR_API GWEN_STRINGLISTENTRY *GWEN_StringList_FindStringEntry(const GWEN_STRINGLIST *sl, const char *s);


/** Traverses the list, calling the callback function 'func' on
 * each list element.  Traversal will stop when 'func' returns a
 * non-NULL value, and the routine will return with that
 * value. Otherwise the routine will return NULL.
 * @param l The list to traverse.
 * @param func The function to be called with each list element.
 * @param user_data A pointer passed on to the function 'func'.
 * @return The non-NULL pointer returned by 'func' as soon as it
 * returns one. Otherwise (i.e. 'func' always returns NULL)
 * returns NULL.
 */
GWENHYWFAR_API
void *GWEN_StringList_ForEach(const GWEN_STRINGLIST *l,
                              void *(*func)(const char *s, void *u),
                              void *user_data);

/** Returns the first string in this list. */
GWENHYWFAR_API
const char *GWEN_StringList_FirstString(const GWEN_STRINGLIST *l);

GWENHYWFAR_API
const char *GWEN_StringList_StringAt(const GWEN_STRINGLIST *l, int idx);

GWENHYWFAR_API
int GWEN_StringList_StringAsIntAt(const GWEN_STRINGLIST *l, int idx, int defaultValue);


/** Sorts this list. Internally this uses qsort(3), so the sorting
 * should be reasonably fast even for large lists.
 *
 * @param l The list to sort.
 *
 * @param ascending If non-zero, the list is sorted ascending,
 * i.e. smallest string first, according to strcmp(3) rules. If zero,
 * the list is sorted descending.
 *
 * @param sortMode See @ref GWEN_StringList_SortModeNoCase and following
 */
GWENHYWFAR_API
void GWEN_StringList_Sort(GWEN_STRINGLIST *l,
                          int ascending,
                          GWEN_STRINGLIST_SORT_MODE sortMode);

GWENHYWFAR_API
GWEN_STRINGLIST *GWEN_StringList_fromString(const char *str, const char *delimiters, int checkDouble);

/**
 * Create a stringlist from a given complex string.
 *
 * In addition to @ref GWEN_StringList_fromString() this version allows to modify the behavior of the function
 * by adding some flags (see @ref GWEN_TEXT_FLAGS_CHECK_BACKSLASH and following).
 * Typically used flags are:
 * - @ref GWEN_TEXT_FLAGS_DEL_QUOTES (delete quotes around single words)
 * - @ref GWEN_TEXT_FLAGS_CHECK_BACKSLASH (handle backslashes as escape characters)
 *
 * @return stringlist object (contains at least one entry) or NULL if no entries/empty string
 * @param str string to dissect
 * @param delimiters word delimiters
 * @param checkDouble if !=0 only add unique strings to the resulting list
 * @param flags (see @ref GWEN_TEXT_FLAGS_DEL_QUOTES and others)
 */
GWENHYWFAR_API
GWEN_STRINGLIST *GWEN_StringList_fromString2(const char *str, const char *delimiters, int checkDouble, uint32_t flags);


/**
 * Remove first equal entries from both lists.
 *
 * If stringlist 1 contains "A", "B", "C", "D" and
 *    stringlist 2 contains "A", "B", "X" then after this function the lists are changed to this:
 *    stringlist 1 contains "C", "D"
 *    stringlist 2 contains "X"
 */
GWENHYWFAR_API
void GWEN_StringList_RemoveCommonFirstEntries(GWEN_STRINGLIST *sl1, GWEN_STRINGLIST *sl2);


#ifdef __cplusplus
}
#endif

#endif


