Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 0 additions & 12 deletions src/native/corehost/hostmisc/pal.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

#include <string>
#include <vector>
#include <fstream>
#include <sstream>
#include <iostream>
#include <cstring>
Expand Down Expand Up @@ -118,14 +117,6 @@ namespace pal
typedef wchar_t char_t;
typedef std::wstring string_t;
typedef std::wstringstream stringstream_t;
// TODO: Agree on the correct encoding of the files: The PoR for now is to
// temporarily wchar for Windows and char for Unix. Current implementation
// implicitly expects the contents on both Windows and Unix as char and
// converts them to wchar in code for Windows. This line should become:
// typedef std::basic_ifstream<char_t> ifstream_t.
typedef std::basic_ifstream<char> ifstream_t;
typedef std::istreambuf_iterator<ifstream_t::char_type> istreambuf_iterator_t;
typedef std::basic_istream<char> istream_t;
typedef HRESULT hresult_t;
typedef HMODULE dll_t;
typedef FARPROC proc_t;
Expand Down Expand Up @@ -207,9 +198,6 @@ namespace pal
typedef char char_t;
typedef std::string string_t;
typedef std::stringstream stringstream_t;
typedef std::basic_ifstream<char> ifstream_t;
typedef std::istreambuf_iterator<ifstream_t::char_type> istreambuf_iterator_t;
typedef std::basic_istream<char> istream_t;
typedef int hresult_t;
typedef void* dll_t;
typedef void* proc_t;
Expand Down
18 changes: 5 additions & 13 deletions src/native/corehost/hostmisc/pal.unix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ bool get_install_location_from_file(const pal::string_t& file_path, bool& file_f
{
file_found = true;
bool install_location_found = false;
FILE* install_location_file = pal::file_open(file_path, "r");
FILE* install_location_file = pal::file_open(file_path, _X("r"));
if (install_location_file != nullptr)
{
if (!get_line_from_file(install_location_file, install_location))
Expand Down Expand Up @@ -819,12 +819,10 @@ pal::string_t pal::get_current_os_rid_platform()
{
// Read the file to get ID and VERSION_ID data that will be used
// to construct the RID.
std::fstream fsVersionFile;

fsVersionFile.open(versionFile, std::fstream::in);
FILE* fsVersionFile = pal::file_open(versionFile, _X("r"));

// Proceed only if we were able to open the file
if (fsVersionFile.good())
if (fsVersionFile != nullptr)
{
pal::string_t line;
pal::string_t strID(_X("ID="));
Expand All @@ -834,11 +832,8 @@ pal::string_t pal::get_current_os_rid_platform()

bool fFoundID = false, fFoundVersion = false;

// Read the first line
std::getline(fsVersionFile, line);

// Loop until we are at the end of file
while (!fsVersionFile.eof())
while (get_line_from_file(fsVersionFile, line))
{
// Look for ID if we have not found it already
if (!fFoundID)
Expand Down Expand Up @@ -872,13 +867,10 @@ pal::string_t pal::get_current_os_rid_platform()
// We have everything we need to form the RID - break out of the loop.
break;
}

// Read the next line
std::getline(fsVersionFile, line);
}

// Close the file now that we are done with it.
fsVersionFile.close();
fclose(fsVersionFile);

if (fFoundID)
{
Expand Down
91 changes: 37 additions & 54 deletions src/native/corehost/json_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,33 +17,9 @@

namespace {

// Try to match 0xEF 0xBB 0xBF byte sequence (no endianness here.)
std::streampos get_utf8_bom_length(pal::istream_t& stream)
{
if (stream.eof())
{
return 0;
}

auto peeked = stream.peek();
if (peeked == EOF || ((peeked & 0xFF) != 0xEF))
{
return 0;
}

unsigned char bytes[3];
stream.read(reinterpret_cast<char*>(bytes), 3);
if ((stream.gcount() < 3) || (bytes[1] != 0xBB) || (bytes[2] != 0xBF))
{
return 0;
}

return 3;
}

void get_line_column_from_offset(const char* data, uint64_t size, size_t offset, int *line, int *column)
{
assert(offset < size);
assert(offset <= size);

*line = *column = 1;

Expand All @@ -68,12 +44,6 @@ void get_line_column_from_offset(const char* data, uint64_t size, size_t offset,

} // empty namespace

void json_parser_t::realloc_buffer(size_t size)
{
m_json.resize(size + 1);
m_json[size] = '\0';
}

bool json_parser_t::parse_raw_data(char* data, int64_t size, const pal::string_t& context)
{
assert(data != nullptr);
Expand Down Expand Up @@ -115,51 +85,64 @@ bool json_parser_t::parse_file(const pal::string_t& path)
{
// This code assumes that the caller has checked that the file `path` exists
// either within the bundle, or as a real file on disk.
assert(m_bundle_data == nullptr);
assert(m_data == nullptr);
assert(m_bundle_location == nullptr);

if (bundle::info_t::is_single_file_bundle())
{
// Due to in-situ parsing on Linux,
// * The json file is mapped as copy-on-write.
// * The mapping cannot be immediately released, and will be unmapped by the json_parser destructor.
m_bundle_data = bundle::info_t::config_t::map(path, m_bundle_location);
m_data = bundle::info_t::config_t::map(path, m_bundle_location);

if (m_bundle_data != nullptr)
if (m_data != nullptr)
{
bool result = parse_raw_data(m_bundle_data, m_bundle_location->size, path);
return result;
m_size = (size_t)m_bundle_location->size;
}
}

pal::ifstream_t file{ path };
if (!file.good())
if (m_data == nullptr)
{
trace::error(_X("Cannot use file stream for [%s]: %s"), path.c_str(), pal::strerror(errno).c_str());
return false;
}
#ifdef _WIN32
// We can't use in-situ parsing on Windows, as JSON data is encoded in
// UTF-8 and the host expects wide strings.
// We do not need copy-on-write, so read-only mapping will be enough.
m_data = (char*)pal::mmap_read(path, &m_size);
#else // _WIN32
m_data = (char*)pal::mmap_copy_on_write(path, &m_size);
#endif // _WIN32

auto current_pos = ::get_utf8_bom_length(file);
file.seekg(0, file.end);
auto stream_size = file.tellg();
if (stream_size == -1)
{
trace::error(_X("Failed to get size of file [%s]"), path.c_str());
return false;
if (m_data == nullptr)
{
trace::error(_X("Cannot use file stream for [%s]: %s"), path.c_str(), pal::strerror(errno).c_str());
return false;
}
}

file.seekg(current_pos, file.beg);
char *data = m_data;
size_t size = m_size;

realloc_buffer(static_cast<size_t>(stream_size - current_pos));
file.read(m_json.data(), stream_size - current_pos);
// Skip over UTF-8 BOM, if present
if (size >= 3 && data[0] == 0xEF && data[1] == 0xBB && data[1] == 0xBF)
{
size -= 3;
data += 3;
}

return parse_raw_data(m_json.data(), m_json.size(), path);
return parse_raw_data(data, size, path);
}

json_parser_t::~json_parser_t()
{
if (m_bundle_data != nullptr)
if (m_data != nullptr)
{
bundle::info_t::config_t::unmap(m_bundle_data, m_bundle_location);
if (m_bundle_location != nullptr)
{
bundle::info_t::config_t::unmap(m_data, m_bundle_location);
}
else
{
pal::munmap((void*)m_data, m_size);
}
}
}
18 changes: 8 additions & 10 deletions src/native/corehost/json_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,24 +40,22 @@ class json_parser_t {
bool parse_file(const pal::string_t& path);

json_parser_t()
: m_bundle_data(nullptr)
: m_data(nullptr)
, m_bundle_location(nullptr) {}

~json_parser_t();

private:
// This is a vector of char and not pal::char_t because JSON data
// parsed by this class is always encoded in UTF-8. On Windows,
// where wide strings are used, m_json is kept in UTF-8, but converted
char* m_data; // The memory mapped bytes of the file
size_t m_size; // Size of the mapped memory

// On Windows, where wide strings are used, m_data is kept in UTF-8, but converted
// to UTF-16 by m_document during load.
std::vector<char> m_json;
document_t m_document;

// If a json file is parsed from a single-file bundle, the following two fields represent:
char* m_bundle_data; // The memory mapped bytes of the application bundle.
const bundle::location_t* m_bundle_location; // Location of this json file within the bundle.

void realloc_buffer(size_t size);
// If a json file is parsed from a single-file bundle, the following fields represents
// the location of this json file within the bundle.
const bundle::location_t* m_bundle_location;
};

#endif // __JSON_PARSER_H__
1 change: 1 addition & 0 deletions src/native/corehost/test/nativehost/host_context_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

#include <iostream>
#include <fstream>
#include <pal.h>
#include <error_codes.h>
#include <future>
Expand Down
Loading