//
// This software is now distributed according to
// the Lesser Gnu Public License.  Please see
// http://www.gnu.org/copyleft/lesser.txt for
// the details.
//    -- Happy Computing!
//
package com.stevesoft.pat;

/**
 Shareware: package pat
 <a href="copyright.html">Copyright 2001, Steven R. Brandt</a>
 */
/**
 * This class is used to store a result from Regex
 */
public class RegRes implements Cloneable
{
  protected int[] marks = null;

  protected boolean didMatch_ = false;

  protected StringLike src = null;

  /** Obtain the text String that was matched against. */
  public String getString()
  {
    return src.toString();
  }

  /** Obtain the source StringLike object. */
  public StringLike getStringLike()
  {
    return src;
  }

  protected int charsMatched_ = 0, matchFrom_ = 0, numSubs_ = 0;

  public String toString()
  {
    StringBuffer sb = new StringBuffer();
    sb.append("match=" + matchedFrom() + ":" + charsMatched());
    if (!didMatch())
    {
      return sb.toString();
    }
    for (int i = 0; i < numSubs(); i++)
    {
      int n = i + 1;
      sb.append(
              " sub(" + n + ")=" + matchedFrom(n) + ":" + charsMatched(n));
    }
    return sb.toString();
  }

  public RegRes()
  {
  }

  public RegRes(RegRes r)
  {
    copyOutOf(r);
  }

  public void copyOutOf(RegRes r)
  {
    if (r.marks == null)
    {
      marks = null;
    }
    else
    {
      try
      {
        // marks = (Hashtable)r.marks.clone();
        marks = new int[r.marks.length];
        for (int i = 0; i < marks.length; i++)
        {
          marks[i] = r.marks[i];
        }
        // marks = (int[])r.marks.clone();
      } catch (Throwable t)
      {
      }
    }
    didMatch_ = r.didMatch_;
    src = r.src;
    charsMatched_ = r.charsMatched_;
    matchFrom_ = r.matchFrom_;
    numSubs_ = r.numSubs_;
  }

  public Object clone()
  {
    return new RegRes(this);
  }

  public boolean equals(RegRes r)
  {
    if (charsMatched_ != r.charsMatched_ || matchFrom_ != r.matchFrom_
            || didMatch_ != r.didMatch_ || numSubs_ != r.numSubs_
            || !src.unwrap().equals(r.src.unwrap()))
    {
      return false;
    }
    if (marks == null && r.marks != null)
    {
      return false;
    }
    if (marks != null && r.marks == null)
    {
      return false;
    }
    for (int i = 1; i <= numSubs_; i++)
    {
      if (matchedFrom(i) != r.matchedFrom(i))
      {
        return false;
      }
      else if (charsMatched(i) != r.charsMatched(i))
      {
        return false;
      }
    }
    return true;
  }

  /** Obtains the match if successful, null otherwise. */
  public String stringMatched()
  {
    int mf = matchedFrom(), cm = charsMatched();
    return !didMatch_ || mf < 0 || cm < 0 ? null
            : src.substring(mf, mf + cm);
  }

  /**
   * Obtains the position backreference number i begins to match, or -1 if
   * backreference i was not matched.
   */
  public int matchedFrom(int i)
  {
    if (marks == null || i > numSubs_)
    {
      return -1;
    }
    // Integer in=(Integer)marks.get("left"+i);
    // return in == null ? -1 : in.intValue();
    return marks[i];
  }

  /**
   * Obtains the number of characters matched by backreference i, or -1 if
   * backreference i was not matched.
   */
  public int charsMatched(int i)
  {
    if (marks == null || i > numSubs_ || !didMatch_)
    {
      return -1;
    }
    // Integer in = (Integer)marks.get("right"+i);
    // int i2 = in==null ? -1 : in.intValue();
    int mf = matchedFrom(i);
    return mf < 0 ? -1 : marks[i + numSubs_] - matchedFrom(i);
  }

  /**
   * This is either equal to matchedFrom(i)+charsMatched(i) if the match was
   * successful, or -1 if it was not.
   */
  public int matchedTo(int i)
  {
    if (marks == null || i > numSubs_ || !didMatch_)
    {
      return -1;
    }
    return marks[i + numSubs_];
  }

  /**
   * Obtains a substring matching the nth set of parenthesis from the pattern.
   * See numSubs(void), or null if the nth backrefence did not match.
   */
  public String stringMatched(int i)
  {
    int mf = matchedFrom(i), cm = charsMatched(i);
    return !didMatch_ || mf < 0 || cm < 0 ? null
            : src.substring(mf, mf + cm);
  }

  /**
   * This returns the part of the string that preceeds the match, or null if the
   * match failed.
   */
  public String left()
  {
    int mf = matchedFrom();
    return !didMatch_ || (mf < 0) ? null : src.substring(0, mf);
  }

  /**
   * This returns the part of the string that follows the ith backreference, or
   * null if the backreference did not match.
   */
  public String left(int i)
  {
    int mf = matchedFrom(i);
    return !didMatch_ || (mf < 0) ? null : src.substring(0, mf);
  }

  /**
   * This returns the part of the string that follows the match, or null if the
   * backreference did not match.
   */
  public String right()
  {
    int mf = matchedFrom(), cm = charsMatched();
    return !didMatch_ || mf < 0 || cm < 0 ? null
            : src.substring(mf + cm, src.length());
  }

  /**
   * This returns the string to the right of the ith backreference, or null if
   * the backreference did not match.
   */
  public String right(int i)
  {
    int mf = matchedFrom(i), cm = charsMatched(i);
    return !didMatch_ || mf < 0 || cm < 0 ? null
            : src.substring(mf + cm, src.length());
  }

  /**
   * After a successful match, this returns the location of the first matching
   * character, or -1 if the match failed.
   */
  public int matchedFrom()
  {
    return !didMatch_ ? -1 : matchFrom_;
  }

  /**
   * After a successful match, this returns the number of characters in the
   * match, or -1 if the match failed.
   */
  public int charsMatched()
  {
    return !didMatch_ || matchFrom_ < 0 ? -1 : charsMatched_;
  }

  /**
   * This is matchedFrom()+charsMatched() after a successful match, or -1
   * otherwise.
   */
  public int matchedTo()
  {
    return !didMatch_ ? -1 : matchFrom_ + charsMatched_;
  }

  /**
   * This returns the number of backreferences (parenthesis) in the pattern,
   * i.e. the pattern "(ab)" has one, the pattern "(a)(b)" has two, etc.
   */
  public int numSubs()
  {
    return numSubs_;
  }

  /** Contains true if the last match was successful. */
  public boolean didMatch()
  {
    return didMatch_;
  }

  /** An older name for matchedFrom. */
  public int matchFrom()
  {
    return matchedFrom();
  }

  /** An older name for stringMatched(). */
  public String substring()
  {
    return stringMatched();
  }

  /** An older name for matchedFrom. */
  public int matchFrom(int i)
  {
    return matchedFrom(i);
  }

  /** An older name for stringMatched. */
  public String substring(int i)
  {
    return stringMatched(i);
  }
}
