// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// Mobius Forensic Toolkit
// Copyright (C) 2008,2009,2010,2011,2012,2013,2014,2015,2016,2017 Eduardo Aguiar
//
// 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, 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, see <http://www.gnu.org/licenses/>.
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
#include <mobius/string_functions.h>
#include <algorithm>

namespace mobius
{

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief convert ASCII string to lowercase
//! \param str string
//! \return lowercased string
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
const std::string
string_tolower (const std::string& str)
{
  std::string tmp (str);

  for (auto& c : tmp)
    c = tolower (c);

  return tmp;
}

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief convert ASCII string to uppercase
//! \param str string
//! \return uppercased string
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
const std::string
string_toupper (const std::string& str)
{
  std::string tmp (str);

  for (auto& c : tmp)
    c = toupper (c);

  return tmp;
}

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief check if a string starts with another one
//! \param str string
//! \param starting starting string
//! \return true if str starts with starting
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
bool
string_startswith (const std::string& str, const std::string& starting)
{
  return str.length () >= starting.length () &&
         str.substr (0, starting.length ()) == starting;
}

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief check if a string ends with another one
//! \param str string
//! \param ending ending string
//! \return true if str ends with ending
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
bool
string_endswith (const std::string& str, const std::string& ending)
{
  return str.length () >= ending.length () &&
         str.substr (str.length () - ending.length (), ending.length ()) == ending;
}

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief remove all occurrences of 'c' in str
//! \param str string
//! \param c char
//! \return a new string
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
const std::string
string_remove_all (const std::string& str, char c)
{
  std::string tmp = str;
  std::string::iterator end_pos = std::remove (tmp.begin(), tmp.end(), ' ');
  tmp.erase (end_pos, tmp.end ());
  return tmp;
}

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief strip chars from both ends of a string
//! \param str string
//! \param chars chars
//! \return a new string
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
const std::string
string_strip (const std::string& str, const std::string& chars)
{
  return string_lstrip (string_rstrip (str, chars));
}

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief strip chars from the beginning of a string
//! \param str string
//! \param chars chars
//! \return a new string
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
const std::string
string_lstrip (const std::string& str, const std::string& chars)
{
  const auto pos = str.find_first_not_of (chars);

  if (pos == std::string::npos)
    return std::string ();

  return str.substr (pos);
}

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief strip chars from the end of a string
//! \param str string
//! \param chars chars
//! \return a new string
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
const std::string
string_rstrip (const std::string& str, const std::string& chars)
{
  const auto pos = str.find_last_not_of (chars);

  if (pos == std::string::npos)
    return std::string ();

  return str.substr (0, pos + 1);
}

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief split string into parts
//! \param str string
//! \param sep separator string
//! \return vector containing parts
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
const std::vector <std::string>
string_split (const std::string& str, const std::string& sep)
{
  std::vector <std::string> result;
  std::string::size_type start = 0;
  std::string::size_type end = str.find (sep);
  
  while (end != std::string::npos)
    {
      result.push_back (str.substr (start, end - start));
      start = end + sep.length ();
      end = str.find (sep, start);
    }

  result.push_back (str.substr (start));
  return result;
}

} // namespace mobius
