// CSV.es.h  (C) 2008 adolfo@di-mare.com

#ifdef Spanish_dox
    /// Documentacin en espaol.
    #define Spanish_dox "Documentacin en espaol"
   /// \def Spanish_dox  ///< Marca bloques de documentacin en espaol.
#endif

/*  \file   CSV.es.h
    \brief  Documentacin en espaol para \c CSV.h.
    \author Adolfo Di Mare <adolfo@di-mare.com>
    \date   2008
*/

#ifdef Spanish_dox
/// \def CSV_h  ///< Evita la inclusin mltiple.
#endif

/** \file  CSV.h
    \brief \c getNextCSV() y \c setQuotedCSV(): Librera para procesar archivos CSV.

    CSV: (<em>Comma Separated Value</em>). El formato CSV ha sido definido
    por IETF with RFC-4180.
    - Si el archivo est grabado de acuerdo al format especificado
      en RFC-4180 sus campos CSV sern extrados correctamente por
      estas rutinas.
    - Trabaja con \c char; no ha sido probada con \c wchar_t.
    - Cuando el contenido del archivo no cumple con RFC-4180 estas
      rutinas no fallan pues retornan un valor "reazonable2. En
      estos casos el programador debe ser cuidadoso, y debe tratar
      de arreglar los valores CSV retornados aplicndoles \c trim()
      o \c trimCSV().
    - Se ha hecho un esfuerzo por cumpliro con RFC-4180:

    \see http://tools.ietf.org/html/rfc4180

    \par Se incluyen 2 rutines principales para procesar archivos CSV:
    - Para obtener valores use la funcin \c getNextCSV().
    - Para almacenar alores use la funcin \c void setQuotedCSV() y luego
      almacene la hilera resultante.

    La clase \c CSV_line es un empaque C++ para estas rutinas, pero
    requiere que no haya caracteres de fin de lnea ( <em>Line Feed</em>
    \c "\n" ) en los renglones del archivo CSV.

    \author Adolfo Di Mare <adolfo@di-mare.com>
    \date   2008
*/

#ifdef __cplusplus // compatibility C <==> C++

#include <string>
#include <iostream>
#include <vector>

// CSV: Comma Separated Values [IETF RFC-4180].
// namespace csv {

/** \fn    void setQuotedCSV( std::string& res , const std::string& value );
    \brief Prepara \c value para ser grabado en un archivo CSV.
    - Almacena un valor nuevo en la hilera \c res.
    - Rodea el resultado de comillas dobles cuando \c value tiene espacios en blanco (<em>whitespace</em>).
    - Rodea el resultado de comillas dobles cuando \c value tiene comillas dobles.
    - Rodea el resultado de comillas dobles cuando \c value tiene comas \c ",".
    - Sustitutye cada comilla doble \c '"' dentro de \c value por 2 comillas dobles \c [""].
    - Trabaja con \c char; no ha sido probada con \c wchar_t.

    \dontinclude test_CSV.cpp
    \skipline    test::setQuotedCSV()
    \until       }}
    \see         test_CSV::setQuotedCSV()
*/

/** \fn    bool getNextCSV( std::string& csv, std::istream& CIN );
    \brief Obtiene del flujo de entrada \c CIN el siguiente valor CSV.
    - \c CIN debiera estar abierto en modo \c std::ios::binary pues los
      caracteres son extrados uno por uno, usando \c CIN.get(ch).
    - El valor obtenido de \c CIN queda almacenado en \c csv.
    - Trabaja bien con \c char, no ha sido probado para \c wchar_t.
    - Elimina de \c csv los caracteres finales (CR+LF or LF)
      ==> \c "\r\n" o \c "\n".
    - En lo posible se ha tratado de cumplir con el RFC-4180.

    \return true cuando el campo CSV termina en \c "\n" (LF -> <em>LineFeed</em>).

    \see http://tools.ietf.org/html/rfc4180
    \see http://www.horstmann.com/cpp/pitfalls.html

    \dontinclude CSV_line.cpp
    \skipline    test::getNextCSV()
    \until       }}
    \see         test_CSV::getNextCSV()
*/

/** \fn    void trim( std::string & str );
    \brief Le elimina a \c "str" los blancos del principio y del final.
    - Tambin elimina los caracteres <code>" \f\n\r\t\v"</code>.
    - Usa \c isspace(ch) para determinar si una letra es o no es
      algn tipo de espacio <em>whitespace</em>.

    \dontinclude test_CSV.cpp
    \skipline    test::trim()
    \until       }}
    \see         test_CSV::test_trim()
*/

/** \fn    void trimCSV( std::string & str );
    \brief Convierte un campo CSV incorrecto en su probable valor correcto.
    - Le elimina a \c "str" los blancos y comillas del principio y del final
      usando \c trim().
    - Si despus de eliminar los espacios en blanco \c "str" comienza y
      termina con comillas, sustituye cada pareja de comillas dobles \c [""]
      por una sla comilla simple \c ["].
    - No verifica que todas las comillas dobles estn correctamente emparejadas.

    En algunas ocasiones un archivo.csv tiene campos entre comillas que
    estn precedidos por espacios en blanco. Esos campos CSV no cumplen con
    los requisitos definidos en la especificacin RFC-4180 por lo que son
    extrados por \c getNextCSV() tal cual vienen, sin eliminar los espacios
    y sin sustituir las parejas de  comillas dobles por comillas simples, como
    se muestra en el siguiente ejemplo en que los parntesis cuadrados se usan
    en lugar de la comilla \c ["] para hacerlo ms legible:

    \code
        ["zero",  "if "" 1" , , " 3xt"  \r\n]
        [....0.,........ 1..,2,.........3...]

         csv field        getNextCSV()    trimCSV()
    +------------------+----------------+----------+
    | ["zero"]         | [zero]         | [zero]   |
    | [,  "if "" 1" ]  | [  "if "" 1" ] | [if " 1] |
    | [, ]             | [ ]            | []       |
    | [, " 3xt"  \r\n] | [ " 3xt"  ]    | [ 3xt]   |
    +------------------+----------------+----------+
    \endcode

    Por sentido comn el programador esperara que todas estas hileras
    fueran reconocidas, pero de acuerdo al RFC-4180 nicamente la primera
    es correcta. Al usar \c trimCSV() en el valor obtenido al procesar
    esta lnea, se obtiene a fin de cuentas el valor esperado.
    - Sin embargo, los campos que contienen cambios de lnea \c "\r"
      o fines de lnea \c "\n" seguramente son procesados de una manera
      diferente a lo esperado por \c getNextCSV(), an antes de ser
      recibidos como argumentos de \c trimCSV(), por lo que es mejor no
      confiar en que esta rutina es una solucin completa cuando se usan
      archivos.csv que no estn escritos con apego estricto a la
      especificacin RFC-4180.

    \dontinclude test_CSV.cpp
    \skipline    test::trimCSV()
    \until       }}
    \see         test_CSV::test_trimCSV()
*/

/** \fn    void chop( std::string & str , char ch=0 );
    \brief Elimina \c ch si es el ltimo caracter de \c str.
    - El caracter eliminado siempre es \c ch.

    \dontinclude test_CSV.cpp
    \skipline    test::chop()
    \until       }}
    \see         test_CSV::test_chop()
*/

// }; // namespace csv

/// Definido por la biblioteca estndar C++
namespace std { } // truco para que Doxygen lo documente

#endif // __cplusplus

#include <stdlib.h> // NULL, etc. [C language]

#ifdef __cplusplus
extern "C" {
#endif


/*  Obtiene del flujo de caracteres \c getChar() el siguiente valor CSV.
    - En cada invocacin a \c getChar() un solo caracter es obtenido.
    - Si no hay ms caracteres, \c getChar() debe retornar \c -1.
*/

/** Retrieves from the input character stream \c getChar() then next CSV value.
    - On each invocation to \c getChar() a single character is retrieved.
    - When nor more caracteres are available \c getChar() must retorn \c -1.
    - Stores the CSV value read into memory buffer \c res.
    - Buffer \c res can hold up to \c res_size char's.
    - If the value read is bigger than what \c res can hold only  as many
      char's as will fit into \c res are retrieved; in this case, the full
      value will not be read.
    - If the full CSV value can be stored into \c res returns \c 1, otherwise
      signals failure returning \c 0.
    - The number of characters retrieved from \c getChar() always is
      \c strlen(res).
*/
int getNextCSV( char* res , size_t res_size , int (getChar)( void* context) );

/** Prepares \c line for output into a CSV file.
    - Stores the resulting string in memory buffer \c res.
    - Buffer \c res can hold up to \c res_size char's.
    - \c NULL is returned whenever more than \c res_size char's are required.
    - Otherwise, returns \c res.

    - Surrounds the result in double-quotes when \c line has whitespace.
    - Surrounds the result in double-quotes when \c line has double-quotes.
    - Surrounds the result in double-quotes when \c line has commas ','.
    - Substitutes any double-quotes '"' within \c line with 2 double-quotes [""].
*/
char* putCSV( char* res , size_t res_size , const char * line );

/** Retorna la mayor subhilera de \c "str" que no tiene blancos al principio o al final.
    - Modifica la hilera \c "str" y retorna un puntero dentro de ella.
    - Si \c "str" tiene blancos al final, los elimina insertndole un \c char(0).
    - Tambin elimina los caracteres <code>" \f\n\r\t\v"</code>.
    - Usa \c isspace(ch) para determinar si una letra es o no es algn tipo de espacio
      <em>whitespace</em>.

    \dontinclude test_CSV.cpp
    \skipline    test::trim_C()
    \until       }}
    \see         test_CSV::test_trim_C()
*/
char * trim( char * str );

/** Elimina \c ch si es el ltimo caracter de \c str.
    - El caracter eliminado siempre es \c ch.

    \dontinclude test_CSV.cpp
    \skipline    test::chop_C()
    \until       }}
    \see         test_CSV::test_chop_C()
*/
void chop( char * str , char ch );

#ifdef __cplusplus
}
#endif

// EOF: CSV.es.h
