fileReader.lib.c
/****************************************************************************************************/
/*                                                                                                  */
/* fileReader.lib.c:                                                                                */
/*                                                                                                  */
/****************************************************************************************************/

/****************************************************************************************************/
/*                                                                                                  */
/*     Copyright (C) 2004 Joerg Kunze                                                               */
/*                                                                                                  */
/*     This file is part of siliconBrain.                                                           */
/*                                                                                                  */
/*     siliconBrain is free software; you can redistribute it and/or modify                         */
/*     it under the terms of the GNU General Public License as published by                         */
/*     the Free Software Foundation; either version 2 of the License, or                            */
/*     (at your option) any later version.                                                          */
/*                                                                                                  */
/*     siliconBrain 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 General Public License for more details.                                                 */
/*                                                                                                  */
/*     You should have received a copy of the GNU General Public License                            */
/*     along with this program; if not, write to the Free Software                                  */
/*     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA                    */
/*                                                                                                  */
/****************************************************************************************************/
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <errno.h>
#include <pwd.h>
#include <fcntl.h>
#include <sys/mman.h>

#include "siliconBrainLib"
#include "siliconBrainSpecification"
#include "siliconBrainOption"

// static const char *siliconBrainRelease       = "$siliconBrainRelease: 0.2.3 $";
// static const char *siliconBrainRcsIdentifier = "$Id: fileReader.lib.c,v 1.10 2004/12/14 23:31:26 joerg Exp $";
// static const char *siliconBrainSaveStamp     = "$siliconBrainSaveStamp: 2004/12/14 22:15:38, Joerg Kunze$";

/****************************************************************************************************/
/*                                                                                                  */
/* fileReader:                                                                                      */
/*                                                                                                  */
/****************************************************************************************************/
static CommandReturnCode fileRead( UserCommand userCommand, void *options, void *commandData, int file ) {

   CommandReturnCode returnCode = commandOk;
   bool              stopit     = 0;
   bool              stopable   = 0;

   struct stat fileStatus;
   off_t       bufferSize = BUFSIZ;
   size_t      fileSize   = 0;

   if( fstat( file, &fileStatus ) != -1 ) {
      fileSize   = fileStatus.st_size;
      bufferSize = fileStatus.st_blksize ?: BUFSIZ;

      if( S_ISREG( fileStatus.st_mode ) ) stopable = 1;
   }

   if( fileSize ) {
      String source = {
         // .begin    = mmap( 0, fileSize, PROT_READ, MAP_SHARED, file, 0 ),
         .begin    = mmap( 0, fileSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, file, 0 ),
         .length   = fileSize,
         .capacity = fileSize
      };

      if( (int)source.begin != -1 ) {
         returnCode = (*userCommand)( options, commandData, source );
         munmap( source.begin, source.length );
         return returnCode;
      }
   }

   String source = {
      .begin    = alloca( bufferSize ),
      .length   = 0,
      .capacity = bufferSize
   };

   while( !stopit && (source.length = read( file, source.begin, source.capacity )) )
      stopit = ( commandStop == (returnCode = (*userCommand)( options, commandData, source )) );

   /*-----------------------------------------------------------------------------------------------------*/
   /* if it is something like a pipe, it is better to consume up the complete file, thus not stopping the */
   /* pipe writing process.                                                                               */
   /*-----------------------------------------------------------------------------------------------------*/
   if( stopit && !stopable )
      while( read( file, source.begin, source.capacity ) );

   return returnCode;
}

/****************************************************************************************************/
/*                                                                                                  */
/* fileReader:                                                                                      */
/*                                                                                                  */
/****************************************************************************************************/
extern CommandReturnCode fileReader( FileReaderContext *context, void *options, int argc, char *argv[] ) {

   CommandReturnCode returnCode = commandOk;
   bool              stopit     = 0;

   int file;

   void *commandData = 0;

   if( context->openCommand ) commandData = context->openCommand( options );

   if( argc ) {
      int fileNumber;
      for( fileNumber = 0; fileNumber < argc && !stopit; ++fileNumber ) {
         file = open( argv[ fileNumber ], O_RDONLY );

         String fileName = { .begin = argv[ fileNumber ], .length = strlen( argv[ fileNumber ] ), .capacity = strlen( argv[ fileNumber ] ) };

         if( context->openFile ) context->openFile( options, commandData, fileName );

         stopit = ( commandStop == (returnCode = fileRead( context->userCommand, options, commandData, file )) );

         if( context->openFile ) returnCode = context->closeFile( options, commandData, fileName );

         close( file );
      }
   }
   else {
      if( context->openFile ) context->openFile( options, commandData, c( "" ) );
      returnCode = fileRead( context->userCommand, options, commandData, 0 );
      if( context->openFile ) returnCode = context->closeFile( options, commandData, c( "" ) );
   }
   if( context->closeCommand ) returnCode = context->closeCommand( options, commandData );

   return returnCode;
}

/****************************************************************************************************/
/*                                                                                                  */
/* pipeReader:                                                                                      */
/*                                                                                                  */
/****************************************************************************************************/
extern CommandReturnCode pipeReader( FileReaderContext *context, void *options, int file ) {

   CommandReturnCode returnCode = commandOk;
   bool              stopit     = 0;

   void *commandData = 0;

   if( context->openCommand ) commandData = context->openCommand( options );
   if( context->openFile ) context->openFile( options, commandData, c( "" ) );

   off_t       bufferSize = BUFSIZ;

   String source = {
      .begin    = alloca( bufferSize ),
      .length   = 0,
      .capacity = bufferSize
   };

   while( !stopit && (source.length = read( file, source.begin, source.capacity )) )
      stopit = ( commandStop == (returnCode = (*context->userCommand)( options, commandData, source )) );

   /*-----------------------------------------------------------------------------------------------------*/
   /* if it is something like a pipe, it is better to consume up the complete file, thus not stopping the */
   /* pipe writing process.                                                                               */
   /*-----------------------------------------------------------------------------------------------------*/
   if( stopit ) while( read( file, source.begin, source.capacity ) );

   if( context->openFile ) returnCode = context->closeFile( options, commandData, c( "" ) );
   if( context->closeCommand ) returnCode = context->closeCommand( options, commandData );

   return returnCode;
}

/*
$Log: fileReader.lib.c,v $
Revision 1.10  2004/12/14 23:31:26  joerg
published for new release 0.2.3

Revision 1.9  2004/12/14 23:17:05  joerg
published for new release 0.2.2

Revision 1.8  2004/12/14 22:20:09  joerg
pipe output of make command into stringSearch c-function
without creating a process for stringSearch. The later is used as a C-function command, not as a main.

*/