summaryrefslogtreecommitdiff
path: root/tools/utils.c
blob: 691070e13bf7048bbb2d021dd1a7d8b67d989ba7 (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
#include "utils.h"
#include <sstream>
#include <iomanip>
#include <stdlib.h>     /* for abs() */
/////                   <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;
}