// ===================================================================
// $Id: basic.cpp,v 1.4 2003/01/15 21:25:20 havran Exp $
//
// basic.cpp
//     Helper routines.
//
// Licence and usage conditions in November 2003:
// This file can be used and modified only with written permission of
// Vlastimil Havran, Pohodli 27, 57001 Litomysl, the Czech Republic.
// This library is granted to be used by Polina Kondratieva within
// her MPI HIWI job working on BRDFLIB library. The usage condition
// may change in the next version of the library. At the moment,
// the library development is supported by Max-Planck-Institut for
// Informatik, Stuhlsatzenhausweg 85, 66123 Saarbruecken Germany
// See WWW: http://www.mpi-sb.mpg.de
// REPLACEMENT_STRING
//
// Initial coding by Vlastimil Havran, 1999.
//
// Given to BRDFLIB project for the Polina Kondratieva's
// HIWI JOB assignment in November 2003.

// BRDFLIB headers
#include "config.h"
#include "basic.h"


__BEGIN_BRDFLIB_SOURCE

// static variables
float
CLimits::Small = 1e-6;
float
CLimits::Large = 1e6;

// VERSION OF THE LIBRARY SET UP MANUALLY HERE
string STRINGVERSION("BRDFLIB-1.0.0");

// Puts the specified number of spaces out to given stream. Used for
// indentation during CObject3D::Describe().
void
indent(ostream &app, int ind)
{
  int i;

  for (i = 0; i < ind; i++)
    app << ' ';
}

// prefix filename by a given directory name e.g. "aa.out","ref" makes
// "ref/aa.out", but "stats/aa.out","ref" makes "stats/ref/aa.out"
void
PrefixNameByDir(const string &filename, const string &dirname,
		string &outputName)
{
  outputName.resize(0);
  char dircat[2];
  dircat[0] = (char) DIRCAT;
  dircat[1] = 0x00;

  unsigned int pos = filename.find_last_of(dircat[0]);

  //DEBUG << "pos = " << pos << endl;
  
  if (pos < filename.length()) { // current name contains some dir separators
    outputName.assign(filename, 0, pos-1);
    //DEBUG << "outputName=" << outputName.c_str()<< endl;
    outputName += dircat;
  }
  else
    pos = 0;

  //DEBUG << "outputName=" << outputName.c_str()<< endl;
    
  outputName.append(dirname);
  //DEBUG << "outputName=" << outputName.c_str()<< endl;
  outputName += dircat;
  //DEBUG << "outputName=" << outputName.c_str()<< endl;
  outputName.append(filename, pos, filename.length()-pos);
  //DEBUG << "outputName=" << outputName.c_str()<< endl;
}

// prefix filename extension by a given extPrefix
// for example the filename "data/tetra.rgb" and extPrefix 0102 makes
// the output filename "data/tetra0102.rgb"
// If no extension is found, then extPrefix is simply appended to the
// file name, e.g. for "balls" makes "balls0102"
void
PrefixExtensionByName(const string &filename, const string &extPrefix,
	  	      string &outputName)
{
  unsigned int pos = filename.find_last_of('.');
  
  if (pos >= filename.length()) {
    outputName = filename;
    outputName.append(extPrefix); // just append
  }
  else {
    // the storage for extension of filename
    outputName.assign(filename, 0, pos);
    // append the extPrefix
    outputName.append(extPrefix);
    outputName.append(filename, pos, filename.length()-pos);
  }

  return;
}

// changing the extension of the filename
// filename .. filename to be changed
// maxLength .. maximal length of array filename that should not be exceeded
// newExtension .. newExtension added/replaced  ("vis", "dbg", "rgb" etc.)
void
ChangeFilenameExtension(const string &filename, const string &newExtension,
			string &outputName)
{
  outputName = filename;
  unsigned int pos = outputName.find_last_of('.');
  
  if ( pos == outputName.length()) {
    outputName.append("."); // filename has no extension
  }
  else // shorten the string
    outputName.resize(pos+1);

  outputName.append(newExtension);
}

// Skip all the rows in a text file starting from the current character,
// when the current character is a 'mark'. All the following lines
// starting with the 'mark' character are also skipped.
void
EatComments(istream &inpf, char mark)
{
  // current character
  char ch;
  
  // first character to be read
  inpf >> ch;
  
  // loop
  while (ch == mark) {
    inpf.ignore(100000, '\n'); // skip the line completely
    // first character to be read
    if (inpf.eof())
      return; // end of the stream
    else
      inpf >> ch; // read the first character on the line
  }
  
  // return the character back to the stream
  inpf.putback(ch);
}

// Skip all the whitespaces in the input stream
void
EatWhitespace(istream &inpf)
{
  // the current character
  char ch;

  // first character to be read
  inpf >> ch;

  // loop
  while (ch==' ' || ch=='\t' || ch=='\n' || ch=='\f' || ch=='\r' || ch=='\b') {
    if (inpf.eof())
      return; // end of the stream
    else
      inpf >> ch; // read the first character on the line
  }
  
  // return the first non-white character back to the stream to be read by the
  // next operation for reading
  inpf.putback(ch);
}

bool
FindLineWithKeyword(istream &inpf, const string &keyword)
{
  char ch;
  int length = keyword.size();

  // now we assume that we are at the beggining of a line,
  // otherwise the same string when multiply stated on a line
  // can be found.
  
  for (;;) {
    bool match = true;
    for (int i = 0; i < length; i++) {
      // i-th character on a line to be read
      if (!inpf.get(ch)) {
	match = false;
	inpf.ignore(100000, '\n');
	if (inpf.eof()) {
	  // end of the stream
	  return true; // text not found - end of stream
	}
      }

      if (ch != keyword[i]) {
	inpf.ignore(100000, '\n'); // skip the line completely
	// first character to be read
	match = false; // next line
	break;
      }
    } // for i

    if (match)
      return false; // OK, line starting with 'mark' string found
    // otherwise go to the next line
  }
  return true; // not found
}

// Converts all the possible characters to lowercase
void
ToLowerCase(string &str)
{
  int i;
  int length = (int) str.length();
  for (i = 0; i < length; i++) {
    str[i] = tolower(str[i]);
  }
}


__END_BRDFLIB_SOURCE
