#ifndef SML3__UTF8_H
#define SML3__UTF8_H

/* ++++++++++++++++++++
 * +++ Beschreibung +++
 * ++++++++++++++++++++

  Enthaelt Funktionen fuer UTF8-Zeichen und -Strings.
  Sind nicht thread-sicher.
  Verwenden setlocale() um CTYPE auf UTF8 zu setzen,
  damit Eigenschaften des UTF8-Zeichens erhalten werden koennen,
  bzw. gross/klein gesetzt werden kann.
  Schlagen fehl, wenn CTYPE nicht auf UTF8 gesetzt werden kann.

+++ */


/* ++++++++++++++++++ */
/* +++ Funktionen +++ */
/* ++++++++++++++++++ */

enum SML3_UTF8_CODE { SML3_UTF8_CODE_ASCII = 0, SML3_UTF8_CODE_8BYTE, SML3_UTF8_CODE_UTF8 };

struct SML3_utf8_typ {  /* Eigenschaften des UTF8-Zeichens */
  int is_alpha;   /* iswalpha(3) */
  int is_blank;   /* iswblank(3) */ 
  int is_cntrl;   /* iswcntrl(3) */
  int is_digit;   /* iswdigit(3) */ 
  int is_graph;   /* iswgraph(3) */
  int is_lower;   /* iswlower(3) */
  int is_print;   /* iswprint(3) */
  int is_punct;   /* iswpunct(3) */ 
  int is_space;   /* iswspace(3) */
  int is_upper;   /* iswupper(3) */
  int is_xdigit;  /* iswxdigit(3) */
};


/** SML3_utf8_codierung:
 * gibt zurueck, ob der String ASCII, 8-Bytes oder UTF-8 ist
 * (braucht kein setlocale())
 * 1.Arg: String
 * Rueckgabe: enum SML3_UTF8_CODE
 */
extern int SML3_utf8_codierung(const char *);


/** SML3_utf8_next:
 * naechstes UTF8-Zeichen erhalten
 * (braucht kein setlocale())
 * 1.Arg: String
 * 2.Arg: Stringlaenge
 * 3.Arg: fuer Rueckgabe Unicode-Codepoint des UTF8-Zeichens, wenn nicht NULL
 * Rueckgabe: Anzahl Bytes des UTF8-Zeichens
 *            oder 0 = Ende
 *            oder -1 = ungueltiges Zeichen
 *
 * Beispiel:
 *   const char *string = "Word";
 *   const char *strptr;
 *   size_t strsize;
 *   int no_bytes, codept;
 *
 *   strptr = string;
 *   strsize = strlen(strptr);
 *   for (;;) {
 *     no_bytes = SML3_utf8_next(strptr, strsize, &codept);
 *     if (no_bytes <= 0) { break; }
 *     printf("UTF8-Zeichen: codept = %d, Anzahl Bytes = %d: %.*s\n", codept, no_bytes, no_bytes, strptr);
 *     strptr += no_bytes;
 *     strsize -= no_bytes;
 *   }
 */
extern int SML3_utf8_next(const char *, size_t, int *);


/** SML3_utf8_from_codepoint:
 * setzt UTF8-character vom Unicode-Codepoint
 * (braucht kein setlocale())
 * 1.Arg: Unicode-Codepoint
 * 2.Arg: fuer Rueckgabe UTF8-Zeichen, wenn nicht NULL,
 *        sollte mindestens 6 Bytes Platz haben
 * Rueckgabe: Anzahl Bytes des UTF8-Zeichens, oder 0 = ungueltig
 *
 * Beispiel:
 *   char cbuf[8];
 *   int no_bytes, codept;
 *
 *   SML3_utf8_next("X", sizeof("X"), &codept);  // Unicode-Codepoint von X erhalten
 *   no_bytes = SML3_utf8_from_codepoint(codept, cbuf);
 *   printf("UTF8-Zeichen: codept = %d, Anzahl Bytes = %d: %.*s\n", codept, no_bytes, no_bytes, cbuf);
 */
extern int SML3_utf8_from_codepoint(int, char *);


/** SML3_utf8_gettyp:
 * Eigenschaften des UTF8-Zeichens erhalten
 * 1.Arg: Unicode-Codepoint
 * 2.Arg: fuer Rueckgabe Eigenschaften
 * Rueckgabe: 1 = OK oder 0 = ungueltiges Zeichen (oder Ende-0)
 */
extern int SML3_utf8_gettyp(int, struct SML3_utf8_typ *);


/** SML3_utf8_toupper:
 * UTF8-Zeichen gross konvertieren
 * 1.Arg: Unicode-Codepoint
 * Rueckgabe: 1.Arg grossgeschrieben oder 1.Arg unveraendert
 */
extern int SML3_utf8_toupper(int);


/** SML3_utf8_tolower:
 * UTF8-Zeichen klein konvertieren
 * 1.Arg: Unicode-Codepoint
 * Rueckgabe: 1.Arg kleingeschrieben oder 1.Arg unveraendert
 */
extern int SML3_utf8_tolower(int);


/** SML3_utf8_strlen:
 * Anzahl UTF8-Zeichen im UTF8-String zurueckgeben
 * (braucht kein setlocale())
 * 1.Arg: String
 * Rueckgabe: Anzahl UTF8-Zeichen
 */
extern size_t SML3_utf8_strlen(const char *);


/** SML3_utf8_strnlen:
 * Anzahl UTF8-Zeichen im UTF8-String zurueckgeben
 * (braucht kein setlocale())
 * 1.Arg: String
 * 2.Arg: Uebergabe: maximale Anzahl Bytes im 1.Arg auswerten
 *        Rueckgabe: Anzahl Bytes im 1.Arg mit vollstaendigen UTF8-Zeichen
 * Rueckgabe: Anzahl UTF8-Zeichen
 */
extern size_t SML3_utf8_strnlen(const char *, size_t *);


/** SML3_utf8_strchr:
 * UTF8-Zeichen im UTF8-String suchen
 * 1.Arg: String
 * 2.Arg: Unicode-Codepoint des UTF8-Zeichens
 * Rueckgabe: Pointer auf UTF8-Zeichen im String, oder NULL
 */
extern char * SML3_utf8_strchr(const char *, int);


/** SML3_utf8_strcasechr:
 * UTF8-Zeichen insensitive im UTF8-String suchen
 * 1.Arg: String
 * 2.Arg: Unicode-Codepoint des UTF8-Zeichens
 * Rueckgabe: Pointer auf UTF8-Zeichen im String, oder NULL
 */
extern char * SML3_utf8_strcasechr(const char *, int);


/** SML3_utf8_strrchr:
 * letztes UTF8-Zeichen im UTF8-String suchen
 * 1.Arg: String
 * 2.Arg: Unicode-Codepoint des UTF8-Zeichens
 * Rueckgabe: Pointer auf UTF8-Zeichen im String, oder NULL
 */
extern char * SML3_utf8_strrchr(const char *, int);


/** SML3_utf8_strcaserchr:
 * letztes UTF8-Zeichen insensitive im UTF8-String suchen
 * 1.Arg: String
 * 2.Arg: Unicode-Codepoint des UTF8-Zeichens
 * Rueckgabe: Pointer auf UTF8-Zeichen im String, oder NULL
 */
extern char * SML3_utf8_strcaserchr(const char *, int);


/** SML3_utf8_strpbrk:
 * Auswahl von UTF8-Zeichen im UTF8-String suchen
 * 1.Arg: String
 * 2.Arg: Auswahl von UTF8-Zeichen
 *        oder %a = Klein-Buchstabe
 *             %A = Gross-Buchstabe
 *             %b = Leerzeichen
 *             %d = Ziffer
 *             %p = sonstiges druckbares Zeichen
 *             %% = Prozent
 * Rueckgabe: Pointer auf gefundenes UTF8-Zeichen im String, oder NULL
 */
extern char * SML3_utf8_strpbrk(const char *, const char *);


/** SML3_utf8_strcasepbrk:
 * Auswahl von UTF8-Zeichen insensitive im UTF8-String suchen
 * 1.Arg: String
 * 2.Arg: Auswahl von UTF8-Zeichen
 *        oder %a = Buchstabe
 *             %A = Buchstabe
 *             %b = Leerzeichen
 *             %d = Ziffer
 *             %p = sonstiges druckbares Zeichen
 *             %% = Prozent
 * Rueckgabe: Pointer auf gefundenes UTF8-Zeichen im String, oder NULL
 */
extern char * SML3_utf8_strcasepbrk(const char *, const char *);


/** SML3_utf8_strspn:
 * wie strspn fuer UTF8
 * 1.Arg: String
 * 2.Arg: Auswahl von UTF8-Zeichen
 *        oder %a = Klein-Buchstabe
 *             %A = Gross-Buchstabe
 *             %b = Leerzeichen
 *             %d = Ziffer
 *             %p = sonstiges druckbares Zeichen
 *             %% = Prozent
 * Rueckgabe: Anzahl Bytes
 */
extern size_t SML3_utf8_strspn(const char *, const char *);


/** SML3_utf8_strcasespn:
 * wie strspn fuer UTF8, aber insensitive
 * 1.Arg: String
 * 2.Arg: Auswahl von UTF8-Zeichen
 *        oder %a = Buchstabe
 *             %A = Buchstabe
 *             %b = Leerzeichen
 *             %d = Ziffer
 *             %p = sonstiges druckbares Zeichen
 *             %% = Prozent
 * Rueckgabe: Anzahl Bytes
 */
extern size_t SML3_utf8_strcasespn(const char *, const char *);


/** SML3_utf8_strcspn:
 * wie strcspn fuer UTF8
 * 1.Arg: String
 * 2.Arg: Auswahl von UTF8-Zeichen
 *        oder %a = Klein-Buchstabe
 *             %A = Gross-Buchstabe
 *             %b = Leerzeichen
 *             %d = Ziffer
 *             %p = sonstiges druckbares Zeichen
 *             %% = Prozent
 * Rueckgabe: Anzahl Bytes
 */
extern size_t SML3_utf8_strcspn(const char *, const char *);


/** SML3_utf8_strcasecspn:
 * wie strcspn fuer UTF8, aber insensitive
 * 1.Arg: String
 * 2.Arg: Auswahl von UTF8-Zeichen
 *        oder %a = Buchstabe
 *             %A = Buchstabe
 *             %b = Leerzeichen
 *             %d = Ziffer
 *             %p = sonstiges druckbares Zeichen
 *             %% = Prozent
 * Rueckgabe: Anzahl Bytes
 */
extern size_t SML3_utf8_strcasecspn(const char *, const char *);


/** SML3_utf8_strstr:
 * wie strstr fuer UTF8 (unnoetig, da strstr() ausreicht)
 * 1.Arg: String
 * 2.Arg: zu suchender String
 * Rueckgabe: Pointer auf Start oder NULL = nicht gefunden
 */
extern char * SML3_utf8_strstr(const char *, const char *);


/** SML3_utf8_strcasestr:
 * wie strcspn fuer UTF8, aber insensitive
 * 1.Arg: String
 * 2.Arg: zu suchender String
 * Rueckgabe: Pointer auf Start oder NULL = nicht gefunden
 */
extern char * SML3_utf8_strcasestr(const char *, const char *);


/** SML3_utf8_strcmp:
 * wie strcmp fuer UTF8 (unnoetig, da strcmp() ausreicht)
 * 1.Arg: String
 * 2.Arg: zu vergleichender String
 * Rueckgabe: -1 = 1.Arg kleiner, 0 = gleich, 1 = 1.Arg groesser
 */
extern int SML3_utf8_strcmp(const char *, const char *);


/** SML3_utf8_strcasecmp:
 * wie strcasecmp fuer UTF8
 * 1.Arg: String
 * 2.Arg: zu vergleichender String
 * Rueckgabe: -1 = 1.Arg kleiner, 0 = gleich, 1 = 1.Arg groesser
 */
extern int SML3_utf8_strcasecmp(const char *, const char *);


/** SML3_utf8_strncmp:
 * wie strncmp fuer UTF8 (unnoetig, da strncmp() ausreicht)
 * 1.Arg: String
 * 2.Arg: zu vergleichender String
 * 3.Arg: maximale Anzahl UTF8-Zeichen
 * Rueckgabe: -1 = 1.Arg kleiner, 0 = gleich, 1 = 1.Arg groesser
 */
extern int SML3_utf8_strncmp(const char *, const char *, size_t);


/** SML3_utf8_strncasecmp:
 * wie strncasecmp fuer UTF8
 * 1.Arg: String
 * 2.Arg: zu vergleichender String
 * 3.Arg: maximale Anzahl UTF8-Zeichen
 * Rueckgabe: -1 = 1.Arg kleiner, 0 = gleich, 1 = 1.Arg groesser
 */
extern int SML3_utf8_strncasecmp(const char *, const char *, size_t);

#endif /* SML3__UTF8_H */
