deps/kb_meme/meme-5.0.1/src/buffer.c
/*
 * buf_fread_token
 * returns a string which ends at (ie. does not include) the first character 
 * that is_delim designates is a delimeter or the end of the file. 
 * The returned string is always null terminated. 
 * The parameter strlen will be set to the length of the found string.
 *
 * Allocation
 * When target is specified it will use it as a destination for the token,
 * it will be filled with up to size -1 characters from the buffer.
 * When target is NULL it will allocate a string to fit up to size -1
 * characters. If size is 0, any length is allowed to be allocated.
 *
 * Errors
 * If the token doesn't fit in the maxlen -1 space then returns NULL with
 * strlen set to the buffer's -(offset+1) from the starting position.
 * If a file read error occurs then NULL is returned with strlen set to zero.
 */
buf_fread_token
returns a string which ends at  the first character
that is_delim designates is a delimeter or the end of the file.
The returned string is always null terminated.
The parameter strlen will be set to the length of the found string.

Allocation
When target is specified it will use it as a destination for the token,
it will be filled with up to size -1 characters from the buffer.
When target is NULL it will allocate a string to fit up to size -1
characters. If size is 0, any length is allowed to be allocated.

Errors
If the token doesn't fit in the maxlen -1 space then returns NULL with
strlen set to the buffer's -(offset+1) from the starting position.
If a file read error occurs then NULL is returned with strlen set to zero.
buf_fread_token returns a string which ends at the first character that is_delim designates is a delimeter or the end of the file . The returned string is always null terminated . The parameter strlen will be set to the length of the found string . Allocation When target is specified it will use it as a destination for the token it will be filled with up to size - 1 characters from the buffer . When target is NULL it will allocate a string to fit up to size - 1 characters . If size is 0 any length is allowed to be allocated . Errors If the token doesn ' t fit in the maxlen - 1 space then returns NULL with strlen set to the buffer ' s - ( offset + 1 ) from the starting position . If a file read error occurs then NULL is returned with strlen set to zero .
char* buf_fread_token(BUF_T *buf, FILE *fp, int (*is_delim)(void*, int), 
    void* config, bool negate_is_delim, char *target, int size, int *strlen) {
  int index, block, need, offset, size_ok;
  char *token;
  assert(buf != NULL);
  assert(fp != NULL);
  assert(is_delim != NULL);
  assert(size >= 0);
  need = 0;
  offset = 0;
  if (target) {
    token = target;
  } else {
    token = NULL;
  } 
  while(true) {
    index = buf_find_next(buf, is_delim, config, negate_is_delim);
    if (index == -1) {
      block = buf_remaining(buf);
    } else {
      block = index - buf->position;
    }
    need += block;
    size_ok = false;
    if (target == NULL && (size == 0 || size > need)) { 
      size_ok = true;
      if (token) { 
        token = mm_realloc(token, sizeof(char)*(need+1));
      } else { 
        token = mm_malloc(sizeof(char)*(need+1));
      }
    } else if (target && size > need) {
      size_ok = true;
    }
    if (!size_ok) { 
      buf_set_position(buf, buf_limit(buf));
      if (strlen) *strlen = -(need+1); 
      if (!target && token) free(token); 
      return NULL;
    }
    offset += buf_getstr(buf, token+offset, block);
    assert(offset == need);
    if (index != -1 || feof(fp)) break;
    buf_compact(buf);
    buf_fread(buf, fp);
    buf_flip(buf); 
    if (ferror(fp)) { 
      if (!target && token) free(token);
      if (strlen) *strlen = 0;
      return NULL;
    }
  }
  token[need] = '\0';
  if (strlen) *strlen = need;
  return token;
}
char * buf_fread_token ( BUF_T * buf , FILE * fp , int ( * is_delim ) ( void * , int ) , void * config , bool negate_is_delim , char * target , int size , int * strlen ) { int index , block , need , offset , size_ok ; char * token ; assert ( buf != NULL ) ; assert ( fp != NULL ) ; assert ( is_delim != NULL ) ; assert ( size >= 0 ) ; need = 0 ; offset = 0 ; if ( target ) { token = target ; } else { token = NULL ; } while ( true ) { index = buf_find_next ( buf , is_delim , config , negate_is_delim ) ; if ( index == -1 ) { block = buf_remaining ( buf ) ; } else { block = index - buf -> position ; } need += block ; size_ok = false ; if ( target == NULL && ( size == 0 || size > need ) ) { size_ok = true ; if ( token ) { token = mm_realloc ( token , sizeof ( char ) * ( need + 1 ) ) ; } else { token = mm_malloc ( sizeof ( char ) * ( need + 1 ) ) ; } } else if ( target && size > need ) { size_ok = true ; } if ( ! size_ok ) { buf_set_position ( buf , buf_limit ( buf ) ) ; if ( strlen ) * strlen = - ( need + 1 ) ; if ( ! target && token ) free ( token ) ; return NULL ; } offset += buf_getstr ( buf , token + offset , block ) ; assert ( offset == need ) ; if ( index != -1 || feof ( fp ) ) break ; buf_compact ( buf ) ; buf_fread ( buf , fp ) ; buf_flip ( buf ) ; if ( ferror ( fp ) ) { if ( ! target && token ) free ( token ) ; if ( strlen ) * strlen = 0 ; return NULL ; } } token [ need ] = ' \0 ' ; if ( strlen ) * strlen = need ; return token ; }
buf_fread_token
 returns a string which ends at (ie.
buf_fread_token returns a string which ends at ( ie .
//we're allowed to allocate more //the allocation can be increased //the initial allocation needs to be made //not enough space to read the token //strlen is relative to buffer position //the user can seek backwards to recover //cleanup //copy over the data to the token //check if we found the end of the token //we didn't find the end so need to keep reading //empty the buffer //load more data into the buffer //prepare for reading from the buffer //there's often no real way to recover from this, but the caller might want their own error message //end while