static string GetExpandedShaderCode(const wchar* path, GrowableList<wstring>& filePaths) { for(uint64 i = 0; i < filePaths.Count(); ++i) if(filePaths[i] == path) return string(); filePaths.Add(path); string fileContents = ReadFileAsString(path); // Look for includes size_t lineStart = 0; while(true) { size_t lineEnd = fileContents.find('\n', lineStart); size_t lineLength = 0; if(lineEnd == string::npos) lineLength = string::npos; else lineLength = lineEnd - lineStart; string line = fileContents.substr(lineStart, lineLength); if(line.find("#include") == 0) { wstring fullIncludePath; size_t startQuote = line.find('\"'); if(startQuote != -1) { size_t endQuote = line.find('\"', startQuote + 1); string includePath = line.substr(startQuote + 1, endQuote - startQuote - 1); fullIncludePath = AnsiToWString(includePath.c_str()); } else { startQuote = line.find('<'); if(startQuote == -1) throw Exception(L"Malformed include statement: \"" + AnsiToWString(line.c_str()) + L"\" in file " + path); size_t endQuote = line.find('>', startQuote + 1); string includePath = line.substr(startQuote + 1, endQuote - startQuote - 1); fullIncludePath = SampleFrameworkDir() + L"Shaders\\" + AnsiToWString(includePath.c_str()); } if(FileExists(fullIncludePath.c_str()) == false) throw Exception(L"Couldn't find #included file \"" + fullIncludePath + L"\" in file " + path); string includeCode = GetExpandedShaderCode(fullIncludePath.c_str(), filePaths); fileContents.insert(lineEnd + 1, includeCode); lineEnd += includeCode.length(); } if(lineEnd == string::npos) break; lineStart = lineEnd + 1; } return fileContents; }
static string GetExpandedShaderCode(const wchar* path, vector<wstring>& filePaths) { for(uint64 i = 0; i < filePaths.size(); ++i) if(filePaths[i] == path) throw Exception(L"File \"" + wstring(path) + L" is recursively included"); filePaths.push_back(path); string fileContents = ReadFileAsString(path); wstring fileDirectory = GetDirectoryFromFilePath(path); // Look for includes size_t lineStart = 0; size_t lineEnd = std::string::npos; while(true) { size_t lineEnd = fileContents.find('\n', lineStart); size_t lineLength = 0; if(lineEnd == string::npos) lineLength = string::npos; else lineLength = lineEnd - lineStart; string line = fileContents.substr(lineStart, lineLength); if(line.find("#include") == 0) { size_t startQuote = line.find('\"'); size_t endQuote = line.find('\"', startQuote + 1); string includePath = line.substr(startQuote + 1, endQuote - startQuote - 1); wstring fullIncludePath = fileDirectory + AnsiToWString(includePath.c_str()); if(FileExists(fullIncludePath.c_str()) == false) throw Exception(L"Couldn't find #included file \"" + fullIncludePath + L"\""); string includeCode = GetExpandedShaderCode(fullIncludePath.c_str(), filePaths); fileContents.insert(lineEnd + 1, includeCode); lineEnd += includeCode.length(); } if(lineEnd == string::npos) break; lineStart = lineEnd + 1; } return fileContents; }
// Extract HTTP headers via temporary file with -D switch. // HTTP status code is extracted from curl output (-w switches). // Redirects are handled recursively. TODO(AlexZ): avoid infinite redirects loop. bool HttpClient::RunHttpRequest() { ScopedRemoveFile headers_deleter(GetTmpFileName()); ScopedRemoveFile body_deleter; ScopedRemoveFile received_file_deleter; string cmd = "curl -s -w '%{http_code}' -X " + m_httpMethod + " -D '" + headers_deleter.m_fileName + "' "; for (auto const & header : m_headers) { cmd += "-H '" + header.first + ": " + header.second + "' "; } if (!m_cookies.empty()) cmd += "-b '" + m_cookies + "' "; if (!m_bodyData.empty()) { body_deleter.m_fileName = GetTmpFileName(); // POST body through tmp file to avoid breaking command line. if (!WriteToFile(body_deleter.m_fileName, m_bodyData)) return false; // TODO(AlexZ): Correctly clean up this internal var to avoid client confusion. m_inputFile = body_deleter.m_fileName; } // Content-Length is added automatically by curl. if (!m_inputFile.empty()) cmd += "--data-binary '@" + m_inputFile + "' "; // Use temporary file to receive data from server. // If user has specified file name to save data, it is not temporary and is not deleted automatically. string rfile = m_outputFile; if (rfile.empty()) { rfile = GetTmpFileName(); received_file_deleter.m_fileName = rfile; } cmd += "-o " + rfile + strings::to_string(" ") + "'" + m_urlRequested + "'"; LOG(LDEBUG, ("Executing", cmd)); try { m_errorCode = stoi(RunCurl(cmd)); } catch (RootException const & ex) { LOG(LERROR, (ex.Msg())); return false; } m_headers.clear(); Headers const headers = ParseHeaders(ReadFileAsString(headers_deleter.m_fileName)); string serverCookies; string headerKey; for (auto const & header : headers) { if (header.first == "Set-Cookie") { serverCookies += header.second + ", "; } else { if (header.first == "Location") m_urlReceived = header.second; if (m_loadHeaders) { headerKey = header.first; strings::AsciiToLower(headerKey); m_headers.emplace(headerKey, header.second); } } } m_headers.emplace("Set-Cookie", NormalizeServerCookies(move(serverCookies))); if (m_urlReceived.empty()) { m_urlReceived = m_urlRequested; // Load body contents in final request only (skip redirects). // Sometimes server can reply with empty body, and it's ok. if (m_outputFile.empty()) m_serverResponse = ReadFileAsString(rfile); } else { // Handle HTTP redirect. // TODO(AlexZ): Should we check HTTP redirect code here? LOG(LDEBUG, ("HTTP redirect", m_errorCode, "to", m_urlReceived)); HttpClient redirect(m_urlReceived); redirect.SetCookies(CombinedCookies()); if (!redirect.RunHttpRequest()) { m_errorCode = -1; return false; } m_errorCode = redirect.ErrorCode(); m_urlReceived = redirect.UrlReceived(); m_headers = move(redirect.m_headers); m_serverResponse = move(redirect.m_serverResponse); } return true; }