//=====================================================
// File   :  btl.hh
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
//=====================================================
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
//
#ifndef BTL_HH
#define BTL_HH

#include "bench_parameter.hh"
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include "utilities.h"

#if (defined __GNUC__)
#define BTL_ALWAYS_INLINE __attribute__((always_inline)) inline
#else
#define BTL_ALWAYS_INLINE inline
#endif

#if (defined __GNUC__)
#define BTL_DONT_INLINE __attribute__((noinline))
#else
#define BTL_DONT_INLINE
#endif

#if (defined __GNUC__)
#define BTL_ASM_COMMENT(X)  asm("#"X)
#else
#define BTL_ASM_COMMENT(X)  
#endif

#if (defined __GNUC__) && (!defined __INTEL_COMPILER)
#define BTL_DISABLE_SSE_EXCEPTIONS()  { \
  int aux; \
  asm( \
  "stmxcsr   %[aux]           \n\t" \
  "orl       $32832, %[aux]   \n\t" \
  "ldmxcsr   %[aux]           \n\t" \
  : : [aux] "m" (aux)); \
}
#else
#define BTL_DISABLE_SSE_EXCEPTIONS()
#endif

/** Enhanced std::string
*/
class BtlString : public std::string
{
public:
    BtlString() : std::string() {}
    BtlString(const BtlString& str) : std::string(static_cast<const std::string&>(str)) {}
    BtlString(const std::string& str) : std::string(str) {}
    BtlString(const char* str) : std::string(str) {}

    operator const char* () const { return c_str(); }

    void trim( bool left = true, bool right = true )
    {
        int lspaces, rspaces, len = length(), i;
        lspaces = rspaces = 0;

        if ( left )
            for (i=0; i<len && (at(i)==' '||at(i)=='\t'||at(i)=='\r'||at(i)=='\n'); ++lspaces,++i);

        if ( right && lspaces < len )
            for(i=len-1; i>=0 && (at(i)==' '||at(i)=='\t'||at(i)=='\r'||at(i)=='\n'); rspaces++,i--);

        *this = substr(lspaces, len-lspaces-rspaces);
    }

    std::vector<BtlString> split( const BtlString& delims = "\t\n ") const
    {
        std::vector<BtlString> ret;
        unsigned int numSplits = 0;
        size_t start, pos;
        start = 0;
        do
        {
            pos = find_first_of(delims, start);
            if (pos == start)
            {
                ret.push_back("");
                start = pos + 1;
            }
            else if (pos == npos)
                ret.push_back( substr(start) );
            else
            {
                ret.push_back( substr(start, pos - start) );
                start = pos + 1;
            }
            //start = find_first_not_of(delims, start);
            ++numSplits;
        } while (pos != npos);
        return ret;
    }

    bool endsWith(const BtlString& str) const
    {
        if(str.size()>this->size())
            return false;
        return this->substr(this->size()-str.size(),str.size()) == str;
    }
    bool contains(const BtlString& str) const
    {
        return this->find(str)<this->size();
    }
    bool beginsWith(const BtlString& str) const
    {
        if(str.size()>this->size())
            return false;
        return this->substr(0,str.size()) == str;
    }

    BtlString toLowerCase( void )
    {
        std::transform(begin(), end(), begin(), static_cast<int(*)(int)>(::tolower) );
        return *this;
    }
    BtlString toUpperCase( void )
    {
        std::transform(begin(), end(), begin(), static_cast<int(*)(int)>(::toupper) );
        return *this;
    }

    /** Case insensitive comparison.
    */
    bool isEquiv(const BtlString& str) const
    {
        BtlString str0 = *this;
        str0.toLowerCase();
        BtlString str1 = str;
        str1.toLowerCase();
        return str0 == str1;
    }

    /** Decompose the current string as a path and a file.
        For instance: "dir1/dir2/file.ext" leads to path="dir1/dir2/" and filename="file.ext"
    */
    void decomposePathAndFile(BtlString& path, BtlString& filename) const
    {
        std::vector<BtlString> elements = this->split("/\\");
        path = "";
        filename = elements.back();
        elements.pop_back();
        if (this->at(0)=='/')
            path = "/";
        for (unsigned int i=0 ; i<elements.size() ; ++i)
            path += elements[i] + "/";
    }
};

class BtlConfig
{
public:
  BtlConfig()
    : overwriteResults(false)
  {
    char * _config;
    _config = getenv ("BTL_CONFIG");
    if (_config!=NULL)
    {
      std::vector<BtlString> config = BtlString(_config).split(" \t\n");
      for (int i = 0; i<config.size(); i++)
      {
        if (config[i].beginsWith("-a"))
        {
          if (i+1==config.size())
          {
            std::cerr << "error processing option: " << config[i] << "\n";
            exit(2);
          }
          Instance.m_selectedActionNames = config[i+1].split(":");

          i += 1;
        }
        else if (config[i].beginsWith("--overwrite"))
        {
          Instance.overwriteResults = true;
        }
      }
    }

    BTL_DISABLE_SSE_EXCEPTIONS();
  }

  BTL_DONT_INLINE static bool skipAction(const std::string& _name)
  {
    if (Instance.m_selectedActionNames.empty())
      return false;

    BtlString name(_name);
    for (int i=0; i<Instance.m_selectedActionNames.size(); ++i)
      if (name.contains(Instance.m_selectedActionNames[i]))
        return false;

    return true;
  }

  static BtlConfig Instance;
  bool overwriteResults;

protected:
  std::vector<BtlString> m_selectedActionNames;
};

#define BTL_MAIN \
  BtlConfig BtlConfig::Instance

#endif // BTL_HH
