//=-- AFRewrite.cpp - Modify accesses with regular expressions ----------------=
//
//  PLUGIN DESCRIPTION:
//
//  This plugin is designed to modify accesses that match specified regular 
//  expressions.  Any portion of the access may be modified, and should be used
//  as a general way to cannonicalize hits.
//  
//  Example of use:
//
//  ["Rewrite", "URL", "^/~sabre", "/sabre"]
//
//  This changes all hits that start with /~sabre to start with /sabre, because
//  the two prefixes refer to the same directory.  So given this, the first
//  parameter is the field name to modify.  The second is the regular expression
//  to match.  The third param is the replacement string.
//
//  PLUGIN AUTHOR:
//    Chris Lattner, Author of Magicstats  (sabre@nondot.org)
//
//  PLUGIN HOMEPAGE:
//     http://www.nondot.org/MagicStats/Plugins/Rewrite
//
//  PLUGIN VERSION / COMPATIBILITY:
//     Rewrite v1.0 / MagicStats 2.0+
//
//=----------------------------------------------------------------------------=
//  This file is copyright (c) 1999-2000 Chris Lattner
//=----------------------------------------------------------------------------=

#include "AccessFilterPlugin.h"
#include "AccessFormatPlugin.h"
#include "FilterManager.h"
#include "VarTable.h"
#include "Regex.h"

class AFRewrite : public PluginTemplate<AccessFilterPlugin,AFRewrite> {
  int FieldNo;         // Field # to play with...
  regex Pattern;       // Pattern to match against...
  String Replacement;  // String to splice in...

public:
  inline AFRewrite(int &CE) : Pattern("") { CE = 0; }

  inline static unsigned int GetCurrentVersion() {
    return 100;                       // Version 1.00
  } 

  inline static const char *GetPluginName() {
    return "Rewrite";
  }

  // Initialize - Initialize plugin, based on the arguments received...
  //
  virtual int Initialize(const VTListExp *Params) {
    if (Params->GetNumElements() != 4) {
      cout << "Rewrite AccessFilter requires three parameters: the field "
              "to modify, a source regular expression, and a destination "
              "string!\nIgnoring filter.\n";
      return 1;
    }

    const VTExp *Field  = Params->GetListElement(1);

    FieldNo = AccessFormatPlugin::GetFieldID(Field->GetStringValue());
    String SourceRE(Params->GetListElement(2)->GetStringValue());
    Replacement = Params->GetListElement(3)->GetStringValue();

    if (SourceRE.Length() == 0) {
      cout << "Rewrite accessfilter requires a nonnull regular expression!"
              "\nIgnoring filter.\n";
      return 1;
    }
    
    if (Pattern.CompileNew(SourceRE)) {
      cout << "Error compiling Rewrite AccessFilter regular expression '" 
           << SourceRE << "': " << Pattern.GetErrorMessage() 
           << "\nIgnoring Filter.\n";
      return 1;
    }

    return 0;
  }


  // FilterAccess - Process the access... check to see if the regular expression
  // matches, and if so, do the replacement!
  //
  virtual int FilterAccess(AccessFormatPlugin &A) {
    String Field = A.GetField(FieldNo);
    int From, To;

    if (Pattern.FindMatch(Field, &From, &To) > 0) {
      //      cout << "Matched '" << Field << "' from " << From 
      //           << " to " << To << endl;
      String Start;
      if (From > 0) {
        Start = Field;
        Start.Left(From);
        Field.Right(Field.Length()-From);
      }

      Field.Right(Field.Length()-(To-From));
      Field = Start + Replacement + Field;  // Splice in replacement

      A.SetField(FieldNo, Field);
    }

    return 0;
  }
};

INIT_PLUGIN(AFRewrite);
