Add new file streaming API

This commit is contained in:
Cole French
2019-07-10 13:12:09 -04:00
committed by Thomas Holder
parent 2d7d280b79
commit 73fdcdaca6
4 changed files with 156 additions and 56 deletions

View File

@@ -13,8 +13,14 @@
#include <stdlib.h>
#include "File.h"
#include "FileStream.h"
#include "MemoryDebug.h"
#include <fstream>
#include <string>
#include "pymol/zstring_view.h"
/*
* Get the size from the current file pointer to the end of the file
*/
@@ -84,3 +90,48 @@ char * FileGetContents(const char *filename, long *size) {
fclose(fp);
return contents;
}
namespace pymol
{
#ifdef _WIN32
std::wstring utf8_to_utf16(pymol::zstring_view utf8)
{
std::wstring utf16(utf8.size(), L'\0');
auto n = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8.c_str(), -1,
&utf16[0], utf16.size() + 1);
if (n == 0) {
throw std::runtime_error("Could not convert to UTF-16");
}
utf16.resize(n - 1);
return utf16;
}
#endif
static long istream_get_size(std::istream& file)
{
auto current = file.tellg();
file.seekg(0, std::ios::end);
auto filesize = file.tellg();
file.seekg(current);
return filesize;
}
static std::string istream_get_contents(std::istream& file)
{
auto filesize = istream_get_size(file);
std::string contents(filesize, '\0');
file.read(&contents[0], filesize);
return contents;
}
std::string file_get_contents(pymol::zstring_view filename)
{
std::ifstream file;
fstream_open(file, filename, std::ios::in | std::ios::binary);
return istream_get_contents(file);
}
} // namespace pymol

60
layer0/FileStream.h Normal file
View File

@@ -0,0 +1,60 @@
/*
* Copyright (c) Schrodinger, LLC.
*
* Basic file IO with C++ streams.
*/
#pragma once
#include <fstream>
#include <string>
#include "pymol/zstring_view.h"
namespace pymol
{
/**
* Reads entire file into a string
* @param filename Path in native filesystem encoding or UTF-8
* @throw ... If file cannot be opened
*/
std::string file_get_contents(pymol::zstring_view filename);
#ifdef _WIN32
/**
* Convert UTF-8 to UTF-16
* @throw ... If input is not valid UTF-8
*/
std::wstring utf8_to_utf16(pymol::zstring_view utf8);
#endif
/**
* File stream open wrapper with UTF-8 support on Windows. On Unix, this simply
* calls `stream.open`.
*
* @tparam T std::fstream, std::ifstream, std::ofstream, or a subclass
* @param stream Stream to open
* @param filename Path in native filesystem encoding or UTF-8
* @param mode see std::fstream::open
* @throw ... If file cannot be opened
*/
template <typename T>
void fstream_open(
T& stream, zstring_view filename, std::ios_base::openmode mode)
{
try {
stream.open(filename.data(), mode);
} catch (const std::ios_base::failure&) {
#ifdef _WIN32
// On Windows, failure may be due to filename being UTF-8
auto wfilename = utf8_to_utf16(filename);
// Windows overloads open to support a wchar_t array
stream.open(wfilename.c_str(), mode);
#else
throw;
#endif
}
}
} // namespace pymol
// vi:ft=cpp:sw=2

View File

@@ -27,7 +27,7 @@ Z* -------------------------------------------------------------------
#include"Util.h"
#include"Feedback.h"
#include"Parse.h"
#include"File.h"
#include"FileStream.h"
#ifndef int2
typedef int int2[2];
@@ -225,39 +225,40 @@ int MatchPreScore(CMatch * I, int *vla1, int n1, int *vla2, int n2, int quiet)
#define BLOSUM62_ROWS 33
#define BLOSUM62_COLS 80
static char blosum62[BLOSUM62_ROWS][BLOSUM62_COLS] = {
static const char blosum62[] = {
#if 0
"# Matrix made by matblas from blosum62.iij\n",
"# * column uses minimum score\n",
"# BLOSUM Clustered Scoring Matrix in 1/2 Bit Units\n",
"# Blocks Database = /data/blocks_5.0/blocks.dat\n",
"# Cluster Percentage: >= 62\n",
"# Entropy = 0.6979, Expected = -0.5209\n",
" A R N D C Q E G H I L K M F P S T W Y V B Z X *\n",
"A 4 -1 -2 -2 0 -1 -1 0 -2 -1 -1 -1 -1 -2 -1 1 0 -3 -2 0 -2 -1 0 -4\n",
"R -1 5 0 -2 -3 1 0 -2 0 -3 -2 2 -1 -3 -2 -1 -1 -3 -2 -3 -1 0 -1 -4\n",
"N -2 0 6 1 -3 0 0 0 1 -3 -3 0 -2 -3 -2 1 0 -4 -2 -3 3 0 -1 -4\n",
"D -2 -2 1 6 -3 0 2 -1 -1 -3 -4 -1 -3 -3 -1 0 -1 -4 -3 -3 4 1 -1 -4\n",
"C 0 -3 -3 -3 9 -3 -4 -3 -3 -1 -1 -3 -1 -2 -3 -1 -1 -2 -2 -1 -3 -3 -2 -4\n",
"Q -1 1 0 0 -3 5 2 -2 0 -3 -2 1 0 -3 -1 0 -1 -2 -1 -2 0 3 -1 -4\n",
"E -1 0 0 2 -4 2 5 -2 0 -3 -3 1 -2 -3 -1 0 -1 -3 -2 -2 1 4 -1 -4\n",
"G 0 -2 0 -1 -3 -2 -2 6 -2 -4 -4 -2 -3 -3 -2 0 -2 -2 -3 -3 -1 -2 -1 -4\n",
"H -2 0 1 -1 -3 0 0 -2 8 -3 -3 -1 -2 -1 -2 -1 -2 -2 2 -3 0 0 -1 -4\n",
"I -1 -3 -3 -3 -1 -3 -3 -4 -3 4 2 -3 1 0 -3 -2 -1 -3 -1 3 -3 -3 -1 -4\n",
"L -1 -2 -3 -4 -1 -2 -3 -4 -3 2 4 -2 2 0 -3 -2 -1 -2 -1 1 -4 -3 -1 -4\n",
"K -1 2 0 -1 -3 1 1 -2 -1 -3 -2 5 -1 -3 -1 0 -1 -3 -2 -2 0 1 -1 -4\n",
"M -1 -1 -2 -3 -1 0 -2 -3 -2 1 2 -1 5 0 -2 -1 -1 -1 -1 1 -3 -1 -1 -4\n",
"F -2 -3 -3 -3 -2 -3 -3 -3 -1 0 0 -3 0 6 -4 -2 -2 1 3 -1 -3 -3 -1 -4\n",
"P -1 -2 -2 -1 -3 -1 -1 -2 -2 -3 -3 -1 -2 -4 7 -1 -1 -4 -3 -2 -2 -1 -2 -4\n",
"S 1 -1 1 0 -1 0 0 0 -1 -2 -2 0 -1 -2 -1 4 1 -3 -2 -2 0 0 0 -4\n",
"T 0 -1 0 -1 -1 -1 -1 -2 -2 -1 -1 -1 -1 -2 -1 1 5 -2 -2 0 -1 -1 0 -4\n",
"W -3 -3 -4 -4 -2 -2 -3 -2 -2 -3 -2 -3 -1 1 -4 -3 -2 11 2 -3 -4 -3 -2 -4\n",
"Y -2 -2 -2 -3 -2 -1 -2 -3 2 -1 -1 -2 -1 3 -3 -2 -2 2 7 -1 -3 -2 -1 -4\n",
"V 0 -3 -3 -3 -1 -2 -2 -3 -3 3 1 -2 1 -1 -2 -2 0 -3 -1 4 -3 -2 -1 -4\n",
"B -2 -1 3 4 -3 0 1 -1 0 -3 -4 0 -3 -3 -2 0 -1 -4 -3 -3 4 1 -1 -4\n",
"Z -1 0 0 1 -3 3 4 -2 0 -3 -3 1 -1 -3 -1 0 -1 -3 -2 -2 1 4 -1 -4\n",
"X 0 -1 -1 -1 -2 -1 -1 -1 -1 -1 -1 -1 -1 -1 -2 0 0 -2 -1 -1 -1 -1 -1 -4\n",
"* -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 1\n",
""
#endif
" A R N D C Q E G H I L K M F P S T W Y V B Z X *\n"
"A 4 -1 -2 -2 0 -1 -1 0 -2 -1 -1 -1 -1 -2 -1 1 0 -3 -2 0 -2 -1 0 -4\n"
"R -1 5 0 -2 -3 1 0 -2 0 -3 -2 2 -1 -3 -2 -1 -1 -3 -2 -3 -1 0 -1 -4\n"
"N -2 0 6 1 -3 0 0 0 1 -3 -3 0 -2 -3 -2 1 0 -4 -2 -3 3 0 -1 -4\n"
"D -2 -2 1 6 -3 0 2 -1 -1 -3 -4 -1 -3 -3 -1 0 -1 -4 -3 -3 4 1 -1 -4\n"
"C 0 -3 -3 -3 9 -3 -4 -3 -3 -1 -1 -3 -1 -2 -3 -1 -1 -2 -2 -1 -3 -3 -2 -4\n"
"Q -1 1 0 0 -3 5 2 -2 0 -3 -2 1 0 -3 -1 0 -1 -2 -1 -2 0 3 -1 -4\n"
"E -1 0 0 2 -4 2 5 -2 0 -3 -3 1 -2 -3 -1 0 -1 -3 -2 -2 1 4 -1 -4\n"
"G 0 -2 0 -1 -3 -2 -2 6 -2 -4 -4 -2 -3 -3 -2 0 -2 -2 -3 -3 -1 -2 -1 -4\n"
"H -2 0 1 -1 -3 0 0 -2 8 -3 -3 -1 -2 -1 -2 -1 -2 -2 2 -3 0 0 -1 -4\n"
"I -1 -3 -3 -3 -1 -3 -3 -4 -3 4 2 -3 1 0 -3 -2 -1 -3 -1 3 -3 -3 -1 -4\n"
"L -1 -2 -3 -4 -1 -2 -3 -4 -3 2 4 -2 2 0 -3 -2 -1 -2 -1 1 -4 -3 -1 -4\n"
"K -1 2 0 -1 -3 1 1 -2 -1 -3 -2 5 -1 -3 -1 0 -1 -3 -2 -2 0 1 -1 -4\n"
"M -1 -1 -2 -3 -1 0 -2 -3 -2 1 2 -1 5 0 -2 -1 -1 -1 -1 1 -3 -1 -1 -4\n"
"F -2 -3 -3 -3 -2 -3 -3 -3 -1 0 0 -3 0 6 -4 -2 -2 1 3 -1 -3 -3 -1 -4\n"
"P -1 -2 -2 -1 -3 -1 -1 -2 -2 -3 -3 -1 -2 -4 7 -1 -1 -4 -3 -2 -2 -1 -2 -4\n"
"S 1 -1 1 0 -1 0 0 0 -1 -2 -2 0 -1 -2 -1 4 1 -3 -2 -2 0 0 0 -4\n"
"T 0 -1 0 -1 -1 -1 -1 -2 -2 -1 -1 -1 -1 -2 -1 1 5 -2 -2 0 -1 -1 0 -4\n"
"W -3 -3 -4 -4 -2 -2 -3 -2 -2 -3 -2 -3 -1 1 -4 -3 -2 11 2 -3 -4 -3 -2 -4\n"
"Y -2 -2 -2 -3 -2 -1 -2 -3 2 -1 -1 -2 -1 3 -3 -2 -2 2 7 -1 -3 -2 -1 -4\n"
"V 0 -3 -3 -3 -1 -2 -2 -3 -3 3 1 -2 1 -1 -2 -2 0 -3 -1 4 -3 -2 -1 -4\n"
"B -2 -1 3 4 -3 0 1 -1 0 -3 -4 0 -3 -3 -2 0 -1 -4 -3 -3 4 1 -1 -4\n"
"Z -1 0 0 1 -3 3 4 -2 0 -3 -3 1 -1 -3 -1 0 -1 -3 -2 -2 1 4 -1 -4\n"
"X 0 -1 -1 -1 -2 -1 -1 -1 -1 -1 -1 -1 -1 -1 -2 0 0 -2 -1 -1 -1 -1 -1 -4\n"
"* -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 1\n"
};
int MatchMatrixFromFile(CMatch * I, const char *fname, int quiet)
@@ -265,8 +266,8 @@ int MatchMatrixFromFile(CMatch * I, const char *fname, int quiet)
PyMOLGlobals *G = I->G;
int ok = 1;
char *buffer = NULL;
char *p;
std::string buffer;
const char *p;
char cc[255];
char *code = NULL;
unsigned int x, y;
@@ -279,32 +280,22 @@ int MatchMatrixFromFile(CMatch * I, const char *fname, int quiet)
&& !(strcmp(fname, "BLOSUM62") == 0)
#endif
) {
buffer = FileGetContents(fname, NULL);
if (!buffer) {
try {
buffer = pymol::file_get_contents(fname);
} catch (...) {
PRINTFB(G, FB_Match, FB_Errors)
" Match-Error: unable to open matrix file '%s'.\n", fname ENDFB(G);
ok = false;
}
} else {
buffer = pymol::malloc<char>(BLOSUM62_ROWS * BLOSUM62_COLS);
if(buffer) {
p = buffer;
a = 0;
while(blosum62[a][0]) {
strcpy(p, &blosum62[a][0]);
p += strlen(p);
a++;
}
} else {
ok = false;
}
buffer = blosum62;
}
if(ok && buffer) {
if(ok && !buffer.empty()) {
/* count codes */
p = buffer;
p = buffer.c_str();
n_entry = 0;
while(*p && ok) {
switch (*p) {
@@ -325,7 +316,7 @@ int MatchMatrixFromFile(CMatch * I, const char *fname, int quiet)
/* read codes */
p = buffer;
p = buffer.c_str();
n_entry = 0;
while(*p && ok) {
switch (*p) {
@@ -343,7 +334,7 @@ int MatchMatrixFromFile(CMatch * I, const char *fname, int quiet)
/* read values */
p = buffer;
p = buffer.c_str();
while((*p) && ok) {
switch (*p) {
case '#':
@@ -364,7 +355,6 @@ int MatchMatrixFromFile(CMatch * I, const char *fname, int quiet)
p = ParseNextLine(p);
}
}
mfree(buffer);
}
if(ok) {
if(!quiet) {

View File

@@ -31,7 +31,7 @@ Z* -------------------------------------------------------------------
#include "Util.h"
#include "Util2.h"
#include "Texture.h"
#include "File.h"
#include "FileStream.h"
#include "Matrix.h"
#include "Parse.h"
@@ -438,7 +438,7 @@ string CShaderMgr::GetShaderSource(const string &filename)
return it->second;
}
char* buffer = nullptr;
std::string buffer;
const char *pl = nullptr, *newpl, *tpl;
std::ostringstream newbuffer;
@@ -457,9 +457,10 @@ string CShaderMgr::GetShaderSource(const string &filename)
string path(pymol_data);
path.append(PATH_SEP).append("shaders").append(PATH_SEP).append(filename);
pl = buffer = FileGetContents(path.c_str(), nullptr);
if (!buffer) {
try {
buffer = pymol::file_get_contents(path);
pl = buffer.c_str();
} catch (...) {
PRINTFB(G, FB_ShaderMgr, FB_Warnings)
" Warning: shaders_from_dist=on, but unable to open file '%s'\n",
path.c_str() ENDFB(G);
@@ -547,8 +548,6 @@ string CShaderMgr::GetShaderSource(const string &filename)
}
}
FreeP(buffer);
string result = newbuffer.str();
shader_cache_processed[filename] = result;
return result;