/*
 * 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;
  
  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(mix))+"]";
      case T_LWOBJECT:
      return sprintf("%O",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;
}
