Logo Search packages:      
Sourcecode: hitop version File versions

stringproc.cc

#include "stringproc.h"
#include "error.h"
#include "dtutils.h"
#include "maths.h"
#include "hitopcore.h"
#include "tables/entities.h"
#include "polytype.h"

#include <algorithm>
#include <cstdio>
#include <cctype>
#include <unistd.h>

bool StringProc::actionMapInitialized=false;
map<string,StringProc::actionFunction> StringProc::actionMap;

void StringProc::REPEAT(__HITOPFUNC__){
  if(params.size()!=1) Error(cur,"REPEAT",e_ParamOne);
  int c=params[0].AsInt();
  if (c==0) {
    data.AsString().erase();
    return;
  }
  string what = data;
  while (--c>0) data.AsString().append(what);
}

void StringProc::LENGTH(__HITOPFUNC__){
  if(params.size()!=0) Error(cur,"LENGTH",e_ParamNone);
  data=(int)data.AsString().length();
}

void StringProc::FREQ(__HITOPFUNC__){
  if(params.size()!=1) Error(cur,"FREQ",e_ParamOne);
  if (params[0].AsString().length()==0) {
    data=(int)data.AsString().length();
  } else {
    int i=-1;
    string::iterator j=data.AsString().begin();
    while (j!=data.AsString().end()) {
      j=search(j,data.AsString().end(),params[0].AsString().begin(),params[0].AsString().end());
      ++i;
      if (j!=data.AsString().end()) ++j;
    }
    if (i==-1) i=0;
    data=i;
  }
}

void StringProc::REPLACE(__HITOPFUNC__){
  if(params.size()>2) Error(cur,"REPLACE",e_ParamWrong);
  if(params.size()==2){
    global_replace(data.AsString(),params[0],params[1]);
  }else{
    global_replace(data.AsString(),params[0],"");
  }
}

void StringProc::UPCASE(__HITOPFUNC__){
  if(params.size()!=0) Error(cur,"UPCASE",e_ParamNone);
  transform(data.AsString().begin(),data.AsString().end(),data.AsString().begin(),ToUpper());
}

void StringProc::DOWNCASE(__HITOPFUNC__){
  if(params.size()!=0) Error(cur,"DOWNCASE",e_ParamNone);
  transform(data.AsString().begin(),data.AsString().end(),data.AsString().begin(),tolower);
}

class StringProc::notin {
public:
  notin (const string& list):m_list(list) {};
  bool operator()(char what) {return (m_list.end()==find(m_list.begin(),m_list.end(),what)); }
private:
  const string& m_list;
};

void StringProc::REMOVENOTOF(__HITOPFUNC__){
  if(params.size()!=1) Error(cur,"REMOVENOTOF",e_ParamOne);
  data.AsString().erase(remove_if(data.AsString().begin(),data.AsString().end(),notin(params[0])),data.AsString().end());
}

void StringProc::ESCAPECHARS(__HITOPFUNC__){
  if(params.size()!=0) Error(cur,"ESCAPECHARS",e_ParamNone);
  data=Entities::Escape(data);
}

void StringProc::UNESCAPECHARS(__HITOPFUNC__){
  if(params.size()!=0) Error(cur,"UNESCAPECHARS",e_ParamNone);
  data=Entities::Unescape(data);
}

void StringProc::ESCAPEURL(__HITOPFUNC__){
  if(params.size()!=0) Error(cur,"ESCAPEURL",e_ParamNone);
  data=escape(data);
}

void StringProc::UNESCAPEURL(__HITOPFUNC__){
  if(params.size()!=0) Error(cur,"UNESCAPEURL",e_ParamNone);
  data = unescape(data);
}

void StringProc::EVAL(__HITOPFUNC__){
  if(params.size()!=0) Error(cur,"EVAL",e_ParamNone);
  data=evaluate(data);
}

void StringProc::RANDOM(__HITOPFUNC__){
  if(params.size()!=0) Error(cur,"RANDOM",e_ParamNone);
  int range=data.AsInt();
  if(range==0){
    data=0;
  }else{
    data=(int)rand()%range;
  }
}

void StringProc::MID(__HITOPFUNC__){
  if(params.size()!=2) Error(cur,"MID",e_ParamWrong);
  int from=params[0].AsInt();
  int len=params[1].AsInt();
  if (from<0) from+=data.AsString().length();
  if (len<0) len+=data.AsString().length();
  if (from<0) {
    len+=from;
    from=0;
  } else if (from>static_cast<int>(data.AsString().length())) {
    data.AsString().erase();
    return;
  }
  if ((from+len)>static_cast<int>(data.AsString().length())) {
    len=data.AsString().length()-from;
  }
  if (len<0) len=0;
  data=data.AsString().substr(from,len);
}

void StringProc::LEFT(__HITOPFUNC__){
  if(params.size()!=1) Error(cur,"LEFT",e_ParamOne);
  int num=params[0].AsInt();
  if(num<0) num+=data.AsString().length();
  if(num<0) {
    num=0;
  } else if (num>static_cast<int>(data.AsString().length())) {
    num=data.AsString().length();
  }
  data=data.AsString().substr(0,num);
}

void StringProc::RIGHT(__HITOPFUNC__){
  if(params.size()!=1) Error(cur,"RIGHT",e_ParamOne);
  int num=params[0].AsInt();
  if (num>0) {
    num=data.AsString().length()-num;
  } else {
    num=-num;
  }
  if(num<0) {
    num=0;
  } else if (num>static_cast<int>(data.AsString().length())) {
    data.AsString().erase();
    return;
  }
  data=data.AsString().substr(num,data.AsString().length()-num);
}

void StringProc::PADLEFT(__HITOPFUNC__){
  string pad=" ";
  if(params.size()==1){
  }else if ((params.size()==2)&&(!params[1].AsString().empty())){
    pad=params[1];
  }else{
    Error(cur,"PADLEFT",e_ParamWrong);
  }
  int size=params[0].AsInt();
  while(int(data.AsString().length())<size){
    data.AsString()=pad+data.AsString();
  }
}

void StringProc::PADRIGHT(__HITOPFUNC__){
  string pad=" ";
  if(params.size()==1){
  }else if((params.size()==2)&&(!params[1].AsString().empty())){
    pad=params[1];
  }else{
    Error(cur,"PADRIGHT",e_ParamWrong);
  }
  int size=params[0].AsInt();
  while(int(data.AsString().length())<size){
    data.AsString()+=pad;
  }
}

void StringProc::BEFORE(__HITOPFUNC__){
  if(params.size()!=1) Error(cur,"BEFORE",e_ParamOne);
  string::iterator found=search(data.AsString().begin(),data.AsString().end(),params[0].AsString().begin(),params[0].AsString().end());
  if(found==data.AsString().end()){
    data.AsString().erase();
    return;
  }
  data=string(data.AsString().begin(),found);
}

void StringProc::AFTER(__HITOPFUNC__){
  if(params.size()!=1) Error(cur,"AFTER",e_ParamOne);
  string::iterator found=search(data.AsString().begin(),data.AsString().end(),params[0].AsString().begin(),params[0].AsString().end());
  if(found==data.AsString().end()){
    data.AsString().erase();
    return;
  }
  data=string(found+params[0].AsString().length(),data.AsString().end());
}

void StringProc::REVERSE(__HITOPFUNC__){
  if(params.size()!=0) Error(cur,"REVERSE",e_ParamNone);
  reverse(data.AsString().begin(),data.AsString().end());
}

static int global_count(const string& st,const string& find){
  int len=find.length(),count=0;
  string::const_iterator pos,first=st.begin(),last=st.end();
  do{
    pos=search(first,last,find.begin(),find.end());
    if(pos==last) break;
    ++count;
    first=pos+len;
  }while(pos!=last);
  return count;
}

void StringProc::WORDS(__HITOPFUNC__){
  int count=params.size();
  string sep;
  if(count==0){
    sep=" ";
  }else if(count==1){
    sep=params[0];
  }else{
    Error(cur,"WORDS",e_ParamWrong);    
  }
  if(data.AsString().empty()){
    data=0;
    return;
  }
  int freq=global_count(data,sep)+1;
  data=freq;
}

void StringProc::WORDSPAN(__HITOPFUNC__){
  int count=params.size();
  string sep;
  if(count==2){
    sep=" ";
  }else if(count==3){
    sep=params[2];
  }else{
    Error(cur,"WORDSPAN",e_ParamWrong);    
  }
  int length=global_count(data,sep)+1;
  int start=params[0].AsInt()-1;
  int end=params[1].AsInt()-1;
  if(start<0) start+=length+1;
  if(end<0) end+=length;
  if(start<0) {
    end+=start;
    start=0;
  }
  ++end;
  if(end<0) end=0;
  string::iterator istart=data.AsString().begin(),iend;
  for (;start!=0;--start) {
    istart=search(istart,data.AsString().end(),sep.begin(),sep.end());
    if (istart!=data.AsString().end()) istart+=sep.length();
  }
  iend=istart;
  for (;end!=0;--end) {
    iend=search(iend,data.AsString().end(),sep.begin(),sep.end());
    if (iend!=data.AsString().end()) iend+=sep.length();
  }
  if ((iend!=data.AsString().end())&&(istart!=iend)) iend-=sep.length();
  data=string(istart,iend);
}

void StringProc::WORD(__HITOPFUNC__){
  int pos,count=params.size();
  string sep;
  if(count==1){
    sep=" ";
  }else if(count==2){
    sep=params[1];
  }else{
    Error(cur,"WORD",e_ParamWrong);
  }
  pos=params[0].AsInt()-1;
  if (pos<0) {
    pos+=global_count(data,sep) +2;
  }
  if (pos <0) {
    data.AsString().erase();
    return;
  }
  string::iterator start=data.AsString().begin(),end;
  for (;pos>0;--pos) {
    start=search(start,data.AsString().end(),sep.begin(),sep.end());
    if (start!=data.AsString().end()) start+=sep.length();
  }
  end=search(start,data.AsString().end(),sep.begin(),sep.end());
  data=string(start,end);
}

static time_t ISOToDate(const string& st){
  tm temp={0,0,0,0,0,0,0,0,0};
  sscanf(st.c_str(),"%d-%d-%d",&temp.tm_year,&temp.tm_mon,&temp.tm_mday);
  temp.tm_year-=1900;
  temp.tm_mon--;
  return mktime(&temp);
}

void StringProc::DATETODAYNUM(__HITOPFUNC__){
  if(params.size()!=0) Error(cur,"DATETODAYNUM",e_ParamNone);
  time_t secs=ISOToDate(data);
  secs=(secs+12*60*60)/(24*60*60)+719162;
  data=(int)secs;
}

void StringProc::DAYNUMTODATE(__HITOPFUNC__){
  if(params.size()!=0) Error(cur,"DAYNUMTODATE",e_ParamNone);
  time_t secs=(data.AsInt()-719162)*(24*60*60)+(12*60*60);
  tm* time=localtime(&secs);
  char temp[11];
  strftime(temp,11,"%Y-%m-%d",time);
  data=(string)temp;
}

void StringProc::DAYOFWEEK(__HITOPFUNC__){
  if(params.size()!=0) Error(cur,"DAYOFWEEK",e_ParamNone);
  time_t secs=ISOToDate(data);
  secs=((secs+12*60*60)/(24*60*60)+719162)%7+1;
  data=(int)secs;
}

void StringProc::C2X(__HITOPFUNC__){
  if(params.size()!=0) Error(cur,"C2X",e_ParamNone);
  string temp;
  char chx[4];
  for(string::iterator i=data.AsString().begin();i!=data.AsString().end();++i){
    sprintf(chx,"%02X",*i);
    temp+=chx;
  }
  data=(string)temp;
}

void StringProc::D2X(__HITOPFUNC__){
  if(params.size()!=0) Error(cur,"D2X",e_ParamNone);
  char ch[20];
  sprintf(ch,"%X",data.AsInt());
  data=(string)ch;
}

void StringProc::ROMAN(__HITOPFUNC__){
  if(params.size()!=0) Error(cur,"ROMAN",e_ParamNone);
  int num=data.AsInt();
  data.AsString().erase();
  if((num<0)||(num>5999)){
    data.AsString()="["+IToS(num)+"]";
  }else{
    while(num>=1000){num-=1000; data.AsString()+="m";}
    while(num>=900){num-=900; data.AsString()+="cm";}
    while(num>=500){num-=500; data.AsString()+="d";}
    while(num>=400){num-=400; data.AsString()+="cd";}
    while(num>=100){num-=100; data.AsString()+="c";}
    while(num>=90){num-=90; data.AsString()+="xc";}
    while(num>=50){num-=50; data.AsString()+="l";}
    while(num>=40){num-=40; data.AsString()+="xl";}
    while(num>=10){num-=10; data.AsString()+="x";}
    while(num>=9){num-=9; data.AsString()+="ix";}
    while(num>=5){num-=5; data.AsString()+="v";}
    while(num>=4){num-=4; data.AsString()+="iv";}
    while(num>=1){num--; data.AsString()+="i";}
  }
}

void StringProc::FORMATINT(__HITOPFUNC__){
  if(params.size()!=1) Error(cur,"FORMATINT",e_ParamOne);
  char buff[65535];
  sprintf(buff,params[0].AsString().c_str(),data.AsInt());
  data=buff;
}

void StringProc::FORMATFLOAT(__HITOPFUNC__){
  if(params.size()!=1) Error(cur,"FORMATFLOAT",e_ParamOne);
  char buff[65535];
  sprintf(buff,params[0].AsString().c_str(),data.AsDouble());
  data=buff;
}

void StringProc::SetFunction(const string& name,actionFunction procedure){
  actionMap[name]=procedure;
}

void StringProc::RegisterFunction(const string& name,actionFunction procedure){
  if (!actionMapInitialized) InitializeActionMap();
  SetFunction(name,procedure);
}

void StringProc::UnregisterFunction(const string& name,actionFunction procedure){
  map<string,actionFunction>::iterator entry= actionMap.find(name);
  if ((entry!=actionMap.end())&&(entry->second==procedure)) actionMap.erase(name);
}

void StringProc::InitializeActionMap(){
  srand(time(NULL)+getpid());

  // Date handling
  SetFunction("DATETODAYNUM",DATETODAYNUM);// ()
  SetFunction("DAYNUMTODATE",DAYNUMTODATE);// ()
  SetFunction("DAYOFWEEK",DAYOFWEEK);      // ()

  // String manipulation
  SetFunction("UPCASE",UPCASE);            // ()
  SetFunction("DOWNCASE",DOWNCASE);        // ()
  SetFunction("ESCAPEURL",ESCAPEURL);      // ()
  SetFunction("UNESCAPEURL",UNESCAPEURL);  // ()
  SetFunction("ESCAPECHARS",ESCAPECHARS);  // ()
  SetFunction("UNESCAPECHARS",UNESCAPECHARS);// ()
  SetFunction("REMOVENOTOF",REMOVENOTOF);  // (s)
  SetFunction("REVERSE",REVERSE);          // ()
  SetFunction("REPLACE",REPLACE);          // (s,s)
  SetFunction("REPEAT",REPEAT);            // (n)
  SetFunction("PADLEFT",PADLEFT);          // (n) (n,s)
  SetFunction("PADRIGHT",PADRIGHT);        // (n) (n,s)

  // String extraction
  SetFunction("BEFORE",BEFORE);            // (s)
  SetFunction("AFTER",AFTER);              // (s)
  SetFunction("LEFT",LEFT);                // (n)
  SetFunction("RIGHT",RIGHT);              // (n)
  SetFunction("MID",MID);                  // (n,n)

  // Enquiry
  SetFunction("LENGTH",LENGTH);            // ()
  SetFunction("FREQ",FREQ);                // (s)

  // Word extraction
  SetFunction("WORD",WORD);                // (n) (n,s)
  SetFunction("WORDS",WORDS);              // () (s)
  SetFunction("WORDSPAN",WORDSPAN);        // (n,n) (n,n,s)

  // Maths & Number
  SetFunction("EVAL",EVAL);                // ()
  SetFunction("RANDOM",RANDOM);            // ()

  // Format Conversion
  SetFunction("C2X",C2X);                  // ()
  SetFunction("D2X",D2X);                  // ()
  SetFunction("ROMAN",ROMAN);              // ()

  SetFunction("FORMATINT",FORMATINT);      // (s)
  SetFunction("FORMATFLOAT",FORMATFLOAT);  // (s)

  actionMapInitialized=true;
}

void StringProc::ProcessString(const HTML& cur,string& data2,const string& inst){
  if(!actionMapInitialized) InitializeActionMap();
  PolyType data(data2);
  enum State {Outside,InBrackets,ExpectColon,InsideQuote,InsideDouble};
  State curState=Outside;
  bool beenQuoted=false;
  string curThing,procName;
  vector<PolyType> param;
  for(string::const_iterator i=inst.begin();i!=inst.end();++i){
    const char& ch(*i);
    if(curState==Outside){
      if(ch=='('){
        procName=curThing;
        curThing.erase();
        curState=InBrackets;
      }else{
        curThing+=ch;
      }
    }else if(curState==InBrackets){
      if((ch==')')||(ch==',')){
        if((!curThing.empty())||beenQuoted) param.push_back(curThing);
        curThing.erase();
        if(ch==')'){
          if(!g_isXML) transform(procName.begin(),procName.end(),procName.begin(),ToUpper());
          map<string,StringProc::actionFunction>::iterator funcPoint=actionMap.find(procName);
          if(funcPoint==actionMap.end()) Error(cur,e_UndefStringProc,procName);
          (*(funcPoint->second))(cur,data,param);
          param.clear();
          curState=ExpectColon;
          beenQuoted=false;
        }
      }else if(ch=='\''){
        curState=InsideQuote;
        beenQuoted=true;
      }else if(ch=='"'){
        curState=InsideDouble;
        beenQuoted=true;
      }else{      
        curThing+=ch;
      }
    }else if(curState==ExpectColon){
      if(ch!=':') Error(cur,e_MissingColon);
      curState=Outside;
    }else if(curState==InsideQuote){
      if(ch=='\'') curState=InBrackets; else curThing+=ch;
    }else if(curState==InsideDouble){
      if(ch=='"') curState=InBrackets; else curThing+=ch;
    }
  }
  if(curState==Outside){
    Error(cur,e_ExpectBrackets);
  }else if(curState==InBrackets){
    Error(cur,e_ExpectCloseBracket);
  }else if((curState==InsideQuote)||(curState==InsideDouble)){
    Error(cur,e_UntermQuotes);
  }
  data2=data.AsString();
}

Generated by  Doxygen 1.6.0   Back to index