🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: pl.comp.lang.c
Article #309335

Re: fir's sicl

#309335
From: (fir)
Date: Mon, 07 Aug 2017 17:12
921 lines
19058 bytes
tutaj jest sam kod (podkreslam ze to kod na brudno - prototypy do testow, idea jest dobra ale forme mozna by poprawic, choc nie wiem czy akurat teraz wykrzesam z siebie checi by to poprawiac, chyba akurat wlasnie nie teraz) 

/*
    small-icl.c

    some routines for text prosessing based
    on chunk idea (it is also based on relocable
    internal pools here)

    version of 27.xi.2016

    (it is early version, some things need to be
    throwed out some added, most revritten but
    it in general works and is usable and quite 
    lot can be done with this easily)



*/



#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <sys/stat.h>
#include <string.h>


void ERROR_EXIT(char *format, ...)
{
  // put your error reporting routine here


    va_list args;
    va_start(args, format);
     vprintf(format, args);
    va_end(args);

    exit(-1);


}


typedef struct
 {
   char* beg;
   char* end;
 }   chunk;

typedef struct
  {
  chunk* first;
  chunk* last;
  }   chunks;


inline chunk Chunk(char* str)
{

  int len = strlen(str);
  chunk c = {str, str+len-1};

  return c;
}


inline int ChunkIsEmpty(chunk c)
{

  if(c.beg==NULL || c.end==NULL || c.beg>c.end)
  {
     c.beg   = NULL;
     c.end   = NULL;
     return 1;
  }

  return 0;
}

inline void AssertChunkValidity(chunk text, char* file, int line)
{
   if(text.beg==NULL)     ERROR_EXIT("text.beg==NULL %s %d", file, line);
   if(text.end==NULL)     ERROR_EXIT("text.end==NULL %s %d", file, line);
   if(text.beg>text.end)  ERROR_EXIT("text.beg>text.end %s %d", file, line);

}

// chunk Chunk2(char* a, char* b)
// {
//   chunk c = {a,b};
//
//   if(a==NULL || b==NULL || a>b) c = { NULL,  NULL };
//
//   return c;
// }

inline int ChunkLength(chunk a)
{
  int len = a.end - a.beg + 1;
  if(len<0) ERROR_EXIT("chunk length < 0");
  return len;
}


 int GetFileSize1(FILE* file)
 {
  int seek_pos = ftell(file);
  int error = fseek(file, 0, SEEK_END);

     if(error) ERROR_EXIT("seek1 error");

  int file_length = ftell(file) ;
  error = fseek(file, seek_pos, SEEK_SET);

     if(error) ERROR_EXIT("seek2 error");

  return file_length;
 }


 int GetFileSize2(char *filename)
 {
    struct stat st;

    if (stat(filename, &st) == 0)
        return (int) st.st_size;

      ERROR_EXIT("error obtaining file size for &s", filename);

    return -1;
}



chunk LoadChunk(char* file_name)
{
  static char* internal_text = NULL;

  FILE * file = fopen(file_name, "rb");

    if(file == NULL) ERROR_EXIT( " cannot open file %s  ", file_name);

  int file_length = GetFileSize1(file);

  internal_text = (char*)realloc(internal_text, file_length + 10);

    if(internal_text == NULL) ERROR_EXIT(" cannot mallock data for file %s ",  file_name);

  int readed =  fread(internal_text, 1, file_length, file);

  int error = fclose(file);

    if(error) ERROR_EXIT("\n cannot close file %s", file_name);

  chunk text = {internal_text, internal_text + file_length - 1};
  return text;

}


void CreateFile(char* filename)
{
  FILE* file = fopen (filename, "wb");

  if(file == NULL) ERROR_EXIT( " cannot open file %s  ", filename);

//  fwrite (ch.beg , 1, ChunkLength(ch), file);

  fclose (file);

}

void SaveChunk(chunk ch, char* filename)
{
  if(ChunkIsEmpty(ch)) return;

  FILE* file = fopen (filename, "wb");

  if(file == NULL) ERROR_EXIT( " cannot open file %s  ", filename);

  fwrite (ch.beg , 1, ChunkLength(ch), file);

  fclose (file);

}

void SaveChunkTextMode(chunk ch, char* filename)
{
  if(ChunkIsEmpty(ch)) return;

  FILE* file = fopen (filename, "wt");

  if(file == NULL) ERROR_EXIT( " cannot open file %s  ", filename);

  fwrite (ch.beg , 1, ChunkLength(ch), file);

  fclose (file);

}

void AppendChunk(chunk ch, char* filename)
{
  if(ChunkIsEmpty(ch)) return;

  FILE* file = fopen (filename, "ab");

    if(file == NULL) ERROR_EXIT( " cannot open file %s  ", filename);

  fwrite (ch.beg , 1, ChunkLength(ch), file);

  fclose (file);

}

// void WriteNewTextChunk(chunk ch, char* filename)
// {
//   FILE* file = fopen (filename, "wt");
//
//     if(file == NULL) ERROR_EXIT( " cannot open file %s  ", filename);
//
//   fwrite (ch.beg , 1, ChunkLength(ch), file);
//
//   fclose (file);
//
// }

void AppendChunkTextMode(chunk ch, char* filename)
{
  FILE* file = fopen (filename, "at");

    if(file == NULL) ERROR_EXIT( " cannot open file %s  ", filename);

  fwrite (ch.beg , 1, ChunkLength(ch), file);

  fclose (file);

}


int PrintChunk(chunk ch)
{
  if(ch.beg == NULL || ch.end == NULL || ch.beg > ch.end )
  {
    printf(" chunk is NULL ");
    return 0;
  }

  int len = ChunkLength(ch);
  printf("%.*s", len, ch);
  return len;
}


int PrintChunkNL(chunk ch)
{
  if(ch.beg == NULL || ch.end == NULL || ch.beg > ch.end )
  {
    printf(" chunk is NULL ");
    return 0;
  }

   int len = ChunkLength(ch);

   if(len<=0) ERROR_EXIT("len<=0 in print line");

   printf("\n%.*s", len, ch);
   return len;

}

int PrintChunkInHex(chunk ch)
{
  //todo
}


chunk ReallocChunk(chunk c, int new_size)
{
     c.beg = (char*) realloc(c.beg, new_size );
     if(c.beg==NULL) ERROR_EXIT("cant realloc chunk");
     c.end = c.beg + new_size - 1;

     return c;

}

chunk PrintfToChunk( char *format, ... )
{



    static chunk ch;

    static int current_ram_size = 1024;

    static int initialised = 0;
    if(!initialised)
    {
      ch = ReallocChunk(ch, current_ram_size);
      initialised = 1;
    }



    va_list args;
    va_start(args, format);

    int len = 0;

    for(;;)
    {

      len = vsnprintf(ch.beg, current_ram_size, format, args);
//      int vasprintf(char **ret, const char *format, va_list ap);
//      char *tab;  vasprintf(&tab,  format, args);

      if( len < current_ram_size )
      {
           ch.end = ch.beg + len - 1;
           break;
      }
      else
      {
            current_ram_size *=2;
            ch = ReallocChunk(ch,  current_ram_size );
//           printf("growing to %d", current_ram_size );
      }


    }

      va_end(args);


      return ch;

}
//////////

inline char* Find1stChar_ByPredicate(chunk text, int (*IsWordCharacter)(char ch))
{
   AssertChunkValidity(text, __FILE__, __LINE__);

   for(char* s=text.beg; s<=text.end; s++)
     if(IsWordCharacter(*s))
      return s;

   return NULL;
}

inline char* Find1stNotChar_ByPredicate(chunk text, int (*IsWordCharacter)(char ch))
{
   AssertChunkValidity(text, __FILE__, __LINE__);

   for(char* s=text.beg; s<=text.end; s++)
     if(!IsWordCharacter(*s))
       return s;

   return NULL;
}

inline chunk Find1stWord_ByPredicate(chunk text, int (*BelongingPredicate)(char ch))
{

   chunk found = {0};

   if(text.beg>text.end) return found;

   found.beg = Find1stChar_ByPredicate(text, BelongingPredicate);

   if(found.beg==NULL) return found;
   if(found.beg==text.end) { found.end=found.beg; return found; }

   text.beg = found.beg + 1;

   char* char_after_word  =  Find1stNotChar_ByPredicate(text, BelongingPredicate);
   if(char_after_word==NULL) {
     found.end = text.end; return found;   }

   found.end = char_after_word -1;

  return found;

}

inline int  PreCountNumberOfWords_ByPredicate(chunk text, int (*BelongingPredicate)(char ch))
{
  int counter = 0;

  chunk where = text;

  for(;;)
  {
   chunk found = Find1stWord_ByPredicate( where, BelongingPredicate);
   if(found.beg == NULL) break;

   counter ++;

   where.beg = found.end +1;
   if(where.beg>where.end) break;
  }

  return counter;

}

/////////

int IsDigit(char c)
{
  if(c>='0' && c<='9') return 1;
  else return 0;
}

int IsLetter(char c)
{
  if(c>='a' && c<='z') return 1;
  if(c>='A' && c<='Z') return 1;

  return 0;

}

int IsHexDigit(char c)
{
  if(IsDigit(c)) return 1;
  if(c>='a' && c<='f') return 1;
  if(c>='A' && c<='F') return 1;
  else return 0;
}


int IsNewline(char c)
{
  if(c==0xd || c==0xa) return 1;

  return 0;
}

int IsWhiteSpace(char c)
{
  if(c == 0x20 ||
     c == 0x09 ||
     c == 0x0a ||
     c == 0x0b ||
     c == 0x0c ||
     c == 0x0d ) return 1;

  return 0;

}

int IsInvisible(char c)
{
  if(c>0 && c<32 && ! IsWhiteSpace(c)) return 1;

  return 0;
}

int IsPunctuation(char c)
{
  if( !IsDigit(c) && !IsLetter(c)
   && !IsWhiteSpace(c) && !IsInvisible(c))
 return 1;

 return 0;

}
////////

int max(int a, int b)
{
  if(a>=b) return a;
  return b;
}

chunks FindAllWordsByPredicate(chunk text, int (*BelongingPredicate)(char ch))
{


  chunks results = {0};


  static chunk* internal_ram_chunks = NULL;
  static int internal_ram_length = 0;
  const  int down_limit_for_internal_ram_chunks = 64*1024;

  if(internal_ram_chunks == NULL)// || internal_ram_length > down_limit_for_internal_ram_chunks) //preallok pool
  {
   internal_ram_length = down_limit_for_internal_ram_chunks;
   internal_ram_chunks = (chunk*) realloc(internal_ram_chunks, internal_ram_length );
  }


  chunk where = text;

  int i;
  int n = internal_ram_length / sizeof(chunk);

//  for(i=0;i< down_limit_for_internal_ram_chunks/sizeof(chunk); i++)
  for(i=0;i< n; i++)
  {

   internal_ram_chunks[i] = Find1stWord_ByPredicate( where, BelongingPredicate);
   if(internal_ram_chunks[0].beg == NULL) return results; //none found


   if( (! internal_ram_chunks[i].beg) || (! internal_ram_chunks[i].end) || (internal_ram_chunks[i].beg > internal_ram_chunks[i].end) )
   {

    //down allock
     if(  ( i*sizeof(chunk)    < internal_ram_length ) &&
          ( internal_ram_length > down_limit_for_internal_ram_chunks) )
          {
            internal_ram_length = max(i*sizeof(chunk), down_limit_for_internal_ram_chunks);
            internal_ram_chunks = (chunk*) realloc(internal_ram_chunks, internal_ram_length );
         //   printf("\nresize");
          }

//     printf("\n internal pool length %d chunks \n", internal_ram_length/sizeof(chunk));

     return results  =  { internal_ram_chunks,  internal_ram_chunks + i - 1 };
   }

   where.beg = internal_ram_chunks[i].end + 1;

  }


  //not enough  prealocked ram
  // resize too needed length

  int how_many_yet = PreCountNumberOfWords_ByPredicate(where, BelongingPredicate);
  if(how_many_yet==0) return  results  =  { internal_ram_chunks,  internal_ram_chunks + i - 1 };

  // up allock

  internal_ram_length += how_many_yet * sizeof(chunk);
  internal_ram_chunks = (chunk*) realloc(internal_ram_chunks, internal_ram_length );
//  printf("\nupsize");


  for(int j=i; j<i+how_many_yet; j++)
  {
   internal_ram_chunks[j] = Find1stWord_ByPredicate( where, BelongingPredicate);
   where.beg = internal_ram_chunks[j].end + 1;
  }
//  printf("\n internal pool length %d chunks \n", internal_ram_length/sizeof(chunk));

  return results  =  { internal_ram_chunks,  internal_ram_chunks + i + how_many_yet - 1 };


}

int WordsBelongingStdPredicate(char ch)
{
   if(IsWhiteSpace(ch)) return 0;
   return 1;


//     if(ch>='a' && ch<='z') return 1;
//     if(ch>='A' && ch<='Z') return 1;
//     if(ch>='0' && ch<='9') return 1;
//     return 0;
}

chunks SplitAllStdWords(chunk text)
{
 chunks s = FindAllWordsByPredicate(text, WordsBelongingStdPredicate );
 return s;
}
//////////////


chunk TrimEdgeWhitespaces(chunk text)
{
   chunk out = text;

   for(char* c=text.beg; c<=text.end; c++)
      if( ! IsWhiteSpace(*c)) { out.beg = c; break;}

   for(char* c=text.end; c>=text.beg; c--)
      if( ! IsWhiteSpace(*c)) { out.end = c; break; }

   return out;

}



 void SkipCharsTillNumber(char** p)
 {
   for(;;)
   {
     if( **p==0 ) break;
     if(IsDigit(**p)) break;

     if((**p)=='-' && IsDigit( *((*p)+1) ) ) break;

   //  printf("\n skipped char: %c", **p);

     (*p)++;
   }

 }


 int DigInt(char**p, int* value)
 {

   for(;;)
   {

     SkipCharsTillNumber(p);
     if(**p==0) break;

     char* s = *p;
     *value = strtol(s, p, 10);

     if (errno)  ERROR_EXIT("\n*** ERROR: Out Of range conversion in DigInt routine at '%.*s' ***", *p-s, s );

     return 1;
   }

   return 0;
 }



chunk FindFirstEmbeddedIntegerChunk(chunk text)
{
  chunk word = {NULL, NULL};

  for(char* i = text.beg; i <= text.end; i++)
  {
   if( IsDigit( *i ) )
   {
          word.beg = i;
          break;
   }
  }


  if(word.beg==NULL) return word;


  for(char* i = word.beg; i <= text.end; i++)
  {
   if( !IsDigit( *i ) )
   {
     word.end = i - 1;

     if(word.beg[-1]=='-' && word.beg-1>=text.beg)
        word.beg--;
     return word;
   }
  }
     word.end = text.end;

     if(word.beg[-1]=='-' && word.beg-1>=text.beg)
        word.beg--;

     return word;

}

int IsPureIntegerChunk(chunk word)
{
    for(char* c=word.beg; c<=word.end; c++)
    {
      if(c==word.beg && (*c=='-')) continue;
      if( ! IsDigit(*c)) return 0;
    }

    if(ChunkLength(word)==1 && word.beg[0]=='-') return 0;

    return 1;
}

int IsPureHexChunk(chunk word)
{
    for(char* c=word.beg; c<=word.end; c++)
    {
       if( ! IsHexDigit(*c)) return 0;
    }

    return 1;

}



long ConvertChunk2Int(chunk word)
{
  static char buf[100];

  int len = word.end - word.beg +  1;

  for(int i=0; i<len; i++)
     buf[i] = word.beg[i];

  buf[len] = 0;

//  int i =  atoi(buf);
  long i =  atol(buf);

  return i;

}



//////////

int ChunksLength(chunks s)
{
//  alert("L");

  if(s.first == NULL || s.last == NULL || s.first > s.last) return 0;

  return s.last - s.first + 1;
}


void SaveChunks(chunks cs, char*filename)
{
  FILE* file = fopen (filename, "wb");
    if(file == NULL) ERROR_EXIT( " cannot open file %s  ", filename);

  for(chunk* s = cs.first; s<=cs.last; s++)
  {
    if(ChunkIsEmpty(*s)) continue;

    fwrite ((*s).beg , 1, ChunkLength(*s), file);
  }

  fclose (file);

}

void PrintChunks(chunks s)
{
  printf("\n");

  int i = 0;

  for(chunk* line = s.first; line<=s.last; line++)
  {
    if(line==NULL) continue;
    printf("\n %d '%.*s'", i++, ChunkLength(*line), *line);


  }

}

 int CountNumberOfSplitChunks(chunk text, char split_character)
{
  int counter = 1;

   for(char* c = text.beg; c <= text.end; c++ )
    if(*c == split_character) counter++;

  return counter;
}


//    splits text into chunks ( not tested for edge cases )
//      array of chunks is reallocked and maneged internally
chunks SplitAfterCharacter(chunk text, char split_character)
{

  int split_chunks_count = CountNumberOfSplitChunks(text, split_character);

  //realloc internal ram to fit
  static chunk* internal_ram_chunks = NULL;
  int internal_ram_length = split_chunks_count * sizeof(chunk);
  internal_ram_chunks = (chunk*) realloc(internal_ram_chunks, internal_ram_length );

  // now internal_ram_chunks is an array of N chunks
  // we will fill it


  int current_chunk_length = 0;
  int current_chunk_number = 0;

  internal_ram_chunks[current_chunk_number].beg = text.beg; //open first


  for(char* c = text.beg; c <= text.end; c++ )
  {

    current_chunk_length++;

    if(*c == split_character) //end chunk
    {
        internal_ram_chunks[current_chunk_number].end = c;


       if(c+1<=text.end)  // open next
       {
        current_chunk_length = 0;
        current_chunk_number ++;

        internal_ram_chunks[current_chunk_number].beg = c + 1;
       }

      }

  }


  internal_ram_chunks[current_chunk_number].end = text.end; //finish last

//  if(split_chunks_count != current_chunk_number + 1) ERROR_("something wrong");

  //send output
  chunks splited = {internal_ram_chunks, internal_ram_chunks + current_chunk_number} ;
  return splited;

}

//////////////



int Compare(chunk a, chunk b)
{
  char* c = a.beg;
  char* d = b.beg;

  if(c==NULL || d==NULL) return 0;

  while( c <= a.end && d <= b.end )
  {
    if((*c) < (*d) ) return -1;
    if((*c) > (*d) ) return +1;

    c++;
    d++;
  }
  if(ChunkLength(a) < ChunkLength(b)) return -1;
  if(ChunkLength(a) > ChunkLength(b)) return +1;
  return 0;
}


void Quicksort(chunks a)
{
  int lo = 0;
  int hi = a.last - a.first ;

 // alert("%d", hi);

    int i = lo;
    int j = hi;

    while (i < hi) {
//    while (i <= hi) {

        chunk pivot =  a.first[(lo+hi)/2];
        // Partition
        while (i <= j)
        {
            while ( Compare(a.first[i], pivot) < 0 )
            {
                i = i + 1;
            }
            while (Compare( a.first[j], pivot) > 0)
            {
                j = j - 1;
            }
            if (i <= j)
            {
                chunk t  = a.first[i];
                a.first[i] = a.first[j];
                a.first[j] = t;
                i = i + 1;
                j = j - 1;
            }
        }

        // Recursion for quicksort
        if (lo < j)
        {
            chunks x = { a.first + lo, a.first + j };

            Quicksort(x);
        }
        lo = i;
        j = hi;
    }
}

void NullRepeatingChunks(chunks s)
{
  for(chunk* l = s.first; l<=s.last; l++)
  {
     if((*l).beg==NULL) continue;

     for(chunk* k = l + 1; k<=s.last; k++)
     {
       if(Compare(*l, *k)==0)
       {
        (*k).beg = NULL;

         continue;
       }

       break;

     }

  }

}


// 919 lines of source
Technical Details
Message-ID: <0c601f7b-4830-4d01-894a-9960dc6333fd@googlegroups.com>
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!news.icm.edu.pl!fu-berlin.de!w51no981662qtc.0!news-out.google.com!e5ni881qta.0!nntp.google.com!w51no981660qtc.0!postnews.google.com!glegroupsg2000goo.googlegroups.com!not-for-mail
References: <6950309e-21a6-436f-a500-301fc68754d5@googlegroups.com>

Show Full Headers
Complete Article Headers
X-Received: by 10.237.46.228 with SMTP id k91mr723821qtd.116.1502125929175;        Mon, 07 Aug 2017 10:12:09 -0700 (PDT)
X-Received: by 10.31.155.201 with SMTP id d192mr8875vke.1.1502125929048; Mon, 07 Aug 2017 10:12:09 -0700 (PDT)
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!news.icm.edu.pl!fu-berlin.de!w51no981662qtc.0!news-out.google.com!e5ni881qta.0!nntp.google.com!w51no981660qtc.0!postnews.google.com!glegroupsg2000goo.googlegroups.com!not-for-mail
Newsgroups: pl.comp.lang.c
Date: Mon, 7 Aug 2017 10:12:08 -0700 (PDT)
In-Reply-To: <6950309e-21a6-436f-a500-301fc68754d5@googlegroups.com>
Complaints-To: groups-abuse@google.com
Injection-Info: glegroupsg2000goo.googlegroups.com; posting-host=5.172.255.87; posting-account=Sb6m8goAAABbWsBL7gouk3bfLsuxwMgN
NNTP-Posting-Host: 5.172.255.87
References: <6950309e-21a6-436f-a500-301fc68754d5@googlegroups.com>
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <0c601f7b-4830-4d01-894a-9960dc6333fd@googlegroups.com>
Subject: Re: fir's sicl
From: "(fir)" <profesor.fir@gmail.com>
Injection-Date: Mon, 07 Aug 2017 17:12:09 +0000
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 7bit