Switch to unified view

a/src/utils/readfile.cpp b/src/utils/readfile.cpp
...
...
38
38
39
#include "readfile.h"
39
#include "readfile.h"
40
40
41
static void caterrno(string *reason, const char *what)
41
static void caterrno(string *reason, const char *what)
42
{
42
{
43
#define ERRBUFSZ 200    
44
    char errbuf[ERRBUFSZ];
45
    if (reason) {
43
    if (reason) {
46
    *reason += "file_to_string: ";
44
    reason->append("file_to_string: ");
47
  *reason += what;
45
  reason->append(what);
48
  *reason += ": ";
46
  reason->append(": ");
49
#ifdef sun
47
#ifdef sun
50
    // Note: sun strerror is noted mt-safe ??
48
    // Note: sun strerror is noted mt-safe ??
51
    *reason += strerror(errno);
49
    reason->append(strerror(errno));
52
#else
50
#else
51
#define ERRBUFSZ 200    
52
  char errbuf[ERRBUFSZ];
53
    strerror_r(errno, errbuf, ERRBUFSZ);
53
    strerror_r(errno, errbuf, ERRBUFSZ);
54
  *reason += errbuf;
54
  reason->append(errbuf);
55
#endif
55
#endif
56
    }
56
    }
57
}
57
}
58
58
59
class FileToString : public FileScanDo {
60
public:
61
    FileToString(string& data) : m_data(data) {}
62
    string& m_data;
63
    bool init(unsigned int size, string *reason) {
64
  if (size > 0)
65
      m_data.reserve(size); 
66
  return true;
67
    }
68
    bool data(const char *buf, int cnt, string *reason) {
69
  try {
70
      m_data.append(buf, cnt);
71
  } catch (...) {
72
      caterrno(reason, "append");
73
      return false;
74
  }
75
  return true;
76
    }
77
};
78
79
bool file_to_string(const string &fn, string &data, string *reason)
80
{
81
    FileToString accum(data);
82
    return file_scan(fn, &accum, reason);
83
}
84
59
// Note: the fstat() + reserve() calls divide cpu usage almost by 2
85
// Note: the fstat() + reserve() (in init()) calls divide cpu usage almost by 2
60
// on both linux i586 and macosx (compared to just append())
86
// on both linux i586 and macosx (compared to just append())
61
// Also tried a version with mmap, but it's actually slower on the mac and not
87
// Also tried a version with mmap, but it's actually slower on the mac and not
62
// faster on linux.
88
// faster on linux.
63
bool file_to_string(const string &fn, string &data, string *reason)
89
bool file_scan(const string &fn, FileScanDo* doer, string *reason)
64
{
90
{
65
    bool ret = false;
91
    bool ret = false;
66
    bool noclosing = true;
92
    bool noclosing = true;
67
    int fd = 0;
93
    int fd = 0;
68
    struct stat st;
94
    struct stat st;
...
...
70
    st.st_size = 0;
96
    st.st_size = 0;
71
97
72
    // If we have a file name, open it, else use stdin.
98
    // If we have a file name, open it, else use stdin.
73
    if (!fn.empty()) {
99
    if (!fn.empty()) {
74
    fd = open(fn.c_str(), O_RDONLY|O_STREAMING);
100
    fd = open(fn.c_str(), O_RDONLY|O_STREAMING);
75
  if (fd < 0 
76
#if 1
77
        || fstat(fd, &st) < 0
101
    if (fd < 0 || fstat(fd, &st) < 0) {
78
#endif
79
      ) {
80
        caterrno(reason, "open/stat");
102
        caterrno(reason, "open/stat");
81
        return false;
103
        return false;
82
    }
104
    }
83
    noclosing = false;
105
    noclosing = false;
84
    }
106
    }
85
    if (st.st_size > 0)
107
    if (st.st_size > 0)
86
  data.reserve(st.st_size+1);
108
  doer->init(st.st_size+1, reason);
87
109
    else 
110
  doer->init(0, reason);
88
    char buf[4096];
111
    char buf[4096];
89
    for (;;) {
112
    for (;;) {
90
    int n = read(fd, buf, 4096);
113
    int n = read(fd, buf, 4096);
91
    if (n < 0) {
114
    if (n < 0) {
92
        caterrno(reason, "read");
115
        caterrno(reason, "read");
93
        goto out;
116
        goto out;
94
    }
117
    }
95
    if (n == 0)
118
    if (n == 0)
96
        break;
119
        break;
97
120
98
  try {
121
  if (!doer->data(buf, n, reason)) {
99
      data.append(buf, n);
100
  } catch (...) {
101
      caterrno(reason, "append");
102
        goto out;
122
        goto out;
103
    }
123
    }
104
    }
124
    }
105
125
106
    ret = true;
126
    ret = true;
...
...
204
      if (walker.getErrCnt() > 0)
224
      if (walker.getErrCnt() > 0)
205
      cout << walker.getReason();
225
      cout << walker.getReason();
206
  } else if (S_ISREG(st.st_mode)) {
226
  } else if (S_ISREG(st.st_mode)) {
207
      string s, reason;
227
      string s, reason;
208
      if (!file_to_string(top, s, &reason)) {
228
      if (!file_to_string(top, s, &reason)) {
209
      cerr << reason;
229
      cerr << reason << endl;
210
      exit(1);
230
      exit(1);
211
      } else {
231
      } else {
212
      cout << s;
232
      cout << s;
213
      }
233
      }
214
  }
234
  }