/*
 * MGtool-1.0
 * File: toollib.c
 * Maintainer: Kirk@MorgenGrauen
 */

/*------------------------------------------*/
/* the original Xtool is copyrighted by Hyp */
/*------------------------------------------*/

#include "toollib.h"
#include <lpctypes.h>
#include <properties.h>
#include <strings.h>

string *strip_explode(string str, string del)
{
  return explode(str, del)-({""});
}

string strip_string(string str)
{
  return trim(str, TRIM_BOTH);
}

int string_compare(string a, string b)
{
  return a==b?0:(a>b?1:-1);
}

string cap_string(string str)
{
  return capitalize(str);
}

string short_path(string file)
{
  int s;
  string tmp;
  
  if(!file)
    return 0;
  if(PL)
  {
    if(file[0.. 8]=="/players/")
    {
      s=sizeof(getuid(PL))+8;
      return "~"+(file[9.. s]==getuid(PL) ? file[s+1.. <1] : file[9.. <1]);
    }
  }
  if(file[0.. 2]=="/d/")
    return "+"+file[3.. <1];
  else
    return file;  
}

string long_path(string file)
{
  return normalize_path(file, getuid(this_interactive() || PL), 1);
}

string *long_get_dir(string pat, int all)
{
  int i, s;
  string str, dir, *file, *tmp;
  
  if(!pat)
    return ({});
  pat=long_path(pat);
  if(tmp=old_explode(pat, "/"))
    dir="/"+implode(tmp[0..sizeof(tmp)-2], "/")+"/";
  else
    dir="/";
  s=sizeof(tmp=get_dir(pat));
  file=({});
  for(i=0;i<s;i++)
  {
    str=dir+tmp[i];
    if(all||file_size(str)>=0)
      file+=({str});
  }
  return file;
}

string lit_string(string str)
{
  str=string_replace(str, "\\", "\\\\");
  str=string_replace(str, "\b", "\\b");
  str=string_replace(str, "\n", "\\n");
  str=string_replace(str, "\r", "\\r");
  str=string_replace(str, "\t", "\\t");
  return string_replace(str, "\"", "\\\"");
}

string mixed_to_string(mixed mix, int lvl)
{
  int i, j, s, t;
  string str;
  mixed *keys;

  if(lvl)
  {
    switch(typeof(mix))
    {
      default:
      case T_INVALID:
      return "<invalid>";
      case T_LVALUE:
      return "&"+mixed_to_string(mix, lvl-1);
      case T_NUMBER:
      case T_FLOAT:
      return to_string(mix);
      case T_STRING:
      return "\""+lit_string(mix)+"\"";
      case T_POINTER:
      return "({"+implode(map(mix,"mixed_to_string",ME,lvl-1),",")+"})";
      case T_OBJECT:
      return "["+short_path(object_name((object)mix))+"]";
      case T_MAPPING:
      s=sizeof(keys=m_indices(mix));
      t=get_type_info(mix, 1);
      str="([";
      for(i=0;i<s;i++)
      {
	str+=mixed_to_string(keys[i], lvl-1);
	if(t)
	{
	  str+=":"+mixed_to_string(mix[keys[i],0], lvl-1);
	  for(j=1;j<t;j++)
	    str+=";"+mixed_to_string(mix[keys[i],j], lvl-1);
	}
	if(i<s-1) str+=",";
      }
      return str+"])";
      case T_CLOSURE:
      case T_SYMBOL:
      return sprintf("%O", mix);
      case T_QUOTED_ARRAY:
      return "'"+mixed_to_string(funcall(lambda(0, mix)), lvl-1);
      case T_BYTES:
      case T_STRUCT:
      return sprintf("%O",mix);
    }
  }
  return "...";
}

int is_player(object obj)
{
  return is_obj(obj)&&query_once_interactive(obj);
}

int is_not_player(object obj)
{
  return is_obj(obj)&&!is_player(obj);
}

int round(float val)
{
  int tmp;

  tmp=(int)val;
  // only positive val
  if( val - tmp >= 0.5 )
    return tmp+1;
  return tmp;
}
