/*
		                  LCRZO
                             Network library
             Copyright(c) 1999,2000,2001,2002 Laurent Constantin
                                  -----

  Main server    : http://www.laurentconstantin.com/
  Backup servers : http://go.to/laurentconstantin/
                   http://laurentconstantin.est-la.com/
                   http://laurentconstantin.free.fr/
                   http://lauconstantin.multimania.com/
  [my current email address is on the web servers]

                                  -----
  This file is part of Lcrzo.

  Lcrzo is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  Lcrzo 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
  Lesser General Public License for more details (http://www.gnu.org).

------------------------------------------------------------------------
*/

/* -- Note about comments and variable names --
   In versions 1.00 up to 2.08, lcrzo was only written in French (my
   mother tongue). Since version 3.00, lcrzo is written in English, but
   most of comments and variable names are still in French.
   In future versions, I'll try to translate everything into English,
   but as you may guess, that's a quite big work...
   So, for the moment, here are some word translation, if you want to
   be able to understand what's going on in the functions :
     afficher - print     ;  ajouter - add         ;  copie - copy
     dernier - last       ;  donnee - data         ;  ecrire - write
     entete - header      ;  envoye - sent         ;  ferme - close
     fichier - file       ;  lire - read           ;  masque - mask 
     nboct - byte number  ;  ouvre, ouvrir - open  ;  paq, paquet - packet
     plage - range        ;  premier - first       ;  recu - received
     reseau - network     ;  retour - return       ;  taille - size
     tunnel - pipe

*/

#include "lcrzo_incl.h"


/*-------------------------------------------------------------*/
int lcrzo_priv_base64cb642ent(lcrzo_uint8 car, lcrzo_uint8 *pentier);
int lcrzo_priv_base64cb642ent(lcrzo_uint8 car, lcrzo_uint8 *pentier)
{ if ( car>='A' && car<='Z' ) *pentier=(lcrzo_uint8)(car-'A');
  else if ( car>='a' && car<='z' ) *pentier=(lcrzo_uint8)(car-'a'+26);
  else if ( car>='0' && car<='9' ) *pentier=(lcrzo_uint8)(car-'0'+52);
  else if ( car=='+' ) *pentier=(62);
  else if ( car=='/' ) *pentier=(63);
  else return(LCRZO_ERR_FMBASE64CHAR);
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_priv_equal_nchar(lcrzo_constdata searchlist,
			   lcrzo_int32 searchlistsize,
			   lcrzo_uint8 c);
int lcrzo_priv_equal_nchar(lcrzo_constdata searchlist,
			   lcrzo_int32 searchlistsize,
			   lcrzo_uint8 c)
{ lcrzo_int32 i;

  for ( i=0 ; i<searchlistsize ; i++ )
  { if (searchlist[i]==c) return(1);
  }
  return(0);
}

/*-------------------------------------------------------------*/
int lcrzo_priv_data_appendm_regexp(lcrzo_constdata datain,
				   lcrzo_int32 datainsize,
				   lcrzo_regexp arrayfoundpos,
				   lcrzo_constdata data_replacing,
				   lcrzo_int32 data_replacingsize,
				   lcrzo_int32 dataoutcurrentsize,
				   lcrzo_data *pdataout,
				   lcrzo_int32 *pdataoutsize);
int lcrzo_priv_data_appendm_regexp(lcrzo_constdata datain,
				   lcrzo_int32 datainsize,
				   lcrzo_regexp arrayfoundpos,
				   lcrzo_constdata data_replacing,
				   lcrzo_int32 data_replacingsize,
				   lcrzo_int32 dataoutcurrentsize,
				   lcrzo_data *pdataout,
				   lcrzo_int32 *pdataoutsize)
{ lcrzo_int32 p, posinf, possup, oldpossup, i, dataoutsize;
  int retour;
  char c;

  p=0;
  oldpossup=1;
  dataoutsize=dataoutcurrentsize;
  retour=lcrzo_data_search_re(data_replacing, data_replacingsize, 0, 1, -1,
			      "\\$.?", NULL, &posinf, NULL, &possup);
  while(retour==LCRZO_ERR_OK)
  { /*end with a '$' alone : error*/
    if (possup-posinf==1)
    { return(LCRZO_ERR_FMREGEXP);
    }
    /*append the start*/
    lcrzo_efr(lcrzo_data_appendm_range(data_replacing, data_replacingsize,
				       oldpossup, posinf,
				       dataoutsize, pdataout, &dataoutsize),
	      { if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize; });
    oldpossup=possup;

    /*$ suivi de quelque chose*/
    c=data_replacing[posinf];
    if ( c>='0' && c<='9' )
    { /*numerodemande*/
      i=c-'0';
      if ( arrayfoundpos[i].startindex_positive!=0 &&
	   arrayfoundpos[i].endindex_positive!=0 )
      { lcrzo_efr(lcrzo_data_appendm_range(datain, datainsize,
					   arrayfoundpos[i].startindex_positive,
                                           arrayfoundpos[i].endindex_positive,
					   dataoutsize, pdataout,&dataoutsize),
		  { if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize; });
      }
    }
    else if ( c=='$' )
    { lcrzo_efr(lcrzo_data_appendm_char('$', 1,
					dataoutsize, pdataout, &dataoutsize),
		{ if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize; });
    }
    else
    { return(LCRZO_ERR_FMREGEXP);
    }

    /*cherche le suivant*/
    retour=lcrzo_data_search_re(data_replacing, data_replacingsize, 0, 
				possup, -1,
				"\\$.?", NULL, &posinf, NULL, &possup);
  }

  /*met la fin*/
  retour=lcrzo_data_appendm_range(data_replacing, data_replacingsize,
				  oldpossup, -1, 
				  dataoutsize, pdataout, &dataoutsize);
  if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize;
  return(retour);
}

/*-------------------------------------------------------------*/
void lcrzo_priv_hexa_twoquart(lcrzo_uint8 in, char *phigh, char *plow);
void lcrzo_priv_hexa_twoquart(lcrzo_uint8 in, char *phigh, char *plow)
{ int tmp;
  tmp=in&0x0F;
  if (tmp<10) *plow=(char)('0'+tmp);
  else *plow=(char)('A'+tmp-10);
  tmp=(in&0xF0)>>4;
  if (tmp<10) *phigh=(char)('0'+tmp);
  else *phigh=(char)('A'+tmp-10);
}

/*-------------------------------------------------------------*/
void lcrzo_priv_base64_int2char(int in, lcrzo_int8 *pc);
void lcrzo_priv_base64_int2char(int in, lcrzo_int8 *pc)
{ if (in<26) *pc=(lcrzo_int8)(in+'A');
  else if (in<52) *pc=(lcrzo_int8)((in-26)+'a');
  else if (in<62) *pc=(lcrzo_int8)((in-52)+'0');
  else if (in==62) *pc='+';
  else if (in==63) *pc='/';
}


/*-------------------------------------------------------------*/
/*-------------------------------------------------------------*/
/*-------------------------------------------------------------*/
#if LCRZO_PRIV_DATA_ALLOC_DEBUG==0
 #define LCRZO_DEBUG_MEMALLOC(po,s) 
 #define LCRZO_DEBUG_MEMFREE(po)
#elif LCRZO_PRIV_DATA_ALLOC_DEBUG==1
 #define LCRZO_DEBUG_MEMALLOC(po,s) fprintf(stdout,"%05d data_alloc : %p %ld\n",getpid(),po,(long int)s)
 #define LCRZO_DEBUG_MEMFREE(po)    fprintf(stdout,"%05d data_free  : %p\n",getpid(),po)
#elif LCRZO_PRIV_DATA_ALLOC_DEBUG==2
 #define LCRZO_DEBUG_MEMALLOC(po,s)
 #define LCRZO_DEBUG_MEMFREE(po)
 #include "../../../externe/checkmemory/checkmemory.c"
#else
 #error "incorrect value for LCRZO_PRIV_DATA_ALLOC_DEBUG"
#endif

/*-------------------------------------------------------------*/
int lcrzo_data_alloc(lcrzo_int32 allocsize, lcrzo_data *pptr)
{
  /*parameters verification*/
  if (pptr==NULL) return(LCRZO_ERR_PANULLPTR);
  if (allocsize<0) return(LCRZO_ERR_PATOOLOW);

  /*"+1" because we use it to put the '\0' of a string in lcrzo_string_xxx
      functions.*/
#if LCRZO_PRIV_DATA_ALLOC_DEBUG==0 || LCRZO_PRIV_DATA_ALLOC_DEBUG==1
  *pptr=malloc(allocsize+1);
#elif LCRZO_PRIV_DATA_ALLOC_DEBUG==2
  *pptr=checkmemory_malloc(allocsize+1);
  /*checkmemory_report();*/
#endif
  LCRZO_DEBUG_MEMALLOC(*pptr, allocsize+1);
  if (*pptr==NULL) return(LCRZO_ERR_FUMALLOC);

  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_data_realloc(lcrzo_int32 newallocsize, lcrzo_data *pptr)
{
  /*parameters verification*/
  if (pptr==NULL) return(LCRZO_ERR_PANULLPTR);
  if (newallocsize<0) return(LCRZO_ERR_PATOOLOW);

  /*"+1" because realloc(p,0)==free(p), so to protect against double free
      Moreover, we use it to put the '\0' of a string in lcrzo_string_xxx
      functions.*/
  if (*pptr==NULL)
  { 
#if LCRZO_PRIV_DATA_ALLOC_DEBUG==0 || LCRZO_PRIV_DATA_ALLOC_DEBUG==1
    *pptr=malloc(newallocsize+1);
#elif LCRZO_PRIV_DATA_ALLOC_DEBUG==2
    *pptr=checkmemory_malloc(newallocsize+1);
#endif
    LCRZO_DEBUG_MEMALLOC(*pptr, newallocsize+1);
    if (*pptr==NULL) return(LCRZO_ERR_FUMALLOC);
  }
  else
  { 
    LCRZO_DEBUG_MEMFREE(*pptr);
#if LCRZO_PRIV_DATA_ALLOC_DEBUG==0 || LCRZO_PRIV_DATA_ALLOC_DEBUG==1
    *pptr=realloc(*pptr, newallocsize+1);
#elif LCRZO_PRIV_DATA_ALLOC_DEBUG==2
    *pptr=checkmemory_realloc(*pptr, newallocsize+1);
#endif
    LCRZO_DEBUG_MEMALLOC(*pptr, newallocsize+1);
    if (*pptr==NULL) return(LCRZO_ERR_FUREALLOC);
  }

  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_data_free(lcrzo_data ptr)
{ 
  LCRZO_DEBUG_MEMFREE(ptr);
#if LCRZO_PRIV_DATA_ALLOC_DEBUG==0 || LCRZO_PRIV_DATA_ALLOC_DEBUG==1
  free(ptr);
#elif LCRZO_PRIV_DATA_ALLOC_DEBUG==2
  checkmemory_free(ptr);
  /*checkmemory_report();*/
#endif
  return(LCRZO_ERR_OK);
}


/*-------------------------------------------------------------*/
int lcrzo_data_init_data(lcrzo_constdata datain,
			 lcrzo_int32 datainsize,
			 lcrzo_int32 dataoutmaxsize,
			 lcrzo_data dataout,
			 lcrzo_int32 *pdataoutsize)
{ return(lcrzo_data_append_data(datain, datainsize, 0,
				dataoutmaxsize, dataout, pdataoutsize));
}

/*-------------------------------------------------------------*/
int lcrzo_data_initm_data(lcrzo_constdata datain,
			  lcrzo_int32 datainsize,
			  lcrzo_data *pdataout,
			  lcrzo_int32 *pdataoutsize)
{ lcrzo_data ptr;

  ptr=NULL;
  lcrzo_er(lcrzo_data_appendm_data(datain, datainsize, 0,
				   &ptr, pdataoutsize));
  if (pdataout!=NULL) *pdataout=ptr;
  else lcrzo_data_free(ptr);
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_data_append_data(lcrzo_constdata datain,
			   lcrzo_int32 datainsize,
			   lcrzo_int32 dataoutcurrentsize,
			   lcrzo_int32 dataoutmaxsize,
			   lcrzo_data dataout,
			   lcrzo_int32 *pdataoutsize)
{
  /*parameters verification*/
  if (datain==NULL && datainsize) return(LCRZO_ERR_PANULLPTRSIZE);
  if (dataoutcurrentsize>dataoutmaxsize) return(LCRZO_ERR_PADATACURSUPMAX);

  if (dataoutcurrentsize+datainsize<=dataoutmaxsize)
  { if (dataout!=NULL)
    { memcpy(dataout+dataoutcurrentsize, datain, datainsize);
    }
    if (pdataoutsize!=NULL) *pdataoutsize=dataoutcurrentsize+datainsize;
    return(LCRZO_ERR_OK);
  }
  else
  { if (dataout!=NULL)
    { memcpy(dataout+dataoutcurrentsize, datain,
	     dataoutmaxsize-dataoutcurrentsize);
    }
    if (pdataoutsize!=NULL) *pdataoutsize=dataoutmaxsize;
    return(LCRZO_ERR_OKDATATRUNCATED);
  }
 
  /*should never be here*/
  return(lcrzo_ierp("lcrzo_data_append_data"));
}

/*-------------------------------------------------------------*/
int lcrzo_data_appendm_data(lcrzo_constdata datain,
			    lcrzo_int32 datainsize,
			    lcrzo_int32 dataoutcurrentsize,
			    lcrzo_data *pdataout,
			    lcrzo_int32 *pdataoutsize)
{ lcrzo_int32 dataoutsize;

  /*parameters verification*/
  if (datain==NULL && datainsize) return(LCRZO_ERR_PANULLPTRSIZE);
  if (datainsize<0) return(LCRZO_ERR_PATOOLOW);
  if (dataoutcurrentsize<0) return(LCRZO_ERR_PATOOLOW);

  /*compute the output size*/
  dataoutsize=dataoutcurrentsize+datainsize;
  if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize;

  /*init pdataout*/
  if (pdataout!=NULL)
  { lcrzo_er(lcrzo_data_realloc(dataoutsize, pdataout));
    memcpy(*pdataout+dataoutcurrentsize, datain, datainsize);
  }

  return(LCRZO_ERR_OK);
}


/*-------------------------------------------------------------*/
int lcrzo_data_init_range(lcrzo_constdata datain,
			  lcrzo_int32 datainsize,
			  lcrzo_int32 datainstartpos,
			  lcrzo_int32 datainendpos,
			  lcrzo_int32 dataoutmaxsize,
			  lcrzo_data dataout,
			  lcrzo_int32 *pdataoutsize)
{ return(lcrzo_data_append_range(datain, datainsize,
				 datainstartpos, datainendpos, 0,
				 dataoutmaxsize, dataout, pdataoutsize));
}

/*-------------------------------------------------------------*/
int lcrzo_data_initm_range(lcrzo_constdata datain,
			   lcrzo_int32 datainsize,
			   lcrzo_int32 datainstartpos,
			   lcrzo_int32 datainendpos,
			   lcrzo_data *pdataout,
			   lcrzo_int32 *pdataoutsize)
{ lcrzo_data ptr;

  ptr=NULL;
  lcrzo_er(lcrzo_data_appendm_range(datain, datainsize,
				    datainstartpos, datainendpos, 0,
				    &ptr, pdataoutsize));
  if (pdataout!=NULL) *pdataout=ptr;
  else lcrzo_data_free(ptr);
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_data_append_range(lcrzo_constdata datain,
			    lcrzo_int32 datainsize,
			    lcrzo_int32 datainstartpos,
			    lcrzo_int32 datainendpos,
			    lcrzo_int32 dataoutcurrentsize,
			    lcrzo_int32 dataoutmaxsize,
			    lcrzo_data dataout,
			    lcrzo_int32 *pdataoutsize)
{ int direction;
  lcrzo_int32 size, i, datainstartp;

  /*parameters verification*/
  if (datain==NULL && datainsize) return(LCRZO_ERR_PANULLPTRSIZE);
  if (datainsize<0) return(LCRZO_ERR_PATOOLOW);
  if (dataoutcurrentsize<0) return(LCRZO_ERR_PATOOLOW);
  if (dataoutmaxsize<0) return(LCRZO_ERR_PATOOLOW);
  if (dataoutcurrentsize>dataoutmaxsize) return(LCRZO_ERR_PADATACURSUPMAX);
  lcrzo_er(lcrzo_priv_managedatarange(datainsize,
				      datainstartpos, datainendpos,
				      NULL, &datainstartp, NULL, NULL,
				      NULL, NULL, &direction, &size));

  if (dataoutcurrentsize+size<=dataoutmaxsize)
  { if (pdataoutsize!=NULL) *pdataoutsize=dataoutcurrentsize+size;
    if (dataout!=NULL)
    { if (direction==LCRZO_PRIV_INCREASE)
      { memcpy(dataout+dataoutcurrentsize, datain+datainstartp-1, size);
      }
      else
      { for ( i=0 ; i<size ; i++ )
        { dataout[dataoutcurrentsize+i]=datain[datainstartp-i-2];
	}
      }
    }
    return(LCRZO_ERR_OK);
  }
  else
  { if (pdataoutsize!=NULL) *pdataoutsize=dataoutmaxsize;
    if (dataout!=NULL)
    { if (direction==LCRZO_PRIV_INCREASE)
      { memcpy(dataout+dataoutcurrentsize, datain+datainstartp-1,
	       dataoutmaxsize-dataoutcurrentsize);
      }
      else
      { for ( i=0 ; i<dataoutmaxsize-dataoutcurrentsize ; i++ )
        { dataout[dataoutcurrentsize+i]=datain[datainstartp-i-2];
	}
      }
      return(LCRZO_ERR_OKDATATRUNCATED);
    }
  }
 
  /*should never be here*/
  return(lcrzo_ierp("lcrzo_data_append_range"));
}

/*-------------------------------------------------------------*/
int lcrzo_data_appendm_range(lcrzo_constdata datain,
			     lcrzo_int32 datainsize,
			     lcrzo_int32 datainstartpos,
			     lcrzo_int32 datainendpos,
			     lcrzo_int32 dataoutcurrentsize,
			     lcrzo_data *pdataout,
			     lcrzo_int32 *pdataoutsize)
{ int direction;
  lcrzo_int32 size, i, datainstartp, dataoutsize;

  /*parameters verification*/
  if (datain==NULL && datainsize) return(LCRZO_ERR_PANULLPTRSIZE);
  if (datainsize<0) return(LCRZO_ERR_PATOOLOW);
  if (dataoutcurrentsize<0) return(LCRZO_ERR_PATOOLOW);
  lcrzo_er(lcrzo_priv_managedatarange(datainsize,
				      datainstartpos, datainendpos,
				      NULL, &datainstartp, NULL, NULL,
				      NULL, NULL, &direction, &size));

  dataoutsize=dataoutcurrentsize+size;
  if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize;
  if (pdataout!=NULL)
  { lcrzo_er(lcrzo_data_realloc(dataoutsize, pdataout));
    if (direction==LCRZO_PRIV_INCREASE)
    { memcpy(*pdataout+dataoutcurrentsize, datain+datainstartp-1, size);
    }
    else
    { for ( i=0 ; i<size ; i++ )
      { (*pdataout)[dataoutcurrentsize+i]=datain[datainstartp-i-2];
      }
    }
  }
  
  return(LCRZO_ERR_OK);
}


/*-------------------------------------------------------------*/
int lcrzo_data_init_fill(lcrzo_constdata datain,
                         lcrzo_int32 datainsize,
                         lcrzo_int32 fillingsize,
                         lcrzo_int32 dataoutmaxsize,
                         lcrzo_data dataout,
                         lcrzo_int32 *pdataoutsize)
{ return(lcrzo_data_append_fill(datain, datainsize, fillingsize, 0,
                                dataoutmaxsize, dataout, pdataoutsize));
}

/*-------------------------------------------------------------*/
int lcrzo_data_initm_fill(lcrzo_constdata datain,
			  lcrzo_int32 datainsize,
			  lcrzo_int32 fillingsize,
			  lcrzo_data *pdataout,
			  lcrzo_int32 *pdataoutsize)
{ lcrzo_data ptr;

  ptr=NULL;
  lcrzo_er(lcrzo_data_appendm_fill(datain, datainsize, fillingsize, 0,
				   &ptr, pdataoutsize));
  if (pdataout!=NULL) *pdataout=ptr;
  else lcrzo_data_free(ptr);
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_data_append_fill(lcrzo_constdata datain,
                           lcrzo_int32 datainsize,
                           lcrzo_int32 fillingsize,
                           lcrzo_int32 dataoutcurrentsize,
                           lcrzo_int32 dataoutmaxsize,
                           lcrzo_data dataout,
                           lcrzo_int32 *pdataoutsize)
{ lcrzo_int32 blocknumber, bytenumberinlastblock, i;
  int ret;

  /*parameters verification*/
  if (datain==NULL && datainsize) return(LCRZO_ERR_PANULLPTRSIZE);
  if (datainsize<=0) return(LCRZO_ERR_PATOOLOW);
  if (fillingsize<=0) return(LCRZO_ERR_PATOOLOW);
  if (dataoutcurrentsize<0) return(LCRZO_ERR_PATOOLOW);
  if (dataoutmaxsize<0) return(LCRZO_ERR_PATOOLOW);
  if (dataoutcurrentsize>dataoutmaxsize) return(LCRZO_ERR_PADATACURSUPMAX);

  /*eventually recompute the filling size*/
  if (dataoutcurrentsize+fillingsize>dataoutmaxsize)
  { fillingsize=dataoutmaxsize-dataoutcurrentsize;
    if (pdataoutsize!=NULL) *pdataoutsize=dataoutmaxsize;
    ret=LCRZO_ERR_OKDATATRUNCATED;
  }
  else
  { if (pdataoutsize!=NULL) *pdataoutsize=dataoutcurrentsize+fillingsize;
    ret=LCRZO_ERR_OK;
  }

  /*we can exit now*/
  if (dataout==NULL) return(ret);

  /*append complete blocks*/
  blocknumber=fillingsize/datainsize;
  for ( i=0 ; i<blocknumber ; i++)
  { memcpy(dataout+dataoutcurrentsize+i*datainsize, datain, datainsize);
  }

  /*append last block*/
  bytenumberinlastblock=fillingsize%datainsize;
  memcpy(dataout+dataoutcurrentsize+blocknumber*datainsize, datain,
         bytenumberinlastblock);

  return(ret);
}

/*-------------------------------------------------------------*/
int lcrzo_data_appendm_fill(lcrzo_constdata datain,
			    lcrzo_int32 datainsize,
			    lcrzo_int32 fillingsize,
			    lcrzo_int32 dataoutcurrentsize,
			    lcrzo_data *pdataout,
			    lcrzo_int32 *pdataoutsize)
{ lcrzo_int32 blocknumber, bytenumberinlastblock, i, dataoutsize;

  /*parameters verification*/
  if (datain==NULL && datainsize) return(LCRZO_ERR_PANULLPTRSIZE);
  if (datainsize<=0) return(LCRZO_ERR_PATOOLOW);
  if (fillingsize<=0) return(LCRZO_ERR_PATOOLOW);
  if (dataoutcurrentsize<0) return(LCRZO_ERR_PATOOLOW);

  /*compute the output size*/
  dataoutsize=dataoutcurrentsize+fillingsize;
  if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize;

  /*init pdataout*/
  if (pdataout!=NULL)
  { lcrzo_er(lcrzo_data_realloc(dataoutsize, pdataout));
    /*append complete blocks*/
    blocknumber=fillingsize/datainsize;
    for ( i=0 ; i<blocknumber ; i++)
    { memcpy(*pdataout+dataoutcurrentsize+i*datainsize, datain, datainsize);
    }
    /*append last block*/
    bytenumberinlastblock=fillingsize%datainsize;
    memcpy(*pdataout+dataoutcurrentsize+blocknumber*datainsize, datain,
	   bytenumberinlastblock);
  }

  return(LCRZO_ERR_OK);
}


/*-------------------------------------------------------------*/
int lcrzo_data_init_char(lcrzo_uint8 c,
			 lcrzo_int32 fillingsize,
			 lcrzo_int32 dataoutmaxsize,
			 lcrzo_data dataout,
			 lcrzo_int32 *pdataoutsize)
{ return(lcrzo_data_append_char(c, fillingsize,
				0, dataoutmaxsize, dataout, pdataoutsize));
}

/*-------------------------------------------------------------*/
int lcrzo_data_initm_char(lcrzo_uint8 c,
			  lcrzo_int32 fillingsize,
			  lcrzo_data *pdataout,
			  lcrzo_int32 *pdataoutsize)
{ lcrzo_data ptr;

  ptr=NULL;
  lcrzo_er(lcrzo_data_appendm_char(c, fillingsize, 0,
				   &ptr, pdataoutsize));
  if (pdataout!=NULL) *pdataout=ptr;
  else lcrzo_data_free(ptr);
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_data_append_char(lcrzo_uint8 c,
			   lcrzo_int32 fillingsize,
			   lcrzo_int32 dataoutcurrentsize,
			   lcrzo_int32 dataoutmaxsize,
			   lcrzo_data dataout,
			   lcrzo_int32 *pdataoutsize)
{ lcrzo_int32 i;
  int ret;

  /*parameters verification*/
  if (fillingsize<=0) return(LCRZO_ERR_PATOOLOW);
  if (dataoutcurrentsize<0) return(LCRZO_ERR_PATOOLOW);
  if (dataoutmaxsize<0) return(LCRZO_ERR_PATOOLOW);
  if (dataoutcurrentsize>dataoutmaxsize) return(LCRZO_ERR_PADATACURSUPMAX);

  /*eventually recompute the filling size*/
  if (dataoutcurrentsize+fillingsize>dataoutmaxsize)
  { fillingsize=dataoutmaxsize-dataoutcurrentsize;
    if (pdataoutsize!=NULL) *pdataoutsize=dataoutmaxsize;
    ret=LCRZO_ERR_OKDATATRUNCATED;
  }
  else
  { if (pdataoutsize!=NULL) *pdataoutsize=dataoutcurrentsize+fillingsize;
    ret=LCRZO_ERR_OK;
  }

  /*we can exit now*/
  if (dataout==NULL) return(ret);

  /*append complete blocks*/
  for ( i=0 ; i<fillingsize ; i++)
  { dataout[dataoutcurrentsize+i]=c;
  }

  return(ret);
}

/*-------------------------------------------------------------*/
int lcrzo_data_appendm_char(lcrzo_uint8 c,
			    lcrzo_int32 fillingsize,
			    lcrzo_int32 dataoutcurrentsize,
			    lcrzo_data *pdataout,
			    lcrzo_int32 *pdataoutsize)
{ lcrzo_int32 i, dataoutsize;

  /*parameters verification*/
  if (fillingsize<=0) return(LCRZO_ERR_PATOOLOW);
  if (dataoutcurrentsize<0) return(LCRZO_ERR_PATOOLOW);

  /*eventually recompute the filling size*/
  dataoutsize=dataoutcurrentsize+fillingsize;
  if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize;

  /*init pdataout*/
  if (pdataout!=NULL)
  { lcrzo_er(lcrzo_data_realloc(dataoutsize, pdataout));
    /*append complete blocks*/
    for ( i=0 ; i<fillingsize ; i++)
    { (*pdataout)[dataoutcurrentsize+i]=c;
    }
  }
  return(LCRZO_ERR_OK);
}


/*-------------------------------------------------------------*/
int lcrzo_data_init_rand(lcrzo_uint8 minvalue,
			 lcrzo_uint8 maxvalue,
			 lcrzo_int32 fillingsize,
			 lcrzo_int32 dataoutmaxsize,
			 lcrzo_data dataout,
			 lcrzo_int32 *pdataoutsize)
{ return(lcrzo_data_append_rand(minvalue, maxvalue, fillingsize,
				0, dataoutmaxsize, dataout, pdataoutsize));
}

/*-------------------------------------------------------------*/
int lcrzo_data_initm_rand(lcrzo_uint8 minvalue,
			  lcrzo_uint8 maxvalue,
			  lcrzo_int32 fillingsize,
			  lcrzo_data *pdataout,
			  lcrzo_int32 *pdataoutsize)
{ lcrzo_data ptr;

  ptr=NULL;
  lcrzo_er(lcrzo_data_appendm_rand(minvalue, maxvalue, fillingsize, 0,
				   &ptr, pdataoutsize));
  if (pdataout!=NULL) *pdataout=ptr;
  else lcrzo_data_free(ptr);
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_data_append_rand(lcrzo_uint8 minvalue,
			   lcrzo_uint8 maxvalue,
			   lcrzo_int32 fillingsize,
			   lcrzo_int32 dataoutcurrentsize,
			   lcrzo_int32 dataoutmaxsize,
			   lcrzo_data dataout,
			   lcrzo_int32 *pdataoutsize)
{ lcrzo_int32 i;
  int ret;

  /*parameters verification*/
  if (fillingsize<=0) return(LCRZO_ERR_PATOOLOW);
  if (dataoutcurrentsize<0) return(LCRZO_ERR_PATOOLOW);
  if (dataoutmaxsize<0) return(LCRZO_ERR_PATOOLOW);
  if (dataoutcurrentsize>dataoutmaxsize) return(LCRZO_ERR_PADATACURSUPMAX);

  /*eventually recompute the filling size*/
  if (dataoutcurrentsize+fillingsize>dataoutmaxsize)
  { fillingsize=dataoutmaxsize-dataoutcurrentsize;
    if (pdataoutsize!=NULL) *pdataoutsize=dataoutmaxsize;
    ret=LCRZO_ERR_OKDATATRUNCATED;
  }
  else
  { if (pdataoutsize!=NULL) *pdataoutsize=dataoutcurrentsize+fillingsize;
    ret=LCRZO_ERR_OK;
  }

  /*we can exit now*/
  if (dataout==NULL) return(ret);

  /*append complete blocks*/
  for ( i=0 ; i<fillingsize ; i++)
  { lcrzo_er(lcrzo_uint8_init_rand(minvalue, maxvalue,
			      &(dataout[dataoutcurrentsize+i]))); 
  }

  return(ret);
}

/*-------------------------------------------------------------*/
int lcrzo_data_appendm_rand(lcrzo_uint8 minvalue,
			    lcrzo_uint8 maxvalue,
			    lcrzo_int32 fillingsize,
			    lcrzo_int32 dataoutcurrentsize,
			    lcrzo_data *pdataout,
			    lcrzo_int32 *pdataoutsize)
{ lcrzo_int32 i, dataoutsize;

  /*parameters verification*/
  if (fillingsize<=0) return(LCRZO_ERR_PATOOLOW);
  if (dataoutcurrentsize<0) return(LCRZO_ERR_PATOOLOW);

  /*eventually recompute the filling size*/
  dataoutsize=dataoutcurrentsize+fillingsize;
  if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize;

  /*init pdataout*/
  if (pdataout!=NULL)
  { lcrzo_er(lcrzo_data_realloc(dataoutsize, pdataout));
    /*append complete blocks*/
    for ( i=0 ; i<fillingsize ; i++)
    { lcrzo_er(lcrzo_uint8_init_rand(minvalue, maxvalue,
				&((*pdataout)[dataoutcurrentsize+i]))); 
    }
  }
  return(LCRZO_ERR_OK);
}


/*-------------------------------------------------------------*/
int lcrzo_data_init_int(lcrzo_int32 integer,
			const char * format,
			lcrzo_int32 dataoutmaxsize,
			lcrzo_data dataout,
			lcrzo_int32 *pdataoutsize)
{ return(lcrzo_data_append_int(integer, format, 0, dataoutmaxsize, 
			       dataout, pdataoutsize));
}

/*-------------------------------------------------------------*/
int lcrzo_data_initm_int(lcrzo_int32 integer,
			 const char * format,
			 lcrzo_data *pdataout,
			 lcrzo_int32 *pdataoutsize)
{ lcrzo_data ptr;

  ptr=NULL;
  lcrzo_er(lcrzo_data_appendm_int(integer, format, 0,
				  &ptr, pdataoutsize));
  if (pdataout!=NULL) *pdataout=ptr;
  else lcrzo_data_free(ptr);
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_data_append_int(lcrzo_int32 integer,
			  const char * format,
			  lcrzo_int32 dataoutcurrentsize,
			  lcrzo_int32 dataoutmaxsize,
			  lcrzo_data dataout,
			  lcrzo_int32 *pdataoutsize)
{ char tmp[101]; /*le format maxi est %+99X -> 100 octets maxi*/
  lcrzo_string newfmt;

  /*parameters verification*/
  if (format==NULL) return(LCRZO_ERR_PANULLPTR);
  if (dataoutcurrentsize<0) return(LCRZO_ERR_PATOOLOW);
  if (dataoutmaxsize<0) return(LCRZO_ERR_PATOOLOW);
  if (dataoutcurrentsize>dataoutmaxsize) return(LCRZO_ERR_PADATACURSUPMAX);

  /*copy the integer*/
  lcrzo_er(lcrzo_priv_int_fmt_check(format, LCRZO_TRUE, &newfmt));
  sprintf(tmp, newfmt, integer);
  lcrzo_string_free(newfmt);
  return(lcrzo_data_append_data((lcrzo_constdata)tmp, strlen(tmp),
				dataoutcurrentsize,
				dataoutmaxsize, dataout, pdataoutsize));
}

/*-------------------------------------------------------------*/
int lcrzo_data_appendm_int(lcrzo_int32 integer,
			   const char * format,
			   lcrzo_int32 dataoutcurrentsize,
			   lcrzo_data *pdataout,
			   lcrzo_int32 *pdataoutsize)
{ char tmp[101]; /*le format maxi est %+99X -> 100 octets maxi*/
  lcrzo_string newfmt;

  /*parameters verification*/
  if (format==NULL) return(LCRZO_ERR_PANULLPTR);
  if (dataoutcurrentsize<0) return(LCRZO_ERR_PATOOLOW);

  /*copy the integer*/
  lcrzo_er(lcrzo_priv_int_fmt_check(format, LCRZO_TRUE, &newfmt));
  sprintf(tmp, newfmt, integer);
  lcrzo_string_free(newfmt);
  return(lcrzo_data_appendm_data((lcrzo_constdata)tmp, strlen(tmp),
				 dataoutcurrentsize,
				 pdataout, pdataoutsize));
}


/*-------------------------------------------------------------*/
int lcrzo_data_init_text(const char * text,
			 lcrzo_int32 dataoutmaxsize,
			 lcrzo_data dataout,
			 lcrzo_int32 *pdataoutsize)
{ return(lcrzo_data_append_text(text, 0, dataoutmaxsize,
				dataout, pdataoutsize));
}

/*-------------------------------------------------------------*/
int lcrzo_data_initm_text(const char * text,
			  lcrzo_data *pdataout,
			  lcrzo_int32 *pdataoutsize)
{ lcrzo_data ptr;

  ptr=NULL;
  lcrzo_er(lcrzo_data_appendm_text(text, 0, &ptr, pdataoutsize));
  if (pdataout!=NULL) *pdataout=ptr;
  else lcrzo_data_free(ptr);
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_data_append_text(const char * text,
			   lcrzo_int32 dataoutcurrentsize,
			   lcrzo_int32 dataoutmaxsize,
			   lcrzo_data dataout,
			   lcrzo_int32 *pdataoutsize)
{
  /*parameters verification*/
  if (text==NULL) return(LCRZO_ERR_PANULLPTR);
  if (dataoutcurrentsize<0) return(LCRZO_ERR_PATOOLOW);
  if (dataoutmaxsize<0) return(LCRZO_ERR_PATOOLOW);
  if (dataoutcurrentsize>dataoutmaxsize) return(LCRZO_ERR_PADATACURSUPMAX);

  return(lcrzo_data_append_data((lcrzo_constdata)text, strlen(text),
				dataoutcurrentsize,
				dataoutmaxsize, dataout, pdataoutsize));
}

/*-------------------------------------------------------------*/
int lcrzo_data_appendm_text(const char * text,
			    lcrzo_int32 dataoutcurrentsize,
			    lcrzo_data *pdataout,
			    lcrzo_int32 *pdataoutsize)
{
  /*parameters verification*/
  if (text==NULL) return(LCRZO_ERR_PANULLPTR);
  if (dataoutcurrentsize<0) return(LCRZO_ERR_PATOOLOW);

  return(lcrzo_data_appendm_data((lcrzo_constdata)text, strlen(text),
				 dataoutcurrentsize,
				 pdataout, pdataoutsize));
}


/*-------------------------------------------------------------*/
int lcrzo_data_init_coretext(const char * text,
			     lcrzo_int32 dataoutmaxsize,
			     lcrzo_data dataout,
			     lcrzo_int32 *pdataoutsize)
{ return(lcrzo_data_append_coretext(text, 0, dataoutmaxsize,
				    dataout, pdataoutsize));
}

/*-------------------------------------------------------------*/
int lcrzo_data_initm_coretext(const char * text,
			      lcrzo_data *pdataout,
			      lcrzo_int32 *pdataoutsize)
{ lcrzo_data ptr;

  ptr=NULL;
  lcrzo_er(lcrzo_data_appendm_coretext(text, 0, &ptr, pdataoutsize));
  if (pdataout!=NULL) *pdataout=ptr;
  else lcrzo_data_free(ptr);
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_data_append_coretext(const char * text,
			       lcrzo_int32 dataoutcurrentsize,
			       lcrzo_int32 dataoutmaxsize,
			       lcrzo_data dataout,
			       lcrzo_int32 *pdataoutsize)
{ lcrzo_int32 startpos, endpos, strlentext, i;
  char c;

  /*parameters verification*/
  if (text==NULL) return(LCRZO_ERR_PANULLPTR);
  if (dataoutcurrentsize<0) return(LCRZO_ERR_PATOOLOW);
  if (dataoutmaxsize<0) return(LCRZO_ERR_PATOOLOW);
  if (dataoutcurrentsize>dataoutmaxsize) return(LCRZO_ERR_PADATACURSUPMAX);

  /*find the start pos*/
  strlentext=strlen(text);
  for ( i=0 ; i<strlentext ; i++ )
  { c=text[i];
    if ( c!=' ' && c!=0x0D && c!=0x0A && c!='\t' ) break;
  }
  if ( i==strlentext )
  { /*it's an empty string*/
    if (pdataoutsize!=NULL) *pdataoutsize=dataoutcurrentsize;
    return(LCRZO_ERR_OK);
  }
  else
    startpos=i+1;

  /*find the end pos*/
  for ( i=strlentext-1 ; i>=0 ; i-- )
  { c=text[i];
    if ( c!=' ' && c!=0x0D && c!=0x0A && c!='\t' ) break;
  }
  endpos=i+2;

  return(lcrzo_data_append_range((lcrzo_constdata)text, strlen(text),
				 startpos, endpos,
				 dataoutcurrentsize,
				 dataoutmaxsize, dataout, pdataoutsize));
}

/*-------------------------------------------------------------*/
int lcrzo_data_appendm_coretext(const char * text,
				lcrzo_int32 dataoutcurrentsize,
				lcrzo_data *pdataout,
				lcrzo_int32 *pdataoutsize)
{ lcrzo_int32 startpos, endpos, strlentext, i;
  char c;

  /*parameters verification*/
  if (text==NULL) return(LCRZO_ERR_PANULLPTR);
  if (dataoutcurrentsize<0) return(LCRZO_ERR_PATOOLOW);

  /*find the start pos*/
  strlentext=strlen(text);
  for ( i=0 ; i<strlentext ; i++ )
  { c=text[i];
    if ( c!=' ' && c!=0x0D && c!=0x0A && c!='\t' ) break;
  }
  if ( i==strlentext )
  { /*it's an empty string*/
    if (pdataout!=NULL)
    { lcrzo_er(lcrzo_data_realloc(dataoutcurrentsize, pdataout));
    }
    if (pdataoutsize!=NULL) *pdataoutsize=dataoutcurrentsize;
    return(LCRZO_ERR_OK);
  }
  else
    startpos=i+1;

  /*find the end pos*/
  for ( i=strlentext-1 ; i>=0 ; i-- )
  { c=text[i];
    if ( c!=' ' && c!=0x0D && c!=0x0A && c!='\t' ) break;
  }
  endpos=i+2;

  return(lcrzo_data_appendm_range((lcrzo_constdata)text, strlen(text),
				  startpos, endpos,
				  dataoutcurrentsize,
				  pdataout, pdataoutsize));
}


/*-------------------------------------------------------------*/
int lcrzo_data_init_hexa(const char * hexa,
			 lcrzo_int32 dataoutmaxsize,
			 lcrzo_data dataout,
			 lcrzo_int32 *pdataoutsize)
{ return(lcrzo_data_append_hexa(hexa, 0, dataoutmaxsize,
				dataout, pdataoutsize));
}

/*-------------------------------------------------------------*/
int lcrzo_data_initm_hexa(const char * hexa,
			  lcrzo_data *pdataout,
			  lcrzo_int32 *pdataoutsize)
{ lcrzo_data ptr;

  ptr=NULL;
  lcrzo_er(lcrzo_data_appendm_hexa(hexa, 0, &ptr, pdataoutsize));
  if (pdataout!=NULL) *pdataout=ptr;
  else lcrzo_data_free(ptr);
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_data_append_hexa(const char * hexa,
			   lcrzo_int32 dataoutcurrentsize,
			   lcrzo_int32 dataoutmaxsize,
			   lcrzo_data dataout,
			   lcrzo_int32 *pdataoutsize)
{ int quartet, quartet1, quartet1rempli, strlenhexa;
  int c, i;
  lcrzo_int32 nboctpacket;

  /*parameters verification*/
  if (hexa==NULL) return(LCRZO_ERR_PANULLPTR);
  if (dataoutcurrentsize<0) return(LCRZO_ERR_PATOOLOW);
  if (dataoutmaxsize<0) return(LCRZO_ERR_PATOOLOW);
  if (dataoutcurrentsize>dataoutmaxsize) return(LCRZO_ERR_PADATACURSUPMAX);

  /*initialisation*/
  quartet1rempli=0;
  quartet=quartet1=0;
  nboctpacket=dataoutcurrentsize;
  strlenhexa=strlen(hexa);
  /*parcours de la table*/
  for ( i=0 ; i<strlenhexa ; i++ )
  { c=hexa[i];
    if ( isxdigit(c) )
    { if (nboctpacket>=dataoutmaxsize)
      { if (pdataoutsize!=NULL) *pdataoutsize=dataoutmaxsize;
        return(LCRZO_ERR_OKDATATRUNCATED);
      }
      if (c>='0'&&c<='9') quartet=c-'0';
      else if (c>='a'&&c<='f') quartet=c-'a'+10;
      else if (c>='A'&&c<='F') quartet=c-'A'+10;
      if (quartet1rempli) 
      { if (dataout!=NULL)
        { dataout[nboctpacket] = (lcrzo_uint8)( (quartet1<<4)|quartet );
	}
        nboctpacket++;
        quartet1rempli=0;
      }
      else
      { quartet1=quartet;
        quartet1rempli=1;
      }
    }
    else if ( c==' ' || c==0x0D || c==0x0A || c=='\t' ) {continue;}
    else
    { return(LCRZO_ERR_FMHEXACHAR);
    }
  }
  /*verification*/
  if ( quartet1rempli ) 
  { return(LCRZO_ERR_FMHEXAODD);
  }

  if (pdataoutsize!=NULL) *pdataoutsize=nboctpacket;
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_data_appendm_hexa(const char * hexa,
			    lcrzo_int32 dataoutcurrentsize,
			    lcrzo_data *pdataout,
			    lcrzo_int32 *pdataoutsize)
{ int quartet, quartet1, quartet1rempli, strlenhexa;
  int c, i;
  lcrzo_int32 nboctpacket;

  /*parameters verification*/
  if (hexa==NULL) return(LCRZO_ERR_PANULLPTR);
  if (dataoutcurrentsize<0) return(LCRZO_ERR_PATOOLOW);

  /*initialisation*/
  quartet1rempli=0;
  quartet=quartet1=0;
  nboctpacket=dataoutcurrentsize;
  strlenhexa=strlen(hexa);

  /*reallocate pdataout (it might be too big, but at the end of this 
    function, we realloc exactly)*/
  if (pdataout!=NULL)
  { lcrzo_er(lcrzo_data_realloc(dataoutcurrentsize+strlenhexa/2, pdataout));
  }

  /*parcours de la table*/
  for ( i=0 ; i<strlenhexa ; i++ )
  { c=hexa[i];
    if ( isxdigit(c) )
    { if (c>='0'&&c<='9') quartet=c-'0';
      else if (c>='a'&&c<='f') quartet=c-'a'+10;
      else if (c>='A'&&c<='F') quartet=c-'A'+10;
      if (quartet1rempli) 
      { if (pdataout!=NULL)
        { (*pdataout)[nboctpacket] = (lcrzo_uint8)( (quartet1<<4)|quartet );
	}
        nboctpacket++;
        quartet1rempli=0;
      }
      else
      { quartet1=quartet;
        quartet1rempli=1;
      }
    }
    else if ( c==' ' || c==0x0D || c==0x0A || c=='\t' ) {continue;}
    else
    { return(LCRZO_ERR_FMHEXACHAR);
    }
  }
  /*verification*/
  if ( quartet1rempli ) 
  { return(LCRZO_ERR_FMHEXAODD);
  }

  /*realloc exactly*/
  if (pdataout!=NULL)
  { lcrzo_er(lcrzo_data_realloc(dataoutcurrentsize+nboctpacket, pdataout));
  }
  if (pdataoutsize!=NULL) *pdataoutsize=nboctpacket;
  return(LCRZO_ERR_OK);
}


/*-------------------------------------------------------------*/
int lcrzo_data_init_mixed(const char * mixed,
			  lcrzo_int32 dataoutmaxsize,
			  lcrzo_data dataout,
			  lcrzo_int32 *pdataoutsize)
{ return(lcrzo_data_append_mixed(mixed, 0, dataoutmaxsize,
				dataout, pdataoutsize));
}

/*-------------------------------------------------------------*/
int lcrzo_data_initm_mixed(const char * mixed,
			   lcrzo_data *pdataout,
			   lcrzo_int32 *pdataoutsize)
{ lcrzo_data ptr;

  ptr=NULL;
  lcrzo_er(lcrzo_data_appendm_mixed(mixed, 0, &ptr, pdataoutsize));
  if (pdataout!=NULL) *pdataout=ptr;
  else lcrzo_data_free(ptr);
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_data_append_mixed(const char * mixed,
			    lcrzo_int32 dataoutcurrentsize,
			    lcrzo_int32 dataoutmaxsize,
			    lcrzo_data dataout,
			    lcrzo_int32 *pdataoutsize)
{ int mode; /* 1:hexa ; 2:ascii */
  int quartet, quartet1, quartet1rempli, strlenmixed;
  int c;
  lcrzo_int32 i, nboctpacket;

  /*parameters verification*/
  if (mixed==NULL) return(LCRZO_ERR_PANULLPTR);
  if (dataoutcurrentsize<0) return(LCRZO_ERR_PATOOLOW);
  if (dataoutmaxsize<0) return(LCRZO_ERR_PATOOLOW);
  if (dataoutcurrentsize>dataoutmaxsize) return(LCRZO_ERR_PADATACURSUPMAX);

  /*initialisations*/
  mode=1;
  nboctpacket=dataoutcurrentsize;
  quartet1rempli=0;
  quartet=quartet1=0;
  strlenmixed=strlen(mixed);

  /*lecture*/
  for ( i=0 ; i<strlenmixed ; i++)
  { c=mixed[i];

    /*lecture des donnees*/
    switch(mode)
    { case 1: /*hexa*/
        /*changement de mode*/
        if (c=='\'')
        { mode=2;
	  if (quartet1rempli ) return(LCRZO_ERR_FMHEXAODD);
	  continue;
        }
        /*calcul de la valeur hexa*/
        if ( isxdigit(c) )
        { if (nboctpacket>=dataoutmaxsize)
	  { if (pdataoutsize!=NULL) *pdataoutsize=dataoutmaxsize;
	    return(LCRZO_ERR_OKDATATRUNCATED);
	  }
	  if (c>='0'&&c<='9') quartet=c-'0';
          else if (c>='a'&&c<='f') quartet=c-'a'+10;
          else if (c>='A'&&c<='F') quartet=c-'A'+10;
          if (quartet1rempli) 
          { if (dataout!=NULL)
            { dataout[nboctpacket]=(lcrzo_uint8)( (quartet1<<4)|quartet );
            }
	    nboctpacket++;
            quartet1rempli=0;
          }
          else
          { quartet1=quartet;
            quartet1rempli=1;
          }
        }
        else if ( c==' ' || c==0x0D || c==0x0A || c=='\t' ) {continue;}
        else return(LCRZO_ERR_FMHEXACHAR);
        break;
      case 2: /*ascii*/
        if (nboctpacket>=dataoutmaxsize)
	{ if (pdataoutsize!=NULL) *pdataoutsize=dataoutmaxsize;
	  return(LCRZO_ERR_OKDATATRUNCATED);
	}
	if (c=='\'')
        { if ((i+1)==strlenmixed) {mode=1; continue;}
          if (mixed[i+1]=='\'') 
	  { if (dataout!=NULL) dataout[nboctpacket]='\'';
	    nboctpacket++;
            i++;
	  }
          else mode=1;
        }
        else
        { if (dataout!=NULL) dataout[nboctpacket]=(lcrzo_uint8)(c);
	  nboctpacket++;
	}
        break;
    }
  } 

  /*cas d'erreur*/
  if ( mode==1 && quartet1rempli ) return(LCRZO_ERR_FMHEXAODD);
  else if ( mode==2 ) return(LCRZO_ERR_FMMIXED);

  if (pdataoutsize!=NULL) *pdataoutsize=nboctpacket;
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_data_appendm_mixed(const char * mixed,
			     lcrzo_int32 dataoutcurrentsize,
			     lcrzo_data *pdataout,
			     lcrzo_int32 *pdataoutsize)
{ int mode; /* 1:hexa ; 2:ascii */
  int quartet, quartet1, quartet1rempli, strlenmixed;
  int c;
  lcrzo_int32 i, nboctpacket;

  /*parameters verification*/
  if (mixed==NULL) return(LCRZO_ERR_PANULLPTR);
  if (dataoutcurrentsize<0) return(LCRZO_ERR_PATOOLOW);

  /*initialisations*/
  mode=1;
  nboctpacket=dataoutcurrentsize;
  quartet1rempli=0;
  quartet=quartet1=0;
  strlenmixed=strlen(mixed);

  /*reallocate pdataout (it might be too big, but at the end of this 
    function, we realloc exactly)*/
  if (pdataout!=NULL)
  { lcrzo_er(lcrzo_data_realloc(dataoutcurrentsize+strlenmixed, pdataout));
  }

  /*lecture*/
  for ( i=0 ; i<strlenmixed ; i++)
  { c=mixed[i];

    /*lecture des donnees*/
    switch(mode)
    { case 1: /*hexa*/
        /*changement de mode*/
        if (c=='\'')
        { mode=2;
	  if (quartet1rempli ) return(LCRZO_ERR_FMHEXAODD);
	  continue;
        }
        /*calcul de la valeur hexa*/
        if ( isxdigit(c) )
        { if (c>='0'&&c<='9') quartet=c-'0';
          else if (c>='a'&&c<='f') quartet=c-'a'+10;
          else if (c>='A'&&c<='F') quartet=c-'A'+10;
          if (quartet1rempli) 
          { if (pdataout!=NULL)
            { (*pdataout)[nboctpacket]=(lcrzo_uint8)( (quartet1<<4)|quartet );
            }
	    nboctpacket++;
            quartet1rempli=0;
          }
          else
          { quartet1=quartet;
            quartet1rempli=1;
          }
        }
        else if ( c==' ' || c==0x0D || c==0x0A || c=='\t' ) {continue;}
        else return(LCRZO_ERR_FMHEXACHAR);
        break;
      case 2: /*ascii*/
        if (c=='\'')
        { if ((i+1)==strlenmixed) {mode=1; continue;}
          if (mixed[i+1]=='\'') 
	  { if (pdataout!=NULL) (*pdataout)[nboctpacket]='\'';
	    nboctpacket++;
            i++;
	  }
          else mode=1;
        }
        else
        { if (pdataout!=NULL) (*pdataout)[nboctpacket]=(lcrzo_uint8)(c);
	  nboctpacket++;
	}
        break;
    }
  } 

  /*cas d'erreur*/
  if ( mode==1 && quartet1rempli ) return(LCRZO_ERR_FMHEXAODD);
  else if ( mode==2 ) return(LCRZO_ERR_FMMIXED);

  /*realloc exactly*/
  if (pdataout!=NULL)
  { lcrzo_er(lcrzo_data_realloc(dataoutcurrentsize+nboctpacket, pdataout));
  }
  if (pdataoutsize!=NULL) *pdataoutsize=nboctpacket;
  return(LCRZO_ERR_OK);
}


/*-------------------------------------------------------------*/
int lcrzo_data_init_base64(const char * base64,
			   lcrzo_int32 dataoutmaxsize,
			   lcrzo_data dataout,
			   lcrzo_int32 *pdataoutsize)
{ return(lcrzo_data_append_base64(base64, 0, dataoutmaxsize,
				  dataout, pdataoutsize));
}

/*-------------------------------------------------------------*/
int lcrzo_data_initm_base64(const char * base64,
			    lcrzo_data *pdataout,
			    lcrzo_int32 *pdataoutsize)
{ lcrzo_data ptr;

  ptr=NULL;
  lcrzo_er(lcrzo_data_appendm_base64(base64, 0, &ptr, pdataoutsize));
  if (pdataout!=NULL) *pdataout=ptr;
  else lcrzo_data_free(ptr);
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_data_append_base64(const char * base64,
			     lcrzo_int32 dataoutcurrentsize,
			     lcrzo_int32 dataoutmaxsize,
			     lcrzo_data dataout,
			     lcrzo_int32 *pdataoutsize)
{ int nboct, i, nbblocscomplets, nbcaracrestant, j;
  lcrzo_uint8 ent1, ent2;
  lcrzo_data ptr;
  lcrzo_int32 ptrdatasize;

  /*parameters verification*/
  if (base64==NULL) return(LCRZO_ERR_PANULLPTR);
  if (dataoutcurrentsize<0) return(LCRZO_ERR_PATOOLOW);
  if (dataoutmaxsize<0) return(LCRZO_ERR_PATOOLOW);
  if (dataoutcurrentsize>dataoutmaxsize) return(LCRZO_ERR_PADATACURSUPMAX);

  lcrzo_er(lcrzo_data_initm_coretext(base64, &ptr, &ptrdatasize));
  ptr[ptrdatasize]='\0';

  /*verification*/
  nboct=strlen((const char*)ptr);
  if (nboct==0)
  { if (pdataoutsize!=NULL) *pdataoutsize=dataoutcurrentsize;
    lcrzo_data_free(ptr);
    return(LCRZO_ERR_OK);
  }
  if ( nboct%4 )
  { lcrzo_data_free(ptr);
    return(LCRZO_ERR_FMBASE64X4);
  }

  /*calcul des blocs complets et incomplets*/
  if ( ptr[nboct-1]=='=' && ptr[nboct-2]=='=' )
  { nbblocscomplets= nboct/4 - 1;
    nbcaracrestant=1;
  }
  else if ( ptr[nboct-1]=='=' )
  { nbblocscomplets= nboct/4 - 1;
    nbcaracrestant=2;
  }
  else
  { nbblocscomplets= nboct/4;
    nbcaracrestant=0;
  }
  if (pdataoutsize!=NULL)
  { *pdataoutsize=dataoutcurrentsize+3*nbblocscomplets+nbcaracrestant;
    if (*pdataoutsize>dataoutmaxsize) *pdataoutsize=dataoutmaxsize;
  }

  j=dataoutcurrentsize;
  /*traite les blocs complets*/
  for ( i=0 ; i<nbblocscomplets ; i++ )
  { if ( lcrzo_priv_base64cb642ent(ptr[4*i], &ent1) ||
	 lcrzo_priv_base64cb642ent(ptr[4*i+1], &ent2) )
    { lcrzo_data_free(ptr);
      return(LCRZO_ERR_FMBASE64CHAR);
    }
    if (j>=dataoutmaxsize) 
    { lcrzo_data_free(ptr);
      return(LCRZO_ERR_OKDATATRUNCATED);
    }
    if (dataout!=NULL) dataout[j++]=(lcrzo_uint8)( (ent1<<2)|(ent2>>4) );
    if ( lcrzo_priv_base64cb642ent(ptr[4*i+1], &ent1) ||
	 lcrzo_priv_base64cb642ent(ptr[4*i+2], &ent2) )
    { lcrzo_data_free(ptr);
      return(LCRZO_ERR_FMBASE64CHAR);
    }
    if (j>=dataoutmaxsize) 
    { lcrzo_data_free(ptr);
      return(LCRZO_ERR_OKDATATRUNCATED);
    }
    if (dataout!=NULL) dataout[j++]=(lcrzo_uint8)( (ent1<<4)|(ent2>>2) );
    if ( lcrzo_priv_base64cb642ent(ptr[4*i+2], &ent1) ||
	 lcrzo_priv_base64cb642ent(ptr[4*i+3], &ent2) )
    { lcrzo_data_free(ptr);
      return(LCRZO_ERR_FMBASE64CHAR);
    }
    if (j>=dataoutmaxsize) 
    { lcrzo_data_free(ptr); 
      return(LCRZO_ERR_OKDATATRUNCATED);
    }
    if (dataout!=NULL) dataout[j++]=(lcrzo_uint8)( (ent1<<6)|(ent2) );
  }
  if ( nbcaracrestant==2 )
  { if ( lcrzo_priv_base64cb642ent(ptr[4*i], &ent1) ||
	 lcrzo_priv_base64cb642ent(ptr[4*i+1], &ent2) )
    { lcrzo_data_free(ptr);
      return(LCRZO_ERR_FMBASE64CHAR);
    }
    if (j>=dataoutmaxsize) 
    { lcrzo_data_free(ptr); 
      return(LCRZO_ERR_OKDATATRUNCATED);
    }
    if (dataout!=NULL) dataout[j++]=(lcrzo_uint8)( (ent1<<2)|(ent2>>4) );
    if ( lcrzo_priv_base64cb642ent(ptr[4*i+1], &ent1) ||
	 lcrzo_priv_base64cb642ent(ptr[4*i+2], &ent2) )
    { lcrzo_data_free(ptr);
      return(LCRZO_ERR_FMBASE64CHAR);
    }
    if (j>=dataoutmaxsize) 
    { lcrzo_data_free(ptr); 
      return(LCRZO_ERR_OKDATATRUNCATED);
    }
    if (dataout!=NULL) dataout[j++]=(lcrzo_uint8)( (ent1<<4)|(ent2>>2) );
  }
  else if ( nbcaracrestant==1 )
  { if ( lcrzo_priv_base64cb642ent(ptr[4*i], &ent1) ||
	 lcrzo_priv_base64cb642ent(ptr[4*i+1], &ent2) )
    { lcrzo_data_free(ptr);
      return(LCRZO_ERR_FMBASE64CHAR);
    }
    if (j>=dataoutmaxsize) 
    { lcrzo_data_free(ptr); 
      return(LCRZO_ERR_OKDATATRUNCATED);
    }
    if (dataout!=NULL) dataout[j++]=(lcrzo_uint8)( (ent1<<2)|(ent2>>4) );
  }

  lcrzo_data_free(ptr);
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_data_appendm_base64(const char * base64,
			      lcrzo_int32 dataoutcurrentsize,
			      lcrzo_data *pdataout,
			      lcrzo_int32 *pdataoutsize)
{ int nboct, i, nbblocscomplets, nbcaracrestant, j, dataoutsize;
  lcrzo_uint8 ent1, ent2;
  lcrzo_data ptr;
  lcrzo_int32 ptrdatasize;

  /*parameters verification*/
  if (base64==NULL) return(LCRZO_ERR_PANULLPTR);
  if (dataoutcurrentsize<0) return(LCRZO_ERR_PATOOLOW);

  lcrzo_er(lcrzo_data_initm_coretext(base64, &ptr, &ptrdatasize));
  ptr[ptrdatasize]='\0';

  /*verification*/
  nboct=strlen((const char*)ptr);
  if (nboct==0)
  { lcrzo_data_free(ptr);
    if (pdataoutsize!=NULL) *pdataoutsize=dataoutcurrentsize;
    if (pdataout!=NULL)
    { lcrzo_er(lcrzo_data_realloc(dataoutcurrentsize, pdataout));
    }
    return(LCRZO_ERR_OK);
  }
  if ( nboct%4 )
  { lcrzo_data_free(ptr);
    return(LCRZO_ERR_FMBASE64X4);
  }

  /*calcul des blocs complets et incomplets*/
  if ( ptr[nboct-1]=='=' && ptr[nboct-2]=='=' )
  { nbblocscomplets= nboct/4 - 1;
    nbcaracrestant=1;
  }
  else if ( ptr[nboct-1]=='=' )
  { nbblocscomplets= nboct/4 - 1;
    nbcaracrestant=2;
  }
  else
  { nbblocscomplets= nboct/4;
    nbcaracrestant=0;
  }

  /*realloc exactly*/
  dataoutsize=dataoutcurrentsize+3*nbblocscomplets+nbcaracrestant;
  if (pdataout!=NULL)
  { lcrzo_efr(lcrzo_data_realloc(dataoutsize, pdataout), lcrzo_data_free(ptr));
  }
  if (pdataoutsize!=NULL)
  { *pdataoutsize=dataoutsize;
  }

  j=dataoutcurrentsize;
  /*traite les blocs complets*/
  for ( i=0 ; i<nbblocscomplets ; i++ )
  { if ( lcrzo_priv_base64cb642ent(ptr[4*i], &ent1) ||
	 lcrzo_priv_base64cb642ent(ptr[4*i+1], &ent2) )
    { lcrzo_data_free(ptr);
      return(LCRZO_ERR_FMBASE64CHAR);
    }
    if (pdataout!=NULL) (*pdataout)[j++]=(lcrzo_uint8)( (ent1<<2)|(ent2>>4) );
    if ( lcrzo_priv_base64cb642ent(ptr[4*i+1], &ent1) ||
	 lcrzo_priv_base64cb642ent(ptr[4*i+2], &ent2) )
    { lcrzo_data_free(ptr);
      return(LCRZO_ERR_FMBASE64CHAR);
    }
    if (pdataout!=NULL) (*pdataout)[j++]=(lcrzo_uint8)( (ent1<<4)|(ent2>>2) );
    if ( lcrzo_priv_base64cb642ent(ptr[4*i+2], &ent1) ||
	 lcrzo_priv_base64cb642ent(ptr[4*i+3], &ent2) )
    { lcrzo_data_free(ptr);
      return(LCRZO_ERR_FMBASE64CHAR);
    }
    if (pdataout!=NULL) (*pdataout)[j++]=(lcrzo_uint8)( (ent1<<6)|(ent2) );
  }
  if ( nbcaracrestant==2 )
  { if ( lcrzo_priv_base64cb642ent(ptr[4*i], &ent1) ||
	 lcrzo_priv_base64cb642ent(ptr[4*i+1], &ent2) )
    { lcrzo_data_free(ptr);
      return(LCRZO_ERR_FMBASE64CHAR);
    }
    if (pdataout!=NULL) (*pdataout)[j++]=(lcrzo_uint8)( (ent1<<2)|(ent2>>4) );
    if ( lcrzo_priv_base64cb642ent(ptr[4*i+1], &ent1) ||
	 lcrzo_priv_base64cb642ent(ptr[4*i+2], &ent2) )
    { lcrzo_data_free(ptr);
      return(LCRZO_ERR_FMBASE64CHAR);
    }
    if (pdataout!=NULL) (*pdataout)[j++]=(lcrzo_uint8)( (ent1<<4)|(ent2>>2) );
  }
  else if ( nbcaracrestant==1 )
  { if ( lcrzo_priv_base64cb642ent(ptr[4*i], &ent1) ||
	 lcrzo_priv_base64cb642ent(ptr[4*i+1], &ent2) )
    { lcrzo_data_free(ptr);
      return(LCRZO_ERR_FMBASE64CHAR);
    }
    if (pdataout!=NULL) (*pdataout)[j++]=(lcrzo_uint8)( (ent1<<2)|(ent2>>4) );
  }

  lcrzo_data_free(ptr);
  return(LCRZO_ERR_OK);
}


/*-------------------------------------------------------------*/
int lcrzo_data_initm_text_stdin(const char * message,
				const char * defaulttext,
				lcrzo_data *pdataout,
				lcrzo_int32 *pdataoutsize)
{ lcrzo_data ptr;

  ptr=NULL;
  lcrzo_er(lcrzo_data_appendm_text_stdin(message, defaulttext, 0,
					 &ptr, pdataoutsize));
  if (pdataout!=NULL) *pdataout=ptr;
  else lcrzo_data_free(ptr);
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_data_appendm_text_stdin(const char * message,
				  const char * defaulttext,
				  lcrzo_int32 dataoutcurrentsize,
				  lcrzo_data *pdataout,
				  lcrzo_int32 *pdataoutsize)
{ char prompt;
  lcrzo_int32 dataoutsize, defaultendsize;
  int ret;
  lcrzo_uint8 c;
  lcrzo_string ptr;
 
  /*parameters verification*/
  if (dataoutcurrentsize<0) return(LCRZO_ERR_PATOOLOW);

  /*verify the default string*/
  defaultendsize=0; /* just because of the compiler warning */
  if (defaulttext!=NULL)
  { lcrzo_er(lcrzo_data_appendm_text(defaulttext, dataoutcurrentsize,
				     NULL, &defaultendsize));
  }

  prompt=':';
  while(LCRZO_TRUE)
  { /*affichage du message*/
    if (message!=NULL) if (message[0]!='\0') 
    { printf("%s ", message);
      if (defaulttext!=NULL)
      { printf("[");
        lcrzo_er(lcrzo_data_print((lcrzo_constdata)defaulttext,
				  strlen(defaulttext),
				  LCRZO_PRINTTYPE_PTEXT));
	printf("]");
      }
      printf("%c ", prompt);
      prompt='>';
    }
    /*gets the user string*/
    lcrzo_er(lcrzo_priv_stdin(&ptr, NULL));
    /*try to convert*/
    ret=lcrzo_data_appendm_text(ptr, dataoutcurrentsize,
				pdataout, &dataoutsize);
    lcrzo_string_free(ptr);
    if (ret==LCRZO_ERR_OK)
    { /*nothing entered and the default value hasn't a null size*/
      if ( dataoutsize==dataoutcurrentsize &&
	   defaultendsize!=dataoutcurrentsize &&
	   defaulttext!=NULL )
      { lcrzo_int16 language;
        lcrzo_er(lcrzo_global_get_language(&language));
	if (language==LCRZO_GLOBAL_LANG_FR)
	{ lcrzo_stdin_char("Voulez-vous la chaine Vide ou la chaine par Defaut ?",
			   (lcrzo_constdata)"vVdD",'d', (lcrzo_uint8*)&c);
	}
	else
	{ lcrzo_stdin_char("Do you want an Empty string or the Default string ?",
			   (const lcrzo_uint8*)"eEdD",'d', (lcrzo_uint8*)&c);
	}
	if ( c=='d' || c=='D' )
	{ ret=lcrzo_data_appendm_text(defaulttext, dataoutcurrentsize,
				      pdataout, &dataoutsize);
	  /*because it should have been tested at the beginning*/
	  if (ret!=LCRZO_ERR_OK)
	    return(lcrzo_ie("lcrzo_data_appendm_text_stdin",
			    "aurait du etre teste en debut de fonction",
			    "should have been tested at the beginning"));
	}
      }
      if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize;
      return(LCRZO_ERR_OK);
    }
  }

  /*should never be here*/
  return(lcrzo_ierp("lcrzo_data_appendm_text_stdin"));
}

/*-------------------------------------------------------------*/
int lcrzo_data_initm_coretext_stdin(const char * message,
				    const char * defaultcoretext,
				    lcrzo_data *pdataout,
				    lcrzo_int32 *pdataoutsize)
{ lcrzo_data ptr;

  ptr=NULL;
  lcrzo_er(lcrzo_data_appendm_coretext_stdin(message, defaultcoretext, 0,
					     &ptr, pdataoutsize));
  if (pdataout!=NULL) *pdataout=ptr;
  else lcrzo_data_free(ptr);
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_data_appendm_coretext_stdin(const char * message,
				      const char * defaultcoretext,
				      lcrzo_int32 dataoutcurrentsize,
				      lcrzo_data *pdataout,
				      lcrzo_int32 *pdataoutsize)
{ char prompt;
  lcrzo_int32 dataoutsize, defaultendsize;
  int ret;
  lcrzo_uint8 c;
  lcrzo_string ptr;
 
  /*parameters verification*/
  if (dataoutcurrentsize<0) return(LCRZO_ERR_PATOOLOW);

  /*verify the default string*/
  defaultendsize=0; /* just because of the compiler warning */
  if (defaultcoretext!=NULL)
  { lcrzo_er(lcrzo_data_appendm_coretext(defaultcoretext, dataoutcurrentsize,
					 NULL, &defaultendsize));
  }

  prompt=':';
  while(LCRZO_TRUE)
  { /*affichage du message*/
    if (message!=NULL) if (message[0]!='\0') 
    { printf("%s ", message);
      if (defaultcoretext!=NULL)
      { printf("[");
        lcrzo_er(lcrzo_data_print((lcrzo_constdata)defaultcoretext, 
				  strlen(defaultcoretext),
				  LCRZO_PRINTTYPE_PTEXT));
	printf("]");
      }
      printf("%c ", prompt);
      prompt='>';
    }
    /*gets the user string*/
    lcrzo_er(lcrzo_priv_stdin(&ptr, NULL));
    /*try to convert*/
    ret=lcrzo_data_appendm_coretext(ptr, dataoutcurrentsize,
				    pdataout, &dataoutsize);
    lcrzo_string_free(ptr);
    if (ret==LCRZO_ERR_OK)
    { /*nothing entered and the default value hasn't a null size*/
      if ( dataoutsize==dataoutcurrentsize &&
	   defaultendsize!=dataoutcurrentsize &&
	   defaultcoretext!=NULL )
      { lcrzo_int16 language;
	lcrzo_er(lcrzo_global_get_language(&language));
	if (language==LCRZO_GLOBAL_LANG_FR)
	{ lcrzo_stdin_char("Voulez-vous la chaine Vide ou la chaine par Defaut ?",
			   (const lcrzo_uint8*)"vVdD",'d', (lcrzo_uint8*)&c);
	}
	else
	{ lcrzo_stdin_char("Do you want an Empty string or the Default string ?",
			   (const lcrzo_uint8*)"eEdD",'d', (lcrzo_uint8*)&c);
	}
	if ( c=='d' || c=='D' )
	{ ret=lcrzo_data_appendm_coretext(defaultcoretext, dataoutcurrentsize,
					  pdataout, &dataoutsize);
	  /*because it should have been tested at the beginning*/
	  if (ret!=LCRZO_ERR_OK)
	    return(lcrzo_ie("lcrzo_data_appendm_coretext_stdin",
			    "aurait du etre teste en debut de fonction",
			    "should have been tested at the beginning"));
	}
      }
      if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize;
      return(LCRZO_ERR_OK);
    }
  }

  /*should never be here*/
  return(lcrzo_ierp("lcrzo_data_appendm_coretext_stdin"));
}

/*-------------------------------------------------------------*/
int lcrzo_data_initm_text_passwd(const char * message,
				const char * defaulttext,
				lcrzo_data *pdataout,
				lcrzo_int32 *pdataoutsize)
{ lcrzo_data ptr;

  ptr=NULL;
  lcrzo_er(lcrzo_data_appendm_text_passwd(message, defaulttext, 0,
					 &ptr, pdataoutsize));
  if (pdataout!=NULL) *pdataout=ptr;
  else lcrzo_data_free(ptr);
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_data_appendm_text_passwd(const char * message,
				  const char * defaulttext,
				  lcrzo_int32 dataoutcurrentsize,
				  lcrzo_data *pdataout,
				  lcrzo_int32 *pdataoutsize)
{ char prompt;
  lcrzo_int32 dataoutsize, defaultendsize;
  int ret;
  lcrzo_uint8 c;
  lcrzo_string ptr;
 
  /*parameters verification*/
  if (dataoutcurrentsize<0) return(LCRZO_ERR_PATOOLOW);

  /*verify the default string*/
  defaultendsize=0; /* just because of the compiler warning */
  if (defaulttext!=NULL)
  { lcrzo_er(lcrzo_data_appendm_text(defaulttext, dataoutcurrentsize,
				     NULL, &defaultendsize));
  }

  prompt=':';
  while(LCRZO_TRUE)
  { /*affichage du message*/
    if (message!=NULL) if (message[0]!='\0') 
    { printf("%s ", message);
      printf("%c ", prompt);
      prompt='>';
    }
    /*gets the user string*/
    lcrzo_er(lcrzo_priv_passwd(&ptr, NULL));
    /*try to convert*/
    ret=lcrzo_data_appendm_text(ptr, dataoutcurrentsize,
				pdataout, &dataoutsize);
    lcrzo_string_free(ptr);
    if (ret==LCRZO_ERR_OK)
    { /*nothing entered and the default value hasn't a null size*/
      if ( dataoutsize==dataoutcurrentsize &&
	   defaultendsize!=dataoutcurrentsize &&
	   defaulttext!=NULL )
      { lcrzo_int16 language;
	lcrzo_er(lcrzo_global_get_language(&language));
	if (language==LCRZO_GLOBAL_LANG_FR)
	{ lcrzo_stdin_char("Voulez-vous la chaine Vide ou la chaine par Defaut ?",
			   (const lcrzo_uint8*)"vVdD",'d', (lcrzo_uint8*)&c);
	}
	else
	{ lcrzo_stdin_char("Do you want an Empty string or the Default string ?",
			   (const lcrzo_uint8*)"eEdD",'d', (lcrzo_uint8*)&c);
	}
	if ( c=='d' || c=='D' )
	{ ret=lcrzo_data_appendm_text(defaulttext, dataoutcurrentsize,
				      pdataout, &dataoutsize);
	  /*because it should have been tested at the beginning*/
	  if (ret!=LCRZO_ERR_OK)
	    return(lcrzo_ie("lcrzo_data_appendm_text_passwd",
			    "aurait du etre teste en debut de fonction",
			    "should have been tested at the beginning"));
	}
      }
      if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize;
      return(LCRZO_ERR_OK);
    }
  }

  /*should never be here*/
  return(lcrzo_ierp("lcrzo_data_appendm_text_passwd"));
}

/*-------------------------------------------------------------*/
int lcrzo_data_initm_coretext_passwd(const char * message,
				    const char * defaultcoretext,
				    lcrzo_data *pdataout,
				    lcrzo_int32 *pdataoutsize)
{ lcrzo_data ptr;

  ptr=NULL;
  lcrzo_er(lcrzo_data_appendm_coretext_passwd(message, defaultcoretext, 0,
					     &ptr, pdataoutsize));
  if (pdataout!=NULL) *pdataout=ptr;
  else lcrzo_data_free(ptr);
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_data_appendm_coretext_passwd(const char * message,
				      const char * defaultcoretext,
				      lcrzo_int32 dataoutcurrentsize,
				      lcrzo_data *pdataout,
				      lcrzo_int32 *pdataoutsize)
{ char prompt;
  lcrzo_int32 dataoutsize, defaultendsize;
  int ret;
  lcrzo_uint8 c;
  lcrzo_string ptr;
 
  /*parameters verification*/
  if (dataoutcurrentsize<0) return(LCRZO_ERR_PATOOLOW);

  /*verify the default string*/
  defaultendsize=0; /* just for the compiler warning */
  if (defaultcoretext!=NULL)
  { lcrzo_er(lcrzo_data_appendm_coretext(defaultcoretext, dataoutcurrentsize,
					 NULL, &defaultendsize));
  }

  prompt=':';
  while(LCRZO_TRUE)
  { /*affichage du message*/
    if (message!=NULL) if (message[0]!='\0') 
    { printf("%s ", message);
      printf("%c ", prompt);
      prompt='>';
    }
    /*gets the user string*/
    lcrzo_er(lcrzo_priv_passwd(&ptr, NULL));
    /*try to convert*/
    ret=lcrzo_data_appendm_coretext(ptr, dataoutcurrentsize,
				    pdataout, &dataoutsize);
    lcrzo_string_free(ptr);
    if (ret==LCRZO_ERR_OK)
    { /*nothing entered and the default value hasn't a null size*/
      if ( dataoutsize==dataoutcurrentsize &&
	   defaultendsize!=dataoutcurrentsize &&
	   defaultcoretext!=NULL )
      { lcrzo_int16 language;
	lcrzo_er(lcrzo_global_get_language(&language));
	if (language==LCRZO_GLOBAL_LANG_FR)
	{ lcrzo_stdin_char("Voulez-vous la chaine Vide ou la chaine par Defaut ?",
			   (const lcrzo_uint8*)"vVdD",'d', (lcrzo_uint8*)&c);
	}
	else
	{ lcrzo_stdin_char("Do you want an Empty string or the Default string ?",
			   (const lcrzo_uint8*)"eEdD",'d', (lcrzo_uint8*)&c);
	}
	if ( c=='d' || c=='D' )
	{ ret=lcrzo_data_appendm_coretext(defaultcoretext, dataoutcurrentsize,
					  pdataout, &dataoutsize);
	  /*because it should have been tested at the beginning*/
	  if (ret!=LCRZO_ERR_OK)
	    return(lcrzo_ie("lcrzo_data_appendm_coretext_passwd",
			    "aurait du etre teste en debut de fonction",
			    "should have been tested at the beginning"));
	}
      }
      if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize;
      return(LCRZO_ERR_OK);
    }
  }

  /*should never be here*/
  return(lcrzo_ierp("lcrzo_data_appendm_coretext_passwd"));
}

/*-------------------------------------------------------------*/
int lcrzo_data_initm_hexa_stdin(const char * message,
				const char * defaulthexa,
				lcrzo_data *pdataout,
				lcrzo_int32 *pdataoutsize)
{ lcrzo_data ptr;

  ptr=NULL;
  lcrzo_er(lcrzo_data_appendm_hexa_stdin(message, defaulthexa, 0,
					 &ptr, pdataoutsize));
  if (pdataout!=NULL) *pdataout=ptr;
  else lcrzo_data_free(ptr);
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_data_appendm_hexa_stdin(const char * message,
				  const char * defaulthexa,
				  lcrzo_int32 dataoutcurrentsize,
				  lcrzo_data *pdataout,
				  lcrzo_int32 *pdataoutsize)
{ char prompt;
  lcrzo_int32 dataoutsize, defaultendsize, ptr2datasize, stdinlen;
  int ret;
  lcrzo_uint8 c;
  lcrzo_string ptr;
  lcrzo_data ptr2;

  /*parameters verification*/
  if (dataoutcurrentsize<0) return(LCRZO_ERR_PATOOLOW);

  /*verify the default string*/
  defaultendsize=0; /* just because of the compiler warning */
  if (defaulthexa!=NULL)
  { lcrzo_er(lcrzo_data_appendm_hexa(defaulthexa, dataoutcurrentsize,
					 NULL, &defaultendsize));
  }

  prompt=':';
  while(LCRZO_TRUE)
  { /*affichage du message*/
    if (message!=NULL) if (message[0]!='\0') 
    { printf("%s ", message);
      if (defaulthexa!=NULL)
      { printf("[");
        lcrzo_er(lcrzo_data_initm_hexa(defaulthexa, &ptr2, &ptr2datasize));
        lcrzo_efr(lcrzo_data_print(ptr2, ptr2datasize, 
                                          LCRZO_PRINTTYPE_HEXA), 
		  lcrzo_data_free(ptr2));
        lcrzo_data_free(ptr2);
	printf("]");
      }
      printf("%c ", prompt);
      prompt='>';
    }
    /*gets the user string*/
    lcrzo_er(lcrzo_priv_stdin(&ptr, NULL));
    stdinlen=strlen(ptr);
    /*try to convert*/
    ret=lcrzo_data_appendm_hexa(ptr, dataoutcurrentsize,
				    pdataout, &dataoutsize);
    lcrzo_string_free(ptr);
    if (ret==LCRZO_ERR_OK)
    { /*nothing entered and the default value hasn't a null size*/
      if ( stdinlen == 0 &&
	   defaulthexa!=NULL &&
	   defaultendsize!=dataoutcurrentsize )
      { lcrzo_int16 language;
	lcrzo_er(lcrzo_global_get_language(&language));
	if (language==LCRZO_GLOBAL_LANG_FR)
	{ lcrzo_stdin_char("Voulez-vous la chaine Vide ou la chaine par Defaut ?",
			   (const lcrzo_uint8*)"vVdD",'d', (lcrzo_uint8*)&c);
	}
	else
	{ lcrzo_stdin_char("Do you want an Empty string or the Default string ?",
			   (const lcrzo_uint8*)"eEdD",'d', (lcrzo_uint8*)&c);
	}
	if ( c=='d' || c=='D' )
	{ ret=lcrzo_data_appendm_hexa(defaulthexa, dataoutcurrentsize,
				      pdataout, &dataoutsize);
	  /*because it should have been tested at the beginning*/
	  if (ret!=LCRZO_ERR_OK)
	    return(lcrzo_ie("lcrzo_data_appendm_hexa_stdin",
			    "aurait du etre teste en debut de fonction",
			    "should have been tested at the beginning"));
	}
      }
      if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize;
      return(LCRZO_ERR_OK);
    }
  }

  /*should never be here*/
  return(lcrzo_ierp("lcrzo_data_appendm_hexa_stdin"));
}

/*-------------------------------------------------------------*/
int lcrzo_data_initm_mixed_stdin(const char * message,
				 const char * defaultmixed,
				 lcrzo_data *pdataout,
				 lcrzo_int32 *pdataoutsize)
{ lcrzo_data ptr;

  ptr=NULL;
  lcrzo_er(lcrzo_data_appendm_mixed_stdin(message, defaultmixed, 0,
					     &ptr, pdataoutsize));
  if (pdataout!=NULL) *pdataout=ptr;
  else lcrzo_data_free(ptr);
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_data_appendm_mixed_stdin(const char * message,
				   const char * defaultmixed,
				   lcrzo_int32 dataoutcurrentsize,
				   lcrzo_data *pdataout,
				   lcrzo_int32 *pdataoutsize)
{ char prompt;
  lcrzo_int32 dataoutsize, defaultendsize, ptr2datasize, stdinlen;
  int ret;
  lcrzo_uint8 c;
  lcrzo_string ptr;
  lcrzo_data ptr2;

  /*parameters verification*/
  if (dataoutcurrentsize<0) return(LCRZO_ERR_PATOOLOW);

  /*verify the default string*/
  defaultendsize=0; /* just because of the compiler warning */
  if (defaultmixed!=NULL)
  { lcrzo_er(lcrzo_data_appendm_mixed(defaultmixed, dataoutcurrentsize,
				      NULL, &defaultendsize));
  }

  prompt=':';
  while(LCRZO_TRUE)
  { /*affichage du message*/
    if (message!=NULL) if (message[0]!='\0') 
    { printf("%s ", message);
      if (defaultmixed!=NULL)
      { printf("[");
        lcrzo_er(lcrzo_data_initm_mixed(defaultmixed, &ptr2, &ptr2datasize));
        lcrzo_efr(lcrzo_data_print(ptr2, ptr2datasize, 
                                          LCRZO_PRINTTYPE_MIXED), 
		  lcrzo_data_free(ptr2));
        lcrzo_data_free(ptr2);
	printf("]");
      }
      printf("%c ", prompt);
      prompt='>';
    }
    /*gets the user string*/
    lcrzo_er(lcrzo_priv_stdin(&ptr, NULL));
    stdinlen=strlen(ptr);
    /*try to convert*/
    ret=lcrzo_data_appendm_mixed(ptr, dataoutcurrentsize,
				 pdataout, &dataoutsize);
    lcrzo_string_free(ptr);
    if (ret==LCRZO_ERR_OK)
    { /*nothing entered and the default value hasn't a null size*/
      if ( stdinlen == 0 &&
	   defaultmixed!=NULL &&
	   defaultendsize!=dataoutcurrentsize )
      { lcrzo_int16 language;
	lcrzo_er(lcrzo_global_get_language(&language));
	if (language==LCRZO_GLOBAL_LANG_FR)
	{ lcrzo_stdin_char("Voulez-vous la chaine Vide ou la chaine par Defaut ?",
			   (const lcrzo_uint8*)"vVdD",'d', (lcrzo_uint8*)&c);
	}
	else
	{ lcrzo_stdin_char("Do you want an Empty string or the Default string ?",
			   (const lcrzo_uint8*)"eEdD",'d', (lcrzo_uint8*)&c);
	}
	if ( c=='d' || c=='D' )
	{ ret=lcrzo_data_appendm_mixed(defaultmixed, dataoutcurrentsize,
				       pdataout, &dataoutsize);
	  /*because it should have been tested at the beginning*/
	  if (ret!=LCRZO_ERR_OK)
	    return(lcrzo_ie("lcrzo_data_appendm_mixed_stdin",
			    "aurait du etre teste en debut de fonction",
			    "should have been tested at the beginning"));
	}
      }
      if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize;
      return(LCRZO_ERR_OK);
    }
  }

  /*should never be here*/
  return(lcrzo_ierp("lcrzo_data_appendm_mixed_stdin"));
}

/*-------------------------------------------------------------*/
int lcrzo_data_initm_base64_stdin(const char * message,
				  const char * defaultbase64,
				  lcrzo_data *pdataout,
				  lcrzo_int32 *pdataoutsize)
{ lcrzo_data ptr;

  ptr=NULL;
  lcrzo_er(lcrzo_data_appendm_base64_stdin(message, defaultbase64, 0,
					   &ptr, pdataoutsize));
  if (pdataout!=NULL) *pdataout=ptr;
  else lcrzo_data_free(ptr);
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_data_appendm_base64_stdin(const char * message,
				    const char * defaultbase64,
				    lcrzo_int32 dataoutcurrentsize,
				    lcrzo_data *pdataout,
				    lcrzo_int32 *pdataoutsize)
{ char prompt;
  lcrzo_int32 dataoutsize, defaultendsize, ptr2datasize, stdinlen;
  int ret;
  lcrzo_uint8 c;
  lcrzo_string ptr;
  lcrzo_data ptr2;

  /*parameters verification*/
  if (dataoutcurrentsize<0) return(LCRZO_ERR_PATOOLOW);

  /*verify the default string*/
  defaultendsize=0; /* just because of the compiler warning */
  if (defaultbase64!=NULL)
  { lcrzo_er(lcrzo_data_appendm_base64(defaultbase64, dataoutcurrentsize,
				       NULL, &defaultendsize));
  }

  prompt=':';
  while(LCRZO_TRUE)
  { /*affichage du message*/
    if (message!=NULL) if (message[0]!='\0') 
    { printf("%s ", message);
      if (defaultbase64!=NULL)
      { printf("[");
        lcrzo_er(lcrzo_data_initm_base64(defaultbase64, &ptr2, &ptr2datasize));
        lcrzo_efr(lcrzo_data_print(ptr2, ptr2datasize, 
				   LCRZO_PRINTTYPE_BASE64),
		  lcrzo_data_free(ptr2));
        lcrzo_data_free(ptr2);
	printf("]");
      }
      printf("%c ", prompt);
      prompt='>';
    }
    /*gets the user string*/
    lcrzo_er(lcrzo_priv_stdin(&ptr, NULL));
    stdinlen=strlen(ptr);
    /*try to convert*/
    ret=lcrzo_data_appendm_base64(ptr, dataoutcurrentsize,
				  pdataout, &dataoutsize);
    lcrzo_string_free(ptr);
    if (ret==LCRZO_ERR_OK)
    { /*nothing entered and the default value hasn't a null size*/
      if ( stdinlen == 0 &&
	   defaultbase64!=NULL &&
	   defaultendsize!=dataoutcurrentsize )
      { lcrzo_int16 language;
	lcrzo_er(lcrzo_global_get_language(&language));
	if (language==LCRZO_GLOBAL_LANG_FR)
	{ lcrzo_stdin_char("Voulez-vous la chaine Vide ou la chaine par Defaut ?",
			   (const lcrzo_uint8*)"vVdD",'d', (lcrzo_uint8*)&c);
	}
	else
	{ lcrzo_stdin_char("Do you want an Empty string or the Default string ?",
			   (const lcrzo_uint8*)"eEdD",'d', (lcrzo_uint8*)&c);
	}
	if ( c=='d' || c=='D' )
	{ ret=lcrzo_data_appendm_base64(defaultbase64, dataoutcurrentsize,
					pdataout, &dataoutsize);
	  /*because it should have been tested at the beginning*/
	  if (ret!=LCRZO_ERR_OK)
	    return(lcrzo_ie("lcrzo_data_appendm_base64_stdin",
			    "aurait du etre teste en debut de fonction",
			    "should have been tested at the beginning"));
	}
      }
      if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize;
      return(LCRZO_ERR_OK);
    }
  }

  /*should never be here*/
  return(lcrzo_ierp("lcrzo_data_appendm_base64_stdin"));
}

/*-------------------------------------------------------------*/
int lcrzo_data_search_char(lcrzo_constdata datain,
			   lcrzo_int32 datainsize,
			   lcrzo_bool searchcomplement, 
			   lcrzo_int32 datainstartpos,
			   lcrzo_int32 datainendpos,
			   lcrzo_uint8 c,
			   lcrzo_int32 *pfoundposition_negative,
			   lcrzo_int32 *pfoundposition_positive)
{ int direction;
  lcrzo_int32 size, infpos, suppos, i;

  /*parameters verification*/
  if (datain==NULL && datainsize) return(LCRZO_ERR_PANULLPTRSIZE);
  if (datainsize<0) return(LCRZO_ERR_PATOOLOW);
  lcrzo_bool_verifbof(searchcomplement);
  lcrzo_er(lcrzo_priv_managedatarange(datainsize,
				      datainstartpos, datainendpos,
				      NULL, &infpos, NULL, &suppos,
				      NULL, NULL, &direction, &size));

  if (direction==LCRZO_PRIV_INCREASE)
  { if (searchcomplement)
    { for ( i=infpos ; i<suppos ; i++ )
      { if ( datain[i-1]!=c )
	{ lcrzo_er(lcrzo_priv_managedatapospos(datainsize, i,
					       pfoundposition_negative,
					       pfoundposition_positive));
	  return(LCRZO_ERR_OK);
	}
      }
    }
    else
    { for ( i=infpos ; i<suppos ; i++ )
      { if ( datain[i-1]==c )
	{ lcrzo_er(lcrzo_priv_managedatapospos(datainsize, i,
					       pfoundposition_negative,
					       pfoundposition_positive));
	  return(LCRZO_ERR_OK);
	}
      }
    }
  }
  else
  { if (searchcomplement)
    { for ( i=infpos-1 ; i>=suppos ; i-- )
      { if ( datain[i-1]!=c )
	{ lcrzo_er(lcrzo_priv_managedatapospos(datainsize, i,
					       pfoundposition_negative,
					       pfoundposition_positive));
	  return(LCRZO_ERR_OK);
	}
      }
    }
    else
    { for ( i=infpos-1 ; i>=suppos ; i-- )
      { if ( datain[i-1]==c )
	{ lcrzo_er(lcrzo_priv_managedatapospos(datainsize, i,
					       pfoundposition_negative,
					       pfoundposition_positive));
	  return(LCRZO_ERR_OK);
	}
      }
    }
  }

  return(LCRZO_ERR_OKSEARCHNOTFOUND);
}

/*-------------------------------------------------------------*/
int lcrzo_data_search_nchar(lcrzo_constdata datain,
			    lcrzo_int32 datainsize,
			    lcrzo_bool searchcomplement, 
			    lcrzo_int32 datainstartpos,
			    lcrzo_int32 datainendpos,
			    lcrzo_constdata searchlist,
			    lcrzo_int32 searchlistsize,
			    lcrzo_int32 *pfoundposition_negative,
			    lcrzo_int32 *pfoundposition_positive)
{ int direction;
  lcrzo_int32 size, infpos, suppos, i;

  /*parameters verification*/
  if (datain==NULL && datainsize) return(LCRZO_ERR_PANULLPTRSIZE);
  if (datainsize<0) return(LCRZO_ERR_PATOOLOW);
  if (searchlist==NULL) return(LCRZO_ERR_PANULLPTR);
  if (searchlistsize<0) return(LCRZO_ERR_PATOOLOW);
  lcrzo_bool_verifbof(searchcomplement);
  lcrzo_er(lcrzo_priv_managedatarange(datainsize,
				      datainstartpos, datainendpos,
				      NULL, &infpos, NULL, &suppos,
				      NULL, NULL, &direction, &size));

  if (searchlistsize==0) return(LCRZO_ERR_OKSEARCHNOTFOUND);

  if (direction==LCRZO_PRIV_INCREASE)
  { if (searchcomplement)
    { for ( i=infpos ; i<suppos ; i++ )
      { if ( !lcrzo_priv_equal_nchar(searchlist, searchlistsize, datain[i-1]) )
	{ lcrzo_er(lcrzo_priv_managedatapospos(datainsize, i,
					       pfoundposition_negative,
					       pfoundposition_positive));
	  return(LCRZO_ERR_OK);
	}
      }
    }
    else
    { for ( i=infpos ; i<suppos ; i++ )
      { if ( lcrzo_priv_equal_nchar(searchlist, searchlistsize, datain[i-1]) )
	{ lcrzo_er(lcrzo_priv_managedatapospos(datainsize, i,
					       pfoundposition_negative,
					       pfoundposition_positive));
	  return(LCRZO_ERR_OK);
	}
      }
    }
  }
  else
  { if (searchcomplement)
    { for ( i=infpos-1 ; i>=suppos ; i-- )
      { if ( !lcrzo_priv_equal_nchar(searchlist, searchlistsize, datain[i-1]) )
	{ lcrzo_er(lcrzo_priv_managedatapospos(datainsize, i,
					       pfoundposition_negative,
					       pfoundposition_positive));
	  return(LCRZO_ERR_OK);
	}
      }
    }
    else
    { for ( i=infpos-1 ; i>=suppos ; i-- )
      { if ( lcrzo_priv_equal_nchar(searchlist, searchlistsize, datain[i-1]) )
	{ lcrzo_er(lcrzo_priv_managedatapospos(datainsize, i,
					       pfoundposition_negative,
					       pfoundposition_positive));
	  return(LCRZO_ERR_OK);
	}
      }
    }
  }

  return(LCRZO_ERR_OKSEARCHNOTFOUND);
}

/*-------------------------------------------------------------*/
int lcrzo_data_search_data(lcrzo_constdata datain,
			   lcrzo_int32 datainsize,
			   lcrzo_bool searchcomplement, 
			   lcrzo_int32 datainstartpos,
			   lcrzo_int32 datainendpos,
			   lcrzo_constdata searcheddata,
			   lcrzo_int32 searcheddatasize,
			   lcrzo_int32 *pstartfoundposition_negative,
			   lcrzo_int32 *pstartfoundposition_positive,
			   lcrzo_int32 *pendfoundposition_negative,
			   lcrzo_int32 *pendfoundposition_positive)
{ int direction, retour;
  lcrzo_int32 infpos, suppos, startfound, endfound, i, poscourante;

  /*parameters verification*/
  if (datain==NULL && datainsize) return(LCRZO_ERR_PANULLPTRSIZE);
  if (datainsize<0) return(LCRZO_ERR_PATOOLOW);
  if (searcheddata==NULL) return(LCRZO_ERR_PANULLPTR);
  if (searcheddatasize<0) return(LCRZO_ERR_PATOOLOW);
  lcrzo_bool_verifbof(searchcomplement);
  lcrzo_er(lcrzo_priv_managedatarange(datainsize,
				      datainstartpos, datainendpos,
				      NULL, &infpos, NULL, &suppos,
				      NULL, NULL, &direction, NULL));

  if (searcheddatasize==0) return(LCRZO_ERR_OKSEARCHNOTFOUND);

  /*normal search*/
  if (!searchcomplement)
  { if (direction==LCRZO_PRIV_INCREASE)
    { for ( i=infpos; i<=suppos-searcheddatasize ; i++ )
      { if ( !memcmp(datain+i-1, searcheddata, searcheddatasize) )
        { lcrzo_er(lcrzo_priv_managedatarange(datainsize, 
					      i, i+searcheddatasize,
					      pstartfoundposition_negative,
					      pstartfoundposition_positive, 
					      pendfoundposition_negative,
					      pendfoundposition_positive,
					      NULL, NULL, NULL, NULL));
          return(LCRZO_ERR_OK);
        }
      }
    }
    else
    { for ( i=infpos-searcheddatasize; i>=suppos ; i-- )
      { if ( !memcmp(datain+i-1, searcheddata, searcheddatasize) )
        { lcrzo_er(lcrzo_priv_managedatarange(datainsize, 
					      i, i+searcheddatasize,
					      pstartfoundposition_negative,
					      pstartfoundposition_positive, 
					      pendfoundposition_negative,
					      pendfoundposition_positive,
					      NULL, NULL, NULL, NULL));
          return(LCRZO_ERR_OK);
        }
      }
    }
  }
  /*recherche de complement*/
  else
  { if (direction==LCRZO_PRIV_INCREASE)
    { poscourante=infpos;
      while(LCRZO_TRUE)
      { if (poscourante==suppos) return(LCRZO_ERR_OKSEARCHNOTFOUND);
        retour=lcrzo_data_search_data(datain, datainsize, 0,
				      poscourante, suppos,
				      searcheddata, searcheddatasize,
				      NULL, &startfound, NULL, &endfound);
        if (retour!=LCRZO_ERR_OK)
        { /*le complement est toute la chaine*/
          lcrzo_er(lcrzo_priv_managedatarange(datainsize, 
					      poscourante, suppos,
					      pstartfoundposition_negative,
					      pstartfoundposition_positive, 
					      pendfoundposition_negative,
					      pendfoundposition_positive,
					      NULL, NULL, NULL, NULL));
          return(LCRZO_ERR_OK);
        }
        if (poscourante==startfound)
	{ poscourante=endfound;
	}
	else
        { /*du debut a startfound, se trouve notre resultat*/
          lcrzo_er(lcrzo_priv_managedatarange(datainsize, 
					      poscourante, startfound,
					      pstartfoundposition_negative,
					      pstartfoundposition_positive, 
					      pendfoundposition_negative,
					      pendfoundposition_positive,
					      NULL, NULL, NULL, NULL));
	  return(LCRZO_ERR_OK);
        }
        
      }
    }
    else
    { poscourante=infpos;
      while(LCRZO_TRUE)
      { if (poscourante==suppos) return(LCRZO_ERR_OKSEARCHNOTFOUND);
        retour=lcrzo_data_search_data(datain, datainsize, 0,
				      poscourante, suppos,
				      searcheddata, searcheddatasize,
				      NULL, &startfound, NULL, &endfound);
        if (retour!=LCRZO_ERR_OK)
        { /*le complement est toute la chaine*/
          lcrzo_er(lcrzo_priv_managedatarange(datainsize, 
					      infpos, poscourante,
					      pstartfoundposition_negative,
					      pstartfoundposition_positive, 
					      pendfoundposition_negative,
					      pendfoundposition_positive,
					      NULL, NULL, NULL, NULL));
          return(LCRZO_ERR_OK);
        }
        if (poscourante==endfound)
	{ poscourante=startfound;
	}
	else
        { /*de possup a la fin, se trouve notre resultat*/
          lcrzo_er(lcrzo_priv_managedatarange(datainsize, 
					      endfound, poscourante,
					      pstartfoundposition_negative,
					      pstartfoundposition_positive, 
					      pendfoundposition_negative,
					      pendfoundposition_positive,
					      NULL, NULL, NULL, NULL));
          return(LCRZO_ERR_OK);
        }
      }
    }
  }

  /*on n'a pas trouve*/
  return(LCRZO_ERR_OKSEARCHNOTFOUND);
}

/*-------------------------------------------------------------*/
int lcrzo_data_search_text(lcrzo_constdata datain,
			   lcrzo_int32 datainsize,
			   lcrzo_bool searchcomplement, 
			   lcrzo_int32 datainstartpos,
			   lcrzo_int32 datainendpos,
			   lcrzo_conststring searchedtext,
			   lcrzo_int32 *pstartfoundposition_negative,
			   lcrzo_int32 *pstartfoundposition_positive,
			   lcrzo_int32 *pendfoundposition_negative,
			   lcrzo_int32 *pendfoundposition_positive)
{ return(lcrzo_data_search_data(datain, datainsize, searchcomplement, 
				datainstartpos, datainendpos,
				(lcrzo_constdata)searchedtext,
				strlen(searchedtext),
				pstartfoundposition_negative,
				pstartfoundposition_positive,
				pendfoundposition_negative,
				pendfoundposition_positive));
}

/*-------------------------------------------------------------*/
int lcrzo_data_search_re(lcrzo_constdata datain,
			 lcrzo_int32 datainsize,
			 lcrzo_bool searchcomplement, 
			 lcrzo_int32 datainstartpos,
			 lcrzo_int32 datainendpos,
			 lcrzo_conststring regularexpression,
			 lcrzo_int32 *pstartfoundposition_negative,
			 lcrzo_int32 *pstartfoundposition_positive,
			 lcrzo_int32 *pendfoundposition_negative,
			 lcrzo_int32 *pendfoundposition_positive)
{ lcrzo_regexp regexparray;

  lcrzo_er(lcrzo_data_search_regexp(datain, datainsize, searchcomplement, 
				    datainstartpos, datainendpos,
				    regularexpression, regexparray));

  if (pstartfoundposition_negative!=NULL)
  { *pstartfoundposition_negative=regexparray[0].startindex_negative;
  }
  if (pstartfoundposition_positive!=NULL)
  { *pstartfoundposition_positive=regexparray[0].startindex_positive;
  }
  if (pendfoundposition_negative!=NULL)
  { *pendfoundposition_negative=regexparray[0].endindex_negative;
  }
  if (pendfoundposition_positive!=NULL)
  { *pendfoundposition_positive=regexparray[0].endindex_positive;
  }
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_priv_regexparray(lcrzo_int32 datainsize,
			   lcrzo_int32 startpos,
			   lcrzo_int32 endpos,
			   lcrzo_regexp arrayfoundpos);
int lcrzo_priv_regexparray(lcrzo_int32 datainsize,
			   lcrzo_int32 startpos,
			   lcrzo_int32 endpos,
			   lcrzo_regexp arrayfoundpos)
{ lcrzo_int32 i;

  arrayfoundpos[0].startindex_positive=startpos;
  arrayfoundpos[0].startindex_negative=startpos-datainsize-2;
  arrayfoundpos[0].endindex_positive=endpos;
  arrayfoundpos[0].endindex_negative=endpos-datainsize-2;

  for ( i=1 ; i<=LCRZO_REGEXP_MAXPAIRS ; i++ )
  { arrayfoundpos[i].startindex_negative=0;
    arrayfoundpos[i].startindex_positive=0;
    arrayfoundpos[i].endindex_negative=0;
    arrayfoundpos[i].endindex_positive=0;
  }
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_data_search_regexp(lcrzo_constdata datain,
			     lcrzo_int32 datainsize,
			     lcrzo_bool searchcomplement, 
			     lcrzo_int32 datainstartpos,
			     lcrzo_int32 datainendpos,
			     lcrzo_conststring regularexpression,
			     lcrzo_regexp arrayfoundpos)
{ int direction, retour;
  lcrzo_int32 infpos, suppos, startfound, endfound, i, poscourante;
  lcrzo_int32 ptrdatasize, add;
  regex_t re;
  regmatch_t pm[LCRZO_REGEXP_MAXPAIRS+1];
  lcrzo_data ptr;
  lcrzo_bool foundinvalid;

  /*parameters verification*/
  if (datain==NULL && datainsize) return(LCRZO_ERR_PANULLPTRSIZE);
  if (datainsize<0) return(LCRZO_ERR_PATOOLOW);
  lcrzo_bool_verifbof(searchcomplement);
  lcrzo_er(lcrzo_priv_managedatarange(datainsize,
				      datainstartpos, datainendpos,
				      NULL, &infpos, NULL, &suppos,
				      NULL, NULL, &direction, NULL));

  if (strlen(regularexpression)==0) return(LCRZO_ERR_OKSEARCHNOTFOUND);

  /*normal search*/
  if (!searchcomplement)
  { /*on compile l'expression reguliere*/
    lcrzo_bool casesensitive;
    lcrzo_er(lcrzo_global_get_data_regexp_casesensitive(&casesensitive));
    retour=regcomp(&re, regularexpression, 
		   REG_EXTENDED | (casesensitive?0:REG_ICASE));
    if (retour)
    { lcrzo_int16 language;
      lcrzo_string errmsg;
      lcrzo_er(lcrzo_string_alloc(500, &errmsg));
      regerror(retour, &re, errmsg, 500);
      regfree(&re);
      lcrzo_er(lcrzo_priv_global_set_errmsgsys(errmsg));
      lcrzo_string_free(errmsg);
      lcrzo_er(lcrzo_global_get_language(&language));
      lcrzo_er(lcrzo_priv_global_set_errmsglcrzo((language==LCRZO_GLOBAL_LANG_FR)?
			 "verifiez votre expression reguliere":
			 "your regular expression may be incorrect"));
      return(LCRZO_ERR_FUREGCOMP);
    }
    if (direction==LCRZO_PRIV_INCREASE)
    { /*convert datain in a string without '\0'*/
      lcrzo_er(lcrzo_data_initm_range(datain, datainsize, infpos, suppos,
				      &ptr, &ptrdatasize));
      for ( i=0 ; i<ptrdatasize ; i++ )
      { if ( ptr[i]=='\0' ) ptr[i]=0x0A;
      }
      ptr[ptrdatasize]='\0';
      /*exec the regex*/
      retour=regexec(&re, (const char *)ptr, LCRZO_REGEXP_MAXPAIRS+1,
                     pm, (infpos==1)?0:REG_NOTBOL);
      regfree(&re);
      lcrzo_data_free(ptr);
      if (retour) return(LCRZO_ERR_OKSEARCHNOTFOUND);
      add=infpos;
    }
    else
    { /*convert datain in a string without '\0'*/
      lcrzo_er(lcrzo_data_initm_range(datain, datainsize, suppos, infpos,
				      &ptr, &ptrdatasize));
      for ( i=0 ; i<ptrdatasize ; i++ )
      { if ( ptr[i]=='\0' ) ptr[i]=1;
      }
      ptr[ptrdatasize]='\0';
      /*exec the regex*/
      for ( i=infpos-suppos-1 ; i>=0 ; i-- )
      { retour=regexec(&re, (const char *)(ptr+i), LCRZO_REGEXP_MAXPAIRS+1,
		       pm, (i)?REG_NOTBOL:0);
        if (retour==0) break;
      }
      regfree(&re);
      lcrzo_data_free(ptr);
      if (i==-1) return(LCRZO_ERR_OKSEARCHNOTFOUND);
      add=suppos+i;
    }
    /*affects the array*/
    if (arrayfoundpos!=NULL)
    { foundinvalid=0;
      for ( i=0 ; i<=LCRZO_REGEXP_MAXPAIRS ; i++ )
      { if ( foundinvalid || pm[i].rm_so==-1 || pm[i].rm_eo==-1 )
	{ /*on est oblige de compliquer un peu car par exemple SuSE
	    en respecte pas ce qui est ecrit dans leur page d'aide :
	    ils ne mettent pas '-1' pour les suivants*/
	  arrayfoundpos[i].startindex_negative=0;
	  arrayfoundpos[i].startindex_positive=0;
	  arrayfoundpos[i].endindex_negative=0;
	  arrayfoundpos[i].endindex_positive=0;
	  foundinvalid=1;
	}
        else
        { arrayfoundpos[i].startindex_positive=add+pm[i].rm_so;
	  arrayfoundpos[i].startindex_negative=add+pm[i].rm_so-datainsize-2;
	  arrayfoundpos[i].endindex_positive=add+pm[i].rm_eo;
	  arrayfoundpos[i].endindex_negative=add+pm[i].rm_eo-datainsize-2;
	}
      }
    }
    return(LCRZO_ERR_OK);
  }
  /*recherche de complement*/
  else
  { if (direction==LCRZO_PRIV_INCREASE)
    { poscourante=infpos;
      while(LCRZO_TRUE)
      { if (poscourante==suppos) return(LCRZO_ERR_OKSEARCHNOTFOUND);
        retour=lcrzo_data_search_re(datain, datainsize, 0,
				    poscourante, suppos,
				    regularexpression, 
				    NULL, &startfound, NULL, &endfound);
        if (retour!=LCRZO_ERR_OK)
        { /*le complement est toute la chaine*/
          lcrzo_er(lcrzo_priv_regexparray(datainsize, poscourante, suppos,
					  arrayfoundpos));
          return(LCRZO_ERR_OK);
        }
        if (poscourante==startfound)
	{ poscourante=endfound;
	}
	else
        { /*du debut a startfound, se trouve notre resultat*/
          lcrzo_er(lcrzo_priv_regexparray(datainsize, poscourante, startfound,
					  arrayfoundpos));
	  return(LCRZO_ERR_OK);
        }
        
      }
    }
    else
    { poscourante=infpos;
      while(LCRZO_TRUE)
      { if (poscourante==suppos) return(LCRZO_ERR_OKSEARCHNOTFOUND);
        retour=lcrzo_data_search_re(datain, datainsize, 0,
				    poscourante, suppos,
				    regularexpression, 
				    NULL, &startfound, NULL, &endfound);
        if (retour!=LCRZO_ERR_OK)
        { /*le complement est toute la chaine*/
          lcrzo_er(lcrzo_priv_regexparray(datainsize, infpos, poscourante,
					  arrayfoundpos));
          return(LCRZO_ERR_OK);
        }
        if (poscourante==endfound)
	{ poscourante=startfound;
	}
	else
        { /*de possup a la fin, se trouve notre resultat*/
          lcrzo_er(lcrzo_priv_regexparray(datainsize, endfound, poscourante,
					  arrayfoundpos));
          return(LCRZO_ERR_OK);
        }
      }
    }
  }

  /*on n'a pas trouve*/
  return(LCRZO_ERR_OKSEARCHNOTFOUND);
}

/*-------------------------------------------------------------*/
int lcrzo_data_token_char(lcrzo_constdata datain,
			  lcrzo_int32 datainsize,
			  lcrzo_bool searchcomplement, 
			  lcrzo_int32 datainstartpos,
			  lcrzo_int32 datainendpos,
			  lcrzo_uint8 c,
			  lcrzo_int32 *ppositionindicator,
			  lcrzo_int32 *pstartfoundposition_negative,
			  lcrzo_int32 *pstartfoundposition_positive,
			  lcrzo_int32 *pendfoundposition_negative,
			  lcrzo_int32 *pendfoundposition_positive)
{ int direction, ret;
  lcrzo_int32 infpos1, suppos1, infpos2, suppos2, startfound, endfound;

  /*parameters verification*/
  if (datain==NULL && datainsize) return(LCRZO_ERR_PANULLPTRSIZE);
  if (datainsize<0) return(LCRZO_ERR_PATOOLOW);
  lcrzo_bool_verifbof(searchcomplement);
  if (ppositionindicator==NULL) return(LCRZO_ERR_PANULLPTR);
  lcrzo_er(lcrzo_priv_managedatarange(datainsize,
				      datainstartpos, datainendpos,
				      &infpos1, &infpos2, &suppos1, &suppos2,
				      NULL, NULL, &direction, NULL));
  
    
  if (direction==LCRZO_PRIV_INCREASE)
  { /*first call*/
    if (*ppositionindicator==0) *ppositionindicator=infpos2;
    /*last call*/
    if (*ppositionindicator==suppos2+1) return(LCRZO_ERR_OKDATAEND);
    /*error : should not happen if positionindicator is correctly used*/
    if (*ppositionindicator<infpos2) return(LCRZO_ERR_PATOOLOW);
    if (*ppositionindicator>suppos2) return(LCRZO_ERR_PATOOBIG);
    /*search the token*/
    if (*ppositionindicator==suppos2)
    { startfound=suppos2;
      endfound=suppos2;
    }
    else
    { startfound=*ppositionindicator;
      ret=lcrzo_data_search_char(datain, datainsize, searchcomplement, 
				 startfound, suppos2, c, NULL, &endfound);
      if (ret!=LCRZO_ERR_OK) endfound=suppos2;
    }
    *ppositionindicator=endfound+1;
  }
  else
  { /*first call*/
    if (*ppositionindicator==0) *ppositionindicator=infpos1;
    /*last call*/
    if (*ppositionindicator==suppos1-1) return(LCRZO_ERR_OKDATAEND);
    /*error : should not happen if positionindicator is correctly used*/
    if (*ppositionindicator>infpos1) return(LCRZO_ERR_PATOOBIG);
    if (*ppositionindicator<suppos1) return(LCRZO_ERR_PATOOLOW);
    /*search the token*/
    if (*ppositionindicator==suppos1)
    { startfound=suppos1;
      endfound=suppos1;
    }
    else
    { endfound=*ppositionindicator;
      ret=lcrzo_data_search_char(datain, datainsize, searchcomplement, 
				 endfound, suppos1, c, &startfound, NULL);
      if (ret!=LCRZO_ERR_OK) startfound=suppos1;
    }
    *ppositionindicator=startfound-1;
  }

  lcrzo_er(lcrzo_priv_managedatarange(datainsize, 
				      startfound, endfound,
				      pstartfoundposition_negative,
				      pstartfoundposition_positive, 
				      pendfoundposition_negative,
				      pendfoundposition_positive,
				      NULL, NULL, NULL, NULL));
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_data_token_nchar(lcrzo_constdata datain,
			   lcrzo_int32 datainsize,
			   lcrzo_bool searchcomplement, 
			   lcrzo_int32 datainstartpos,
			   lcrzo_int32 datainendpos,
			   lcrzo_constdata searchlist,
			   lcrzo_int32 searchlistsize,
			   lcrzo_int32 *ppositionindicator,
			   lcrzo_int32 *pstartfoundposition_negative,
			   lcrzo_int32 *pstartfoundposition_positive,
			   lcrzo_int32 *pendfoundposition_negative,
			   lcrzo_int32 *pendfoundposition_positive)
{ int direction, ret;
  lcrzo_int32 infpos1, suppos1, infpos2, suppos2, startfound, endfound;

  /*parameters verification*/
  if (datain==NULL && datainsize) return(LCRZO_ERR_PANULLPTRSIZE);
  if (datainsize<0) return(LCRZO_ERR_PATOOLOW);
  lcrzo_bool_verifbof(searchcomplement);
  if (ppositionindicator==NULL) return(LCRZO_ERR_PANULLPTR);
  lcrzo_er(lcrzo_priv_managedatarange(datainsize,
				      datainstartpos, datainendpos,
				      &infpos1, &infpos2, &suppos1, &suppos2,
				      NULL, NULL, &direction, NULL));
  
    
  if (direction==LCRZO_PRIV_INCREASE)
  { /*first call*/
    if (*ppositionindicator==0) *ppositionindicator=infpos2;
    /*last call*/
    if (*ppositionindicator==suppos2+1) return(LCRZO_ERR_OKDATAEND);
    /*error : should not happen if positionindicator is correctly used*/
    if (*ppositionindicator<infpos2) return(LCRZO_ERR_PATOOLOW);
    if (*ppositionindicator>suppos2) return(LCRZO_ERR_PATOOBIG);
    /*search the token*/
    if (*ppositionindicator==suppos2)
    { startfound=suppos2;
      endfound=suppos2;
    }
    else
    { startfound=*ppositionindicator;
      ret=lcrzo_data_search_nchar(datain, datainsize, searchcomplement, 
				  startfound, suppos2,
				  searchlist, searchlistsize,
				  NULL, &endfound);
      if (ret!=LCRZO_ERR_OK) endfound=suppos2;
    }
    *ppositionindicator=endfound+1;
  }
  else
  { /*first call*/
    if (*ppositionindicator==0) *ppositionindicator=infpos1;
    /*last call*/
    if (*ppositionindicator==suppos1-1) return(LCRZO_ERR_OKDATAEND);
    /*error : should not happen if positionindicator is correctly used*/
    if (*ppositionindicator>infpos1) return(LCRZO_ERR_PATOOBIG);
    if (*ppositionindicator<suppos1) return(LCRZO_ERR_PATOOLOW);
    /*search the token*/
    if (*ppositionindicator==suppos1)
    { startfound=suppos1;
      endfound=suppos1;
    }
    else
    { endfound=*ppositionindicator;
      ret=lcrzo_data_search_nchar(datain, datainsize, searchcomplement, 
				  endfound, suppos1,
				  searchlist, searchlistsize,
				  &startfound, NULL);
      if (ret!=LCRZO_ERR_OK) startfound=suppos1;
    }
    *ppositionindicator=startfound-1;
  }

  lcrzo_er(lcrzo_priv_managedatarange(datainsize, 
				      startfound, endfound,
				      pstartfoundposition_negative,
				      pstartfoundposition_positive, 
				      pendfoundposition_negative,
				      pendfoundposition_positive,
				      NULL, NULL, NULL, NULL));
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_data_token_data(lcrzo_constdata datain,
			  lcrzo_int32 datainsize,
			  lcrzo_bool searchcomplement, 
			  lcrzo_int32 datainstartpos,
			  lcrzo_int32 datainendpos,
			  lcrzo_constdata searcheddata,
			  lcrzo_int32 searcheddatasize,
			  lcrzo_int32 *ppositionindicator,
			  lcrzo_int32 *pstartfoundposition_negative,
			  lcrzo_int32 *pstartfoundposition_positive,
			  lcrzo_int32 *pendfoundposition_negative,
			  lcrzo_int32 *pendfoundposition_positive)
{ int direction, ret;
  lcrzo_int32 infpos1, suppos1, infpos2, suppos2, startfound, endfound;

  /*parameters verification*/
  if (datain==NULL && datainsize) return(LCRZO_ERR_PANULLPTRSIZE);
  if (datainsize<0) return(LCRZO_ERR_PATOOLOW);
  lcrzo_bool_verifbof(searchcomplement);
  if (ppositionindicator==NULL) return(LCRZO_ERR_PANULLPTR);
  lcrzo_er(lcrzo_priv_managedatarange(datainsize,
				      datainstartpos, datainendpos,
				      &infpos1, &infpos2, &suppos1, &suppos2,
				      NULL, NULL, &direction, NULL));
  
    
  if (direction==LCRZO_PRIV_INCREASE)
  { /*first call*/
    if (*ppositionindicator==0) *ppositionindicator=infpos2;
    /*last call*/
    if (*ppositionindicator==suppos2+1) return(LCRZO_ERR_OKDATAEND);
    /*error : should not happen if positionindicator is correctly used*/
    if (*ppositionindicator<infpos2) return(LCRZO_ERR_PATOOLOW);
    if (*ppositionindicator>suppos2) return(LCRZO_ERR_PATOOBIG);
    /*search the token*/
    if (*ppositionindicator==suppos2)
    { startfound=suppos2;
      endfound=suppos2;
      *ppositionindicator=endfound+1;
    }
    else
    { startfound=*ppositionindicator;
      ret=lcrzo_data_search_data(datain, datainsize, searchcomplement, 
				 startfound, suppos2, 
				 searcheddata, searcheddatasize,
				 NULL, &endfound, NULL, ppositionindicator);
      if (ret!=LCRZO_ERR_OK)
      { endfound=suppos2;
        *ppositionindicator=endfound+1;
      }
    }
  }
  else
  { /*first call*/
    if (*ppositionindicator==0) *ppositionindicator=infpos1;
    /*last call*/
    if (*ppositionindicator==suppos1-1) return(LCRZO_ERR_OKDATAEND);
    /*error : should not happen if positionindicator is correctly used*/
    if (*ppositionindicator>infpos1) return(LCRZO_ERR_PATOOBIG);
    if (*ppositionindicator<suppos1) return(LCRZO_ERR_PATOOLOW);
    /*search the token*/
    if (*ppositionindicator==suppos1)
    { startfound=suppos1;
      endfound=suppos1;
      *ppositionindicator=startfound-1;
    }
    else
    { endfound=*ppositionindicator;
      ret=lcrzo_data_search_data(datain, datainsize, searchcomplement, 
				 endfound, suppos1,
				 searcheddata, searcheddatasize,
				 ppositionindicator, NULL, &startfound, NULL);
      if (ret!=LCRZO_ERR_OK)
      { startfound=suppos1;
        *ppositionindicator=startfound-1;
      }
    }
  }

  lcrzo_er(lcrzo_priv_managedatarange(datainsize, 
				      startfound, endfound,
				      pstartfoundposition_negative,
				      pstartfoundposition_positive, 
				      pendfoundposition_negative,
				      pendfoundposition_positive,
				      NULL, NULL, NULL, NULL));
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_data_token_text(lcrzo_constdata datain,
			  lcrzo_int32 datainsize,
			  lcrzo_bool searchcomplement, 
			  lcrzo_int32 datainstartpos,
			  lcrzo_int32 datainendpos,
			  lcrzo_conststring searchedtext,
			  lcrzo_int32 *ppositionindicator,
			  lcrzo_int32 *pstartfoundposition_negative,
			  lcrzo_int32 *pstartfoundposition_positive,
			  lcrzo_int32 *pendfoundposition_negative,
			  lcrzo_int32 *pendfoundposition_positive)
{ return(lcrzo_data_token_data(datain, datainsize,
			       searchcomplement, datainstartpos, datainendpos,
			       (lcrzo_constdata)searchedtext,
			       strlen(searchedtext),
			       ppositionindicator,
			       pstartfoundposition_negative,
			       pstartfoundposition_positive,
			       pendfoundposition_negative,
			       pendfoundposition_positive));
}

/*-------------------------------------------------------------*/
int lcrzo_data_token_re(lcrzo_constdata datain,
			lcrzo_int32 datainsize,
			lcrzo_bool searchcomplement, 
			lcrzo_int32 datainstartpos,
			lcrzo_int32 datainendpos,
			lcrzo_conststring regularexpression,
			lcrzo_int32 *ppositionindicator,
			lcrzo_int32 *pstartfoundposition_negative,
			lcrzo_int32 *pstartfoundposition_positive,
			lcrzo_int32 *pendfoundposition_negative,
			lcrzo_int32 *pendfoundposition_positive)
{ int direction, ret;
  lcrzo_int32 infpos1, suppos1, infpos2, suppos2, startfound, endfound;

  /*parameters verification*/
  if (datain==NULL && datainsize) return(LCRZO_ERR_PANULLPTRSIZE);
  if (datainsize<0) return(LCRZO_ERR_PATOOLOW);
  lcrzo_bool_verifbof(searchcomplement);
  if (ppositionindicator==NULL) return(LCRZO_ERR_PANULLPTR);
  lcrzo_er(lcrzo_priv_managedatarange(datainsize,
				      datainstartpos, datainendpos,
				      &infpos1, &infpos2, &suppos1, &suppos2,
				      NULL, NULL, &direction, NULL));
  
    
  if (direction==LCRZO_PRIV_INCREASE)
  { /*first call*/
    if (*ppositionindicator==0) *ppositionindicator=infpos2;
    /*last call*/
    if (*ppositionindicator==suppos2+1) return(LCRZO_ERR_OKDATAEND);
    /*error : should not happen if positionindicator is correctly used*/
    if (*ppositionindicator<infpos2) return(LCRZO_ERR_PATOOLOW);
    if (*ppositionindicator>suppos2) return(LCRZO_ERR_PATOOBIG);
    /*search the token*/
    if (*ppositionindicator==suppos2)
    { startfound=suppos2;
      endfound=suppos2;
      *ppositionindicator=endfound+1;
    }
    else
    { startfound=*ppositionindicator;
      ret=lcrzo_data_search_re(datain, datainsize, searchcomplement, 
			       startfound, suppos2, regularexpression,
			       NULL, &endfound, NULL, ppositionindicator);
      if (ret!=LCRZO_ERR_OK)
      { endfound=suppos2;
        *ppositionindicator=endfound+1;
      }
    }
  }
  else
  { /*first call*/
    if (*ppositionindicator==0) *ppositionindicator=infpos1;
    /*last call*/
    if (*ppositionindicator==suppos1-1) return(LCRZO_ERR_OKDATAEND);
    /*error : should not happen if positionindicator is correctly used*/
    if (*ppositionindicator>infpos1) return(LCRZO_ERR_PATOOBIG);
    if (*ppositionindicator<suppos1) return(LCRZO_ERR_PATOOLOW);
    /*search the token*/
    if (*ppositionindicator==suppos1)
    { startfound=suppos1;
      endfound=suppos1;
      *ppositionindicator=startfound-1;
    }
    else
    { endfound=*ppositionindicator;
      ret=lcrzo_data_search_re(datain, datainsize, searchcomplement, 
			       endfound, suppos1, regularexpression,
			       ppositionindicator, NULL, &startfound, NULL);
      if (ret!=LCRZO_ERR_OK)
      { startfound=suppos1;
        *ppositionindicator=startfound-1;
      }
    }
  }

  lcrzo_er(lcrzo_priv_managedatarange(datainsize, 
				      startfound, endfound,
				      pstartfoundposition_negative,
				      pstartfoundposition_positive, 
				      pendfoundposition_negative,
				      pendfoundposition_positive,
				      NULL, NULL, NULL, NULL));
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_data_replacem_char(lcrzo_constdata datain,
			     lcrzo_int32 datainsize,
			     lcrzo_bool searchcomplement, 
			     lcrzo_int32 datainstartpos,
			     lcrzo_int32 datainendpos,
			     lcrzo_int32 maxnumberofreplacement,
			     lcrzo_uint8 c_toreplace,
			     lcrzo_constdata data_replacing,
			     lcrzo_int32 data_replacingsize,
			     lcrzo_data *pdataout,
			     lcrzo_int32 *pdataoutsize)
{ lcrzo_int32 p, i, dataoutsize, infpos, suppos, supposrange, startat;
  lcrzo_int32 infposrange;
  int ret, direction;

  /*parameters verification*/
  if (datain==NULL && datainsize) return(LCRZO_ERR_PANULLPTRSIZE);
  if (datainsize<0) return(LCRZO_ERR_PATOOLOW);
  lcrzo_bool_verifbof(searchcomplement);
  if (maxnumberofreplacement<0) return(LCRZO_ERR_PATOOLOW);
  if (data_replacing==NULL) return(LCRZO_ERR_PANULLPTR);
  if (data_replacingsize<0) return(LCRZO_ERR_PATOOLOW);
  lcrzo_er(lcrzo_priv_managedatarange(datainsize,
				      datainstartpos, datainendpos,
				      NULL, &infposrange,
				      NULL, &supposrange,
				      NULL, NULL, &direction, NULL));
 
  p=0;
  i=0;
  if (direction==LCRZO_PRIV_INCREASE)
  { lcrzo_efr(lcrzo_data_initm_range(datain, datainsize,
				     1, infposrange,
				     pdataout, &dataoutsize),
	      { if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize; });
    while (LCRZO_TRUE)
    { ret=lcrzo_data_token_char(datain, datainsize, searchcomplement,
				datainstartpos, datainendpos, c_toreplace,
				&p, NULL, &infpos, NULL, &suppos);
      /*specific exit*/
      if (ret==LCRZO_ERR_OK) {/*continue below*/}
      else if (ret==LCRZO_ERR_OKDATAEND) break;
      else return(ret);
      /*append the data from datain*/
      lcrzo_efr(lcrzo_data_appendm_range(datain, datainsize,
					 infpos, suppos,
					 dataoutsize, pdataout, &dataoutsize),
		{ if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize; });
      /*append the replacing data except for the last token*/
      if ( suppos!=supposrange &&
	   ( !maxnumberofreplacement || i!=maxnumberofreplacement ) )
      { lcrzo_efr(lcrzo_data_appendm_data(data_replacing, data_replacingsize,
					  dataoutsize, pdataout, &dataoutsize),
		  { if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize; });
      }
      /*increment now, because the precedent "if" must use the last value*/
      i++;
      /*if we reached the maxnumberofreplacement, append the end, then exit*/
      if ( maxnumberofreplacement && i>maxnumberofreplacement )
      { lcrzo_efr(lcrzo_data_appendm_range(datain, datainsize,
					   suppos, supposrange,
					   dataoutsize, pdataout,&dataoutsize),
		  { if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize; });
        break;
      }
    }
    lcrzo_efr(lcrzo_data_appendm_range(datain, datainsize,
				       supposrange, -1,
				       dataoutsize, pdataout, &dataoutsize),
	      { if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize; });
    if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize;
  }
  else
  { /*find the inferior replacement location*/
    if (!maxnumberofreplacement)
    { startat=datainendpos;
    }
    else
    { startat=0; /*just for the compiler, it will produce an error*/
      suppos=0; /* just because of the compiler warning */
      for ( i=0 ; i<=maxnumberofreplacement ; i++ )
      { ret=lcrzo_data_token_char(datain, datainsize, searchcomplement,
				  datainstartpos, datainendpos, c_toreplace,
				  &p, NULL, NULL, NULL, &suppos);
        /*specific exit*/
        if (ret==LCRZO_ERR_OK) {/*continue*/}
	else if (ret==LCRZO_ERR_OKDATAEND) { startat=datainendpos; break;}
	else return(ret);
      }
      if (i==maxnumberofreplacement+1)
      { startat=suppos;
      }
    }
    /*then, it's the same as for increasing*/
    return(lcrzo_data_replacem_char(datain, datainsize,
				    searchcomplement, 
				    startat, datainstartpos,
				    0, c_toreplace,
				    data_replacing, data_replacingsize,
				    pdataout, pdataoutsize));
  }
  
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_data_replacem_nchar(lcrzo_constdata datain,
			      lcrzo_int32 datainsize,
			      lcrzo_bool searchcomplement, 
			      lcrzo_int32 datainstartpos,
			      lcrzo_int32 datainendpos,
			      lcrzo_int32 maxnumberofreplacement,
			      lcrzo_constdata searchlist,
			      lcrzo_int32 searchlistsize,
			      lcrzo_constdata data_replacing,
			      lcrzo_int32 data_replacingsize,
			      lcrzo_data *pdataout,
			      lcrzo_int32 *pdataoutsize)
{ lcrzo_int32 p, i, dataoutsize, infpos, suppos, supposrange, startat;
  lcrzo_int32 infposrange;
  int ret, direction;

  /*parameters verification*/
  if (datain==NULL && datainsize) return(LCRZO_ERR_PANULLPTRSIZE);
  if (datainsize<0) return(LCRZO_ERR_PATOOLOW);
  lcrzo_bool_verifbof(searchcomplement);
  if (maxnumberofreplacement<0) return(LCRZO_ERR_PATOOLOW);
  if (searchlist==NULL) return(LCRZO_ERR_PANULLPTR);
  if (searchlistsize<0) return(LCRZO_ERR_PATOOLOW);
  if (data_replacing==NULL) return(LCRZO_ERR_PANULLPTR);
  if (data_replacingsize<0) return(LCRZO_ERR_PATOOLOW);
  lcrzo_er(lcrzo_priv_managedatarange(datainsize,
				      datainstartpos, datainendpos,
				      NULL, &infposrange,
				      NULL, &supposrange,
				      NULL, NULL, &direction, NULL));
 
  p=0;
  i=0;
  if (direction==LCRZO_PRIV_INCREASE)
  { lcrzo_efr(lcrzo_data_initm_range(datain, datainsize,
				     1, infposrange,
				     pdataout, &dataoutsize),
	      { if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize; });
    while (LCRZO_TRUE)
    { ret=lcrzo_data_token_nchar(datain, datainsize, searchcomplement,
				 datainstartpos, datainendpos, 
				 searchlist, searchlistsize,
				 &p, NULL, &infpos, NULL, &suppos);
      /*specific exit*/
      if (ret==LCRZO_ERR_OK) {/*continue below*/}
      else if (ret==LCRZO_ERR_OKDATAEND) break;
      else return(ret);
      /*append the data from datain*/
      lcrzo_efr(lcrzo_data_appendm_range(datain, datainsize,
					 infpos, suppos,
					 dataoutsize, pdataout, &dataoutsize),
		{ if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize; });
      /*append the replacing data except for the last token*/
      if ( suppos!=supposrange &&
	   ( !maxnumberofreplacement || i!=maxnumberofreplacement ) )
      { lcrzo_efr(lcrzo_data_appendm_data(data_replacing, data_replacingsize,
					  dataoutsize, pdataout, &dataoutsize),
		  { if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize; });
      }
      /*increment now, because the precedent "if" must use the last value*/
      i++;
      /*if we reached the maxnumberofreplacement, append the end, then exit*/
      if ( maxnumberofreplacement && i>maxnumberofreplacement )
      { lcrzo_efr(lcrzo_data_appendm_range(datain, datainsize,
					   suppos, supposrange,
					   dataoutsize, pdataout,&dataoutsize),
		  { if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize; });
        break;
      }
    }
    lcrzo_efr(lcrzo_data_appendm_range(datain, datainsize,
				       supposrange, -1,
				       dataoutsize, pdataout, &dataoutsize),
	      { if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize; });
    if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize;
  }
  else
  { /*find the inferior replacement location*/
    if (!maxnumberofreplacement)
    { startat=datainendpos;
    }
    else
    { startat=0; /*just for the compiler, it will produce an error*/
      suppos=0; /* just because of the compiler warning */
      for ( i=0 ; i<=maxnumberofreplacement ; i++ )
      { ret=lcrzo_data_token_nchar(datain, datainsize, searchcomplement,
				   datainstartpos, datainendpos, 
				   searchlist, searchlistsize,
				   &p, NULL, NULL, NULL, &suppos);
        /*specific exit*/
        if (ret==LCRZO_ERR_OK) {/*continue*/}
	else if (ret==LCRZO_ERR_OKDATAEND) { startat=datainendpos; break;}
	else return(ret);
      }
      if (i==maxnumberofreplacement+1)
      { startat=suppos;
      }
    }
    /*then, it's the same as for increasing*/
    return(lcrzo_data_replacem_nchar(datain, datainsize,
				     searchcomplement, 
				     startat, datainstartpos,
				     0, searchlist, searchlistsize,
				     data_replacing, data_replacingsize,
				     pdataout, pdataoutsize));
  }
  
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_data_replacem_data(lcrzo_constdata datain,
			     lcrzo_int32 datainsize,
			     lcrzo_bool searchcomplement, 
			     lcrzo_int32 datainstartpos,
			     lcrzo_int32 datainendpos,
			     lcrzo_int32 maxnumberofreplacement,
			     lcrzo_constdata searcheddata,
			     lcrzo_int32 searcheddatasize,
			     lcrzo_constdata data_replacing,
			     lcrzo_int32 data_replacingsize,
			     lcrzo_data *pdataout,
			     lcrzo_int32 *pdataoutsize)
{ lcrzo_int32 p, i, dataoutsize, infpos, suppos, supposrange, startat;
  lcrzo_int32 infposrange;
  int ret, direction;

  /*parameters verification*/
  if (datain==NULL && datainsize) return(LCRZO_ERR_PANULLPTRSIZE);
  if (datainsize<0) return(LCRZO_ERR_PATOOLOW);
  lcrzo_bool_verifbof(searchcomplement);
  if (maxnumberofreplacement<0) return(LCRZO_ERR_PATOOLOW);
  if (searcheddata==NULL) return(LCRZO_ERR_PANULLPTR);
  if (searcheddatasize<0) return(LCRZO_ERR_PATOOLOW);
  if (data_replacing==NULL) return(LCRZO_ERR_PANULLPTR);
  if (data_replacingsize<0) return(LCRZO_ERR_PATOOLOW);
  lcrzo_er(lcrzo_priv_managedatarange(datainsize,
				      datainstartpos, datainendpos,
				      NULL, &infposrange,
				      NULL, &supposrange,
				      NULL, NULL, &direction, NULL));
 
  p=0;
  i=0;
  if (direction==LCRZO_PRIV_INCREASE)
  { lcrzo_efr(lcrzo_data_initm_range(datain, datainsize,
				     1, infposrange,
				     pdataout, &dataoutsize),
	      { if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize; });
    while (LCRZO_TRUE)
    { ret=lcrzo_data_token_data(datain, datainsize, searchcomplement,
				datainstartpos, datainendpos,
				searcheddata, searcheddatasize,
				&p, NULL, &infpos, NULL, &suppos);
      /*specific exit*/
      if (ret==LCRZO_ERR_OK) {/*continue below*/}
      else if (ret==LCRZO_ERR_OKDATAEND) break;
      else return(ret);
      /*append the data from datain*/
      lcrzo_efr(lcrzo_data_appendm_range(datain, datainsize,
					 infpos, suppos,
					 dataoutsize, pdataout, &dataoutsize),
		{ if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize; });
      /*append the replacing data except for the last token*/
      if ( suppos!=supposrange &&
	   ( !maxnumberofreplacement || i!=maxnumberofreplacement ) )
      { lcrzo_efr(lcrzo_data_appendm_data(data_replacing, data_replacingsize,
					  dataoutsize, pdataout, &dataoutsize),
		  { if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize; });
      }
      /*increment now, because the precedent "if" must use the last value*/
      i++;
      /*if we reached the maxnumberofreplacement, append the end, then exit*/
      if ( maxnumberofreplacement && i>maxnumberofreplacement )
      { lcrzo_efr(lcrzo_data_appendm_range(datain, datainsize,
					   suppos, supposrange,
					   dataoutsize, pdataout,&dataoutsize),
		  { if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize; });
        break;
      }
    }
    lcrzo_efr(lcrzo_data_appendm_range(datain, datainsize,
				       supposrange, -1,
				       dataoutsize, pdataout, &dataoutsize),
	      { if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize; });
    if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize;
  }
  else
  { /*find the inferior replacement location*/
    if (!maxnumberofreplacement)
    { startat=datainendpos;
    }
    else
    { startat=0; /*just for the compiler, it will produce an error*/
      suppos=0; /* just because of the compiler warning */
      for ( i=0 ; i<=maxnumberofreplacement ; i++ )
      { ret=lcrzo_data_token_data(datain, datainsize, searchcomplement,
				  datainstartpos, datainendpos,
				  searcheddata, searcheddatasize,
				  &p, NULL, NULL, NULL, &suppos);
        /*specific exit*/
        if (ret==LCRZO_ERR_OK) {/*continue*/}
	else if (ret==LCRZO_ERR_OKDATAEND) { startat=datainendpos; break;}
	else return(ret);
      }
      if (i==maxnumberofreplacement+1)
      { startat=suppos;
      }
    }
    /*then, it's the same as for increasing*/
    return(lcrzo_data_replacem_data(datain, datainsize,
				    searchcomplement, 
				    startat, datainstartpos,
				    0, searcheddata, searcheddatasize,
				    data_replacing, data_replacingsize,
				    pdataout, pdataoutsize));
  }
  
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_data_replacem_text(lcrzo_constdata datain,
			     lcrzo_int32 datainsize,
			     lcrzo_bool searchcomplement, 
			     lcrzo_int32 datainstartpos,
			     lcrzo_int32 datainendpos,
			     lcrzo_int32 maxnumberofreplacement,
			     lcrzo_conststring searchedtext,
			     lcrzo_constdata data_replacing,
			     lcrzo_int32 data_replacingsize,
			     lcrzo_data *pdataout,
			     lcrzo_int32 *pdataoutsize)
{ return(lcrzo_data_replacem_data(datain, datainsize, searchcomplement,
				  datainstartpos, datainendpos,
				  maxnumberofreplacement,
				  (lcrzo_constdata)searchedtext, 
				  strlen(searchedtext), data_replacing,
				  data_replacingsize, pdataout, pdataoutsize));
}

/*-------------------------------------------------------------*/
int lcrzo_data_replacem_re(lcrzo_constdata datain,
			   lcrzo_int32 datainsize,
			   lcrzo_bool searchcomplement, 
			   lcrzo_int32 datainstartpos,
			   lcrzo_int32 datainendpos,
			   lcrzo_int32 maxnumberofreplacement,
			   lcrzo_conststring regularexpression,
			   lcrzo_constdata data_replacing,
			   lcrzo_int32 data_replacingsize,
			   lcrzo_data *pdataout,
			   lcrzo_int32 *pdataoutsize)
{ lcrzo_int32 p, i, dataoutsize, infpos, suppos, supposrange, startat;
  lcrzo_int32 infposrange;
  int ret, direction;

  /*parameters verification*/
  if (datain==NULL && datainsize) return(LCRZO_ERR_PANULLPTRSIZE);
  if (datainsize<0) return(LCRZO_ERR_PATOOLOW);
  lcrzo_bool_verifbof(searchcomplement);
  if (maxnumberofreplacement<0) return(LCRZO_ERR_PATOOLOW);
  if (regularexpression==NULL) return(LCRZO_ERR_PANULLPTR);
  if (data_replacing==NULL) return(LCRZO_ERR_PANULLPTR);
  if (data_replacingsize<0) return(LCRZO_ERR_PATOOLOW);
  lcrzo_er(lcrzo_priv_managedatarange(datainsize,
				      datainstartpos, datainendpos,
				      NULL, &infposrange,
				      NULL, &supposrange,
				      NULL, NULL, &direction, NULL));
 
  p=0;
  i=0;
  if (direction==LCRZO_PRIV_INCREASE)
  { lcrzo_efr(lcrzo_data_initm_range(datain, datainsize,
				     1, infposrange,
				     pdataout, &dataoutsize),
	      { if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize; });
    while (LCRZO_TRUE)
    { ret=lcrzo_data_token_re(datain, datainsize, searchcomplement,
			      datainstartpos, datainendpos, regularexpression,
			      &p, NULL, &infpos, NULL, &suppos);
      /*specific exit*/
      if (ret==LCRZO_ERR_OK) {/*continue below*/}
      else if (ret==LCRZO_ERR_OKDATAEND) break;
      else return(ret);
      /*append the data from datain*/
      lcrzo_efr(lcrzo_data_appendm_range(datain, datainsize,
					 infpos, suppos,
					 dataoutsize, pdataout, &dataoutsize),
		{ if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize; });
      /*append the replacing data except for the last token*/
      if ( suppos!=supposrange &&
	   ( !maxnumberofreplacement || i!=maxnumberofreplacement ) )
      { lcrzo_efr(lcrzo_data_appendm_data(data_replacing, data_replacingsize,
					  dataoutsize, pdataout, &dataoutsize),
		  { if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize; });
      }
      /*increment now, because the precedent "if" must use the last value*/
      i++;
      /*if we reached the maxnumberofreplacement, append the end, then exit*/
      if ( maxnumberofreplacement && i>maxnumberofreplacement )
      { lcrzo_efr(lcrzo_data_appendm_range(datain, datainsize,
					   suppos, supposrange,
					   dataoutsize, pdataout,&dataoutsize),
		  { if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize; });
        break;
      }
    }
    lcrzo_efr(lcrzo_data_appendm_range(datain, datainsize,
				       supposrange, -1,
				       dataoutsize, pdataout, &dataoutsize),
	      { if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize; });
    if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize;
  }
  else
  { /*find the inferior replacement location*/
    if (!maxnumberofreplacement)
    { startat=datainendpos;
    }
    else
    { startat=0; /*just for the compiler, it will produce an error*/
      suppos=0; /* just because of the compiler warning */
      for ( i=0 ; i<=maxnumberofreplacement ; i++ )
      { ret=lcrzo_data_token_re(datain, datainsize, searchcomplement,
				datainstartpos, datainendpos, 
				regularexpression,
				&p, NULL, NULL, NULL, &suppos);
        /*specific exit*/
        if (ret==LCRZO_ERR_OK) {/*continue*/}
	else if (ret==LCRZO_ERR_OKDATAEND) { startat=datainendpos; break;}
	else return(ret);
      }
      if (i==maxnumberofreplacement+1)
      { startat=suppos;
      }
    }
    /*then, it's the same as for increasing*/
    return(lcrzo_data_replacem_re(datain, datainsize,
				  searchcomplement, 
				  startat, datainstartpos,
				  0, regularexpression,
				  data_replacing, data_replacingsize,
				  pdataout, pdataoutsize));
  }
  
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_data_replacem_regexp(lcrzo_constdata datain,
			       lcrzo_int32 datainsize,
			       lcrzo_bool searchcomplement, 
			       lcrzo_int32 datainstartpos,
			       lcrzo_int32 datainendpos,
			       lcrzo_int32 maxnumberofreplacement,
			       lcrzo_conststring regularexpression,
			       lcrzo_constdata data_replacing,
			       lcrzo_int32 data_replacingsize,
			       lcrzo_data *pdataout,
			       lcrzo_int32 *pdataoutsize)
{ lcrzo_int32 p, i, dataoutsize, infpos, suppos, supposrange, startat;
  lcrzo_int32 infposrange;
  int ret, direction;
  lcrzo_regexp arrayfoundpos;

  /*parameters verification*/
  if (datain==NULL && datainsize) return(LCRZO_ERR_PANULLPTRSIZE);
  if (datainsize<0) return(LCRZO_ERR_PATOOLOW);
  lcrzo_bool_verifbof(searchcomplement);
  if (maxnumberofreplacement<0) return(LCRZO_ERR_PATOOLOW);
  if (regularexpression==NULL) return(LCRZO_ERR_PANULLPTR);
  if (data_replacing==NULL) return(LCRZO_ERR_PANULLPTR);
  if (data_replacingsize<0) return(LCRZO_ERR_PATOOLOW);
  lcrzo_er(lcrzo_priv_managedatarange(datainsize,
				      datainstartpos, datainendpos,
				      NULL, &infposrange,
				      NULL, &supposrange,
				      NULL, NULL, &direction, NULL));
 
  p=0;
  i=0;
  if (direction==LCRZO_PRIV_INCREASE)
  { lcrzo_efr(lcrzo_data_initm_range(datain, datainsize,
				     1, infposrange,
				     pdataout, &dataoutsize),
	      { if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize; });
    p=infposrange;
    while (LCRZO_TRUE)
    { /*tokenize with regexp*/
      if (p==supposrange+1) break;
      if (p==supposrange)
      { infpos=supposrange;
        suppos=supposrange;
	p=suppos+1;
      }
      else
      { infpos=p;
        ret=lcrzo_data_search_regexp(datain, datainsize, searchcomplement, 
				     infpos, supposrange, regularexpression,
				     arrayfoundpos);
	if (ret==LCRZO_ERR_OK)
	{ suppos=arrayfoundpos[0].startindex_positive;
          p=arrayfoundpos[0].endindex_positive;
	}
	else
	{ suppos=supposrange;
          p=suppos+1;
	}
      }
      /*append the data from datain*/
      lcrzo_efr(lcrzo_data_appendm_range(datain, datainsize,
					 infpos, suppos,
					 dataoutsize, pdataout, &dataoutsize),
		{ if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize; });
      /*append the replacing data except for the last token*/
      if ( suppos!=supposrange &&
	   ( !maxnumberofreplacement || i!=maxnumberofreplacement ) )
      { lcrzo_efr(lcrzo_priv_data_appendm_regexp(datain, datainsize,
						 arrayfoundpos,
						 data_replacing,
						 data_replacingsize,
						 dataoutsize, pdataout,
						 &dataoutsize),
		  { if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize; });
      }
      /*increment now, because the precedent "if" must use the last value*/
      i++;
      /*if we reached the maxnumberofreplacement, append the end, then exit*/
      if ( maxnumberofreplacement && i>maxnumberofreplacement )
      { lcrzo_efr(lcrzo_data_appendm_range(datain, datainsize,
					   suppos, supposrange,
					   dataoutsize, pdataout,&dataoutsize),
		  { if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize; });
        break;
      }
    }
    lcrzo_efr(lcrzo_data_appendm_range(datain, datainsize,
				       supposrange, -1,
				       dataoutsize, pdataout, &dataoutsize),
	      { if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize; });
    if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize;
  }
  else
  { /*find the inferior replacement location*/
    if (!maxnumberofreplacement)
    { startat=datainendpos;
    }
    else
    { startat=0; /*just for the compiler, it will produce an error*/
      suppos=0; /* just because of the compiler warning */
      for ( i=0 ; i<=maxnumberofreplacement ; i++ )
      { ret=lcrzo_data_token_re(datain, datainsize, searchcomplement,
				datainstartpos, datainendpos, 
				regularexpression,
				&p, NULL, NULL, NULL, &suppos);
        /*specific exit*/
        if (ret==LCRZO_ERR_OK) {/*continue*/}
	else if (ret==LCRZO_ERR_OKDATAEND) { startat=datainendpos; break;}
	else return(ret);
      }
      if (i==maxnumberofreplacement+1)
      { startat=suppos;
      }
    }
    /*then, it's the same as for increasing*/
    return(lcrzo_data_replacem_regexp(datain, datainsize,
				      searchcomplement, 
				      startat, datainstartpos,
				      0, regularexpression,
				      data_replacing, data_replacingsize,
				      pdataout, pdataoutsize));
  }
  
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_hexa_initm_data(lcrzo_constdata datain,
			  lcrzo_int32 datainsize,
			  lcrzo_string *phexaout)
{ lcrzo_string ptr;
  lcrzo_int32 i, j;

  /*parameters verification*/
  if (datain==NULL && datainsize) return(LCRZO_ERR_PANULLPTRSIZE);

  /*alloc sufficiently space*/
  lcrzo_er(lcrzo_string_alloc(2*datainsize+1, &ptr));

  /*create the string*/
  j=0;
  for ( i=0 ; i<datainsize ; i++ )
  { lcrzo_priv_hexa_twoquart(datain[i], &(ptr[j]), &(ptr[j+1]));
    j+=2;
  }

  /*put the '\0'*/
  ptr[j]='\0';

  /*end*/
  if (phexaout!=NULL) *phexaout=ptr;
  else lcrzo_string_free(ptr);
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_mixed_initm_data(lcrzo_constdata datain,
			   lcrzo_int32 datainsize,
			   lcrzo_string *pmixedout)
{ lcrzo_string ptr;
  lcrzo_int32 i, j;
  lcrzo_bool guillemetecrit, first;
  lcrzo_uint8 c;

  /*parameters verification*/
  if (datain==NULL && datainsize) return(LCRZO_ERR_PANULLPTRSIZE);

  /*alloc sufficiently space*/
  lcrzo_er(lcrzo_string_alloc(4*datainsize+1, &ptr));

  /*create the string*/
  j=0;
  guillemetecrit=0;
  first=1;
  for ( i=0 ; i<datainsize ; i++ )
  { c=datain[i];
    if (c<32 || c>126)
    { if (guillemetecrit)
      { ptr[j++]='\'';
        guillemetecrit=0;
      }
      if (first)
        first=0;
      else
        ptr[j++]=' ';
      lcrzo_priv_hexa_twoquart(c, &(ptr[j]), &(ptr[j+1]));
      j+=2;
    }
    else
    { if (!guillemetecrit) 
      { if (first)
          first=0;
        else
	  ptr[j++]=' ';
        ptr[j++]='\'';
        guillemetecrit=1;
      }
      if (c=='\'')
      { ptr[j++]='\'';
        ptr[j++]='\'';
      }
      else
      { ptr[j++]=c;
      }
    }
  }
  if (guillemetecrit) ptr[j++]='\'';

  /*put the '\0'*/
  ptr[j]='\0';

  /*realloc exactly*/
  lcrzo_er(lcrzo_string_realloc(strlen(ptr), &ptr));

  /*end*/
  if (pmixedout!=NULL) *pmixedout=ptr;
  else lcrzo_string_free(ptr);
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_base64_initm_data(lcrzo_constdata datain,
			    lcrzo_int32 datainsize,
			    lcrzo_string *pbase64out)
{ lcrzo_string ptr;
  lcrzo_int32 i, j, completeblocs, lastsblocs;

  /*parameters verification*/
  if (datain==NULL && datainsize) return(LCRZO_ERR_PANULLPTRSIZE);

  /*alloc sufficiently space*/
  lcrzo_er(lcrzo_string_alloc(2*datainsize+1, &ptr));

  /*create the string*/
  j=0;
  completeblocs=datainsize/3;
  lastsblocs=datainsize-3*completeblocs;
  /*traite les blocs complets*/
  for ( i=0 ; i<completeblocs ; i++ )
  { lcrzo_priv_base64_int2char(datain[3*i]>>2, &(ptr[j]));
    j++;
    lcrzo_priv_base64_int2char(((datain[3*i]&3)<<4) | (datain[3*i+1]>>4), 
			       &(ptr[j]));
    j++;
    lcrzo_priv_base64_int2char(((datain[3*i+1]&0xF)<<2) | (datain[3*i+2]>>6),
			       &(ptr[j]));
    j++;
    lcrzo_priv_base64_int2char(datain[3*i+2]&0x3F, &(ptr[j]));
    j++;
  }
  /*traite selon le nombre de caracteres restants*/
  if (lastsblocs==1)
  { lcrzo_priv_base64_int2char(datain[3*i]>>2, &(ptr[j]));
    j++;
    lcrzo_priv_base64_int2char(((datain[3*i]&3)<<4), &(ptr[j]));
    j++;
    ptr[j++]='=';
    ptr[j++]='=';
  }
  else if (lastsblocs==2)
  { lcrzo_priv_base64_int2char(datain[3*i]>>2, &(ptr[j]));
    j++;
    lcrzo_priv_base64_int2char(((datain[3*i]&3)<<4) | (datain[3*i+1]>>4), 
			       &(ptr[j]));
    j++;
    lcrzo_priv_base64_int2char(((datain[3*i+1]&0xF)<<2), 
			       &(ptr[j]));
    j++;
    ptr[j++]='=';
  }
  
  /*put the '\0'*/
  ptr[j]='\0';

  /*realloc exactly*/
  lcrzo_er(lcrzo_string_realloc(strlen(ptr), &ptr));

  /*end*/
  if (pbase64out!=NULL) *pbase64out=ptr;
  else lcrzo_string_free(ptr);
  return(LCRZO_ERR_OK);
}


/*-------------------------------------------------------------*/
int lcrzo_data_checksum(lcrzo_constdata data,
			lcrzo_int32 datasize, 
			lcrzo_uint16 *pchecksum)
{ register lcrzo_uint32 somme;
  register lcrzo_int32 i;
  lcrzo_uint16 resu;

  /*parameters verification*/
  if (data==NULL && datasize) return(LCRZO_ERR_PANULLPTRSIZE);

  i=0;
  somme=0;
  /*travaille par packets de 2*/
  if (datasize>1)
  { while ( i<(datasize-1) )
    { somme += data[i++];
      somme += (data[i++])<<8;
    }
  }
  /*travaille eventuellement sur le dernier octet*/
  if (datasize%2)
  { somme += data[i];
  }
  /*on additionne le word fort, le word faible, et la retenue*/
  somme = (somme >> 16) + (somme & 0xffff);
  somme += (somme >> 16);
  /*le resultat est le complement*/
  resu=(lcrzo_uint16)~somme;
  /*les deux mots doivent etre inverses pour que le resultat soit
    au format host*/
  if (pchecksum!=NULL) *pchecksum = (lcrzo_uint16)( (resu>>8) | (resu<<8) );

  return(LCRZO_ERR_OK);
}
