// kleinkram.h

#pragma once

bool fastnull(float x)
{
 const float dd=0.01f;
 return (x > -dd && x < dd);
}

void mystrncpy(char* dest, const char* src, int max)
{
 // wie strncpy() aber mit Fehlerabfang
 char *d=dest;
 const char *s=src;
 int i;
 for(i=1; i<max && *s!=0; i++)  {*d++ = *s++;}
 *d++ = 0;
 if(i==max) fprintf(stderr,"Error in mystrncpy(dest, src=\"%s\", max=%d)\n",src,max);
}

const char* myindex(const char* str, int c)
{
 while(*str != 0 && *str != c)  str++;
 if(*str==0) return NULL;//kein Zeichen c im String str gefunden
 return str; //Rueckgabewert ist Zeiger auf erstes gefundenes c
}

bool hatendung(const char *name,const char *endung)
{
 int n = strlen(name) - strlen(endung);
 return (n>0 && strcmp(&name[n],endung)==0);
}

void endung_ersetzen(char *name,const char *endung)
{
 int n1=strlen(name);
 int n2=strlen(endung);
 if(n2>=n1) {printf("Error: endung_ersetzen(%s,%s) endung zu lang\n",name,endung); return;}
 int n=n1;
 while(n>0 && name[--n]!='.') {}
 if(n==0) {printf("Error: endung_ersetzen(%s,%s) keine endung gefunden\n",name,endung); return;}
 if(endung[0]!='.') n++;
 for(int i=0; endung[i]!=0; i++)
   {name[n++] = endung[i];}
 name[n]=0;
}

void kommentare_entfernen(char *zeile)
{
 int n,c;
 for(n=0; (c=zeile[n])!=0; n++) //Kommentare suchen
  if(c=='#' || (c=='/' && zeile[n+1]=='/'))
   {zeile[n]=0; break;}
 n=strlen(zeile);
 while(n>0 && zeile[n-1]==' ') //Leerstellen am Zeilenende loeschen
   {--n;}
 zeile[n]=0;
}

FILE* myfopen(const char* name, const char* mode)
{
 //wie fopen() aber mit Fehlerabfang
 FILE* fp;
#ifdef _WIN32
//VisualStudio meint man solle fopen_s verwenden.
//wenn trotzdem fopen verwendet werden soll, dieses Pragma setzen:
//#pragma warning(disable : 4996)
 int err=fopen_s(&fp, name, mode);
 if(err!=0) fp=NULL;
#else
 //unter Linux gibts kein fopen_s
 fp=fopen(name,mode);
#endif
 if(fp==NULL) fprintf(stderr,"Error in myfopen(\"%s\", \"%s\")\n",name,mode);
 return fp;
}

FILE* myfopen_models(const char* name, const char* mode)
{
 FILE* fp=myfopen(name,mode);
 if(fp!=NULL) return fp;
 char txt[400];
 sprintf(txt,"models/%s",name);
 fp=myfopen(txt,mode);
 if(fp==NULL) printf("Error: file \"%s\" not found\n",txt);
 return fp;
}

uint32 filelaenge(const char *name)
{
 FILE *fp=myfopen(name,"rb");
 if(fp==NULL) return 0;
 uint32 n=0;
 int c;
 while((c=getc(fp))!=EOF) {n++;}
 fclose(fp);
 return n;
}

char *file_einlesen(const char *name)
{
 uint32 nbytes = filelaenge(name);
 if(nbytes==0) return NULL;
 char *data = new char[nbytes];
 FILE *fp=myfopen(name,"rb");
 int c;
 for(uint32 i=0; (c=getc(fp))!=EOF && i<nbytes;)
  {data[i++] = c;}
 return data;
}

int getline(FILE *fp,char *s,int lim)
{		/* liest eine Textzeile oder maximal lim Zeichen */
		/* und ersetzt den Zeilentrenner durch 0         */
 int c=0;
 while(--lim && (c=getc(fp))!=EOF && c!='\n')
  {if(c!='\r') *s++ = c;}
 *s=0;
 return (c!=EOF);	/* TRUE wenn erfolgreich, FALSE wenn Fileende */
}

bool schonvorhanden(const char *name)
{
 FILE *fp=myfopen(name,"rb");
 if(fp==NULL) return false;
 fclose(fp);
 return true;
}

bool ist_stlname(const char *zeile)
{
 int n = strlen(zeile) - 4;
 return (n>0 && strcmp(&zeile[n],".stl")==0);
}

bool ist_bmfname(const char *zeile)
{
 int n = strlen(zeile) - 4;
 return (n>0 && strcmp(&zeile[n],".bmf")==0);
}

bool ist_calcname(const char *zeile)
{
 int n = strlen(zeile) - 5;
 return (n>0 && strcmp(&zeile[n],".calc")==0);
}

void data_read(const char* &src, char *dest, size_t n)
{
 while(n>0) {*dest++ = *src++; --n;}
}

/*** Routinen zum STL-Dateien einlesen: ***/
void farbe_einlesen(const char *zeile, float *data)
{
 float r,g,b;
 while(*zeile!=0 && (*zeile++)!=':') {}
 int n=sscanf(zeile,"%f, %f, %f",&r,&g,&b);
 if(n!=3) {printf("Fehler in farbe_einlesen(): zu wenige Parameter\n");}
 if(r>1 || g>1 || b>1)
  {
   r /= 255.0f;  g /= 255.0f;  b /= 255.0f;
  }
 data[0]=r;
 data[1]=g;
 data[2]=b;
}

void drei_floats_einlesen(const char *zeile, float *data)
{
 float x,y,z;
 int n=sscanf(zeile,"%f, %f, %f",&x,&y,&z);
 if(n!=3) {printf("Fehler in drei_floats_einlesen(): zu wenige Parameter\n");}
 data[0]=x;
 data[1]=y;
 data[2]=z;
}

float hoch4(float x)
{
 x = x*x;
 return x*x;
}

uint32 calc_typ(const char *name)
{
 uint32 typ = name[0]&0xFF;
 for(int i=0;name[i]!=0 && i<4;i++)
  typ = (typ<<8)+(name[i]&0xFF);
 return typ;
}

const char* typ2str(uint32 typ)
{
 static char name[8];
 int i=4;
 name[i]=0;
 while(i!=0)
  {
   name[--i] = typ&0xFF;
   typ >>= 8;
  }
 return name;
}

void printmatrix(glm::mat4 m)
{
 float *a;
 a = (float*)&m;
 for(int i=0;i<16;i++)
  {
   printf("  %f",*a++);
   if((i+1)%4==0) printf("\n");
  }
}

float zufall(float a, float b) //Zufallszahl zwischen a und b
{
 float d=b-a;
 return a+d*(rand()/(float)RAND_MAX);
}

const char *ohnepfad(const char *name)
{
 int n=strlen(name);
 // Beispiel: "textur/name.jpg"
 while(n>0 && name[n-1]!='/') {--n;}
 return &name[n];
}
