You could evaluate this at compile time without "macro-fying" things by using a
if constexpr
check instead (hugely more helpful with messages catching ill-formed expressions instead of the sometimes not-so-helpful messages if you screw something up with macros). If you needed to keep track of line endings throughout your program and if those line endings are changing, I would recommend just wrapping the known line endings into an enum and unordered map:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
enum class Platform{
unix = 0,
windows = 1,
mac = 2,
//etc
};
std::unordered_map<Platform, const char*> line_endings{
{
{unix, "\\n"} ,
{windows, "\\r\\n"},
{mac, "\\r"},
//etc
};
|
which would allow you to do a runtime check similar to what you're doing and just indexing into the map with the platform type.
i.e.
1 2 3 4 5
|
if(str.back() == '\r')
{
delimiter = mac;
// do whatever you need to do to the file/store delimiter and file here
}...
|
1 2 3 4 5 6 7
|
...
switch(delimiter){
case Platform::mac:
fileLine.append(line_endings.at(mac));
break;
...
|
You could then store that delimiter to use, although, that delimiter storage only helps if you're processing one file at a time in this context.
If you're processing multiple files at once, you could use something like
std::pair
to couple the file and delimiter together, store them in something like a vector, and use structured bindings to retrieve those values later to deal with the line endings (although you would need a way to match the file correctly in this case).
If you did store the delimiter with the file (assuming multiple files) then it becomes easy to handle the file if you needed to say, append more to that file in the same format. Converting file types is a bit more involved.
It all depends on your use case and intent really. As far as I'm aware, there's a multitude of ways to go about this - but as coder777 stated
The preprocessor macros are processed before the compiler set in...#define will not change at runtime. |
so your runtime evaluation really doesn't alter anything here
I hope you get a solution that answers your question better (I'm a hobby self-taught programmer so my approaches tend to not be a part of the "well known and tested" thought processes, but just wanted to give some insight in case it might have been helpful lol )
As an example of what you may use this approach with:
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
|
if(getline(chk, str)) {
auto eol { str.back() };
if( eol == '\r'){
delimiter = Platform::mac;
} else if (eol == '\n') {
delimiter = Platform::unix;
} else if (eol == '\r\n') {
delimiter = Platform::windows;
}
}
...
if(delimiter == windows){
delimiterSize = 2;
} else {
delimiterSize = 1;
}
while(getline(chl, str) {
str.erase(str.rbegin() + str.rbegin() + delimiterSize);
// pretending you're storing these lines in a container
fileLines.emplace_back(str);
} // while loop
...
// convert windows line endings to mac for instance
for( auto & line : fileLines) {
line.append(line_endings.at(Platform::mac));
}
// then chunk the data for easier writes to another file or just append
// each line to one large string and write that large string in one write call
|