/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 
/* vim: set ts=2 et sw=2 tw=80: */
#if !defined(NET_FOSSIL_SCM_FSL_INTERNAL_H_INCLUDED)
#define NET_FOSSIL_SCM_FSL_INTERNAL_H_INCLUDED
/*
** Copyright (c) 2013 D. Richard Hipp
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the Simplified BSD License (also
** known as the "2-Clause License" or "FreeBSD License".)
**
** This program 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.
**
** Author contact information:
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*******************************************************************************
** This file declares library-level internal APIs which are shared
** across the library.
*/

#include <stdio.h> /* FILE type */
#include <sqlite3.h> /* include this here, instead of each impl file,
                        to simplify porting if we move to v4 */

#include "fossil/fossil2.h"

#if defined(__cplusplus)
extern "C" {
#endif

  
  /*
  ** The main Fossil "context" type. This is the first argument to
  ** most Fossil v2 API routines.
  **
  ** This type will likely eventually be made opaque to client code -
  ** do not depend on any of its members/contents. Having it
  ** non-opaque also has advantages, though. We'll see. Binary
  ** compatibility concerns might force us to make it opaque.  But for
  ** now having it public simplifies testing and debugging.
  **
  ** An instance's lifetime looks like:
  **
  ** @code
  ** int rc;
  ** fsl_ctx * f = NULL;
  ** rc = fsl_init( &f, NULL );
  ** assert(!rc);
  ** rc = fsl_repo_open_db( f, "myrepo.fsl" );
  ** ...
  ** fsl_finalize(f);
  ** @endcode
  */
  struct fsl_ctx {
    /*
    ** Current repository db.
    */
    fsl_db dbRepo;
    /*
    ** Output channel used by fsl_output() and friends.
    */
    fsl_outputer output;
    /*
    ** Can be used to tie client-specific data to the context. Its
    ** finalizer is called when fsl_finalize() cleans up.
    */
    fsl_state clientState;
    /*
    ** Holds error state. As a general rule, this information is
    ** updated only by routines which need to return more info than a
    ** simple integer error string. This is primarily db-related
    ** routines, where we add the db-driver-provided error state
    ** here. It is not used by "simple" routines for which an integer
    ** code always suffices.  APIs which set this should denote it
    ** with a comment like "sets the context's error state on error."
    */
    fsl_error error;
    /*
    ** Optimization: reusable scratchpad for creating strings.
    */
    fsl_buffer scratch;

    /*
    ** Not yet used. Needed?
    **
    ** The directory part of an opened repository db.
    */
    fsl_buffer repoDir;

    struct {
      char traceSql;
      char printSql;
    } debug;
    
    /* no state related to server/user/etc. That is higher-level stuff. */
  };

  /** Initialized-with-defaults fsl_ctx instance. */
#define fsl_ctx_empty_m { fsl_db_empty_m /*dbRepo*/,    \
      fsl_outputer_FILE_m /*output*/,              \
      fsl_state_empty_m /*clientState*/,            \
      fsl_error_empty_m /*error*/,                  \
      fsl_buffer_empty_m /*scratch*/,               \
      fsl_buffer_empty_m /*repoDir*/,               \
      {/*debug*/                                    \
        0/*traceSql*/,                              \
        0/*printSql*/ \
      }                                         \
      }

  /** Initialized-with-defaults fsl_ctx instance. */
  extern const fsl_ctx fsl_ctx_empty;

  
  /*
  ** Quivalent to fopen(3) but expects name to be UTF8-encoded.
  */
  FILE * fsl_fopen(char const * name, char const *mode);

  /*
  ** Closes the given db handle. Returns 0 on success. Note that db itself
  ** is not freed - it is assumed to either be on the stack or part of
  ** a larger struct.
  */
  int fsl_db_close( fsl_db * db );

  /*
  ** Opens the given db file and populates db with its handle.
  ** db must have been cleanly initialized by copy-constructing it from
  ** fsl_db_empty. Failure to do so will lead to undefined behaviour.
  **
  ** Returns FSL_RC_MISUSE if !db, !repoDbFile, !*repoDbFile, or
  ** if db->dbh is not NULL.
  **
  ** ACHTUNG: it is up to the caller to set db->f. That is currently
  ** used by some error reporting code.
  **
  ** On error db->dbh will not be set, but db->dbh.error might contain
  ** error details. Regardless of success or failure, db should be
  ** passed to fsl_db_close() to free up all memory associated with it.
  **
  ** openFlags is not yet used. Just pass 0.
  */
  int fsl_db_open( fsl_db * db, char const * repoDbFile, int openFlags );

  
#ifdef _WIN32
  /*
  ** Translate MBCS to UTF-8.  Return a pointer to the translated
  ** text.  ACHTUNG: Call fsl_mbcs_free() (not fsl_free()) to
  ** deallocate any memory used to store the returned pointer when
  ** done.
  */
  char * fsl_mbcs_to_utf8(char const * mbcs);

  /*
  ** Frees a string allocated from fsl_mbcs_to_utf8(). Results are undefined
  ** if mbcs was allocated using any other mechanism.
  */
  void fsl_mbcs_free(char * mbcs);
#endif
  /* _WIN32 */

  /*
  ** Translate Unicode text into UTF-8.
  ** Return a pointer to the translated text.
  ** Call fsl_unicode_free() to deallocate any memory used to store the
  ** returned pointer when done.
  **
  ** This function exists only for Windows. On other platforms it
  ** behaves like fsl_strdup().
  */
  char *fsl_unicode_to_utf8(const void *zUnicode);

  /*
  ** Translate UTF-8 to unicode for use in system calls.  Return a
  ** pointer to the translated text. The returned value must
  ** eventually be passed to fsl_free() to deallocate any memory used
  ** to store the returned pointer when done.
  **
  ** This function exists only for Windows. On other platforms
  ** it behaves like fsl_strdup().
  ** 
  */
  void *fsl_utf8_to_unicode(const char *zUtf8);

  /*
  ** Translate text from the filename character set into UTF-8.
  ** Return a pointer to the translated text.  Call
  ** fsl_filename_free() to deallocate any memory used to store the
  ** returned pointer when done.
  **
  ** This function must not convert '\' to '/' on windows/cygwin, as it is
  ** used in places where we are not sure it's really filenames we are handling,
  ** e.g. fsl_getenv() or handling the argv arguments from main().
  **
  ** On Windows, translate some characters in the in the range
  ** U+F001 - U+F07F (private use area) to ASCII. Cygwin sometimes
  ** generates such filenames. See:
  ** <http://cygwin.com/cygwin-ug-net/using-specialnames.html>
  */
  char *fsl_filename_to_utf8(const void *zFilename);

  /*
  ** Translate text from UTF-8 to the filename character set.
  ** Return a pointer to the translated text.
  ** Call fossil_filename_free() to deallocate any memory used to store the
  ** returned pointer when done.
  **
  ** On Windows, characters in the range U+0001 to U+0031 and the
  ** characters '"', '*', ':', '<', '>', '?' and '|' are invalid
  ** to be used. Therefore, translate those to characters in the
  ** in the range U+F001 - U+F07F (private use area), so those
  ** characters never arrive in any Windows API. The filenames might
  ** look strange in Windows explorer, but in the cygwin shell
  ** everything looks as expected.
  **
  ** See: <http://cygwin.com/cygwin-ug-net/using-specialnames.html>
  **
  */
  void *fsl_utf8_to_filename(const char *zUtf8);

  
  /*
  ** Deallocate pOld, which must have been allocated by
  ** fsl_filename_to_utf8() or fsl_utf8_to_filename().
  */
  void fsl_filename_free(void *pOld);

  /*
  ** Returns true (non-0) if ch is-a alpha character.
  */
  char fsl_isalpha(int ch);

#if defined(__cplusplus)
} /*extern "C"*/
#endif
#endif
/* NET_FOSSIL_SCM_FSL_INTERNAL_H_INCLUDED */
