"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "Common/OS.cpp" between
getdp-3.4.0-source.tgz and getdp-3.5.0-source.tgz

About: GetDP is a general finite element solver using mixed elements to discretize de Rham-type complexes in one, two and three dimensions.

OS.cpp  (getdp-3.4.0-source.tgz):OS.cpp  (getdp-3.5.0-source.tgz)
// GetDP - Copyright (C) 1997-2021 P. Dular and C. Geuzaine, University of Liege // GetDP - Copyright (C) 1997-2022 P. Dular and C. Geuzaine, University of Liege
// //
// See the LICENSE.txt file for license information. Please report all // See the LICENSE.txt file for license information. Please report all
// issues on https://gitlab.onelab.info/getdp/getdp/issues. // issues on https://gitlab.onelab.info/getdp/getdp/issues.
// This file contains a bunch of functions that depend on OS-dependent // This file contains a bunch of functions that depend on OS-dependent
// features and/or system calls // features and/or system calls
// these are available on all OSes // these are available on all OSes
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
skipping to change at line 47 skipping to change at line 47
#include <io.h> #include <io.h>
#include <sys/timeb.h> #include <sys/timeb.h>
#endif #endif
#include "Message.h" #include "Message.h"
#if defined(WIN32) && !defined(__CYGWIN__) #if defined(WIN32) && !defined(__CYGWIN__)
// Unicode utility routines borrowed from FLTK // Unicode utility routines borrowed from FLTK
static unsigned int utf8decode(const char* p, const char* end, int* len) static unsigned int utf8decode(const char *p, const char *end, int *len)
{ {
static unsigned short cp1252[32] = { static unsigned short cp1252[32] = {
0x20ac, 0x0081, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, 0x20ac, 0x0081, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021,
0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008d, 0x017d, 0x008f, 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008d, 0x017d, 0x008f,
0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x009d, 0x017e, 0x0178 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x009d, 0x017e, 0x0178};
}; unsigned char c = *(unsigned char *)p;
unsigned char c = *(unsigned char*)p; if(c < 0x80) {
if (c < 0x80) { if(len) *len = 1;
if (len) *len = 1;
return c; return c;
} else if (c < 0xa0) { }
if (len) *len = 1; else if(c < 0xa0) {
return cp1252[c-0x80]; if(len) *len = 1;
} else if (c < 0xc2) { return cp1252[c - 0x80];
}
else if(c < 0xc2) {
goto FAIL; goto FAIL;
} }
if ( (end && p+1 >= end) || (p[1]&0xc0) != 0x80) goto FAIL; if((end && p + 1 >= end) || (p[1] & 0xc0) != 0x80) goto FAIL;
if (c < 0xe0) { if(c < 0xe0) {
if (len) *len = 2; if(len) *len = 2;
return return ((p[0] & 0x1f) << 6) + ((p[1] & 0x3f));
((p[0] & 0x1f) << 6) + }
((p[1] & 0x3f)); else if(c == 0xe0) {
} else if (c == 0xe0) { if(((unsigned char *)p)[1] < 0xa0) goto FAIL;
if (((unsigned char*)p)[1] < 0xa0) goto FAIL;
goto UTF8_3; goto UTF8_3;
} else if (c < 0xf0) { }
else if(c < 0xf0) {
UTF8_3: UTF8_3:
if ( (end && p+2 >= end) || (p[2]&0xc0) != 0x80) goto FAIL; if((end && p + 2 >= end) || (p[2] & 0xc0) != 0x80) goto FAIL;
if (len) *len = 3; if(len) *len = 3;
return return ((p[0] & 0x0f) << 12) + ((p[1] & 0x3f) << 6) + ((p[2] & 0x3f));
((p[0] & 0x0f) << 12) + }
((p[1] & 0x3f) << 6) + else if(c == 0xf0) {
((p[2] & 0x3f)); if(((unsigned char *)p)[1] < 0x90) goto FAIL;
} else if (c == 0xf0) {
if (((unsigned char*)p)[1] < 0x90) goto FAIL;
goto UTF8_4; goto UTF8_4;
} else if (c < 0xf4) { }
else if(c < 0xf4) {
UTF8_4: UTF8_4:
if ( (end && p+3 >= end) || (p[2]&0xc0) != 0x80 || (p[3]&0xc0) != 0x80) goto if((end && p + 3 >= end) || (p[2] & 0xc0) != 0x80 || (p[3] & 0xc0) != 0x80)
FAIL; goto FAIL;
if (len) *len = 4; if(len) *len = 4;
return return ((p[0] & 0x07) << 18) + ((p[1] & 0x3f) << 12) +
((p[0] & 0x07) << 18) + ((p[2] & 0x3f) << 6) + ((p[3] & 0x3f));
((p[1] & 0x3f) << 12) + }
((p[2] & 0x3f) << 6) + else if(c == 0xf4) {
((p[3] & 0x3f)); if(((unsigned char *)p)[1] > 0x8f) goto FAIL; // after 0x10ffff
} else if (c == 0xf4) {
if (((unsigned char*)p)[1] > 0x8f) goto FAIL; // after 0x10ffff
goto UTF8_4; goto UTF8_4;
} else { }
else {
FAIL: FAIL:
if (len) *len = 1; if(len) *len = 1;
return c; return c;
} }
} }
static unsigned int utf8toUtf16(const char* src, unsigned int srclen, static unsigned int utf8toUtf16(const char *src, unsigned int srclen,
unsigned short* dst, unsigned int dstlen) unsigned short *dst, unsigned int dstlen)
{ {
const char* p = src; const char *p = src;
const char* e = src+srclen; const char *e = src + srclen;
unsigned int count = 0; unsigned int count = 0;
if (dstlen) for (;;) { if(dstlen)
if (p >= e) {dst[count] = 0; return count;} for(;;) {
if (!(*p & 0x80)) { // ascii if(p >= e) {
dst[count] = *p++; dst[count] = 0;
} else { return count;
int len; unsigned int ucs = utf8decode(p,e,&len); }
p += len; if(!(*p & 0x80)) { // ascii
if (ucs < 0x10000) { dst[count] = *p++;
dst[count] = ucs; }
} else { else {
// make a surrogate pair: int len;
if (count+2 >= dstlen) {dst[count] = 0; count += 2; break;} unsigned int ucs = utf8decode(p, e, &len);
dst[count] = (((ucs-0x10000u)>>10)&0x3ff) | 0xd800; p += len;
dst[++count] = (ucs&0x3ff) | 0xdc00; if(ucs < 0x10000) { dst[count] = ucs; }
else {
// make a surrogate pair:
if(count + 2 >= dstlen) {
dst[count] = 0;
count += 2;
break;
}
dst[count] = (((ucs - 0x10000u) >> 10) & 0x3ff) | 0xd800;
dst[++count] = (ucs & 0x3ff) | 0xdc00;
}
}
if(++count == dstlen) {
dst[count - 1] = 0;
break;
} }
} }
if (++count == dstlen) {dst[count-1] = 0; break;}
}
// we filled dst, measure the rest: // we filled dst, measure the rest:
while (p < e) { while(p < e) {
if (!(*p & 0x80)) p++; if(!(*p & 0x80))
p++;
else { else {
int len; unsigned int ucs = utf8decode(p,e,&len); int len;
unsigned int ucs = utf8decode(p, e, &len);
p += len; p += len;
if (ucs >= 0x10000) ++count; if(ucs >= 0x10000) ++count;
} }
++count; ++count;
} }
return count; return count;
} }
static unsigned int utf8FromUtf16(char* dst, unsigned int dstlen, static unsigned int utf8FromUtf16(char *dst, unsigned int dstlen,
const wchar_t* src, unsigned int srclen) const wchar_t *src, unsigned int srclen)
{ {
unsigned int i = 0; unsigned int i = 0;
unsigned int count = 0; unsigned int count = 0;
if (dstlen) { if(dstlen) {
for (;;) { for(;;) {
unsigned int ucs; unsigned int ucs;
if (i >= srclen) {dst[count] = 0; return count;} if(i >= srclen) {
dst[count] = 0;
return count;
}
ucs = src[i++]; ucs = src[i++];
if (ucs < 0x80U) { if(ucs < 0x80U) {
dst[count++] = ucs; dst[count++] = ucs;
if (count >= dstlen) {dst[count-1] = 0; break;} if(count >= dstlen) {
dst[count - 1] = 0;
break;
}
} }
else if (ucs < 0x800U) { /* 2 bytes */ else if(ucs < 0x800U) { /* 2 bytes */
if (count+2 >= dstlen) {dst[count] = 0; count += 2; break;} if(count + 2 >= dstlen) {
dst[count] = 0;
count += 2;
break;
}
dst[count++] = 0xc0 | (ucs >> 6); dst[count++] = 0xc0 | (ucs >> 6);
dst[count++] = 0x80 | (ucs & 0x3F); dst[count++] = 0x80 | (ucs & 0x3F);
} }
else if (ucs >= 0xd800 && ucs <= 0xdbff && i < srclen && else if(ucs >= 0xd800 && ucs <= 0xdbff && i < srclen &&
src[i] >= 0xdc00 && src[i] <= 0xdfff) { src[i] >= 0xdc00 && src[i] <= 0xdfff) {
/* surrogate pair */ /* surrogate pair */
unsigned int ucs2 = src[i++]; unsigned int ucs2 = src[i++];
ucs = 0x10000U + ((ucs&0x3ff)<<10) + (ucs2&0x3ff); ucs = 0x10000U + ((ucs & 0x3ff) << 10) + (ucs2 & 0x3ff);
/* all surrogate pairs turn into 4-byte utf8 */ /* all surrogate pairs turn into 4-byte utf8 */
if (count+4 >= dstlen) {dst[count] = 0; count += 4; break;} if(count + 4 >= dstlen) {
dst[count] = 0;
count += 4;
break;
}
dst[count++] = 0xf0 | (ucs >> 18); dst[count++] = 0xf0 | (ucs >> 18);
dst[count++] = 0x80 | ((ucs >> 12) & 0x3F); dst[count++] = 0x80 | ((ucs >> 12) & 0x3F);
dst[count++] = 0x80 | ((ucs >> 6) & 0x3F); dst[count++] = 0x80 | ((ucs >> 6) & 0x3F);
dst[count++] = 0x80 | (ucs & 0x3F); dst[count++] = 0x80 | (ucs & 0x3F);
} }
else { else {
/* all others are 3 bytes: */ /* all others are 3 bytes: */
if (count+3 >= dstlen) {dst[count] = 0; count += 3; break;} if(count + 3 >= dstlen) {
dst[count] = 0;
count += 3;
break;
}
dst[count++] = 0xe0 | (ucs >> 12); dst[count++] = 0xe0 | (ucs >> 12);
dst[count++] = 0x80 | ((ucs >> 6) & 0x3F); dst[count++] = 0x80 | ((ucs >> 6) & 0x3F);
dst[count++] = 0x80 | (ucs & 0x3F); dst[count++] = 0x80 | (ucs & 0x3F);
} }
} }
} }
/* we filled dst, measure the rest: */ /* we filled dst, measure the rest: */
while (i < srclen) { while(i < srclen) {
unsigned int ucs = src[i++]; unsigned int ucs = src[i++];
if (ucs < 0x80U) { if(ucs < 0x80U) { count++; }
count++; else if(ucs < 0x800U) { /* 2 bytes */
}
else if (ucs < 0x800U) { /* 2 bytes */
count += 2; count += 2;
} }
else if (ucs >= 0xd800 && ucs <= 0xdbff && i < srclen-1 && else if(ucs >= 0xd800 && ucs <= 0xdbff && i < srclen - 1 &&
src[i+1] >= 0xdc00 && src[i+1] <= 0xdfff) { src[i + 1] >= 0xdc00 && src[i + 1] <= 0xdfff) {
/* surrogate pair */ /* surrogate pair */
++i; ++i;
count += 4; count += 4;
} }
else { else {
count += 3; count += 3;
} }
} }
return count; return count;
} }
static wchar_t *wbuf[2] = {NULL, NULL}; static wchar_t *wbuf[2] = {NULL, NULL};
static void setwbuf(int i, const char *f) static void setwbuf(int i, const char *f)
{ {
// all strings in GetDP are supposed to be UTF8-encoded, which is natively // all strings in GetDP are supposed to be UTF8-encoded, which is natively
// supported by Mac and Linux. Windows does not support UTF-8, but UTF-16 // supported by Mac and Linux. Windows does not support UTF-8, but UTF-16
// (through wchar_t), so we need to convert. // (through wchar_t), so we need to convert.
if(i != 0 && i != 1) return; if(i != 0 && i != 1) return;
size_t l = strlen(f); size_t l = strlen(f);
unsigned int wn = utf8toUtf16(f, (unsigned int) l, NULL, 0) + 1; unsigned int wn = utf8toUtf16(f, (unsigned int)l, NULL, 0) + 1;
wbuf[i] = (wchar_t*)realloc(wbuf[i], sizeof(wchar_t)*wn); wbuf[i] = (wchar_t *)realloc(wbuf[i], sizeof(wchar_t) * wn);
wn = utf8toUtf16(f, (unsigned int) l, (unsigned short *)wbuf[i], wn); wn = utf8toUtf16(f, (unsigned int)l, (unsigned short *)wbuf[i], wn);
wbuf[i][wn] = 0; wbuf[i][wn] = 0;
} }
#endif #endif
FILE *FOpen(const char *f, const char *mode) FILE *FOpen(const char *f, const char *mode)
{ {
#if defined(HAVE_NX) && !defined(__APPLE__) #if defined(HAVE_NX) && !defined(__APPLE__)
return fopen64(f, mode); return fopen64(f, mode);
#elif defined (WIN32) && !defined(__CYGWIN__) #elif defined(WIN32) && !defined(__CYGWIN__)
setwbuf(0, f); setwbuf(0, f);
setwbuf(1, mode); setwbuf(1, mode);
return _wfopen(wbuf[0], wbuf[1]); return _wfopen(wbuf[0], wbuf[1]);
#else #else
return fopen(f, mode); return fopen(f, mode);
#endif #endif
} }
void GetResources(double *s, long *mem) void GetResources(double *s, long *mem)
{ {
#if defined(WIN32) && !defined(__CYGWIN__) #if defined(WIN32) && !defined(__CYGWIN__)
FILETIME creation, exit, kernel, user; FILETIME creation, exit, kernel, user;
if(GetProcessTimes(GetCurrentProcess(), &creation, &exit, &kernel, &user)){ if(GetProcessTimes(GetCurrentProcess(), &creation, &exit, &kernel, &user)) {
*s = 1.e-7 * 4294967296. * (double)user.dwHighDateTime + *s = 1.e-7 * 4294967296. * (double)user.dwHighDateTime +
1.e-7 * (double)user.dwLowDateTime; 1.e-7 * (double)user.dwLowDateTime;
} }
PROCESS_MEMORY_COUNTERS info; PROCESS_MEMORY_COUNTERS info;
GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info)); GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info));
*mem = (long)info.PeakWorkingSetSize; *mem = (long)info.PeakWorkingSetSize;
#else #else
static struct rusage r; static struct rusage r;
getrusage(RUSAGE_SELF, &r); getrusage(RUSAGE_SELF, &r);
*s = (double)r.ru_utime.tv_sec + 1.e-6 * (double)r.ru_utime.tv_usec; *s = (double)r.ru_utime.tv_sec + 1.e-6 * (double)r.ru_utime.tv_usec;
skipping to change at line 263 skipping to change at line 293
#endif #endif
} }
double GetTotalRam() double GetTotalRam()
{ {
double ram = 0; double ram = 0;
#if defined(__APPLE__) #if defined(__APPLE__)
int name[] = {CTL_HW, HW_MEMSIZE}; int name[] = {CTL_HW, HW_MEMSIZE};
int64_t value; int64_t value;
size_t len = sizeof(value); size_t len = sizeof(value);
if(sysctl(name, 2, &value, &len, NULL, 0) != -1) if(sysctl(name, 2, &value, &len, NULL, 0) != -1) ram = value / (1024 * 1024);
ram = value / (1024 * 1024); #elif defined(WIN32)
#elif defined (WIN32)
MEMORYSTATUSEX status; MEMORYSTATUSEX status;
status.dwLength = sizeof(status); status.dwLength = sizeof(status);
GlobalMemoryStatusEx(&status); GlobalMemoryStatusEx(&status);
ram = status.ullTotalPhys / ((double)1024 * 1024); ram = status.ullTotalPhys / ((double)1024 * 1024);
#elif defined(BUILD_ANDROID) #elif defined(BUILD_ANDROID)
ram = 1024; ram = 1024;
#elif defined(__linux__) #elif defined(__linux__)
struct sysinfo infos; struct sysinfo infos;
if(sysinfo(&infos) != -1) if(sysinfo(&infos) != -1)
ram = infos.totalram * (unsigned long)infos.mem_unit / ((double)1024 * 1024) ram =
; infos.totalram * (unsigned long)infos.mem_unit / ((double)1024 * 1024);
#endif #endif
return ram; return ram;
} }
double GetTimeOfDay() double GetTimeOfDay()
{ {
#if defined(WIN32) && !defined(__CYGWIN__) #if defined(WIN32) && !defined(__CYGWIN__)
struct _timeb localTime; struct _timeb localTime;
_ftime(&localTime); _ftime(&localTime);
return localTime.time + 1.e-3 * localTime.millitm; return localTime.time + 1.e-3 * localTime.millitm;
#else #else
struct timeval t; struct timeval t;
gettimeofday(&t, NULL); gettimeofday(&t, NULL);
return t.tv_sec + 1.e-6 * t.tv_usec; return t.tv_sec + 1.e-6 * t.tv_usec;
#endif #endif
} }
void IncreaseStackSize() void IncreaseStackSize()
{ {
#if !defined (WIN32) || defined(__CYGWIN__) #if !defined(WIN32) || defined(__CYGWIN__)
static struct rlimit r; static struct rlimit r;
getrlimit(RLIMIT_STACK, &r); getrlimit(RLIMIT_STACK, &r);
// Try to get at least 16 MB of stack. Running with too small a stack // Try to get at least 16 MB of stack. Running with too small a stack
// can cause crashes in the recursive calls (cf. Cal_Quantity) // can cause crashes in the recursive calls (cf. Cal_Quantity)
if(r.rlim_cur < 16 * 1024 * 1024){ if(r.rlim_cur < 16 * 1024 * 1024) {
Message::Info("Increasing process stack size (%d kB < 16 MB)", r.rlim_cur / Message::Info("Increasing process stack size (%d kB < 16 MB)",
1024); r.rlim_cur / 1024);
r.rlim_cur = r.rlim_max; r.rlim_cur = r.rlim_max;
setrlimit(RLIMIT_STACK, &r); setrlimit(RLIMIT_STACK, &r);
} }
#endif #endif
} }
void SleepSeconds(double s) void SleepSeconds(double s)
{ {
#if defined(WIN32) && !defined(__CYGWIN__) #if defined(WIN32) && !defined(__CYGWIN__)
Sleep((long)(1.e3 * s)); Sleep((long)(1.e3 * s));
skipping to change at line 327 skipping to change at line 358
} }
int BlockingSystemCall(const char *command) int BlockingSystemCall(const char *command)
{ {
#if defined(WIN32) #if defined(WIN32)
STARTUPINFO suInfo; STARTUPINFO suInfo;
PROCESS_INFORMATION prInfo; PROCESS_INFORMATION prInfo;
memset(&suInfo, 0, sizeof(suInfo)); memset(&suInfo, 0, sizeof(suInfo));
suInfo.cb = sizeof(suInfo); suInfo.cb = sizeof(suInfo);
Message::Info("Calling '%s'", command); Message::Info("Calling '%s'", command);
CreateProcess(NULL, (char*)command, NULL, NULL, FALSE, CreateProcess(NULL, (char *)command, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS,
NORMAL_PRIORITY_CLASS, NULL, NULL, &suInfo, &prInfo); NULL, NULL, &suInfo, &prInfo);
// wait until child process exits. // wait until child process exits.
WaitForSingleObject(prInfo.hProcess, INFINITE); WaitForSingleObject(prInfo.hProcess, INFINITE);
// close process and thread handles. // close process and thread handles.
CloseHandle(prInfo.hProcess); CloseHandle(prInfo.hProcess);
CloseHandle(prInfo.hThread); CloseHandle(prInfo.hThread);
return 0; return 0;
#elif(BUILD_IOS) #elif(BUILD_IOS)
Message::Warning("SystemCall is not supported on iOS"); Message::Warning("SystemCall is not supported on iOS");
#else #else
if(!system(NULL)) { if(!system(NULL)) {
skipping to change at line 407 skipping to change at line 438
do { do {
cur = dirName.find("/", cur + 1); cur = dirName.find("/", cur + 1);
if(!CreateDir(dirName.substr(0, cur))) ret = 0; if(!CreateDir(dirName.substr(0, cur))) ret = 0;
} while(cur != std::string::npos); } while(cur != std::string::npos);
return ret; return ret;
} }
static std::vector<std::string> splitFileName(const std::string &fileName) static std::vector<std::string> splitFileName(const std::string &fileName)
{ {
std::vector<std::string> s; s.resize(3); std::vector<std::string> s;
if(fileName.size()){ s.resize(3);
if(fileName.size()) {
// returns [path, baseName, extension] // returns [path, baseName, extension]
int idot = (int)fileName.find_last_of('.'); int idot = (int)fileName.find_last_of('.');
int islash = (int)fileName.find_last_of("/\\"); int islash = (int)fileName.find_last_of("/\\");
if(idot == (int)std::string::npos) idot = -1; if(idot == (int)std::string::npos) idot = -1;
if(islash == (int)std::string::npos) islash = -1; if(islash == (int)std::string::npos) islash = -1;
if(idot > 0) if(idot > 0) s[2] = fileName.substr(idot);
s[2] = fileName.substr(idot); if(islash > 0) s[0] = fileName.substr(0, islash + 1);
if(islash > 0) s[1] =
s[0] = fileName.substr(0, islash + 1); fileName.substr(s[0].size(), fileName.size() - s[0].size() - s[2].size());
s[1] = fileName.substr(s[0].size(), fileName.size() - s[0].size() - s[2].siz
e());
} }
return s; return s;
} }
std::string GetDirName(const std::string &fileName) std::string GetDirName(const std::string &fileName)
{ {
return splitFileName(fileName)[0]; return splitFileName(fileName)[0];
} }
std::string GetBaseName(const std::string &fileName) std::string GetBaseName(const std::string &fileName)
{ {
return splitFileName(fileName)[1]; return splitFileName(fileName)[1];
} }
std::string GetFullPath(const std::string &fileName) std::string GetFullPath(const std::string &fileName)
{ {
#if defined(WIN32) && !defined(__CYGWIN__) #if defined(WIN32) && !defined(__CYGWIN__)
setwbuf(0, fileName.c_str()); setwbuf(0, fileName.c_str());
wchar_t path[MAX_PATH]; wchar_t path[MAX_PATH];
unsigned long size = GetFullPathNameW(wbuf[0], MAX_PATH, path, NULL); unsigned long size = GetFullPathNameW(wbuf[0], MAX_PATH, path, NULL);
if(size){ if(size) {
char dst[MAX_PATH]; char dst[MAX_PATH];
utf8FromUtf16(dst, MAX_PATH, path, size); utf8FromUtf16(dst, MAX_PATH, path, size);
return std::string(dst); return std::string(dst);
} }
#else #else
char path[4096]; char path[4096];
if(realpath(fileName.c_str(), path)) if(realpath(fileName.c_str(), path)) return path;
return path;
#endif #endif
return fileName; return fileName;
} }
 End of changes. 45 change blocks. 
115 lines changed or deleted 141 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)