MudOSa4DGD/
MudOSa4DGD/bin/
MudOSa4DGD/data/
MudOSa4DGD/doc/
MudOSa4DGD/doc/driver/
MudOSa4DGD/doc/efun/bitstrings/
MudOSa4DGD/doc/efun/command/
MudOSa4DGD/doc/efun/communication/
MudOSa4DGD/doc/efun/heart_beat/
MudOSa4DGD/doc/efun/interactive/
MudOSa4DGD/doc/efun/inventory/
MudOSa4DGD/doc/efun/living/
MudOSa4DGD/doc/efun/mappings/
MudOSa4DGD/doc/efun/strings/
MudOSa4DGD/doc/efun/uid/
MudOSa4DGD/doc/funs/
MudOSa4DGD/doc/language/
MudOSa4DGD/mudlib/dgd/doc/
MudOSa4DGD/mudlib/dgd/lib/include/dgd/
MudOSa4DGD/mudlib/dgd/lib/std/
MudOSa4DGD/mudlib/dgd/lib/sys/
MudOSa4DGD/mudlib/dgd/log/
MudOSa4DGD/mudlib/log/
MudOSa4DGD/mudlib/std/include/
MudOSa4DGD/mudlib/std/obj/
/*
 * string.c
 *
 * Some handy string functions
 *
 * (C) Frank Schmidt, Jesus@NorseMUD
 *
 */

/* capitalize first letter in a string */
static string capitalize(string str) {
  if (str[0] >= 'a' && str[0] <= 'z')
    str[0] += 'A' - 'a';
  return str;
}


/* lowercase first letter in a string */
static string decapitalize(string str) {  
  if (str[0] >= 'A' && str[0] <= 'Z')
    str[0] += 'a' - 'A';
  return str;
}


/* capitalize all letters in a string */
static string toupper(string str) {
  int i, diff;
  diff = 'A' - 'a';
  for (i=strlen(str); --i>=0; )
    if (str[i] >= 'a' && str[i] <= 'z')
      str[i] += diff;
  return str;
}


/* lowercase all letters in a string */
static string tolower(string str) {
  int i, diff;
  diff = 'a' - 'A';
  for (i=strlen(str); --i>=0; )
    if (str[i] >= 'A' && str[i] <= 'Z')
      str[i] += diff;
  return str;
}


/* extract a substring from a string, 
   accepts negative values and out of bounds
*/
static string extract_string(string str, int from, int to) {
  int sz;
  sz = strlen(str);
  if (to < 0)
    to = sz+to;
  else if (to >= sz)
    to = sz-1;
  if (to < from || from >= sz)
    return "";
  if (from <= 0) return str[..to];
  return str[from..to];
}


/* nifty function that returns all but the part you specify, 
   accepts negative values and out of bounds
*/
static string exclude_string(string str, int from, int to) {
  string fore;
  int sz;
  sz = strlen(str);
  if (to < 0)
    to = sz+to;
  else if (to >= sz)
    to = sz-1;
  if (to < from || from >= sz)
    return str;
  if (from > 0)
    fore = str[..from-1];
  else
    fore = "";
  if (to >= sz-1) return fore;
  return fore + str[to+1..];
}


/* inserts string into a string safely, 
   accepts out of bounds values
*/
static string insert_string(string str, string what, int where) {
  if (where <= 0)
    return what + str;
  if (where >= strlen(str))
    return str + what;
  return str[..where-1] + what + str[where..];
}



/* compare if <one> is a part of <two> (common one way)
*/
static int strcocmp(string one, string two) {
  int sz1;
  sz1 = strlen(one);
  if (sz1 <= strlen(two)) {
    if (sz1 > 0)
      return one == two[..sz1-1];
  }
  return 0;
}


/* compare if <one> or <two> is a part of one another (both ways) */
static int strccmp(string one, string two) {
  int sz1, sz2;
  sz1 = strlen(one);
  sz2 = strlen(two);
  if (sz1 < sz2) {
    if (sz1 > 0)
      return one == two[..sz1-1];
  }
  else {
    if (sz2 > 0)
      return two == one[..sz2-1];
  }
  return 0;
}


/* compare two strings lexically */
static int strcmp(string one, string two) {
  int sz1, sz2, size, i;
  sz1 = strlen(one);
  sz2 = strlen(two);
  size = min(sz1, sz2);
  /* compare each element until difference is found */
  for (; i < size; ++i) {
    int o, t;
    if ((o=one[i]) > (t=two[i]))
      return 1;
    else if (o < t)
      return -1;
  }
  /* decide final relationship */
  if (sz1 > sz2) return 1;
  if (sz1 < sz2) return -1;
  return 0;
}



/* search for a string within a string at occurence <num>
   accepts negative number
*/
#if 1
/* FAST VERSION */
static varargs int strsrch(string str1, string str2, int num) {
  if (num >= 0) {
    string t;
    int i, s2len;
    s2len = strlen(str2);
    i = -s2len;
    do {
      /* using sscanf is fast from the left */
      if (sscanf(str1, "%s"+str2+"%s", t, str1) >= 1) {
	i += strlen(t)+s2len;
	if (!str1) str1 = "";
      }
      else
	return -1;
    } while (num-- > 0);
    return i;
  }
  else {
    int sz;
    mixed *expl;
    if ((sz=::sizeof(expl = big_explode(str1, str2))) > -num) {
      /* use implode() to avoid counting length of first separator */
      return strlen(implode(expl[..sz+num-1], str2));
    }
  }
  return -1;
}
#else
/* SLOW VERSION */
static varargs int strsrch(string str1, mixed str2, int num) {
  int i, sz1, sz2;

  if (num >= 0) {
    /* scan from forwards */
    if (stringp(str2)) {
      sz2 = strlen(str2)-1;
      sz1 = strlen(str1)-sz2;
      do {
	for (; i < sz1; ++i)
	  if (str1[i..i+sz2] == str2)
	    /* found a match */
	    break;
      } while (num-- > 0);
    }
    else {
      /* scan for character */
      sz1 = strlen(str1);
      do {
	for (; i < sz1; ++i)
	  if (str1[i] == str2)
	    /* found a match */
	    break;
      } while (num-- > 0);
    }
    /* return final index */
    if (i < sz1) return i;
    return -1;
  }
  else {
    /* scan backwards */
    if (stringp(str2)) {
      sz2 = strlen(str2)-1;
      i = strlen(str1)-sz2;
      do {
	while (--i >= 0)
	  if (str1[i..i+sz2] == str2)
	    /* found a match */
	    break;
      } while (++num < 0);
    }
    else {
      /* scan for character */
      i=strlen(str1);
      do {
	while (--i >= 0)
	  if (str1[i] == str2)
	    /* found a match */
	    break;
      } while (++num < 0);
    }
    return i;
  }
  /* should never make it here, but who cares? */
  return -1;
}
#endif


/* replace patterns within a string, optional <max> occurences from left or right 
   accepts negative number, defaults to replacing ALL occurences
*/
static varargs string replace_string(string str, mixed patt, string repl, int max) {
  if (max == 0) {
    /* replace ALL (fastest) */
    return big_implode(big_explode(str, patt), repl);
  }
  else {
    int sz;
    string *expl;

    /* replace n occurences from left (positive <max>) or right (negative <max>) */
    sz = ::sizeof(expl = big_explode(str, patt));
    if (max >= 0) {
      if (max < sz)
	/* from left (concatenating with implode() using ({""}) as bridge) */
	return implode(expl[..max-1]+({""}), repl)+implode(expl[max..], patt);
    }
    else if (max > -sz) {
      /* from right (concatenating with implode() using ({""}) as bridge) */
      return implode(expl[..sz+max-1], patt)+implode(({""})+expl[sz+max..], repl);
    }
    /* replacing all anyways, since max is bigger than occurences found */
    return big_implode(expl, repl);
  }
}


/* return a string filled with <fyll> with length of <n> */
static string fill_string(string fyll, int n) {
  int i;
  if (n <= 0 || !(i=strlen(fyll)))
    return "";

  /* expand fillstring until it gets big enough */
  while (i < n) {
    fyll += fyll;
    fyll += fyll;
    i += i;
  }
  return fyll[..n-1];
}


/* strip string for whitespaces */
static varargs string strip_string(string raw, string whitespace) {
  string *words;
  /* default whitespace */
  if (!whitespace)
    whitespace = " ";
  /* get rid of nasty spaces between each word and at ends of string */
  return implode(explode(raw,whitespace)-({""}),  whitespace);
}


#ifndef atoi
/* convert a string to an integer */
static int atoi(string str) {
  return (int)str;
}
#endif


#ifndef atof
/* convert a string to a float */
static float atof(string str) {
  return (float)str;
}
#endif


/* return a visual string representation for a float (approximate) */
static string float2str(float flt) {
  string str;
  int i, c;
  str = (string) flt;
  if (strsrch(str, ".") >= 0 || strsrch(str, "e") >= 0)
    return str;
  return str + ".0";
}