More string swapping and cleaning up main().
This commit is contained in:
37
src/poly/main.h
Normal file
37
src/poly/main.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef POLY_MAIN_H_
|
||||
#define POLY_MAIN_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <poly/platform.h>
|
||||
|
||||
namespace poly {
|
||||
|
||||
// Returns true if there is a user-visible console attached to receive stdout.
|
||||
bool has_console_attached();
|
||||
|
||||
// Extern defined by user code. This must be present for the application to
|
||||
// launch.
|
||||
struct EntryInfo {
|
||||
std::wstring name;
|
||||
std::wstring usage;
|
||||
int (*entry_point)(std::vector<std::wstring>& args);
|
||||
};
|
||||
EntryInfo GetEntryInfo();
|
||||
|
||||
#define DEFINE_ENTRY_POINT(name, usage, entry_point) \
|
||||
poly::EntryInfo poly::GetEntryInfo() { return {name, usage, entry_point}; }
|
||||
|
||||
} // namespace poly
|
||||
|
||||
#endif // POLY_MAIN_H_
|
||||
41
src/poly/main_posix.cc
Normal file
41
src/poly/main_posix.cc
Normal file
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include <poly/main.h>
|
||||
|
||||
#include <poly/string.h>
|
||||
|
||||
namespace poly {
|
||||
|
||||
bool has_console_attached() {
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace poly
|
||||
|
||||
|
||||
extern "C" int main(int argc, char** argv) {
|
||||
auto entry_info = poly::GetEntryInfo();
|
||||
|
||||
google::SetUsageMessage(std::string("usage: ") +
|
||||
poly::to_string(entry_info.usage));
|
||||
google::SetVersionString("1.0");
|
||||
google::ParseCommandLineFlags(&argc, &argv, true);
|
||||
|
||||
std::vector<std::wstring> args;
|
||||
for (int n = 0; n < argc; n++) {
|
||||
args.push_back(poly::to_wstring(argv[n]));
|
||||
}
|
||||
|
||||
// Call app-provided entry point.
|
||||
int result = entry_info.entry_point(args);
|
||||
|
||||
google::ShutDownCommandLineFlags();
|
||||
return result;
|
||||
}
|
||||
105
src/poly/main_win.cc
Normal file
105
src/poly/main_win.cc
Normal file
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include <poly/main.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#include <shellapi.h>
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
#include <poly/string.h>
|
||||
|
||||
namespace poly {
|
||||
|
||||
bool has_console_attached_ = true;
|
||||
|
||||
bool has_console_attached() { return has_console_attached_; }
|
||||
|
||||
void AttachConsole() {
|
||||
bool has_console = ::AttachConsole(ATTACH_PARENT_PROCESS) == TRUE;
|
||||
if (!has_console) {
|
||||
// We weren't launched from a console, so just return.
|
||||
// We could alloc our own console, but meh:
|
||||
// has_console = AllocConsole() == TRUE;
|
||||
has_console_attached_ = false;
|
||||
return;
|
||||
}
|
||||
has_console_attached_ = true;
|
||||
|
||||
auto std_handle = (intptr_t)GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
auto con_handle = _open_osfhandle(std_handle, _O_TEXT);
|
||||
auto fp = _fdopen(con_handle, "w");
|
||||
*stdout = *fp;
|
||||
setvbuf(stdout, NULL, _IONBF, 0);
|
||||
|
||||
std_handle = (intptr_t)GetStdHandle(STD_ERROR_HANDLE);
|
||||
con_handle = _open_osfhandle(std_handle, _O_TEXT);
|
||||
fp = _fdopen(con_handle, "w");
|
||||
*stderr = *fp;
|
||||
setvbuf(stderr, NULL, _IONBF, 0);
|
||||
}
|
||||
|
||||
} // namespace poly
|
||||
|
||||
// Used in console mode apps; automatically picked based on subsystem.
|
||||
int wmain(int argc, wchar_t* argv[]) {
|
||||
auto entry_info = poly::GetEntryInfo();
|
||||
|
||||
google::SetUsageMessage(std::string("usage: ") +
|
||||
poly::to_string(entry_info.usage));
|
||||
google::SetVersionString("1.0");
|
||||
|
||||
// Convert all args to narrow, as gflags doesn't support wchar.
|
||||
int argca = argc;
|
||||
char** argva = (char**)alloca(sizeof(char*) * argca);
|
||||
for (int n = 0; n < argca; n++) {
|
||||
size_t len = wcslen(argv[n]);
|
||||
argva[n] = (char*)alloca(len + 1);
|
||||
wcstombs_s(NULL, argva[n], len + 1, argv[n], _TRUNCATE);
|
||||
}
|
||||
|
||||
// Parse flags; this may delete some of them.
|
||||
google::ParseCommandLineFlags(&argc, &argva, true);
|
||||
|
||||
// Widen all remaining flags and convert to usable strings.
|
||||
std::vector<std::wstring> args;
|
||||
for (int n = 0; n < argc; n++) {
|
||||
args.push_back(poly::to_wstring(argva[n]));
|
||||
}
|
||||
|
||||
// Call app-provided entry point.
|
||||
int result = entry_info.entry_point(args);
|
||||
|
||||
google::ShutDownCommandLineFlags();
|
||||
return result;
|
||||
}
|
||||
|
||||
// Used in windowed apps; automatically picked based on subsystem.
|
||||
int WINAPI wWinMain(HINSTANCE, HINSTANCE, LPWSTR command_line, int) {
|
||||
// Attach a console so we can write output to stdout. If the user hasn't
|
||||
// redirected output themselves it'll pop up a window.
|
||||
poly::AttachConsole();
|
||||
|
||||
auto entry_info = poly::GetEntryInfo();
|
||||
|
||||
// Convert to an argv-like format so we can share code/use gflags.
|
||||
std::wstring buffer = entry_info.name + L" " + command_line;
|
||||
int argc;
|
||||
wchar_t** argv = CommandLineToArgvW(buffer.c_str(), &argc);
|
||||
if (!argv) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Run normal entry point.
|
||||
int result = wmain(argc, argv);
|
||||
|
||||
LocalFree(argv);
|
||||
return result;
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef POLY_POLY_PRIVATE_H_
|
||||
#define POLY_POLY_PRIVATE_H_
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
|
||||
#endif // POLY_POLY_PRIVATE_H_
|
||||
@@ -1,13 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include <poly/poly.h>
|
||||
#include <poly/poly-private.h>
|
||||
|
||||
namespace poly {} // namespace poly
|
||||
@@ -7,13 +7,12 @@
|
||||
'debugging.h',
|
||||
'config.h',
|
||||
'cxx_compat.h',
|
||||
'main.h',
|
||||
'math.cc',
|
||||
'math.h',
|
||||
'memory.cc',
|
||||
'memory.h',
|
||||
'platform.h',
|
||||
'poly-private.h',
|
||||
'poly.cc',
|
||||
'poly.h',
|
||||
'string.cc',
|
||||
'string.h',
|
||||
@@ -23,6 +22,7 @@
|
||||
'conditions': [
|
||||
['OS == "mac" or OS == "linux"', {
|
||||
'sources': [
|
||||
'main_posix.cc',
|
||||
],
|
||||
}],
|
||||
['OS == "linux"', {
|
||||
@@ -39,6 +39,7 @@
|
||||
['OS == "win"', {
|
||||
'sources': [
|
||||
'debugging_win.cc',
|
||||
'main_win.cc',
|
||||
'threading_win.cc',
|
||||
],
|
||||
}],
|
||||
|
||||
@@ -39,4 +39,52 @@ std::string::size_type find_first_of_case(const std::string& target,
|
||||
}
|
||||
}
|
||||
|
||||
std::wstring to_absolute_path(const std::wstring& path) {
|
||||
#if XE_LIKE_WIN32
|
||||
wchar_t buffer[poly::max_path];
|
||||
_wfullpath(buffer, path.c_str(), sizeof(buffer) / sizeof(wchar_t));
|
||||
return buffer;
|
||||
#else
|
||||
char buffer[poly::max_path];
|
||||
realpath(poly::to_string(path).c_str(), buffer);
|
||||
return poly::to_wstring(buffer);
|
||||
#endif // XE_LIKE_WIN32
|
||||
}
|
||||
|
||||
std::wstring join_paths(const std::wstring& left, const std::wstring& right,
|
||||
wchar_t sep) {
|
||||
if (!left.size()) {
|
||||
return right;
|
||||
} else if (!right.size()) {
|
||||
return left;
|
||||
}
|
||||
if (left[left.size() - 1] == sep) {
|
||||
return left + right;
|
||||
} else {
|
||||
return left + sep + right;
|
||||
}
|
||||
}
|
||||
|
||||
std::wstring fix_path_separators(const std::wstring& source, wchar_t new_sep) {
|
||||
// Swap all separators to new_sep.
|
||||
wchar_t old_sep = new_sep == '\\' ? '/' : '\\';
|
||||
std::wstring::size_type pos = 0;
|
||||
std::wstring dest = source;
|
||||
while ((pos = source.find_first_of(old_sep, pos)) != std::wstring::npos) {
|
||||
dest[pos] = new_sep;
|
||||
++pos;
|
||||
}
|
||||
// Replace redundant separators.
|
||||
pos = 0;
|
||||
while ((pos = dest.find_first_of(new_sep, pos)) != std::wstring::npos) {
|
||||
if (pos < dest.size() - 1) {
|
||||
if (dest[pos + 1] == new_sep) {
|
||||
dest.erase(pos + 1, 1);
|
||||
}
|
||||
}
|
||||
++pos;
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
} // namespace poly
|
||||
|
||||
@@ -24,9 +24,22 @@ namespace poly {
|
||||
std::string to_string(const std::wstring& source);
|
||||
std::wstring to_wstring(const std::string& source);
|
||||
|
||||
// find_first_of string, case insensitive.
|
||||
std::string::size_type find_first_of_case(const std::string& target,
|
||||
const std::string& search);
|
||||
|
||||
// Converts the given path to an absolute path based on cwd.
|
||||
std::wstring to_absolute_path(const std::wstring& path);
|
||||
|
||||
// Joins two path segments with the given separator.
|
||||
std::wstring join_paths(const std::wstring& left, const std::wstring& right,
|
||||
wchar_t sep = poly::path_separator);
|
||||
|
||||
// Replaces all path separators with the given value and removes redundant
|
||||
// separators.
|
||||
std::wstring fix_path_separators(const std::wstring& source,
|
||||
wchar_t new_sep = poly::path_separator);
|
||||
|
||||
} // namespace poly
|
||||
|
||||
#endif // POLY_STRING_H_
|
||||
|
||||
Reference in New Issue
Block a user