//==================================================================================================
// S t a n d a r d                                                                        Interface
// S t r e a m
//                                                                                By Bruno Bachelet
//==================================================================================================
// Copyright (c) 1999-2016
// Bruno Bachelet - bruno@nawouak.net - http://www.nawouak.net
//
// This file is part of the B++ Library. This library is free software; you can redistribute it
// and/or modify it under the terms of the GNU Library General Public License as published by the
// Free Software Foundation; either version 2 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 Library General Public License for more details (http://www.gnu.org).

/*DESCRIPTION*/
/* This module provides facilities to manage streams, files and folders. */

// File Name //-------------------------------------------------------------------------------------
#line __LINE__ "standard/stream.hpp"

// Guardian //--------------------------------------------------------------------------------------
#ifndef guStandardStream
#define guStandardStream

// Headers //---------------------------------------------------------------------------------------
#include <bpp/dependency.hpp> /*INCLUDE*/

#ifdef DIR_HEADER_1
#include DIR_HEADER_1 /*INCLUDE*/
#endif

#ifdef DIR_HEADER_2
#include DIR_HEADER_2 /*INCLUDE*/
#endif

#ifndef NEED_FOLDER_MANAGEMENT
 #include <dirent.h> /*INCLUDE*/
#endif

#include <bpp/standard/error.hpp> /*INCLUDE*/
#include <contribution/string.hpp> /*INCLUDE*/

// Portability //-----------------------------------------------------------------------------------
#ifdef MKDIR_COMMAND
inline int mkdir(const char * agPath) {
 char * lcCommand;
 int    lcReturn;

 lcCommand = new char [bpp::low::string::length(agPath)+bpp::low::string::length(MKDIR_COMMAND)+2];
 bpp::low::string::copy(lcCommand,MKDIR_COMMAND);
 bpp::low::string::concatenate(lcCommand," ");
 bpp::low::string::concatenate(lcCommand,agPath);
 lcReturn=system(lcCommand);
 return (lcReturn);
}
#endif

#ifdef RMDIR_COMMAND
inline int rmdir(const char * agPath) {
 char * lcCommand;
 int    lcReturn;

 lcCommand=new char [bpp::low::string::length(agPath)+bpp::low::string::length(RMDIR_COMMAND)+2];
 bpp::low::string::copy(lcCommand,RMDIR_COMMAND);
 bpp::low::string::concatenate(lcCommand," ");
 bpp::low::string::concatenate(lcCommand,agPath);
 lcReturn=system(lcCommand);
 delete [] lcCommand;
 return (lcReturn);
}
#endif

#ifdef MKDIR_CALL
inline int mkdir(const char * agPath) { return (MKDIR_CALL(agPath)); }
#endif

#ifdef RMDIR_CALL
inline int rmdir(const char * agPath) { return (RMDIR_CALL(agPath)); }
#endif

namespace bpp {

// Importation/Exportation //-----------------------------------------------------------------------
#ifdef STANDARD_DLL
 #define dll_export DLL_EXPORT
#else
 #define dll_export DLL_IMPORT
#endif

// Namespaces //------------------------------------------------------------------------------------
#define public_area  standardStream
#define private_area standardStream_private

namespace public_area  {
 /*NAMESPACE*/ using namespace standardBasicString;
 /*NAMESPACE*/ using namespace standardError;
}

namespace private_area { using namespace public_area; }

extern_module_name;

// Initialization //--------------------------------------------------------------------------------
#define iniStandardStream
has_initializer;

// Macrocommands //---------------------------------------------------------------------------------

// Types & Classes //-------------------------------------------------------------------------------
namespace public_area  {
 //------------------------------------------------------------------------------------------Classes
 class clFolderProcessing;
 //-----------------------------------------------------------------------------------Variable Types
 /*TYPE*/ /* Input file. */
 typedef std::ifstream clInFile;

 /*TYPE*/ /* Output file. */
 typedef std::ofstream clOutFile;

 /*TYPE*/ /* Input stream. */
 typedef std::istream clInStream;

 /*TYPE*/ /* Output stream. */
 typedef std::ostream clOutStream;

 /*TYPE*/ /* Input and output stream. */
 typedef std::iostream clStream;

 /*TYPE*/ /* List of file names. */
 typedef std_vector(clString) clFileNameS;

 #ifndef NEED_FOLDER_MANAGEMENT
  /*TYPE*/ /* Represents a folder (in the case that the <CODE>DIR</CODE> structure exists). */
  typedef DIR * tyFolder;
 #endif

 /*TYPE*/ /* Opening mode of a file. */
 typedef FILE_OPENING_MODE_TYPE tyFileMode;

 /*TYPE*/ /* Relative position in a stream. */
 typedef std::streamoff tyStreamOffset;

 /*TYPE*/ /* Absolute position in a stream. */
 typedef std::streampos tyStreamPosition;

 /*TYPE*/ /* Size in a stream. */
 typedef std::streamsize tyStreamSize;

 /*TYPE*/ /* Symbolic constants for the kinds of entity in a folder. */
 enumeration { unknownEntity, fileEntity, folderEntity, referenceEntity } tyDiskEntityKind;
 //-----------------------------------------------------------------------------------Constant Types
 typedef const clFolderProcessing ctFolderProcessing;

 typedef const clInFile    ctInFile;
 typedef const clOutFile   ctOutFile;
 typedef const clInStream  ctInStream;
 typedef const clOutStream ctOutStream;
 typedef const clStream    ctStream;
 typedef const clFileNameS ctFileNameS;

 typedef const tyFolder ctFolder;

 typedef const tyFileMode       tcFileMode;
 typedef const tyStreamOffset   tcStreamOffset;
 typedef const tyStreamPosition tcStreamPosition;

 typedef const tyDiskEntityKind tcDiskEntityKind;
}

namespace private_area {
 class clFolderProcessingCopy;
 class clFolderProcessingDelete;
 class clFolderProcessingGetFileList;
 class clFolderProcessingList;

 typedef const clFolderProcessingList ctFolderProcessingCopy;
 typedef const clFolderProcessingList ctFolderProcessingDelete;
 typedef const clFolderProcessingList ctFolderProcessingList;

 typedef std_map(tyPointer,clString *) clPrimaryFileRegister;
 typedef std_vector(clString *)        clSecondaryFileRegister;
}

// Functions Interface //---------------------------------------------------------------------------
namespace public_area {
 inline tyBoolean isFileNameSeparator(tyCharacter);
 inline tyBoolean isFileNameSeparator(tcString);

 inline void close(clInFile &);
 inline void close(clOutFile &);
 inline void open(clInFile &,tcString,tyFileMode);
 inline void open(clOutFile &,tcString,tyFileMode);

 function void buildFileName(clString &);
 function void buildFolderName(clString &);
 function void buildFullName(clString &,ctString &,ctString &);
 function void extractShortName(clString &,clString &,ctString &);
 function void separateFileName(clString &,clString &,ctString &);

 function void copy(clOutStream &,clInStream &,tyBoolean);

 function tyBoolean fileExists(tcString);
 function tyInteger fileSize(tcString);
 function tyBoolean folderExists(tcString);
 function tyInteger size(clInFile &);

 function void changeName(tcString,tcString);
 function void createFolder(tcString);
 function void copyFile(tcString,tcString);
 function void copyFolder(tcString,tcString);
 function void removeFile(tcString);
 function void removeFolder(tcString);

 function void     close(tyFolder &);
 function tcString nextEntity(tyFolder &);
 function void     open(tyFolder &,tcString);

 inline void getFileList(tcString,tcString,clFileNameS &,tyBoolean = true);

 inline void listFolder(clOutStream &,tcString,tcString = nil,tyBoolean = true,tyBoolean = true,
                        tcString = "");

 function void scanFolder(tcString,clFolderProcessing &,tyBoolean = true);

 function tyDiskEntityKind diskEntityKind(tcString);
 function tcString         diskEntityKindString(tyDiskEntityKind);

 function void outFileRegister(clOutStream &);
}

namespace private_area {
 function tyString   copy(ctString &);
 function void       registerFile(clInFile &,tcString);
 function void       registerFile(clOutFile &,tcString);
 function tyCardinal removeCarriageReturn(tyString,tyCardinal);
 function void       unregisterFile(clInFile &);
 function void       unregisterFile(clOutFile &);

 testing_mode ( function void test(void); )
}

// Errors //----------------------------------------------------------------------------------------
namespace public_area {
 /*ERROR*/ extern_error erEntityIdentification; /* Can not identify an entity in the folder. */
 /*ERROR*/ extern_error erFileNotRegistered; /* The file is not registered. */
 /*ERROR*/ extern_error erFileOpening; /* Can not open the file. */
 /*ERROR*/ extern_error erFileReading; /* Can not read from the file. */
 /*ERROR*/ extern_error erFileWriting; /* Can not write into the file. */
 /*ERROR*/ extern_error erStreamReading; /* Can not read from the stream. */
 /*ERROR*/ extern_error erStreamWriting; /* Can not write into the stream. */
 /*ERROR*/ extern_error erFindFileSize; /* Can not find the file's size. */
 /*ERROR*/ extern_error erFileAlreadyExists; /* The file already exists. */
 /*ERROR*/ extern_error erFileFolderRenaming; /* Can not rename the file or the folder. */
 /*ERROR*/ extern_error erFileRemoving; /* Can not remove the file. */
 /*ERROR*/ extern_error erFolderClosing; /* Can not close the folder. */
 /*ERROR*/ extern_error erFolderCreation; /* Can not create the folder. */
 /*ERROR*/ extern_error erFolderOpening; /* Can not open the folder. */
 /*ERROR*/ extern_error erFolderRemoving; /* Can not remove the folder. */
}

// Constants & Variables //-------------------------------------------------------------------------
/*CONSTANT*/ /* Symbol that separates file names in a path. */
extern_static_constant(public,tcString,goFileNameSeparator,fileNameSeparator);

/*CONSTANT*/ /* Symbol that separates paths in an environment variable. */
extern_static_constant(public,tcString,goPathSeparator,pathSeparator);

/*CONSTANT*/ /* Size of the buffer for stream readings and writings. */
extern_static_constant(public,tyCardinal,goStreamBufferSize,streamBufferSize);

/*CONSTANT*/ /* Maximum possible length of a string representing a path. */
extern_static_constant(public,tyCardinal,goMaximumPathLength,maximumPathLength);

extern_static_constant(private,tcString,goFileRegisterFileName,?);
extern_dynamic_constant(private,clPrimaryFileRegister,goPrimaryFileRegister,?);
extern_dynamic_constant(private,clSecondaryFileRegister,goSecondaryFileRegister,?);
extern_dynamic_constant(private,clString,goDataLocation,?);
extern_static_constant(private,clMutex,goMutex,?);

// F o l d e r P r o c e s s i n g  Interface //----------------------------------------------------
namespace public_area {
 /*CLASS clFolderProcessing */
 /* Used by <CODE>scanFolder</CODE> to perform a process upon the entities found during the
    scanning of a folder. It is an abstract class. The methods of this class
    must be implemented. */
 class clFolderProcessing {
  //-----------------------------------------------------------------------------------------Private
  private_property constructor clFolderProcessing(const clFolderProcessing &);
  private_property clFolderProcessing & operator = (const clFolderProcessing &);
  //------------------------------------------------------------------------------------------Public
  public_property constructor clFolderProcessing(void);
  public_property virtual destructor clFolderProcessing(void);

  /*AMETHOD clFolderProcessing */
  /* Is called when a folder is open. Abstract method. */
  public_property virtual void startFolder(ctString &) = 0;

  /*AMETHOD clFolderProcessing */
  /* Is called when a folder is closed. Abstract method. */
  public_property virtual void endFolder(ctString &) = 0;

  /*AMETHOD clFolderProcessing */
  /* Is called when a file is found. Abstract method. */
  public_property virtual void file(ctString &) = 0;

  /*AMETHOD clFolderProcessing */
  /* Is called when an unknown entity is found. Abstract method. */
  public_property virtual void unknown(ctString &) = 0;
 };
}

// F o l d e r P r o c e s s i n g C o p y  Interface //--------------------------------------------
namespace private_area {
 class clFolderProcessingCopy : public clFolderProcessing {
  //-----------------------------------------------------------------------------------------Friends
  friend class private_area::clInitializer;
  //-----------------------------------------------------------------------------------------Private
  private_property clString atTargetPath;

  private_property constructor clFolderProcessingCopy(const clFolderProcessingCopy &);
  private_property clFolderProcessingCopy & operator = (const clFolderProcessingCopy &);
  //------------------------------------------------------------------------------------------Public
  public_property constructor clFolderProcessingCopy(tcString);
  public_property virtual destructor clFolderProcessingCopy(void);

  public_property void startFolder(ctString &);
  public_property void endFolder(ctString &);
  public_property void file(ctString &);
  public_property void unknown(ctString &);
 };
}

// F o l d e r P r o c e s s i n g D e l e t e  Interface //----------------------------------------
namespace private_area {
 class clFolderProcessingDelete : public clFolderProcessing {
  //-----------------------------------------------------------------------------------------Friends
  friend class private_area::clInitializer;
  //-----------------------------------------------------------------------------------------Private
  private_property constructor clFolderProcessingDelete(const clFolderProcessingDelete &);
  private_property clFolderProcessingDelete & operator = (const clFolderProcessingDelete &);
  //------------------------------------------------------------------------------------------Public
  public_property constructor clFolderProcessingDelete(void);
  public_property virtual destructor clFolderProcessingDelete(void);

  public_property void startFolder(ctString &);
  public_property void endFolder(ctString &);
  public_property void file(ctString &);
  public_property void unknown(ctString &);
 };
}

// F o l d e r P r o c e s s i n g G e t F i l e L i s t  Interface //------------------------------
namespace private_area {
 class clFolderProcessingGetFileList : public clFolderProcessing {
  //-----------------------------------------------------------------------------------------Friends
  friend class private_area::clInitializer;
  //-----------------------------------------------------------------------------------------Private
  private_property tyString      atFormat;
  private_property tyBoolean     atCaseSensitive;
  private_property clFileNameS & atFileNameS;

  private_property
  constructor clFolderProcessingGetFileList(const clFolderProcessingGetFileList &);

  private_property
  clFolderProcessingGetFileList & operator = (const clFolderProcessingGetFileList &);
  //------------------------------------------------------------------------------------------Public
  public_property constructor clFolderProcessingGetFileList(tcString,clFileNameS &,
                                                            tyBoolean = true);

  public_property virtual destructor clFolderProcessingGetFileList(void);

  public_property void startFolder(ctString &);
  public_property void endFolder(ctString &);
  public_property void file(ctString &);
  public_property void unknown(ctString &);
 };
}

// F o l d e r P r o c e s s i n g L i s t  Interface //--------------------------------------------
namespace private_area {
 class clFolderProcessingList : public clFolderProcessing {
  //-----------------------------------------------------------------------------------------Friends
  friend class private_area::clInitializer;
  //-----------------------------------------------------------------------------------------Private
  private_property tyString      atFormat;
  private_property clOutStream & atStream;
  private_property tyBoolean     atCaseSensitive;
  private_property clString      atBlankSpace;

  private_property constructor clFolderProcessingList(const clFolderProcessingList &);
  private_property clFolderProcessingList & operator = (const clFolderProcessingList &);
  //------------------------------------------------------------------------------------------Public
  public_property constructor clFolderProcessingList(clOutStream &,tcString = nil,
                                                     tyBoolean = true,tcString = "");

  public_property virtual destructor clFolderProcessingList(void);

  public_property void startFolder(ctString &);
  public_property void endFolder(ctString &);
  public_property void file(ctString &);
  public_property void unknown(ctString &);
 };
}

// Functions Inline //------------------------------------------------------------------------------
namespace public_area  {
 //------------------------------------------------------------------------------IsFileNameSeparator
 /*FUNCTION*/ /* Checks if a character is a separator for file names. */
 inline tyBoolean isFileNameSeparator(tyCharacter agCharacter) {
  return (agCharacter=='\\' or agCharacter=='/' or agCharacter==fileNameSeparator()[0]);
 }
 //------------------------------------------------------------------------------IsFileNameSeparator
 /*FUNCTION*/ /* Checks if a string is a separator for file names. */
 inline tyBoolean isFileNameSeparator(tcString agString) {
  return (compare(agString,"\\")==0
          or compare(agString,"/")==0
          or compare(agString,fileNameSeparator())==0);
 }
 //--------------------------------------------------------------------------------------------Close
 /*FUNCTION*/ /* Closes an input file. */
 inline void close(clInFile & agFile) {
  private_area::unregisterFile(agFile);
  agFile.close();
 }
 //--------------------------------------------------------------------------------------------Close
 /*FUNCTION*/ /* Closes an output file. */
 inline void close(clOutFile & agFile) {
  private_area::unregisterFile(agFile);
  agFile.close();
 }
 //---------------------------------------------------------------------------------------------Open
 /*FUNCTION*/ /* Opens an input file in a given mode. */
 inline void open(clInFile & agFile,tcString agFileName,tyFileMode agMode) {
  agFile.clear();
  agFile.open(agFileName,agMode);
  if (not agFile.rdbuf()->is_open()) send_inline_error(erFileOpening,"open");
  private_area::registerFile(agFile,agFileName);
 }
 //---------------------------------------------------------------------------------------------Open
 /*FUNCTION*/ /* Opens an output file in a given mode. */
 inline void open(clOutFile & agFile,tcString agFileName,tyFileMode agMode) {
  agFile.clear();
  agFile.open(agFileName,agMode);
  if (not agFile.rdbuf()->is_open()) send_inline_error(erFileOpening,"open");
  private_area::registerFile(agFile,agFileName);
 }
 //--------------------------------------------------------------------------------------GetFileList
 /*FUNCTION*/
 /* Stores the files of a folder into a list. The scanning is not recursive. The matching can be
    case sensitive. */
 inline void getFileList(tcString agFolderName,tcString agFormat,clFileNameS & agFileNameS,
                         tyBoolean agCaseSensitive) {
  private_area::clFolderProcessingGetFileList lcProcessing(agFormat,agFileNameS,agCaseSensitive);

  scanFolder(agFolderName,lcProcessing,false);
 }
 //---------------------------------------------------------------------------------------ListFolder
 /*FUNCTION*/
 /* Lists the content of a folder into a stream. The scanning can be recursive. Only the files
    matching a given format are listed. The matching can be case sensitive. */
 inline void listFolder(clOutStream & agStream,tcString agFolder,tcString agFormat,
                        tyBoolean agRecursive,tyBoolean agCaseSensitive,tcString agBlankSpace)
 {
  private_area::clFolderProcessingList
  lcProcessing(agStream,agFormat,agCaseSensitive,agBlankSpace);

  scanFolder(agFolder,lcProcessing,agRecursive);
 }
}

namespace private_area {}

// F o l d e r P r o c e s s i n g  Inline //-------------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clFolderProcessing */ /* Builds a default processing. */
 inline clFolderProcessing::clFolderProcessing(void) {}
}

// F o l d e r P r o c e s s i n g C o p y  Inline //-----------------------------------------------
namespace private_area {
 //--------------------------------------------------------------------------------------Constructor
 inline clFolderProcessingCopy::clFolderProcessingCopy(tcString atTargetFolder)
 : atTargetPath(atTargetFolder) {}
}

// F o l d e r P r o c e s s i n g D e l e t e  Inline //-------------------------------------------
namespace private_area {
 //--------------------------------------------------------------------------------------Constructor
 inline clFolderProcessingDelete::clFolderProcessingDelete(void) {}
 //--------------------------------------------------------------------------------------StartFolder
 inline void clFolderProcessingDelete::startFolder(ctString &) {}
 //----------------------------------------------------------------------------------------EndFolder
 inline void clFolderProcessingDelete::endFolder(ctString & agFullName) {
  if (rmdir(agFullName.data())!=0)
   send_inline_error(erFolderRemoving,"folderProcessingDelete::endFolder");
 }
 //---------------------------------------------------------------------------------------------File
 inline void clFolderProcessingDelete::file(ctString & agFullName)
 { removeFile(agFullName.data()); }
 //------------------------------------------------------------------------------------------Unknown
 inline void clFolderProcessingDelete::unknown(ctString &) {}
}

// End //-------------------------------------------------------------------------------------------
}
#undef dll_export
#undef public_area
#undef private_area
#endif
 
//==================================================================================================
// S t a n d a r d                                                                   Implementation
// S t r e a m
//                                                                                By Bruno Bachelet
//==================================================================================================
// Copyright (c) 1999-2016
// Bruno Bachelet - bruno@nawouak.net - http://www.nawouak.net
//
// This file is part of the B++ Library. This library is free software; you can redistribute it
// and/or modify it under the terms of the GNU Library General Public License as published by the
// Free Software Foundation; either version 2 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 Library General Public License for more details (http://www.gnu.org).

// File Name //-------------------------------------------------------------------------------------
#line __LINE__ "standard/stream.cpp"

// DLL Belonging //---------------------------------------------------------------------------------
#define STANDARD_DLL

// Headers //---------------------------------------------------------------------------------------
#include <cstdio> /*NEED*/
#include <set> /*NEED*/
#include <bpp/file_name.hpp> /*NEED*/
#include <bpp/standard/stream.hpp> /*INTERFACE*/

namespace bpp {

// Namespaces //------------------------------------------------------------------------------------
#define public_area  standardStream
#define private_area standardStream_private
#define dll_export   DLL_EXPORT

namespace public_area  {}
namespace private_area {}

static_module_name("Standard/Stream");

// Initialization //--------------------------------------------------------------------------------
#undef iniStandardStream
static_constant(private_area::clInitializer,goInitializer);

// Errors //----------------------------------------------------------------------------------------
namespace public_area {
 static_error erEntityIdentification;
 static_error erFileNotRegistered;
 static_error erFileOpening;
 static_error erFileReading;
 static_error erFileWriting;
 static_error erStreamReading;
 static_error erStreamWriting;
 static_error erFindFileSize;
 static_error erFileAlreadyExists;
 static_error erFileFolderRenaming;
 static_error erFileRemoving;
 static_error erFolderCreation;
 static_error erFolderRemoving;
 static_error erFolderOpening;
 static_error erFolderClosing;
}

// Constants & Variables //-------------------------------------------------------------------------
static_constant(tcString,goFileNameSeparator);
static_constant(tcString,goPathSeparator);
static_constant(tyCardinal,goStreamBufferSize);
static_constant(tyCardinal,goMaximumPathLength);

static_constant(tcString,goFileRegisterFileName);
dynamic_constant(clPrimaryFileRegister,goPrimaryFileRegister);
dynamic_constant(clSecondaryFileRegister,goSecondaryFileRegister);
dynamic_constant(clString,goDataLocation);
static_constant(clMutex,goMutex);

// Static Members //--------------------------------------------------------------------------------
namespace public_area  {}
namespace private_area {}

// Functions Implementation //----------------------------------------------------------------------
namespace public_area {
 //------------------------------------------------------------------------------------BuildFileName
 /*FUNCTION*/
 /* Makes a string a file name (removes the eventual file name separator at the end of the
    string). */
 function void buildFileName(clString & agName) {
  if (agName.size()>0 and isFileNameSeparator(agName[agName.size()-1]))
   agName=agName.part(0,agName.size()-1);
 }
 //----------------------------------------------------------------------------------BuildFolderName
 /*FUNCTION*/
 /* Makes a string a folder name (adds a file name separator at the end of the string if there is
    not already one). */
 function void buildFolderName(clString & agName) {
  if (agName.size()>0 and (not isFileNameSeparator(agName[agName.size()-1]))
      and agName[agName.size()-1]!=':')
   agName+=fileNameSeparator();
 }
 //------------------------------------------------------------------------------------BuildFullName
 /*FUNCTION*/ /* Builds a full file name from a path and a short file name. */
 function void buildFullName(clString & agFullName,ctString & agPath,ctString & agShortName) {
  clString lcString = agPath;

  buildFolderName(lcString);
  agFullName=lcString+agShortName;
 }
 //---------------------------------------------------------------------------------ExtractShortName
 /*FUNCTION*/ /* Extracts a short name and a path from a full file name. */
 function void extractShortName(clString & agPath,clString & agShortName,ctString & agFullName) {
  tyCardinal lcCounter;
  tyCardinal lcEnd;

  lcCounter=agFullName.size();

  if (lcCounter==0) {
   agPath="";
   agShortName="";
   return;
  }

  lcEnd=--lcCounter;

  while (lcCounter>0 and agFullName[lcCounter]!=':'
         and (not isFileNameSeparator(agFullName[lcCounter]))) lcCounter--;

  if (lcCounter==0) {
   agShortName=agFullName;
   agPath="";
  }
  else {
   if (lcCounter<lcEnd) agShortName=agFullName.part(lcCounter+1,lcEnd-lcCounter);
   else agShortName="";

   agPath=agFullName.part(0,lcCounter+1);
  }
 }
 //---------------------------------------------------------------------------------SeparateFileName
 /*FUNCTION*/ /* Separates a file name into a body string and an extension string. */
 function void separateFileName(clString & agBody,clString & agExtension,ctString & agName) {
  tyCardinal lcCounter;
  tyCardinal lcEnd;

  lcCounter=agName.size();

  if (lcCounter==0) {
   agBody="";
   agExtension="";
  }

  lcEnd=--lcCounter;

  while (lcCounter>0 and agName[lcCounter]!='.' and agName[lcCounter]!=':'
         and (not isFileNameSeparator(agName[lcCounter]))) lcCounter--;

  if (agName[lcCounter]=='.') {
   if (lcCounter<lcEnd) agExtension=agName.part(lcCounter+1,lcEnd-lcCounter);
   else agExtension="";

   if (lcCounter>=1) agBody=agName.part(0,lcCounter);
   else agBody="";
  }
  else {
   agExtension="";
   agBody=agName;
  }
 }
 //---------------------------------------------------------------------------------------------Copy
 /*FUNCTION*/
 /* Copies an input stream into an output stream until the input stream ends. The last argument
    indicates if the output stream is open in binary mode. */
 function void copy(clOutStream & agSout,clInStream & agSin,tyBoolean agBinary) {
  method_name("copy");

  tyString     lcBuffer;
  tyInteger    lcCounter;
  tyStreamSize lcLength;

  #ifdef CONSOLE
   tyCardinal lcSize;
  #endif

  tyStreamPosition lcStartPosition = agSin.tellg();

  agSin.seekg(0,ios::end);
  lcLength=tyStreamSize(agSin.tellg()-lcStartPosition);
  agSin.seekg(lcStartPosition);
  lcBuffer=new tyCharacter[streamBufferSize()];
  lcCounter=lcLength/streamBufferSize();

  while (lcCounter>0) {
   agSin.read(lcBuffer,streamBufferSize());

   #ifdef CONSOLE
    if (agBinary) agSout.write(lcBuffer,streamBufferSize());
    else {
     lcSize=private_area::removeCarriageReturn(lcBuffer,streamBufferSize());
     agSout.write(lcBuffer,lcSize);
    }
   #else
    agSout.write(lcBuffer,streamBufferSize());
   #endif

   --lcCounter;
   if (agSin.fail()) send_error(erStreamReading);
   if (agSout.fail()) send_error(erStreamWriting);
  }

  lcLength=lcLength%streamBufferSize();
  agSin.read(lcBuffer,lcLength);

  #ifdef CONSOLE
   if (agBinary) agSout.write(lcBuffer,lcLength);
   else {
    lcSize=private_area::removeCarriageReturn(lcBuffer,lcLength);
    agSout.write(lcBuffer,lcSize);
   }
  #else
   agSout.write(lcBuffer,lcLength);
  #endif

  delete [] lcBuffer;
  if (agSin.fail()) send_error(erStreamReading);
  if (agSout.fail()) send_error(erStreamWriting);
 }
 //---------------------------------------------------------------------------------------FileExists
 /*FUNCTION*/ /* Checks if a file exists. */
 function tyBoolean fileExists(tcString agName) {
  clInFile lcFile;

  if (folderExists(agName)) return (false);
  lcFile.open(agName,ios::in);

  if (not lcFile.fail()) {
   lcFile.close();
   return (true);
  }

  return (false);
 }
 //-----------------------------------------------------------------------------------------FileSize
 /*FUNCTION*/ /* Returns the size of a file. */
 function tyInteger fileSize(tcString agName) {
  method_name("fileSize");

  clInFile  lcFile;
  tyInteger lcSize;

  lcFile.open(agName,ios::in|ios::binary);
  lcSize=size(lcFile);
  lcFile.close();
  if (lcFile.fail()) send_error(erFileReading);
  return (lcSize);
 }
 //-------------------------------------------------------------------------------------FolderExists
 /*FUNCTION*/ /* Checks if a folder exists. */
 function tyBoolean folderExists(tcString agName) {
  #ifdef NEED_FOLDER_MANAGEMENT
   tyCharacter lcCurrentPath[MAXIMUM_PATH_LENGTH];

   getcwd(lcCurrentPath,256);

   if (chdir(agName)==0) {
    chdir(lcCurrentPath);
    return (true);
   }
   else return (false);
  #else
   tyFolder lcFolder;

   lcFolder=opendir(agName);

   if (lcFolder!=nil) {
    closedir(lcFolder);
    return (true);
   }

   return (false);
  #endif
 }
 //---------------------------------------------------------------------------------------------Size
 /*FUNCTION*/ /* Returns the size of an open file. */
 tyInteger size(clInFile & lcFile) {
  method_name("size");

  tyStreamSize     lcLength;
  tyStreamPosition lcStartPosition = lcFile.tellg();

  lcFile.seekg(0,ios::end);
  lcLength=tyStreamSize(lcFile.tellg()-lcStartPosition);
  lcFile.seekg(tyStreamOffset(lcStartPosition),ios::beg);
  if (lcFile.fail()) send_error(erFindFileSize);

  return (lcLength);
 }
 //---------------------------------------------------------------------------------------ChangeName
 /*FUNCTION*/ /* Changes the name of a file or a folder. */
 function void changeName(tcString agOldName,tcString agNewName) {
  method_name("changeName");

  if (std::rename(agOldName,agNewName)!=0) send_error(erFileFolderRenaming);
 }
 //-------------------------------------------------------------------------------------CreateFolder
 /*FUNCTION*/ /* Creates a new folder. */
 function void createFolder(tcString agName) {
  method_name("createFolder");

  if (mkdir(agName)!=0) send_error(erFolderCreation);
 }
 //---------------------------------------------------------------------------------------RemoveFile
 /*FUNCTION*/ /* Removes a file. */
 function void removeFile(tcString agName) {
  method_name("removeFile");

  if (std::remove(agName)!=0) send_error(erFileRemoving);
 }
 //-------------------------------------------------------------------------------------RemoveFolder
 /*FUNCTION*/ /* Removes a folder and its content. */
 function void removeFolder(tcString agFolderName) {
  private_area::clFolderProcessingDelete lcProcessing;

  lcProcessing.startFolder(clString(agFolderName));
  scanFolder(agFolderName,lcProcessing,true);
  lcProcessing.endFolder(clString(agFolderName));
 }
 //-----------------------------------------------------------------------------------------CopyFile
 /*FUNCTION*/ /* Copies the content of a file into another one. */
 function void copyFile(tcString agTargetName,tcString agSourceName) {
  method_name("copyFile");

  clInFile  lcSourceFile;
  clOutFile lcTargetFile;

  open(lcSourceFile,agSourceName,ios::in|ios::binary);
  if (lcSourceFile.fail()) send_error(erFileReading);
  if (fileExists(agTargetName)) send_error(erFileAlreadyExists);
  open(lcTargetFile,agTargetName,ios::out|ios::trunc|ios::binary);
  if (lcTargetFile.fail()) send_error(erFileWriting);
  copy(lcTargetFile,lcSourceFile,true);
  close(lcSourceFile);
  close(lcTargetFile);
 }
 //---------------------------------------------------------------------------------------CopyFolder
 /*FUNCTION*/ /* Copies the content of a folder into another one. */
 function void copyFolder(tcString agTargetName,tcString agFolderName) {
  private_area::clFolderProcessingCopy lcProcessing(agTargetName);

  lcProcessing.startFolder(clString(agFolderName));
  scanFolder(agFolderName,lcProcessing,true);
  lcProcessing.endFolder(clString(agFolderName));
 }
 //--------------------------------------------------------------------------------------------Close
 /*FUNCTION*/ /* Closes a folder. */
 function void close(tyFolder & agFolder) {
  method_name("close");

  if (closedir(agFolder)!=0) send_error(erFolderClosing);
 }
 //---------------------------------------------------------------------------------------NextEntity
 /*FUNCTION*/ /* Moves to the next entity of a folder. */
 function tcString nextEntity(tyFolder & agFolder) {
  struct dirent * lcEntity;

  lcEntity=readdir(agFolder);

  if (lcEntity==nil) return (tcString(nil));
  else return (lcEntity->d_name);
 }
 //---------------------------------------------------------------------------------------------Open
 /*FUNCTION*/ /* Opens a folder. */
 function void open(tyFolder & agFolder,tcString agName) {
  method_name("open");

  if (not folderExists(agName)) send_error(erFolderOpening);
  agFolder=opendir(agName);
  if (agFolder==nil) send_error(erFolderOpening);
 }
 //-----------------------------------------------------------------------------------DiskEntityKind
 /*FUNCTION*/ /* Returns the kind of the entity. */
 function tyDiskEntityKind diskEntityKind(tcString agName) {
  tcString lcEnd1;
  tcString lcEnd2;

  if (standardBasicString::size(agName)>=2) lcEnd1=agName+standardBasicString::size(agName)-2;
  else lcEnd1="";

  if (standardBasicString::size(agName)>=3) lcEnd2=agName+standardBasicString::size(agName)-3;
  else lcEnd2="";

  if (agName==clString(".") or agName==clString("..")
      or lcEnd1==(clString(fileNameSeparator())+".")
      or lcEnd2==(clString(fileNameSeparator())+"..")) return (referenceEntity);

  if (folderExists(agName)) return (folderEntity);
  if (fileExists(agName)) return (fileEntity);

  return (unknownEntity);
 }
 //-----------------------------------------------------------------------------DiskEntityKindString
 /*FUNCTION*/ /* Converts an entity kind into a string. */
 function tcString diskEntityKindString(tyDiskEntityKind agKind) {
  if (agKind==unknownEntity) return ("unknown");
  if (agKind==fileEntity) return ("file");
  if (agKind==folderEntity) return ("folder");
  if (agKind==referenceEntity) return ("reference");
  return ("unknown");
 }
 //---------------------------------------------------------------------------------------ScanFolder
 /*FUNCTION*/
 /* Scans a folder and performs a given process upon the entities found in it. The scanning can be
    recursive. */
 function void scanFolder(tcString agName,clFolderProcessing & agProcessing,
                          tyBoolean agRecursive) {
  typedef std_set(clString) clNameS;

  clNameS lcFileS;
  clNameS lcFolderS;
  clNameS lcUnknownS;

  clNameS::const_iterator lcCurrentEntity;
  clNameS::const_iterator lcLastEntity;

  tcString         lcEntity;
  tyFolder         lcFolder;
  clString         lcFolderName;
  clString         lcFullName;
  tyDiskEntityKind lcKind;
  clString         lcShortName;
  tyString         lcTempo;

  // Folder Scanning //-----------------------------------------------------------------------------
  lcFolderName=agName;
  buildFolderName(lcFolderName);
  lcTempo=private_area::copy(lcFolderName);
  open(lcFolder,lcTempo);
  delete [] lcTempo;
  lcEntity=nextEntity(lcFolder);

  while (lcEntity!=nil) {
   lcShortName=clString(lcEntity);

   if (lcShortName!="." and lcShortName!="..") {
    buildFullName(lcFullName,lcFolderName,clString(lcEntity));
    lcTempo=private_area::copy(lcFullName);
    lcKind=diskEntityKind(lcTempo);
    delete [] lcTempo;

    if (lcKind==folderEntity) lcFolderS.insert(lcFullName);
    else if (lcKind==fileEntity) lcFileS.insert(lcFullName);
    else if (lcKind==unknownEntity) lcUnknownS.insert(lcFullName);
   }

   lcEntity=nextEntity(lcFolder);
  }

  // Folders Processing //--------------------------------------------------------------------------
  close(lcFolder);
  lcCurrentEntity=lcFolderS.begin();
  lcLastEntity=lcFolderS.end();

  while (lcCurrentEntity!=lcLastEntity) {
   agProcessing.startFolder(*lcCurrentEntity);

   if (agRecursive) {
    lcTempo=private_area::copy(*lcCurrentEntity);
    scanFolder(lcTempo,agProcessing,agRecursive);
    delete [] lcTempo;
   }

   agProcessing.endFolder(*lcCurrentEntity);
   lcCurrentEntity++;
  }

  // Files Processing //----------------------------------------------------------------------------
  lcCurrentEntity=lcFileS.begin();
  lcLastEntity=lcFileS.end();

  while (lcCurrentEntity!=lcLastEntity) {
   agProcessing.file(*lcCurrentEntity);
   lcCurrentEntity++;
  }

  // Unknown Entities Processing //-----------------------------------------------------------------
  lcCurrentEntity=lcUnknownS.begin();
  lcLastEntity=lcUnknownS.end();

  while (lcCurrentEntity!=lcLastEntity) {
   agProcessing.unknown(*lcCurrentEntity);
   lcCurrentEntity++;
  }
 }
 //----------------------------------------------------------------------------------OutFileRegister
 /*FUNCTION*/ /* Writes into a stream the list of the files still open in the program. */
 function void outFileRegister(clOutStream & agStream) {
  method_name("outFileRegister");

  typedef private_area::clPrimaryFileRegister::const_iterator   clPrimaryIterator;
  typedef private_area::clSecondaryFileRegister::const_iterator clSecondaryIterator;

  safe_yes ( private_area::goMutex.lock(); )

  clPrimaryIterator   lcCurrentPrimary   = private_area::goPrimaryFileRegister->begin();
  clSecondaryIterator lcCurrentSecondary = private_area::goSecondaryFileRegister->begin();
  clPrimaryIterator   lcLastPrimary      = private_area::goPrimaryFileRegister->end();
  clSecondaryIterator lcLastSecondary    = private_area::goSecondaryFileRegister->end();

  while (lcCurrentSecondary!=lcLastSecondary) {
   agStream << "    Name = " << *(*lcCurrentSecondary) << end_line;
   lcCurrentSecondary++;
  }

  while (lcCurrentPrimary!=lcLastPrimary) {
   agStream << "    Name = " << *((*lcCurrentPrimary).second) << end_line;
   lcCurrentPrimary++;
  }

  safe_yes ( private_area::goMutex.release(); )
  if (agStream.fail()) send_error(erStreamWriting);
 }
}

namespace private_area {
 //---------------------------------------------------------------------------------------------Copy
 function tyString copy(ctString & agString) {
  tyString lcString = new tyCharacter [agString.size()+1];

  standardBasicString::copy(lcString,agString.data());
  lcString[agString.size()]=end_string;
  return (lcString);
 }
 //-------------------------------------------------------------------------------------RegisterFile
 function void registerFile(clInFile & agFile,tcString agFileName) {
  safe_yes ( private_area::goMutex.lock(); )

  if (goPrimaryFileRegister->count(&agFile) == 1) {
   goSecondaryFileRegister->push_back((*(goPrimaryFileRegister->find(&agFile))).second);
   goPrimaryFileRegister->erase(&agFile);
  }

  goPrimaryFileRegister->insert(std_make_pair(&agFile,new clString(agFileName)));
  safe_yes ( private_area::goMutex.release(); )
 }
 //-------------------------------------------------------------------------------------RegisterFile
 function void registerFile(clOutFile & agFile,tcString agFileName) {
  safe_yes ( private_area::goMutex.lock(); )

  if (goPrimaryFileRegister->count(&agFile) == 1) {
   goSecondaryFileRegister->push_back((*(goPrimaryFileRegister->find(&agFile))).second);
   goPrimaryFileRegister->erase(&agFile);
  }

  goPrimaryFileRegister->insert(std_make_pair(&agFile,new clString(agFileName)));
  safe_yes ( private_area::goMutex.release(); )
 }
 //-----------------------------------------------------------------------------RemoveCarriageReturn
 function tyCardinal removeCarriageReturn(tyString agString,tyCardinal agLength) {
  tyCardinal lcCounter1 = 0;
  tyCardinal lcCounter2;

  while (lcCounter1<agLength-1) {
   if (agString[lcCounter1]==0x0D and agString[lcCounter1+1]==0x0A) {
    --agLength;
    lcCounter2=lcCounter1;

    while (lcCounter2<agLength) {
     agString[lcCounter2]=agString[lcCounter2+1];
     ++lcCounter2;
    }
   }

   ++lcCounter1;
  }

  return (agLength);
 }
 //-----------------------------------------------------------------------------------UnregisterFile
 function void unregisterFile(clInFile & agFile) {
  method_name("unregisterFile");

  safe_yes ( private_area::goMutex.lock(); )

  if (goPrimaryFileRegister->count(&agFile) == 0) {
   safe_yes ( private_area::goMutex.release(); )
   send_error(erFileNotRegistered);
  }

  delete (*(goPrimaryFileRegister->find(&agFile))).second;
  goPrimaryFileRegister->erase(&agFile);
  safe_yes ( private_area::goMutex.release(); )
 }
 //-----------------------------------------------------------------------------------UnregisterFile
 function void unregisterFile(clOutFile & agFile) {
  method_name("unregisterFile");

  safe_yes ( private_area::goMutex.lock(); )

  if (goPrimaryFileRegister->count(&agFile) == 0) {
   safe_yes ( private_area::goMutex.release(); )
   send_error(erFileNotRegistered);
  }

  delete (*(goPrimaryFileRegister->find(&agFile))).second;
  goPrimaryFileRegister->erase(&agFile);
  safe_yes ( private_area::goMutex.release(); )
 }
}

// F o l d e r P r o c e s s i n g  Implementation //-----------------------------------------------
namespace public_area {
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clFolderProcessing */ /* Destructs the processing. */
 property clFolderProcessing::~clFolderProcessing(void) {}
}

// F o l d e r P r o c e s s i n g C o p y  Implementation //---------------------------------------
namespace private_area {
 //---------------------------------------------------------------------------------------Destructor
 property clFolderProcessingCopy::~clFolderProcessingCopy(void) {}
 //--------------------------------------------------------------------------------------StartFolder
 property void clFolderProcessingCopy::startFolder(ctString & agFullName) {
  clString lcPath;
  clString lcShortName;

  extractShortName(lcPath,lcShortName,agFullName);
  buildFullName(lcPath,atTargetPath,lcShortName);
  atTargetPath=lcPath;
  if (not folderExists(atTargetPath.data())) createFolder(atTargetPath.data());
 }
 //----------------------------------------------------------------------------------------EndFolder
 property void clFolderProcessingCopy::endFolder(ctString &) {
  clString lcPath;
  clString lcShortName;

  extractShortName(lcPath,lcShortName,atTargetPath);
  atTargetPath=lcPath;
  buildFileName(atTargetPath);
 }
 //---------------------------------------------------------------------------------------------File
 property void clFolderProcessingCopy::file(ctString & agFullName) {
  clString lcFullName;
  clString lcPath;
  clString lcShortName;

  extractShortName(lcPath,lcShortName,agFullName);
  buildFullName(lcFullName,atTargetPath,lcShortName);
  copyFile(lcFullName.data(),agFullName.data());
 }
 //------------------------------------------------------------------------------------------Unknown
 property void clFolderProcessingCopy::unknown(ctString &)
 { send_inline_error(erEntityIdentification,"folderProcessingCopy::unknown"); }
}

// F o l d e r P r o c e s s i n g D e l e t e  Implementation //-----------------------------------
namespace private_area {
 //---------------------------------------------------------------------------------------Destructor
 property clFolderProcessingDelete::~clFolderProcessingDelete(void) {}
}

// F o l d e r P r o c e s s i n g G e t F i l e L i s t  Implementation //-------------------------
namespace private_area {
 //--------------------------------------------------------------------------------------Constructor
 property clFolderProcessingGetFileList::clFolderProcessingGetFileList(tcString agFormat,
 clFileNameS & agFileNameS,tyBoolean agCaseSensitive)
 : atFormat(tyString(agFormat)),atCaseSensitive(agCaseSensitive),atFileNameS(agFileNameS) {
  if (agFormat!=nil and not agCaseSensitive) {
   atFormat=new tyCharacter[standardBasicString::size(agFormat)+1];
   standardBasicString::copy(atFormat,agFormat);
   lowerCase(atFormat);
  }
 }
 //---------------------------------------------------------------------------------------Destructor
 property clFolderProcessingGetFileList::~clFolderProcessingGetFileList(void)
 { if (atFormat!=nil and not atCaseSensitive) delete [] atFormat; }
 //--------------------------------------------------------------------------------------StartFolder
 property void clFolderProcessingGetFileList::startFolder(ctString &) {}
 //----------------------------------------------------------------------------------------EndFolder
 property void clFolderProcessingGetFileList::endFolder(ctString &) {}
 //---------------------------------------------------------------------------------------------File
 property void clFolderProcessingGetFileList::file(ctString & agFullName) {
  clString lcPath;
  clString lcShortName;
  tyString lcTempo;

  extractShortName(lcPath,lcShortName,agFullName);
  lcTempo=private_area::copy(lcShortName);
  if (not atCaseSensitive) lowerCase(tyString(lcTempo));
  if (atFormat==nil or matched(lcTempo,atFormat)) atFileNameS.push_back(lcShortName);
  delete [] lcTempo;
 }
 //------------------------------------------------------------------------------------------Unknown
 property void clFolderProcessingGetFileList::unknown(ctString &) {}
}

// F o l d e r P r o c e s s i n g L i s t  Implementation //---------------------------------------
namespace private_area {
 //--------------------------------------------------------------------------------------Constructor
 property clFolderProcessingList::
 clFolderProcessingList(clOutStream & agStream,tcString agFormat,tyBoolean agCaseSensitive,
                        tcString agBlankSpace)
 : atFormat(tyString(agFormat)),atStream(agStream),atCaseSensitive(agCaseSensitive),
   atBlankSpace(agBlankSpace) {
  if (agFormat!=nil and not agCaseSensitive) {
   atFormat=new tyCharacter[standardBasicString::size(agFormat)+1];
   standardBasicString::copy(atFormat,agFormat);
   lowerCase(atFormat);
  }
 }
 //---------------------------------------------------------------------------------------Destructor
 property clFolderProcessingList::~clFolderProcessingList(void)
 { if (atFormat!=nil and not atCaseSensitive) delete [] atFormat; }
 //--------------------------------------------------------------------------------------StartFolder
 property void clFolderProcessingList::startFolder(ctString & agFullName) {
  clString lcPath;
  clString lcShortName;

  extractShortName(lcPath,lcShortName,agFullName);
  atStream << atBlankSpace << lcShortName << ":" << end_line;
  atBlankSpace+=" ";
 }
 //----------------------------------------------------------------------------------------EndFolder
 property void clFolderProcessingList::endFolder(ctString &) {
  atBlankSpace=atBlankSpace.part(0,atBlankSpace.size()-1);
 }
 //---------------------------------------------------------------------------------------------File
 property void clFolderProcessingList::file(ctString & agFullName) {
  clString lcBody;
  clString lcExtension;
  clString lcPath;
  clString lcShortName;
  tyString lcTempo;

  extractShortName(lcPath,lcShortName,agFullName);
  lcTempo=private_area::copy(lcShortName);
  if (not atCaseSensitive) lowerCase(tyString(lcTempo));

  if (atFormat==nil or matched(lcTempo,atFormat)) {
   delete [] lcTempo;
   separateFileName(lcBody,lcExtension,lcShortName);
   atStream << atBlankSpace << lcShortName << " [" << lcExtension << "] ";
   lcTempo=private_area::copy(agFullName);
   atStream << fileSize(lcTempo) << " bytes" << end_line;
  }

  delete [] lcTempo;
 }
 //------------------------------------------------------------------------------------------Unknown
 property void clFolderProcessingList::unknown(ctString & agFullName) {
  clString lcPath;
  clString lcShortName;

  extractShortName(lcPath,lcShortName,agFullName);
  atStream << atBlankSpace << lcShortName << '?' << end_line;
 }
}

// I n i t i a l i z e r  Implementation //---------------------------------------------------------
namespace private_area {
 //--------------------------------------------------------------------------------------------Start
 property void clInitializer::start(void) {
  if (atCounter++ == 0) {
   try {
    #include <bpp/modules.hpp> /*NEED*/
    registerStop(this);
    environment::informInitialization(goModuleName);

    erEntityIdentification.create("Can't identify an entity in the folder.");
    erFileNotRegistered.create("The file isn't registered.");
    erFileOpening.create("Can't open the file.");
    erFileReading.create("Can't read from the file.");
    erFileWriting.create("Can't write into the file.");
    erStreamReading.create("Can't read from the stream.");
    erStreamWriting.create("Can't write into the stream.");
    erFindFileSize.create("Can't find the file's size.");
    erFileAlreadyExists.create("The file already exists.");
    erFileFolderRenaming.create("Can't rename the file or the folder.");
    erFileRemoving.create("Can't remove the file.");
    erFolderClosing.create("Can't close the folder.");
    erFolderCreation.create("Can't create the folder.");
    erFolderOpening.create("Can't open the folder.");
    erFolderRemoving.create("Can't remove the folder.");

    goFileNameSeparator = FILE_NAME_SEPARATOR;
    goPathSeparator     = PATH_SEPARATOR;
    goStreamBufferSize  = STREAM_BUFFER_SIZE;
    goMaximumPathLength = MAXIMUM_PATH_LENGTH;

    goFileRegisterFileName  = FILE_REGISTER_FILE;
    goPrimaryFileRegister   = new clPrimaryFileRegister;
    goSecondaryFileRegister = new clSecondaryFileRegister;

    goDataLocation = new clString(environment::dataLocation()+fileNameSeparator()
                     +"standard"+fileNameSeparator()+"stream");
   }

   initializer_catch;
  }
 }
 //---------------------------------------------------------------------------------------------Stop
 property void clInitializer::stop(void) {
  clOutFile lcFout;

  try {
   environment::informTermination(goModuleName);

   method_name("initializer::destructor");

   if (not (goPrimaryFileRegister->empty() and goSecondaryFileRegister->empty())) {
    using namespace environment;

    nextLine();
    out("[!] Warning: Many files haven't been properly closed.",true,true);
    out("For more details, see the '",false,true); out(goFileRegisterFileName);
    out("' file.",true);
    nextLine();

    lcFout.open(goFileRegisterFileName,ios::out|ios::trunc);
    lcFout << "===============================================================================" << end_line;
    lcFout << " F i l e s   R e g i s t e r                             Debugging Information" << end_line;
    lcFout << "===============================================================================" << end_line;
    lcFout << end_line;
    outInformation(lcFout);
    lcFout << end_line;
    environment::outContext(lcFout);
    lcFout << end_line;
    lcFout << "[>] Files Still Open:" << end_line;
    lcFout << end_line;
    outFileRegister(lcFout);
    lcFout << end_line;
    lcFout << "===============================================================================" << end_line;
    lcFout.close();
    if (lcFout.fail()) send_error(erFileWriting);
   }

   delete goPrimaryFileRegister;
   delete goSecondaryFileRegister;
   delete goDataLocation;
  }

  initializer_catch;
 }
}

// End //-------------------------------------------------------------------------------------------
}