/* Strings manipulation
 *
 * (c) 2002-2006, OLO
 * This file is provided as is (no warranties).
 */

#if defined _string_included
  #endinput
#endif
#define _string_included

/* Checks if source contains string. On success function
* returns position in source, on failure returns -1. */
native contain(const source[], const string[]);

/* Checks if source contains string with case ignoring. On success function
* returns position in source, on failure returns -1. */
native containi(const source[], const string[]);

/* Replaces given string with another in given text. */
native replace(text[], len, const what[], const with[]);

/* Adds one string to another. Last parameter different from 0, specifies
* how many chars we want to add. Function returns number of all merged chars. */
native add(dest[], len, const src[], max=0);

/* Fills string with given format and parameters.
* Function returns number of copied chars.
* Example: format(dest, "Hello %s. You are %d years old", "Tom", 17). */
native format(output[], len, const format[], {Float,_}:...);

/* Same as format(), except does not perform a "copy back" check.
 * This means formatex() is faster, but DOES NOT ALLOW this type
 * of call:
 *  formatex(buffer, len, "%s", buffer)
 *  formatex(buffer, len, buffer, buffer)
 *  formatex(buffer, len, "%s", buffer[5])
 * This is because the output is directly stored into "buffer",
 *  rather than copied back at the end.
 */
native formatex(output[], len, const format[], {Float,_}:...);

/* Gets parameters from function as formatted string. */
native format_args(output[], len, pos=0);

/* Converts number to string. */
native num_to_str(num, string[], len);
native numtostr(num, string[], len);

/* Converts string to number. */
native str_to_num(const string[]);
native strtonum(const string[]);

/* Checks if two strings equal. If len var is set
* then there are only c chars compared. */
native equal(const a[], const b[], c=0);

/* Checks if two strings equal with case ignoring.
* If len var is set then there are only c chars compared. */
native equali(const a[], const b[], c=0);

/* Copies one string to another. By len var
*  you may specify max. number of chars to copy. */
native copy(dest[], len, const src[]);

/* Copies one string to another until char ch is found.
*  By len var you may specify max. number of chars to copy. */
native copyc(dest[], len, const src[], ch);

/* Sets string with given character. */
native setc(src[], len, ch);

/* Gets parameters from text.
* Example: to split text: "^"This is^" the best year",
* call function like this: parse(text,arg1,len1,arg2,len2,arg3,len3,arg4,len4)
* and you will get: "This is", "the", "best", "year"
* Function returns number of parsed parameters. */
native parse(const text[], ...);

/* Converts all chars in string to lower case. */
native strtolower(string[]);

/* Converts all chars in string to upper case. */
native strtoupper(string[]);

/* Returns true when value is digit. */
native isdigit(ch);

/* Returns true when value is letter. */
native isalpha(ch);

/* Returns true when value is space. */
native isspace(ch);

/* Returns true when value is letter or digit. */
native isalnum(ch);

// C++ Version By AMXMODX Dev Team
stock strtok(const string[], left[], leftLen, right[], rightLen, token=' ', trim=0) {
  left[0] = '^0';
  right[0] = '^0';
  new left_pos = 0;
  new right_pos = 0;
  new i = 0;
  new bool:done_flag = false;
  new len = strlen(string);
  for(i = 0; i < len; ++i) {
    if(!done_flag && string[i] == token) {
      done_flag = true;
      ++i;
    }
    if(done_flag) {
      if(right_pos < rightLen) {
        right[right_pos++] = string[i];
      }
    }
    else {
      if(left_pos < leftLen) {
        left[left_pos++] = string[i];
      }
    }
  }
  right[right_pos] = 0;
  left[left_pos] = 0;
  if(trim) {
    i = 0;
    while(isspace(left[i])) {
      replace(left, leftLen, " ", "");
    }
    i = strlen(left) - 1;
    while(i >= 0 && isspace(left[i])) {
      replace(left[i], leftLen, " ", "");
      i--;
    }
  }
  return 1;
}

// C++ Version By AMXMODX Dev Team
stock strbreak(const text[], Left[], leftLen, Right[], rightLen) {
  Left[0] = '^0';
  Right[0] = '^0';
  new len = strlen(text);
  parse(text, Left, leftLen, Right, rightLen);
  new len1 = strlen(Left), len2 = strlen(Right);
  while(len1 < len && !equal(text[len1], Right, len2)) { ++len1; }
  if(len1 < len) {
    copy(Right, rightLen, text[len1]);
  }
  return 1;
}

// C++ Version By AMXMODX Dev Team
stock trim(text[]) {
  new i = 0, len = strlen(text);
  while(isspace(text[i])) {
    replace(text, len, " ", "");
  }
  i = strlen(text) - 1;
  while(i >= 0 && isspace(text[i])) {
    replace(text[i], len, " ", "");
    i--;
  }
  return 1;
}

/* Tests if given string contains only digits. */
// By AMXMODX Dev Team
stock bool:is_str_num(string[]) {
  new i = 0;
  while(string[i] && isdigit(string[i]))
    ++i;
  return (string[i] == 0 && i != 0);
}

/* It is basically strbreak but you have a delimiter that is more than one character in length.
 * You pass the Input string, the Left output, the max length of the left output,
 * the right output , the max right length, and then the delimiter string.
 * By Suicid3 */
stock split(szInput[], szLeft[], pL_Max, szRight[], pR_Max, szDelim[]) {
  new iEnd = contain(szInput, szDelim);
  new iStart = iEnd + strlen(szDelim);
  if(iEnd == -1) {
    iStart = copy(szLeft, pL_Max, szInput);
    copy(szRight, pR_Max, szInput[iStart]);
    return;
  }
  if(pL_Max >= iEnd) {
    copy(szLeft, iEnd, szInput);
  }
  else {
    copy(szLeft, pL_Max, szInput);
  }
  copy(szRight, pR_Max, szInput[iStart]);
  return;
}

/* Replaces a contained string. Returns number of replacements. */
stock replace_all(string[], len, what[], with[]) {
  new pos = 0;
  if((pos = contain(string, what)) == -1) { // By AMXMODX Dev Team
    return 0;
  }
  new with_len = strlen(with);
  new total_len = strlen(string);
  new diff_len = strlen(what) - with_len;
  if(total_len - diff_len > len) {
    return 0;
  }
  new num = 0, temp_test = 0;
  while(replace(string[pos], len-pos, what, with) != 0) {
    total_len -= diff_len;
    if(total_len - diff_len > len) {
      break;
    }
    pos += with_len;
    if(pos >= total_len) {
      break;
    }
    if((temp_test = contain(string[pos], what)) == -1) { // By AMXMODX Dev Team
      break;
    }
    pos += temp_test;
    ++num;
  }
  return num;
}
