yat  0.21pre
utility.h
Go to the documentation of this file.
1 #ifndef _theplu_yat_utility_utility_
2 #define _theplu_yat_utility_utility_
3 
4 // $Id: utility.h 4262 2023-01-10 00:05:51Z peter $
5 
6 /*
7  Copyright (C) 2005 Jari Häkkinen, Peter Johansson, Markus Ringnér
8  Copyright (C) 2006 Jari Häkkinen
9  Copyright (C) 2007, 2008 Jari Häkkinen, Peter Johansson
10  Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022 Peter Johansson
11 
12  This file is part of the yat library, http://dev.thep.lu.se/yat
13 
14  The yat library is free software; you can redistribute it and/or
15  modify it under the terms of the GNU General Public License as
16  published by the Free Software Foundation; either version 3 of the
17  License, or (at your option) any later version.
18 
19  The yat library is distributed in the hope that it will be useful,
20  but WITHOUT ANY WARRANTY; without even the implied warranty of
21  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22  General Public License for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with yat. If not, see <http://www.gnu.org/licenses/>.
26 */
27 
33 
34 #include "config_public.h"
35 
36 #include "concept_check.h"
37 #include "deprecate.h"
38 #include "Exception.h"
39 #include "iterator_traits.h"
40 #include "WeightIterator.h"
41 #include "yat_assert.h"
42 
43 #include <boost/iterator/iterator_concepts.hpp>
44 #include <boost/concept_check.hpp>
45 
46 #include <algorithm>
47 #include <cctype>
48 #include <cmath>
49 #include <cstdlib>
50 #include <cstring>
51 #include <functional>
52 #include <limits>
53 #include <locale>
54 #include <istream>
55 #include <iostream>
56 #include <numeric>
57 #include <string>
58 #include <stdexcept>
59 #include <sstream>
60 #include <utility>
61 #include <vector>
62 
63 namespace theplu {
64 namespace yat {
65 namespace utility {
66 
77  std::string basename(const std::string& fn);
78 
89  template<typename T>
90  std::istream& binary_read(std::istream& is, T& x)
91  {
92  const unsigned char type_size=sizeof(T);
93  YAT_ASSERT(type_size <= 16);
94  char buffer[16];
95  is.read(buffer, type_size);
96  memcpy(&x, buffer, type_size);
97  return is;
98  }
99 
100 
112  template<typename T>
113  void binary_write(std::ostream& os, T x)
114  {
115  const unsigned char type_size=sizeof(T);
116  YAT_ASSERT(type_size <= 16);
117  char buffer[16];
118  memcpy(buffer, &x, type_size);
119  os.write(buffer, type_size);
120  }
121 
141  template<typename InputIterator, typename OutputIterator>
142  bool binary_weight(InputIterator first, InputIterator last,
143  OutputIterator result);
144 
155  void chdir(const std::string& dir);
156 
165  void chmod(const std::string& filename, mode_t mode);
166 
174  template<typename charT, class Traits, class Allocator>
175  bool contains(const std::basic_string<charT, Traits, Allocator>& str,
176  const std::basic_string<charT, Traits, Allocator>& substr);
177 
179  template<typename charT, class Traits, class Allocator>
180  bool contains(const std::basic_string<charT, Traits, Allocator>& str,
181  charT substr);
182 
184  template<typename charT, class Traits, class Allocator>
185  bool contains(const std::basic_string<charT, Traits, Allocator>& str,
186  const charT* substr);
187 
188 
200  template<typename T>
201  std::string convert(T input);
202 
208  template<typename T>
209  T convert(const std::string& s);
210 
221  template<typename T>
222  bool convert_try(const std::string& s, T& t);
223 
230  void copy_file(const std::string& source, const std::string& target);
231 
232 
243  std::string dirname(const std::string& fn);
244 
252  template<typename charT, class Traits, class Allocator>
253  bool ends_with(const std::basic_string<charT, Traits, Allocator>& str,
254  const std::basic_string<charT, Traits, Allocator>& suffix);
255 
257  template<typename charT, class Traits, class Allocator>
258  bool ends_with(const std::basic_string<charT, Traits, Allocator>& str,
259  charT suffix);
260 
262  template<typename charT, class Traits, class Allocator>
263  bool ends_with(const std::basic_string<charT, Traits, Allocator>& str,
264  const charT* suffix);
265 
276  bool fnmatch(const std::string& pattern, const std::string& str,
277  int flags=0);
278 
286  std::string getcwd(void);
287 
297  void gsl_error_handler(const char* reason, const char* file,
298  int line, int gsl_errno);
299 
305  template<typename T>
306  bool is(const std::string& s);
307 
314  bool is_double(const std::string&) YAT_DEPRECATE;
315 
324  bool is_equal(std::string s, std::string other);
325 
332  bool is_float(const std::string&) YAT_DEPRECATE;
333 
340  bool is_int(const std::string&) YAT_DEPRECATE;
341 
345  bool is_nan(const std::string& s);
346 
382  template<typename T>
383  void load(std::istream& is, std::vector<std::vector<T> >& vec, char sep='\0',
384  char line_sep='\n', bool ignore_empty=false, bool rectangle=true);
385 
407  template<typename T>
408  void load(std::istream& is, std::vector<T>& vec, char sep='\0');
409 
417  template<typename T>
418  T log2(T x) { return std::log2(x); }
419 
429  void mkdir(const std::string& dir, mode_t mode=0777);
430 
438  void mkdir_p(const std::string& dir, mode_t mode=0777);
439 
446 #define YAT_MOVE(arg) std::move(arg)
447 #define YAT_MOVE_IF_NOEXCEPT(arg) std::move_if_noexcept(arg)
449 
461  void print_what(const std::exception& error, std::ostream& out=std::cerr);
462 
470  void remove(const std::string& fn);
471 
480  void rename(const std::string& from, const std::string& to);
481 
491  void replace(std::string& full_str, const std::string& old_str,
492  const std::string& new_str);
493 
494 
502  template<typename charT, class Traits, class Allocator>
503  bool starts_with(const std::basic_string<charT, Traits, Allocator>& str,
504  const std::basic_string<charT, Traits, Allocator>& prefix);
505 
507  template<typename charT, class Traits, class Allocator>
508  bool starts_with(const std::basic_string<charT, Traits, Allocator>& str,
509  charT prefix);
510 
512  template<typename charT, class Traits, class Allocator>
513  bool starts_with(const std::basic_string<charT, Traits, Allocator>& str,
514  const charT* prefix);
515 
528  template<typename Iterator>
529  double sum_weight(Iterator first, Iterator last);
530 
541  void symlink(const std::string& path1, const std::string& path2);
542 
544 
545 // private namespace
546 namespace detail {
547 
551  template<typename T>
552  struct VectorPusher
553  {
559  void operator()(const std::string& element, std::vector<T>& vec)
560  {
561  if (!element.size())
562  vec.push_back(std::numeric_limits<T>::quiet_NaN());
563  else {
564  vec.push_back(convert<T>(element));
565  }
566  }
567  };
568 
574  template<>
575  struct VectorPusher<std::string>
576  {
580  void operator()(const std::string& element, std::vector<std::string>& vec)
581  {
582  vec.push_back(element);
583  }
584 
585  void operator()(std::string&& element, std::vector<std::string>& vec)
586  {
587  vec.push_back(std::move(element));
588  }
589  };
590 
591 
592  template<typename Iterator>
593  double sum_weight(Iterator first, Iterator last, unweighted_iterator_tag tag)
594  {
595  return std::distance(first, last);
596  }
597 
598 
599  template<typename Iterator>
600  double sum_weight(Iterator first, Iterator last, weighted_iterator_tag tag)
601  {
602  return std::accumulate(weight_iterator(first), weight_iterator(last), 0);
603  }
604 
605 
606 } // end of namespace detail
607 
609 
610  // template implementations
611 
612  template<typename InputIterator, typename OutputIterator>
613  bool binary_weight(InputIterator first, InputIterator last,
614  OutputIterator result)
615  {
616  BOOST_CONCEPT_ASSERT((boost_concepts::SinglePassIterator<InputIterator>));
617  BOOST_CONCEPT_ASSERT((boost_concepts::ReadableIterator<InputIterator>));
618  BOOST_CONCEPT_ASSERT((boost_concepts::IncrementableIterator<OutputIterator>));
619  BOOST_CONCEPT_ASSERT((boost_concepts::WritableIterator<OutputIterator, float>));
620 
621  bool nan=false;
622  while (first!=last) {
623  if (std::isnan(*first)) {
624  *result=0;
625  nan=true;
626  }
627  else
628  *result = 1.0;
629  ++first;
630  ++result;
631  }
632  return nan;
633  }
634 
635 
636  template<typename charT, class Traits, class Allocator>
637  bool contains(const std::basic_string<charT, Traits, Allocator>& str,
638  const std::basic_string<charT, Traits, Allocator>& substr)
639  {
640 #ifdef YAT_HAVE_FUNC_STRING_CONTAINS
641  return str.contains(substr);
642 #else
643  return str.find(substr)!=std::basic_string<charT, Traits,Allocator>::npos;
644 #endif
645  }
646 
647 
648  template<typename charT, class Traits, class Allocator>
649  bool contains(const std::basic_string<charT, Traits, Allocator>& str,
650  charT substr)
651  {
652 #ifdef YAT_HAVE_FUNC_STRING_CONTAINS
653  return str.contains(substr);
654 #else
655  return str.find(substr)!=std::basic_string<charT, Traits,Allocator>::npos;
656 #endif
657  }
658 
659 
660  template<typename charT, class Traits, class Allocator>
661  bool contains(const std::basic_string<charT, Traits, Allocator>& str,
662  const charT* substr)
663  {
664 #ifdef YAT_HAVE_FUNC_STRING_CONTAINS
665  return str.contains(substr);
666 #else
667  return str.find(substr)!=std::basic_string<charT, Traits,Allocator>::npos;
668 #endif
669  }
670 
671 
672  template<typename T>
673  std::string convert(T input)
674  {
675  std::ostringstream ss;
676  ss << input;
677  return ss.str();
678  }
679 
680 
681  template<typename T>
682  T convert(const std::string& s)
683  {
684  T result;
685  if (!convert_try(s, result))
686  throw runtime_error(std::string("yat::utility::convert(\"")+s+
687  std::string("\")"));
688  return result;
689  }
690 
691 
692  template<typename charT, class Traits, class Allocator>
693  bool ends_with(const std::basic_string<charT, Traits, Allocator>& str,
694  const std::basic_string<charT, Traits, Allocator>& suffix)
695  {
696 #ifdef YAT_HAVE_FUNC_STRING_ENDS_WITH
697  return str.ends_with(suffix);
698 #else
699  size_t n = suffix.size();
700  return n <= str.size() && !str.compare(str.size()-n, n, suffix);
701 #endif
702  }
703 
704 
705  template<typename charT, class Traits, class Allocator>
706  bool ends_with(const std::basic_string<charT, Traits, Allocator>& str,
707  charT suffix)
708  {
709 #ifdef YAT_HAVE_FUNC_STRING_ENDS_WITH
710  return str.ends_with(suffix);
711 #else
712  Traits traits;
713  return str.size() && traits.eq(str.back(), suffix);
714 #endif
715  }
716 
717 
718  template<typename charT, class Traits, class Allocator>
719  bool ends_with(const std::basic_string<charT, Traits, Allocator>& str,
720  const charT* suffix)
721  {
722 #ifdef YAT_HAVE_FUNC_STRING_ENDS_WITH
723  return str.ends_with(suffix);
724 #else
725  Traits traits;
726  size_t n = traits.length(suffix);
727  return n <= str.size() && !str.compare(str.size()-n, n, suffix);
728 #endif
729  }
730 
731 
732  template<typename T>
733  bool is(const std::string& s)
734  {
735  T tmp;
736  return convert_try(s, tmp);
737  }
738 
739 
740  template<typename T>
741  void load(std::istream& is, std::vector<std::vector<T> >& matrix,
742  char sep, char line_sep, bool ignore_empty,
743  bool rectangle)
744  {
745  size_t nof_columns=0;
746  std::string line;
747  while(getline(is, line, line_sep)){
748  if (line.empty() && ignore_empty)
749  continue;
750  std::vector<T> v;
751  v.reserve(nof_columns);
752  bool empty_last_element = !line.empty() && line.back()==sep;
753  std::stringstream ss(std::move(line));
754  load(ss, v, sep);
755  // add NaN for final separator (or empty string if T=std::string)
756  detail::VectorPusher<T> pusher;
757  if (empty_last_element && sep!='\0')
758  pusher("", v);
759 
760  if (rectangle && nof_columns && v.size()!=nof_columns) {
761  std::ostringstream s;
762  s << "load stream error: "
763  << "line " << matrix.size() << " has " << v.size()
764  << " columns; expected " << nof_columns << " columns.";
765  throw utility::IO_error(s.str());
766  }
767  nof_columns = std::max(nof_columns, v.size());
768  matrix.push_back(std::move(v));
769  }
770 
771  // manipulate the state of the stream to be good
772  is.clear(std::ios::goodbit);
773  }
774 
775  template<typename T>
776  void load(std::istream& is, std::vector<T>& vec, char sep)
777  {
778  detail::VectorPusher<T> pusher;
779  while(true) {
780  std::string element;
781  if(sep=='\0')
782  is>>element;
783  else
784  getline(is, element, sep);
785  if(is.fail())
786  break;
787  pusher(std::move(element), vec);
788  }
789  }
790 
791 
792  template<typename charT, class Traits, class Allocator>
793  bool starts_with(const std::basic_string<charT, Traits, Allocator>& str,
794  const std::basic_string<charT, Traits, Allocator>& prefix)
795  {
796 #ifdef YAT_HAVE_FUNC_STRING_STARTS_WITH
797  return str.starts_with(prefix);
798 #else
799  size_t n = prefix.size();
800  return n <= str.size() && !str.compare(0, n, prefix);
801 #endif
802  }
803 
804 
805  template<typename charT, class Traits, class Allocator>
806  bool starts_with(const std::basic_string<charT, Traits, Allocator>& str,
807  charT prefix)
808  {
809 #ifdef YAT_HAVE_FUNC_STRING_STARTS_WITH
810  return str.starts_with(prefix);
811 #else
812  Traits traits;
813  return str.size() && traits.eq(str[0], prefix);
814 #endif
815  }
816 
817 
818  template<typename charT, class Traits, class Allocator>
819  bool starts_with(const std::basic_string<charT, Traits, Allocator>& str,
820  const charT* prefix)
821  {
822 #ifdef YAT_HAVE_FUNC_STRING_STARTS_WITH
823  return str.starts_with(prefix);
824 #else
825  Traits traits;
826  size_t n = traits.length(prefix);
827  return n <= str.size() && !str.compare(0, n, prefix);
828 #endif
829  }
830 
831 
832  template<typename Iterator>
833  double sum_weight(Iterator first, Iterator last)
834  {
835  BOOST_CONCEPT_ASSERT((DataIteratorConcept<Iterator>));
836  BOOST_CONCEPT_ASSERT((boost_concepts::ReadableIterator<Iterator>));
837  BOOST_CONCEPT_ASSERT((boost_concepts::SinglePassIterator<Iterator>));
839  return detail::sum_weight(first, last, tag);
840  }
841 
842 
843 
844  template<typename T>
845  bool convert_try(const std::string& s, T& result)
846  {
847  if (!std::numeric_limits<T>::is_signed) {
848  // first non-whitespace character
849  std::string::const_iterator iter = s.begin();
850  while (iter!=s.end() && std::isspace(*iter))
851  ++iter;
852  // unsigned int cannot start with a '-' and with some compilers
853  // operation ss >> result won't fail so catch it like this instead.
854  if (iter==s.end() || *iter=='-')
855  return false;
856  }
857  std::istringstream ss(s);
858  ss >> result;
859  if (ss.fail()) {
860  if (is_nan(s) || is_equal(s, "-nan")) {
861  result = std::numeric_limits<T>::quiet_NaN();
862  return true;
863  }
864  if (is_equal(s, "inf")) {
865  result = std::numeric_limits<T>::infinity();
866  return true;
867  }
868  if (is_equal(s, "-inf")) {
869  // unsigned types are caught in prologue
870  YAT_ASSERT(std::numeric_limits<T>::is_signed);
871  result = -std::numeric_limits<T>::infinity();
872  return true;
873  }
874  return false;
875  }
876  // Check that nothing is left on stream
877  std::string b;
878  ss >> b;
879  return b.empty();
880  }
881 
882 }}} // of namespace utility, yat, and theplu
883 
884 #endif
bool is(const std::string &s)
check if string is convertible to (numerical) type T
Definition: utility.h:733
bool is_int(const std::string &)
detail::weighted_iterator_traits_detail< value >::type type
Definition: iterator_traits.h:114
void chdir(const std::string &dir)
std::string dirname(const std::string &fn)
void symlink(const std::string &path1, const std::string &path2)
Concept check for Data Iterator.
Definition: concept_check.h:240
double sum_weight(Iterator first, Iterator last)
Definition: utility.h:833
void rename(const std::string &from, const std::string &to)
The Department of Theoretical Physics namespace as we define it.
void copy_file(const std::string &source, const std::string &target)
Copy file source to target.
bool ends_with(const std::basic_string< charT, Traits, Allocator > &str, const std::basic_string< charT, Traits, Allocator > &suffix)
Definition: utility.h:693
Definition: stl_utility.h:64
bool is_double(const std::string &)
bool is_float(const std::string &)
void mkdir_p(const std::string &dir, mode_t mode=0777)
T max(const T &a, const T &b, const T &c)
Definition: stl_utility.h:699
void print_what(const std::exception &error, std::ostream &out=std::cerr)
recursively print exception what
Class used for all runtime error detected within yat library.
Definition: Exception.h:53
void chmod(const std::string &filename, mode_t mode)
bool is_nan(const std::string &s)
std::string getcwd(void)
current directory
void gsl_error_handler(const char *reason, const char *file, int line, int gsl_errno)
void replace(std::string &full_str, const std::string &old_str, const std::string &new_str)
bool is_equal(std::string s, std::string other)
bool fnmatch(const std::string &pattern, const std::string &str, int flags=0)
Class to report errors associated with IO operations.
Definition: Exception.h:124
bool binary_weight(InputIterator first, InputIterator last, OutputIterator result)
Definition: utility.h:613
T log2(T x)
Definition: utility.h:418
bool contains(const std::basic_string< charT, Traits, Allocator > &str, const std::basic_string< charT, Traits, Allocator > &substr)
Definition: utility.h:637
void binary_write(std::ostream &os, T x)
Definition: utility.h:113
void load(std::istream &is, std::vector< std::vector< T > > &vec, char sep='\0', char line_sep='\n', bool ignore_empty=false, bool rectangle=true)
Definition: utility.h:741
bool convert_try(const std::string &s, T &t)
try to convert
Definition: utility.h:845
std::string basename(const std::string &fn)
void mkdir(const std::string &dir, mode_t mode=0777)
create a directory dir
std::string convert(T input)
convert T to a string
Definition: utility.h:673
bool starts_with(const std::basic_string< charT, Traits, Allocator > &str, const std::basic_string< charT, Traits, Allocator > &prefix)
Definition: utility.h:793
std::istream & binary_read(std::istream &is, T &x)
Definition: utility.h:90

Generated on Wed Jan 25 2023 03:34:29 for yat by  doxygen 1.8.14