Repository navigation
Expand file tree
/
Copy pathWindowsScanning.hpp
More file actions
79 lines (72 loc) · 3.16 KB
/
Copy pathWindowsScanning.hpp
File metadata and controls
79 lines (72 loc) · 3.16 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
#ifndef CORE_LIBS_PRX_LIBC_INCLUDE_WINDOWSSCANNING_HPP
#define CORE_LIBS_PRX_LIBC_INCLUDE_WINDOWSSCANNING_HPP
#include "WindowsFormatting.hpp"
#include "General.hpp"
#include <algorithm>
#include <cerrno>
#include <cstring>
namespace LibcDetail {
template <typename TScanner>
inline int ScanWindowsArguments_nid_no_patch(const char* format, const void* source, TScanner scan) {
if (!format || !source) { errno = 22; return EOF; }
std::string translated;
std::vector<void*> pointers;
std::vector<int> suppressedEnds(static_cast<size_t>(std::count(format, format + std::strlen(format), '%')), -1);
size_t suppressedCount = 0;
FormatArguments args(source);
while (*format) {
const char value = *format++;
translated += value;
if (value != '%') continue;
if (*format == '%') { translated += *format++; continue; }
const bool suppressed = *format == '*';
if (suppressed) translated += *format++;
while (*format >= '0' && *format <= '9') translated += *format++;
std::string length;
if (*format && std::strchr("hljztL", *format)) {
length += *format++;
if ((length == "h" && *format == 'h') || (length == "l" && *format == 'l')) length += *format++;
}
const char conversion = *format;
if (!conversion) { errno = 22; return EOF; }
if (!std::strchr("diouxXaAeEfFgGcspn[", conversion)) {
NotImplemented_nid_no_patch("vsscanf format conversion");
return EOF;
}
++format;
if (std::strchr("diouxXn", conversion) && (length == "l" || length == "j" || length == "z" || length == "t"))
translated += "ll";
else translated += length;
translated += conversion;
if (conversion == '[') {
if (*format == '^') translated += *format++;
if (*format == ']') translated += *format++;
while (*format && *format != ']') translated += *format++;
if (*format != ']') { errno = 22; return EOF; }
translated += *format++;
}
if (!suppressed) pointers.push_back(args.Next<void*>());
else if (conversion != 'n') {
translated += "%n";
pointers.push_back(&suppressedEnds[suppressedCount++]);
}
}
const int result = scan(translated.c_str(), reinterpret_cast<char*>(pointers.data()));
if (result == EOF && std::any_of(suppressedEnds.begin(), suppressedEnds.begin() + suppressedCount, [](int end) { return end >= 0; }))
return 0;
return result;
}
inline int ScanWindows(const char* input, const char* format, const void* source) {
if (!input) { errno = 22; return EOF; }
return ScanWindowsArguments_nid_no_patch(format, source, [input](const char* translated, char* pointers) {
return std::vsscanf(input, translated, pointers);
});
}
inline int ScanFileWindows_nid_no_patch(std::FILE* stream, const char* format, const void* source) {
if (!stream) { errno = 22; return EOF; }
return ScanWindowsArguments_nid_no_patch(format, source, [stream](const char* translated, char* pointers) {
return std::vfscanf(stream, translated, pointers);
});
}
}
#endif