-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathformat.C
More file actions
executable file
·141 lines (131 loc) · 4 KB
/
format.C
File metadata and controls
executable file
·141 lines (131 loc) · 4 KB
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
#include "random.h"
#include <cstdio>
#include <cstdlib>
#include <cstring>
/*
GenRan: non-Gaussian random field generator.
Copyright (C) 2006 Peter Grassl
Distributed under the MIT licence.
Minimal reader for .ini-style input files: keys on the left, ':' or '='
separator, value on the right. Each lookup reopens and rescans the
file; this is O(K·filesize) for K lookups but acceptable since a typical
input has a dozen keys and a typical run reads them all once.
*/
namespace {
// Scan `fname` for a line whose start (case-insensitive) matches `lhs` and
// copy it into `out`. Returns true on hit; on miss leaves `out` empty.
bool readMatchingLine(const char *fname, const char *lhs, char *out, size_t out_size)
{
FILE *inp = std::fopen(fname, "r");
if (!inp) return false;
out[0] = '\0';
char buf[256];
const size_t lhs_len = std::strlen(lhs);
bool found = false;
while (std::fgets(buf, sizeof(buf), inp)) {
if (!strncasecmp(lhs, buf, lhs_len)) {
std::strncpy(out, buf, out_size - 1);
out[out_size - 1] = '\0';
found = true;
break;
}
}
std::fclose(inp);
return found;
}
// Locate the value separator (`:` or `=`) in `line`. Returns NULL if none.
const char *valuePointer(const char *line)
{
const char *ptr = std::strstr(line, ":");
if (!ptr) ptr = std::strstr(line, "=");
return ptr;
}
} // namespace
int getint_ini(const char *fname, const char *lhs)
{
char line[256];
if (!readMatchingLine(fname, lhs, line, sizeof(line))) {
// Distinguish "file missing" from "key missing" for the user.
FILE *probe = std::fopen(fname, "r");
if (!probe) {
std::printf("File not found: '%s'\n", fname);
} else {
std::fclose(probe);
std::printf("Cannot find string '%s' in ini file '%s'.\n", lhs, fname);
}
std::exit(-1);
}
const char *ptr = valuePointer(line);
if (!ptr) {
std::printf("Cannot parse line '%s' in ini file '%s'\n", lhs, fname);
std::exit(-1);
}
int result;
if (std::sscanf(ptr + 1, "%d", &result) != 1) {
std::printf("Cannot parse line '%s' in ini file '%s'\n", lhs, fname);
std::exit(-1);
}
return result;
}
double getdouble_ini(const char *fname, const char *lhs)
{
char line[256];
if (!readMatchingLine(fname, lhs, line, sizeof(line))) {
FILE *probe = std::fopen(fname, "r");
if (!probe) {
std::printf("Ini file not found: '%s'\n", fname);
} else {
std::fclose(probe);
std::printf("Cannot find string '%s' in ini file '%s'.\n", lhs, fname);
}
std::exit(-1);
}
const char *ptr = valuePointer(line);
if (!ptr) {
std::printf("Cannot parse line '%s' in ini file '%s'\n", lhs, fname);
std::exit(-1);
}
double result;
if (std::sscanf(ptr + 1, "%lf", &result) != 1) {
std::printf("Cannot parse line '%s' in ini file '%s'\n", lhs, fname);
std::exit(-1);
}
return result;
}
// Like getint_ini but returns false (without exiting) when the key is
// missing. Still exits on a malformed line. The file must exist.
bool tryGetint_ini(const char *fname, const char *lhs, int *out)
{
char line[256];
if (!readMatchingLine(fname, lhs, line, sizeof(line))) {
return false;
}
const char *ptr = valuePointer(line);
if (!ptr) {
std::printf("Cannot parse line '%s' in ini file '%s'\n", lhs, fname);
std::exit(-1);
}
if (std::sscanf(ptr + 1, "%d", out) != 1) {
std::printf("Cannot parse line '%s' in ini file '%s'\n", lhs, fname);
std::exit(-1);
}
return true;
}
// Companion to getdouble_ini that returns false when the key is missing.
bool tryGetdouble_ini(const char *fname, const char *lhs, double *out)
{
char line[256];
if (!readMatchingLine(fname, lhs, line, sizeof(line))) {
return false;
}
const char *ptr = valuePointer(line);
if (!ptr) {
std::printf("Cannot parse line '%s' in ini file '%s'\n", lhs, fname);
std::exit(-1);
}
if (std::sscanf(ptr + 1, "%lf", out) != 1) {
std::printf("Cannot parse line '%s' in ini file '%s'\n", lhs, fname);
std::exit(-1);
}
return true;
}