summaryrefslogtreecommitdiff
path: root/tools/utils.c
blob: 3895215d1d6bcea915d389ccf2fdc39cfbbf1817 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#include "utils.h"
#include <sstream>
#include <iomanip>
#include <stdlib.h>     /* for abs() */
#include <string.h>     /* for strerror_r() */
/////                   <cmath> would not be an improvement
/////                   due to lack of interger abs()
/////                   and ambiguous (and inefficient) promotion
#include <ctype.h>      /* for isalnum() */

using namespace std;

// strip off the directory part of a path, leaving just
// the basic filename
string basename(const string path){
  size_t where = path.rfind("/");
  if (where != string::npos) return path.substr(1+where);
  return path;
}

////////////////
// little utility to help with argument parsing:
//
int prefix(const string shorter, const string longer){
  return shorter == longer.substr(0, shorter.length());
}

///////////////
// print a time as (-)hh:mm:ss
//
string time_out(const int _ttt){
  int ttt(abs(_ttt));
  int sec(ttt % 60);
  int min((ttt / 60) % 60);
  int hr(ttt / 3600);
  stringstream foo;
  int didsome(0);
  if (_ttt < 0) foo << "-";
  if (hr) {
    foo << hr << ":";
    didsome++;
  }
  if (didsome || min){
    foo << setw(didsome?2:1) << setfill('0') << min << ":";
    didsome++;
  }
  foo << setw(didsome?2:1) << setfill('0') << sec;
  return foo.str();
}

string toLower(const string a){
  string rslt = a;
  string::iterator rr;
  for (rr = rslt.begin(); rr != rslt.end(); rr++){
    *rr = tolower(*rr);
  }
  return rslt;
}

string ltrim(const string foo, const string strip){
  size_t where = foo.find_first_not_of(strip);
  if (where == foo.npos) return foo;
  return foo.substr(where);
}

string rtrim(const string foo, const string strip){
  size_t where = foo.find_last_not_of(strip);
  if (where == foo.npos) return "";
  return foo.substr(0, where+1);
}

string trim(const string foo, const string bar){
  return ltrim(rtrim(foo, bar), bar);
}

static const string Pure_Enough("+-_.,@%~");

string purify(const string arg){
  string rslt(arg);
  for (string::iterator ptr = rslt.begin();
        ptr != rslt.end(); ptr++){
    char ch = *ptr;
    if (isalnum(ch)) continue;
    if (Pure_Enough.find(ch) != string::npos) continue;
    *ptr = '~';
  }
  return rslt;
}

// Returns negative if a is less than b in alphabetical order
// returns 0 if they are the same, or positive if a is greater.
// Like perl cmp operator, but ignores case.
int cmp_casefold(const std::string& a, const std::string& b) {
  string::const_iterator aa, bb;
  aa = a.begin();
  bb = b.begin();
  while (aa != a.end() && bb != b.end()){
    char ca = tolower(*aa++);
    char cb = tolower(*bb++);
    if (ca != cb) return ca < cb ? -2 : 2;
  }
  if (aa != a.end()) return 1;          // a is longer
  if (bb != b.end()) return -1;         // b is longer
  return 0;
}

string noCR(const string bar){
  string foo(bar);
  int len = foo.length();
  if (len){
    if (foo[len-1] == '\r') {
      foo.erase(len-1);
    }
  }
  return foo;
}

// sorta like Perl's join(...)
string join(const string sep, const list<string> stuff){
  string rslt;
  for (list<string>::const_iterator ptr = stuff.begin();
        ptr != stuff.end(); ptr++){
    if (rslt.length()) rslt += sep;
    rslt += *ptr;
  }
  return rslt;
}

string strError(const int errnum){
  char buf[1000];
  char* rslt = strerror_r(errnum, buf, sizeof(buf));
  return rslt;
#ifdef XSI_not_gnu
  if (rslt) {
    cerr << "strerror_r() failed: " << rslt << " "
    perror(0);
    exit(1);
  }
#endif
}

extern int errno;
string strError(){
  return strError(errno);
}