mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-08-21 22:04:56 -06:00
Core: Refactored Stream interface (dword->int), fixed LauchWebBrowser for certaion situations (thanks Koldo)
git-svn-id: svn://ultimatepp.org/upp/trunk@4759 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
4cc60f1340
commit
cfd894c242
10 changed files with 1212 additions and 1170 deletions
|
|
@ -391,12 +391,29 @@ void AppExit__()
|
|||
#endif
|
||||
}
|
||||
|
||||
#if defined(PLATFORM_WIN32) && !defined(PLATFORM_WINCE)
|
||||
static rawthread_t rawthread__ sShellExecuteOpen(void *str)
|
||||
{
|
||||
ShellExecuteW(NULL, L"open", (wchar *)str, NULL, L".", SW_SHOWDEFAULT);
|
||||
free(str);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LaunchWebBrowser(const String& url)
|
||||
{
|
||||
WString wurl = ToSystemCharsetW(url);
|
||||
if (int(ShellExecuteW(NULL, L"open", wurl, NULL, L".", SW_SHOWDEFAULT)) <= 32) {
|
||||
int l = 2 * wurl.GetLength() + 1;
|
||||
char *curl = (char *)malloc(l);
|
||||
memcpy(curl, wurl, l);
|
||||
StartRawThread(sShellExecuteOpen, curl);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PLATFORM_POSIX
|
||||
void LaunchWebBrowser(const String& url)
|
||||
{
|
||||
#if defined(PLATFORM_WIN32) && !defined(PLATFORM_WINCE)
|
||||
ShellExecute(NULL, "open", url, NULL, ".", SW_SHOWDEFAULT);
|
||||
#endif
|
||||
#ifdef PLATFORM_POSIX
|
||||
const char * browser[] = {
|
||||
"htmlview", "xdg-open", "x-www-browser", "firefox", "konqueror", "opera", "epiphany", "galeon", "netscape"
|
||||
};
|
||||
|
|
@ -407,8 +424,8 @@ void LaunchWebBrowser(const String& url)
|
|||
);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
String GetDataFile(const char *filename)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -586,4 +586,24 @@ LazyUpdate::LazyUpdate()
|
|||
|
||||
#endif
|
||||
|
||||
bool StartRawThread(rawthread_t (rawthread__ *fn)(void *ptr), void *ptr)
|
||||
{
|
||||
#ifdef PLATFORM_WIN32
|
||||
HANDLE handle;
|
||||
handle = (HANDLE)_beginthreadex(0, 0, fn, ptr, 0, NULL);
|
||||
if(handle) {
|
||||
CloseHandle(handle);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
#ifdef PLATFORM_POSIX
|
||||
pthread_t handle;
|
||||
if(pthread_create(&handle, 0, fn, ptr) == 0) {
|
||||
pthread_detach(handle);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -553,3 +553,45 @@ inline void AssertST() {}
|
|||
|
||||
typedef Mutex CriticalSection; // deprecated
|
||||
typedef StaticMutex StaticCriticalSection; // deprecated
|
||||
|
||||
// Raw multirthreading intended for use even in single-threaded applications
|
||||
// to resolve some host platform issues. Raw threads cannot use U++ heap
|
||||
|
||||
#ifdef PLATFORM_WIN32
|
||||
#define rawthread_t uintptr_t
|
||||
#define rawthread__ __stdcall
|
||||
#else
|
||||
#define rawthread_t void *
|
||||
#define rawthread__
|
||||
#endif
|
||||
|
||||
#ifdef PLATFORM_WIN32
|
||||
struct RawMutex {
|
||||
CRITICAL_SECTION cs;
|
||||
|
||||
void Enter() { EnterCriticalSection(&cs); }
|
||||
void Leave() { LeaveCriticalSection(&cs); }
|
||||
|
||||
RawMutex() { InitializeCriticalSection(&cs); }
|
||||
~RawMutex() { DeleteCriticalSection(&cs); }
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef PLATFORM_POSIX
|
||||
struct RawMutex {
|
||||
pthread_mutex_t mutex[1];
|
||||
|
||||
void Enter() { pthread_mutex_lock(mutex); }
|
||||
void Leave() { pthread_mutex_unlock(mutex); }
|
||||
|
||||
RawMutex() {
|
||||
pthread_mutexattr_t mutex_attr[1];
|
||||
pthread_mutexattr_init(mutex_attr);
|
||||
pthread_mutexattr_settype(mutex_attr, PTHREAD_MUTEX_RECURSIVE);
|
||||
pthread_mutex_init(mutex, mutex_attr);
|
||||
}
|
||||
~RawMutex() { pthread_mutex_destroy(mutex); }
|
||||
};
|
||||
#endif
|
||||
|
||||
bool StartRawThread(rawthread_t (rawthread__ *fn)(void *ptr), void *ptr);
|
||||
|
|
|
|||
4
uppsrc/Core/SSL/SSL.h
Normal file
4
uppsrc/Core/SSL/SSL.h
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
#ifndef _SSL_SSL_h
|
||||
#define _SSL_SSL_h
|
||||
|
||||
#endif
|
||||
1
uppsrc/Core/SSL/SSL.upp
Normal file
1
uppsrc/Core/SSL/SSL.upp
Normal file
|
|
@ -0,0 +1 @@
|
|||
file "SSL.h";
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -82,7 +82,7 @@ bool Stream::GetAll(void *data, dword size) {
|
|||
return true;
|
||||
}
|
||||
|
||||
String Stream::Get(dword size)
|
||||
String Stream::Get(int size)
|
||||
{
|
||||
StringBuffer b(size);
|
||||
int n = Get(~b, size);
|
||||
|
|
@ -417,8 +417,9 @@ void Stream::Put(Stream& s, int64 size, dword click) {
|
|||
}
|
||||
}
|
||||
|
||||
void Stream::SerializeRLE(byte *data, dword size)
|
||||
void Stream::SerializeRLE(byte *data, int size)
|
||||
{
|
||||
ASSERT(size >= 0);
|
||||
if(IsError()) return;
|
||||
byte *s = (byte *)data;
|
||||
byte *lim = s + size;
|
||||
|
|
@ -465,7 +466,8 @@ void Stream::SerializeRLE(byte *data, dword size)
|
|||
}
|
||||
}
|
||||
|
||||
void Stream::SerializeRaw(byte *data, dword size) {
|
||||
void Stream::SerializeRaw(byte *data, int size) {
|
||||
ASSERT(size >= 0);
|
||||
if(IsError()) return;
|
||||
if(IsLoading())
|
||||
GetAll(data, size);
|
||||
|
|
@ -473,7 +475,8 @@ void Stream::SerializeRaw(byte *data, dword size) {
|
|||
Put(data, size);
|
||||
}
|
||||
|
||||
void Stream::SerializeRaw(word *data, dword count) {
|
||||
void Stream::SerializeRaw(word *data, int count) {
|
||||
ASSERT(count >= 0);
|
||||
#ifdef CPU_BE
|
||||
EndianSwap(data, count);
|
||||
#endif
|
||||
|
|
@ -483,7 +486,8 @@ void Stream::SerializeRaw(word *data, dword count) {
|
|||
#endif
|
||||
}
|
||||
|
||||
void Stream::SerializeRaw(dword *data, dword count) {
|
||||
void Stream::SerializeRaw(dword *data, int count) {
|
||||
ASSERT(count >= 0);
|
||||
#ifdef CPU_BE
|
||||
EndianSwap(data, count);
|
||||
#endif
|
||||
|
|
@ -493,7 +497,8 @@ void Stream::SerializeRaw(dword *data, dword count) {
|
|||
#endif
|
||||
}
|
||||
|
||||
void Stream::SerializeRaw(uint64 *data, dword count) {
|
||||
void Stream::SerializeRaw(uint64 *data, int count) {
|
||||
ASSERT(count >= 0);
|
||||
#ifdef CPU_BE
|
||||
EndianSwap(data, count);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -80,16 +80,17 @@ public:
|
|||
|
||||
void Put(int c) { if(ptr < wrlim) *ptr++ = c; else _Put(c); }
|
||||
int Term() { return ptr < rdlim ? *ptr : _Term(); }
|
||||
int Peek() { return Term(); }
|
||||
int Get() { return ptr < rdlim ? *ptr++ : _Get(); }
|
||||
|
||||
const byte *Peek(int size = 1) { ASSERT(size > 0); return ptr + size <= rdlim ? ptr : NULL; }
|
||||
const byte *PeekPtr(int size = 1){ ASSERT(size > 0); return ptr + size <= rdlim ? ptr : NULL; }
|
||||
byte *PutPtr(int size = 1) { ASSERT(size > 0); if(ptr + size <= wrlim) { byte *p = ptr; ptr += size; return p; }; return NULL; }
|
||||
|
||||
void Put(const void *data, dword size) { if(ptr + size <= wrlim) { memcpy(ptr, data, size); ptr += size; } else _Put(data, size); }
|
||||
dword Get(void *data, dword size) { if(ptr + size <= rdlim) { memcpy(data, ptr, size); ptr += size; return size; } return _Get(data, size); }
|
||||
void Put(const void *data, int size) { ASSERT(size >= 0); if(ptr + size <= wrlim) { memcpy(ptr, data, size); ptr += size; } else _Put(data, size); }
|
||||
int Get(void *data, int size) { ASSERT(size >= 0); if(ptr + size <= rdlim) { memcpy(data, ptr, size); ptr += size; return size; } return _Get(data, size); }
|
||||
|
||||
void Put(const String& s) { Put((const char *) s, s.GetLength()); }
|
||||
String Get(dword size);
|
||||
void Put(const String& s) { Put((const char *) s, s.GetLength()); }
|
||||
String Get(int size);
|
||||
|
||||
void LoadThrowing() { style |= STRM_THROW; }
|
||||
void LoadError();
|
||||
|
|
@ -183,12 +184,12 @@ public:
|
|||
bool IsLoading() { return style & STRM_LOADING; }
|
||||
bool IsStoring() { return !IsLoading(); }
|
||||
|
||||
void SerializeRaw(byte *data, dword count);
|
||||
void SerializeRaw(word *data, dword count);
|
||||
void SerializeRaw(dword *data, dword count);
|
||||
void SerializeRaw(uint64 *data, dword count);
|
||||
void SerializeRaw(byte *data, int count);
|
||||
void SerializeRaw(word *data, int count);
|
||||
void SerializeRaw(dword *data, int count);
|
||||
void SerializeRaw(uint64 *data, int count);
|
||||
|
||||
void SerializeRLE(byte *data, dword count);
|
||||
void SerializeRLE(byte *data, int count);
|
||||
|
||||
Stream& operator%(bool& d);
|
||||
Stream& operator%(char& d);
|
||||
|
|
|
|||
|
|
@ -1,349 +1,349 @@
|
|||
String FormatIP(dword _ip);
|
||||
|
||||
String UrlEncode(const String& s);
|
||||
String UrlEncode(const String& s, const char *specials);
|
||||
String UrlDecode(const char *b, const char *e);
|
||||
inline String UrlDecode(const String& s) { return UrlDecode(s.Begin(), s.End() ); }
|
||||
|
||||
String Base64Encode(const char *b, const char *e);
|
||||
inline String Base64Encode(const String& data) { return Base64Encode(data.Begin(), data.End()); }
|
||||
String Base64Decode(const char *b, const char *e);
|
||||
inline String Base64Decode(const String& data) { return Base64Decode(data.Begin(), data.End()); }
|
||||
|
||||
#ifdef PLATFORM_WIN32
|
||||
#define rawthread_t uintptr_t
|
||||
#define rawthread__ __stdcall
|
||||
#else
|
||||
#define rawthread_t void *
|
||||
#define rawthread__
|
||||
#endif
|
||||
|
||||
class IpAddrInfo {
|
||||
enum { COUNT = 32 };
|
||||
struct Entry {
|
||||
const char *host;
|
||||
const char *port;
|
||||
int status;
|
||||
addrinfo *addr;
|
||||
};
|
||||
static Entry pool[COUNT];
|
||||
|
||||
enum {
|
||||
EMPTY = 0, WORKING, CANCELED, RESOLVED, FAILED
|
||||
};
|
||||
|
||||
String host, port;
|
||||
Entry *entry;
|
||||
Entry exe[1];
|
||||
|
||||
static void EnterPool();
|
||||
static void LeavePool();
|
||||
static rawthread_t rawthread__ Thread(void *ptr);
|
||||
|
||||
void Start();
|
||||
|
||||
public:
|
||||
void Start(const String& host, int port);
|
||||
bool InProgress();
|
||||
bool Execute(const String& host, int port);
|
||||
addrinfo *GetResult();
|
||||
void Clear();
|
||||
|
||||
IpAddrInfo();
|
||||
~IpAddrInfo() { Clear(); }
|
||||
};
|
||||
|
||||
enum { WAIT_READ = 1, WAIT_WRITE = 2, WAIT_EXCEPTION = 4, WAIT_ALL = 7 };
|
||||
|
||||
class TcpSocket {
|
||||
enum { BUFFERSIZE = 512 };
|
||||
SOCKET socket;
|
||||
char buffer[BUFFERSIZE];
|
||||
char *ptr;
|
||||
char *end;
|
||||
bool is_eof;
|
||||
bool is_error;
|
||||
bool is_abort;
|
||||
bool ipv6;
|
||||
|
||||
int timeout;
|
||||
int waitstep;
|
||||
int done;
|
||||
|
||||
int errorcode;
|
||||
String errordesc;
|
||||
|
||||
|
||||
SOCKET AcceptRaw(dword *ipaddr, int timeout_msec);
|
||||
bool Open(int family, int type, int protocol);
|
||||
int Recv(void *buffer, int maxlen);
|
||||
int Send(const void *buffer, int maxlen);
|
||||
bool RawConnect(addrinfo *info);
|
||||
|
||||
void ReadBuffer();
|
||||
int Get_();
|
||||
int Peek_();
|
||||
|
||||
void Reset();
|
||||
|
||||
void SetSockError(const char *context, const char *errdesc);
|
||||
void SetSockError(const char *context);
|
||||
|
||||
static int GetErrorCode();
|
||||
static bool WouldBlock();
|
||||
|
||||
public:
|
||||
Callback WhenWait;
|
||||
|
||||
static String GetHostName();
|
||||
|
||||
int GetDone() const { return done; }
|
||||
|
||||
static void Init();
|
||||
|
||||
bool IsOpen() const { return socket != INVALID_SOCKET; }
|
||||
bool IsEof() const { return is_eof && ptr == end; }
|
||||
|
||||
bool IsError() const { return is_error; }
|
||||
void ClearError() { is_error = false; errorcode = 0; errordesc.Clear(); }
|
||||
int GetError() const { return errorcode; }
|
||||
String GetErrorDesc() const { return errordesc; }
|
||||
|
||||
void Abort() { is_abort = true; }
|
||||
bool IsAbort() const { return is_abort; }
|
||||
void ClearAbort() { is_abort = false; }
|
||||
|
||||
SOCKET GetSOCKET() const { return socket; }
|
||||
String GetPeerAddr() const;
|
||||
|
||||
void Attach(SOCKET socket);
|
||||
bool Connect(const char *host, int port);
|
||||
bool Connect(IpAddrInfo& info);
|
||||
bool Listen(int port, int listen_count, bool ipv6 = false, bool reuse = true);
|
||||
bool Accept(TcpSocket& listen_socket);
|
||||
void Close();
|
||||
void Shutdown();
|
||||
|
||||
void NoDelay();
|
||||
void Linger(int msecs);
|
||||
void NoLinger() { Linger(Null); }
|
||||
void Reuse(bool reuse = true);
|
||||
|
||||
bool Wait(dword events);
|
||||
bool WaitRead() { return Wait(WAIT_READ); }
|
||||
bool WaitWrite() { return Wait(WAIT_WRITE); }
|
||||
|
||||
int Peek() { return ptr < end ? *ptr : Peek_(); }
|
||||
int Term() { return Peek(); }
|
||||
int Get() { return ptr < end ? *ptr++ : Get_(); }
|
||||
int Get(void *buffer, int len);
|
||||
String Get(int len);
|
||||
int GetAll(void *buffer, int len) { return Get(buffer, len) == len; }
|
||||
String GetAll(int len) { String s = Get(len); return s.GetCount() == len ? s : String::GetVoid(); }
|
||||
String GetLine(int maxlen = 2000000);
|
||||
|
||||
int Put(const char *s, int len);
|
||||
int Put(const String& s) { return Put(s.Begin(), s.GetLength()); }
|
||||
bool PutAll(const char *s, int len) { return Put(s, len) == len; }
|
||||
bool PutAll(const String& s) { return Put(s) == s.GetCount(); }
|
||||
|
||||
TcpSocket& Timeout(int ms) { timeout = ms; return *this; }
|
||||
int GetTimeout() const { return timeout; }
|
||||
TcpSocket& Blocking() { return Timeout(Null); }
|
||||
|
||||
TcpSocket();
|
||||
~TcpSocket() { Close(); }
|
||||
};
|
||||
|
||||
class SocketWaitEvent {
|
||||
Vector< Tuple2<int, dword> > socket;
|
||||
fd_set read[1], write[1], exception[1];
|
||||
|
||||
public:
|
||||
void Clear() { socket.Clear(); }
|
||||
void Add(SOCKET s, dword events = WAIT_ALL) { socket.Add(MakeTuple((int)s, events)); }
|
||||
void Add(TcpSocket& s, dword events = WAIT_ALL) { Add(s.GetSOCKET(), events); }
|
||||
int Wait(int timeout);
|
||||
dword Get(int i) const;
|
||||
dword operator[](int i) const { return Get(i); }
|
||||
|
||||
SocketWaitEvent();
|
||||
};
|
||||
|
||||
struct HttpHeader {
|
||||
String first_line;
|
||||
VectorMap<String, String> fields;
|
||||
|
||||
String operator[](const char *id) { return fields.Get(id, Null); }
|
||||
|
||||
bool Response(String& protocol, int& code, String& reason);
|
||||
bool Request(String& method, String& uri, String& version);
|
||||
|
||||
void Clear();
|
||||
bool Parse(const String& hdrs);
|
||||
};
|
||||
|
||||
class HttpRequest : public TcpSocket {
|
||||
int phase;
|
||||
String data;
|
||||
int count;
|
||||
|
||||
HttpHeader header;
|
||||
|
||||
String error;
|
||||
String body;
|
||||
|
||||
enum {
|
||||
DEFAULT_HTTP_PORT = 80,
|
||||
};
|
||||
|
||||
enum {
|
||||
METHOD_GET,
|
||||
METHOD_POST,
|
||||
METHOD_HEAD,
|
||||
METHOD_PUT,
|
||||
};
|
||||
|
||||
int max_header_size;
|
||||
int max_content_size;
|
||||
int max_redirects;
|
||||
int max_retries;
|
||||
int timeout;
|
||||
|
||||
String host;
|
||||
int port;
|
||||
String proxy_host;
|
||||
int proxy_port;
|
||||
String proxy_username;
|
||||
String proxy_password;
|
||||
String path;
|
||||
|
||||
int method;
|
||||
String accept;
|
||||
String agent;
|
||||
bool force_digest;
|
||||
bool is_post;
|
||||
bool std_headers;
|
||||
bool hasurlvar;
|
||||
String contenttype;
|
||||
String username;
|
||||
String password;
|
||||
String digest;
|
||||
String request_headers;
|
||||
String postdata;
|
||||
|
||||
String protocol;
|
||||
int status_code;
|
||||
String reason_phrase;
|
||||
|
||||
int start_time;
|
||||
int retry_count;
|
||||
int redirect_count;
|
||||
|
||||
int chunk;
|
||||
|
||||
IpAddrInfo addrinfo;
|
||||
int bodylen;
|
||||
bool gzip;
|
||||
Zlib z;
|
||||
|
||||
void Init();
|
||||
|
||||
void StartPhase(int s);
|
||||
void Start();
|
||||
void Dns();
|
||||
void StartRequest();
|
||||
bool SendingData();
|
||||
bool ReadingHeader();
|
||||
void StartBody();
|
||||
bool ReadingBody();
|
||||
void ReadingChunkHeader();
|
||||
void Finish();
|
||||
|
||||
void HttpError(const char *s);
|
||||
void ContentOut(const void *ptr, dword size);
|
||||
void Out(const void *ptr, dword size);
|
||||
|
||||
String CalculateDigest(const String& authenticate) const;
|
||||
|
||||
public:
|
||||
Callback2<const void *, dword> WhenContent;
|
||||
|
||||
HttpRequest& MaxHeaderSize(int m) { max_header_size = m; return *this; }
|
||||
HttpRequest& MaxContentSize(int m) { max_content_size = m; return *this; }
|
||||
HttpRequest& MaxRedirect(int n) { max_redirects = n; return *this; }
|
||||
HttpRequest& MaxRetries(int n) { max_retries = n; return *this; }
|
||||
HttpRequest& RequestTimeout(int ms) { timeout = ms; return *this; }
|
||||
HttpRequest& ChunkSize(int n) { chunk = n; return *this; }
|
||||
|
||||
HttpRequest& Method(int m) { method = m; return *this; }
|
||||
HttpRequest& GET() { return Method(METHOD_GET); }
|
||||
HttpRequest& POST() { return Method(METHOD_POST); }
|
||||
HttpRequest& HEAD() { return Method(METHOD_HEAD); }
|
||||
HttpRequest& PUT() { return Method(METHOD_PUT); }
|
||||
|
||||
HttpRequest& Host(const String& h) { host = h; return *this; }
|
||||
HttpRequest& Port(int p) { port = p; return *this; }
|
||||
HttpRequest& Path(const String& p) { path = p; return *this; }
|
||||
HttpRequest& User(const String& u, const String& p) { username = u; password = p; return *this; }
|
||||
HttpRequest& Digest() { force_digest = true; return *this; }
|
||||
HttpRequest& Digest(const String& d) { digest = d; return *this; }
|
||||
HttpRequest& Url(const char *url);
|
||||
HttpRequest& UrlVar(const char *id, const String& data);
|
||||
HttpRequest& operator()(const char *id, const String& data) { return UrlVar(id, data); }
|
||||
HttpRequest& PostData(const String& pd) { postdata = pd; return *this; }
|
||||
HttpRequest& PostUData(const String& pd) { return PostData(UrlEncode(pd)); }
|
||||
HttpRequest& Post(const String& data) { POST(); return PostData(data); }
|
||||
HttpRequest& Post(const char *id, const String& data);
|
||||
|
||||
HttpRequest& Headers(const String& h) { request_headers = h; return *this; }
|
||||
HttpRequest& ClearHeaders() { return Headers(Null); }
|
||||
HttpRequest& AddHeaders(const String& h) { request_headers.Cat(h); return *this; }
|
||||
HttpRequest& Header(const char *id, const String& data);
|
||||
|
||||
HttpRequest& StdHeaders(bool sh) { std_headers = sh; return *this; }
|
||||
HttpRequest& NoStdHeaders() { return StdHeaders(false); }
|
||||
HttpRequest& Accept(const String& a) { accept = a; return *this; }
|
||||
HttpRequest& Agent(const String& a) { agent = a; return *this; }
|
||||
HttpRequest& ContentType(const String& a) { contenttype = a; return *this; }
|
||||
|
||||
HttpRequest& Proxy(const String& host, int port) { proxy_host = host; proxy_port = port; return *this; }
|
||||
HttpRequest& Proxy(const char *url);
|
||||
HttpRequest& ProxyAuth(const String& u, const String& p) { proxy_username = u; proxy_password = p; return *this; }
|
||||
|
||||
bool IsSocketError() const { return TcpSocket::IsError(); }
|
||||
bool IsHttpError() const { return !IsNull(error) ; }
|
||||
bool IsError() const { return IsSocketError() || IsHttpError(); }
|
||||
String GetErrorDesc() const { return IsSocketError() ? TcpSocket::GetErrorDesc() : error; }
|
||||
void ClearError() { TcpSocket::ClearError(); error.Clear(); }
|
||||
|
||||
String GetHeader(const char *s) { return header[s]; }
|
||||
String operator[](const char *s) { return GetHeader(s); }
|
||||
String GetRedirectUrl();
|
||||
int GetContentLength();
|
||||
int GetStatusCode() const { return status_code; }
|
||||
String GetReasonPhrase() const { return reason_phrase; }
|
||||
|
||||
String GetContent() const { return body; }
|
||||
String operator~() const { return GetContent(); }
|
||||
operator String() const { return GetContent(); }
|
||||
void ClearContent() { body.Clear(); }
|
||||
|
||||
enum Phase {
|
||||
START, DNS, REQUEST, HEADER, BODY, CHUNK_HEADER, CHUNK_BODY, TRAILER, FINISHED, FAILED
|
||||
};
|
||||
|
||||
bool Do();
|
||||
int GetPhase() const { return phase; }
|
||||
String GetPhaseName() const;
|
||||
bool InProgress() const { return phase != FAILED && phase != FINISHED; }
|
||||
bool IsFailure() const { return phase == FAILED; }
|
||||
bool IsSuccess() const { return phase == FINISHED && status_code >= 200 && status_code < 300; }
|
||||
|
||||
String Execute();
|
||||
|
||||
HttpRequest();
|
||||
HttpRequest(const char *url);
|
||||
|
||||
static void Trace(bool b = true);
|
||||
};
|
||||
String FormatIP(dword _ip);
|
||||
|
||||
String UrlEncode(const String& s);
|
||||
String UrlEncode(const String& s, const char *specials);
|
||||
String UrlDecode(const char *b, const char *e);
|
||||
inline String UrlDecode(const String& s) { return UrlDecode(s.Begin(), s.End() ); }
|
||||
|
||||
String Base64Encode(const char *b, const char *e);
|
||||
inline String Base64Encode(const String& data) { return Base64Encode(data.Begin(), data.End()); }
|
||||
String Base64Decode(const char *b, const char *e);
|
||||
inline String Base64Decode(const String& data) { return Base64Decode(data.Begin(), data.End()); }
|
||||
|
||||
class IpAddrInfo {
|
||||
enum { COUNT = 32 };
|
||||
struct Entry {
|
||||
const char *host;
|
||||
const char *port;
|
||||
int status;
|
||||
addrinfo *addr;
|
||||
};
|
||||
static Entry pool[COUNT];
|
||||
|
||||
enum {
|
||||
EMPTY = 0, WORKING, CANCELED, RESOLVED, FAILED
|
||||
};
|
||||
|
||||
String host, port;
|
||||
Entry *entry;
|
||||
Entry exe[1];
|
||||
|
||||
static void EnterPool();
|
||||
static void LeavePool();
|
||||
static rawthread_t rawthread__ Thread(void *ptr);
|
||||
|
||||
void Start();
|
||||
|
||||
public:
|
||||
void Start(const String& host, int port);
|
||||
bool InProgress();
|
||||
bool Execute(const String& host, int port);
|
||||
addrinfo *GetResult();
|
||||
void Clear();
|
||||
|
||||
IpAddrInfo();
|
||||
~IpAddrInfo() { Clear(); }
|
||||
};
|
||||
|
||||
enum { WAIT_READ = 1, WAIT_WRITE = 2, WAIT_EXCEPTION = 4, WAIT_ALL = 7 };
|
||||
|
||||
class TcpSocket {
|
||||
enum { BUFFERSIZE = 512 };
|
||||
SOCKET socket;
|
||||
char buffer[BUFFERSIZE];
|
||||
char *ptr;
|
||||
char *end;
|
||||
bool is_eof;
|
||||
bool is_error;
|
||||
bool is_abort;
|
||||
bool ipv6;
|
||||
|
||||
int timeout;
|
||||
int waitstep;
|
||||
int done;
|
||||
|
||||
int errorcode;
|
||||
String errordesc;
|
||||
|
||||
struct SSLBase {
|
||||
virtual void Secure(TcpSocket& s) = 0;
|
||||
virtual void Send(TcpSocket& s) = 0;
|
||||
virtual void Recv(TcpSocket& s) = 0;
|
||||
};
|
||||
|
||||
One<SSLBase> ssl;
|
||||
|
||||
SOCKET AcceptRaw(dword *ipaddr, int timeout_msec);
|
||||
bool Open(int family, int type, int protocol);
|
||||
int Recv(void *buffer, int maxlen);
|
||||
int Send(const void *buffer, int maxlen);
|
||||
bool RawConnect(addrinfo *info);
|
||||
void CreateSSL();
|
||||
|
||||
void ReadBuffer();
|
||||
int Get_();
|
||||
int Peek_();
|
||||
|
||||
void Reset();
|
||||
|
||||
void SetSockError(const char *context, const char *errdesc);
|
||||
void SetSockError(const char *context);
|
||||
|
||||
static int GetErrorCode();
|
||||
static bool WouldBlock();
|
||||
|
||||
public:
|
||||
Callback WhenWait;
|
||||
|
||||
static String GetHostName();
|
||||
|
||||
int GetDone() const { return done; }
|
||||
|
||||
static void Init();
|
||||
|
||||
bool IsOpen() const { return socket != INVALID_SOCKET; }
|
||||
bool IsEof() const { return is_eof && ptr == end; }
|
||||
|
||||
bool IsError() const { return is_error; }
|
||||
void ClearError() { is_error = false; errorcode = 0; errordesc.Clear(); }
|
||||
int GetError() const { return errorcode; }
|
||||
String GetErrorDesc() const { return errordesc; }
|
||||
|
||||
void Abort() { is_abort = true; }
|
||||
bool IsAbort() const { return is_abort; }
|
||||
void ClearAbort() { is_abort = false; }
|
||||
|
||||
SOCKET GetSOCKET() const { return socket; }
|
||||
String GetPeerAddr() const;
|
||||
|
||||
void Attach(SOCKET socket);
|
||||
bool Connect(const char *host, int port);
|
||||
bool Connect(IpAddrInfo& info);
|
||||
bool Listen(int port, int listen_count, bool ipv6 = false, bool reuse = true);
|
||||
bool Accept(TcpSocket& listen_socket);
|
||||
void Close();
|
||||
void Shutdown();
|
||||
|
||||
void NoDelay();
|
||||
void Linger(int msecs);
|
||||
void NoLinger() { Linger(Null); }
|
||||
void Reuse(bool reuse = true);
|
||||
|
||||
bool Wait(dword events);
|
||||
bool WaitRead() { return Wait(WAIT_READ); }
|
||||
bool WaitWrite() { return Wait(WAIT_WRITE); }
|
||||
|
||||
int Peek() { return ptr < end ? *ptr : Peek_(); }
|
||||
int Term() { return Peek(); }
|
||||
int Get() { return ptr < end ? *ptr++ : Get_(); }
|
||||
int Get(void *buffer, int len);
|
||||
String Get(int len);
|
||||
int GetAll(void *buffer, int len) { return Get(buffer, len) == len; }
|
||||
String GetAll(int len) { String s = Get(len); return s.GetCount() == len ? s : String::GetVoid(); }
|
||||
String GetLine(int maxlen = 2000000);
|
||||
|
||||
int Put(const char *s, int len);
|
||||
int Put(const String& s) { return Put(s.Begin(), s.GetLength()); }
|
||||
bool PutAll(const char *s, int len) { return Put(s, len) == len; }
|
||||
bool PutAll(const String& s) { return Put(s) == s.GetCount(); }
|
||||
|
||||
TcpSocket& Timeout(int ms) { timeout = ms; return *this; }
|
||||
int GetTimeout() const { return timeout; }
|
||||
TcpSocket& Blocking() { return Timeout(Null); }
|
||||
|
||||
TcpSocket();
|
||||
~TcpSocket() { Close(); }
|
||||
};
|
||||
|
||||
class SocketWaitEvent {
|
||||
Vector< Tuple2<int, dword> > socket;
|
||||
fd_set read[1], write[1], exception[1];
|
||||
|
||||
public:
|
||||
void Clear() { socket.Clear(); }
|
||||
void Add(SOCKET s, dword events = WAIT_ALL) { socket.Add(MakeTuple((int)s, events)); }
|
||||
void Add(TcpSocket& s, dword events = WAIT_ALL) { Add(s.GetSOCKET(), events); }
|
||||
int Wait(int timeout);
|
||||
dword Get(int i) const;
|
||||
dword operator[](int i) const { return Get(i); }
|
||||
|
||||
SocketWaitEvent();
|
||||
};
|
||||
|
||||
struct HttpHeader {
|
||||
String first_line;
|
||||
VectorMap<String, String> fields;
|
||||
|
||||
String operator[](const char *id) { return fields.Get(id, Null); }
|
||||
|
||||
bool Response(String& protocol, int& code, String& reason);
|
||||
bool Request(String& method, String& uri, String& version);
|
||||
|
||||
void Clear();
|
||||
bool Parse(const String& hdrs);
|
||||
};
|
||||
|
||||
class HttpRequest : public TcpSocket {
|
||||
int phase;
|
||||
String data;
|
||||
int count;
|
||||
|
||||
HttpHeader header;
|
||||
|
||||
String error;
|
||||
String body;
|
||||
|
||||
enum {
|
||||
DEFAULT_HTTP_PORT = 80,
|
||||
};
|
||||
|
||||
enum {
|
||||
METHOD_GET,
|
||||
METHOD_POST,
|
||||
METHOD_HEAD,
|
||||
METHOD_PUT,
|
||||
};
|
||||
|
||||
int max_header_size;
|
||||
int max_content_size;
|
||||
int max_redirects;
|
||||
int max_retries;
|
||||
int timeout;
|
||||
|
||||
String host;
|
||||
int port;
|
||||
String proxy_host;
|
||||
int proxy_port;
|
||||
String proxy_username;
|
||||
String proxy_password;
|
||||
String path;
|
||||
|
||||
int method;
|
||||
String accept;
|
||||
String agent;
|
||||
bool force_digest;
|
||||
bool is_post;
|
||||
bool std_headers;
|
||||
bool hasurlvar;
|
||||
String contenttype;
|
||||
String username;
|
||||
String password;
|
||||
String digest;
|
||||
String request_headers;
|
||||
String postdata;
|
||||
|
||||
String protocol;
|
||||
int status_code;
|
||||
String reason_phrase;
|
||||
|
||||
int start_time;
|
||||
int retry_count;
|
||||
int redirect_count;
|
||||
|
||||
int chunk;
|
||||
|
||||
IpAddrInfo addrinfo;
|
||||
int bodylen;
|
||||
bool gzip;
|
||||
Zlib z;
|
||||
|
||||
void Init();
|
||||
|
||||
void StartPhase(int s);
|
||||
void Start();
|
||||
void Dns();
|
||||
void StartRequest();
|
||||
bool SendingData();
|
||||
bool ReadingHeader();
|
||||
void StartBody();
|
||||
bool ReadingBody();
|
||||
void ReadingChunkHeader();
|
||||
void Finish();
|
||||
|
||||
void HttpError(const char *s);
|
||||
void ContentOut(const void *ptr, dword size);
|
||||
void Out(const void *ptr, dword size);
|
||||
|
||||
String CalculateDigest(const String& authenticate) const;
|
||||
|
||||
public:
|
||||
Callback2<const void *, dword> WhenContent;
|
||||
|
||||
HttpRequest& MaxHeaderSize(int m) { max_header_size = m; return *this; }
|
||||
HttpRequest& MaxContentSize(int m) { max_content_size = m; return *this; }
|
||||
HttpRequest& MaxRedirect(int n) { max_redirects = n; return *this; }
|
||||
HttpRequest& MaxRetries(int n) { max_retries = n; return *this; }
|
||||
HttpRequest& RequestTimeout(int ms) { timeout = ms; return *this; }
|
||||
HttpRequest& ChunkSize(int n) { chunk = n; return *this; }
|
||||
|
||||
HttpRequest& Method(int m) { method = m; return *this; }
|
||||
HttpRequest& GET() { return Method(METHOD_GET); }
|
||||
HttpRequest& POST() { return Method(METHOD_POST); }
|
||||
HttpRequest& HEAD() { return Method(METHOD_HEAD); }
|
||||
HttpRequest& PUT() { return Method(METHOD_PUT); }
|
||||
|
||||
HttpRequest& Host(const String& h) { host = h; return *this; }
|
||||
HttpRequest& Port(int p) { port = p; return *this; }
|
||||
HttpRequest& Path(const String& p) { path = p; return *this; }
|
||||
HttpRequest& User(const String& u, const String& p) { username = u; password = p; return *this; }
|
||||
HttpRequest& Digest() { force_digest = true; return *this; }
|
||||
HttpRequest& Digest(const String& d) { digest = d; return *this; }
|
||||
HttpRequest& Url(const char *url);
|
||||
HttpRequest& UrlVar(const char *id, const String& data);
|
||||
HttpRequest& operator()(const char *id, const String& data) { return UrlVar(id, data); }
|
||||
HttpRequest& PostData(const String& pd) { postdata = pd; return *this; }
|
||||
HttpRequest& PostUData(const String& pd) { return PostData(UrlEncode(pd)); }
|
||||
HttpRequest& Post(const String& data) { POST(); return PostData(data); }
|
||||
HttpRequest& Post(const char *id, const String& data);
|
||||
|
||||
HttpRequest& Headers(const String& h) { request_headers = h; return *this; }
|
||||
HttpRequest& ClearHeaders() { return Headers(Null); }
|
||||
HttpRequest& AddHeaders(const String& h) { request_headers.Cat(h); return *this; }
|
||||
HttpRequest& Header(const char *id, const String& data);
|
||||
|
||||
HttpRequest& StdHeaders(bool sh) { std_headers = sh; return *this; }
|
||||
HttpRequest& NoStdHeaders() { return StdHeaders(false); }
|
||||
HttpRequest& Accept(const String& a) { accept = a; return *this; }
|
||||
HttpRequest& Agent(const String& a) { agent = a; return *this; }
|
||||
HttpRequest& ContentType(const String& a) { contenttype = a; return *this; }
|
||||
|
||||
HttpRequest& Proxy(const String& host, int port) { proxy_host = host; proxy_port = port; return *this; }
|
||||
HttpRequest& Proxy(const char *url);
|
||||
HttpRequest& ProxyAuth(const String& u, const String& p) { proxy_username = u; proxy_password = p; return *this; }
|
||||
|
||||
bool IsSocketError() const { return TcpSocket::IsError(); }
|
||||
bool IsHttpError() const { return !IsNull(error) ; }
|
||||
bool IsError() const { return IsSocketError() || IsHttpError(); }
|
||||
String GetErrorDesc() const { return IsSocketError() ? TcpSocket::GetErrorDesc() : error; }
|
||||
void ClearError() { TcpSocket::ClearError(); error.Clear(); }
|
||||
|
||||
String GetHeader(const char *s) { return header[s]; }
|
||||
String operator[](const char *s) { return GetHeader(s); }
|
||||
String GetRedirectUrl();
|
||||
int GetContentLength();
|
||||
int GetStatusCode() const { return status_code; }
|
||||
String GetReasonPhrase() const { return reason_phrase; }
|
||||
|
||||
String GetContent() const { return body; }
|
||||
String operator~() const { return GetContent(); }
|
||||
operator String() const { return GetContent(); }
|
||||
void ClearContent() { body.Clear(); }
|
||||
|
||||
enum Phase {
|
||||
START, DNS, REQUEST, HEADER, BODY, CHUNK_HEADER, CHUNK_BODY, TRAILER, FINISHED, FAILED
|
||||
};
|
||||
|
||||
bool Do();
|
||||
int GetPhase() const { return phase; }
|
||||
String GetPhaseName() const;
|
||||
bool InProgress() const { return phase != FAILED && phase != FINISHED; }
|
||||
bool IsFailure() const { return phase == FAILED; }
|
||||
bool IsSuccess() const { return phase == FINISHED && status_code >= 200 && status_code < 300; }
|
||||
|
||||
String Execute();
|
||||
|
||||
HttpRequest();
|
||||
HttpRequest(const char *url);
|
||||
|
||||
static void Trace(bool b = true);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -324,15 +324,15 @@ by GetLastError call in Win32 or in errno in Posix). This error
|
|||
can be interpreted by GetErrorMessage function.&]
|
||||
[s3; &]
|
||||
[s4;%- &]
|
||||
[s5;K%- [@(0.0.255) int]_[* GetError]()_[@(0.0.255) const]&]
|
||||
[s7; [*/ Return value]-|Current error`-code. Zero indicates no error.&]
|
||||
[s5;:Stream`:`:GetError`(`)const:%- [@(0.0.255) int]_[* GetError]()_[@(0.0.255) const]&]
|
||||
[s2; Returns current error`-code. Zero indicates no error.&]
|
||||
[s3; &]
|
||||
[s4;%- &]
|
||||
[s5;:Stream`:`:ClearError`(`):%- [@(0.0.255) void]_[* ClearError]()&]
|
||||
[s2; Clears error code.&]
|
||||
[s3; &]
|
||||
[s4;%- &]
|
||||
[s5;K%- [_^int64^ int64]_[* GetPos]()_[@(0.0.255) const]&]
|
||||
[s5;:Stream`:`:GetPos`(`)const:%- [_^int64^ int64]_[* GetPos]()_[@(0.0.255) const]&]
|
||||
[s7; [*/ Return value]-|Current position in the stream.&]
|
||||
[s3; &]
|
||||
[s4;%- &]
|
||||
|
|
@ -341,9 +341,10 @@ can be interpreted by GetErrorMessage function.&]
|
|||
Is also true in case of error.&]
|
||||
[s3; &]
|
||||
[s4;%- &]
|
||||
[s5;K%- [_^int64^ int64]_[* GetLeft]()_[@(0.0.255) const]&]
|
||||
[s5;:Stream`:`:GetLeft`(`)const:%- [_^int64^ int64]_[* GetLeft]()_[@(0.0.255) const]&]
|
||||
[s7; [*/ Return value]-|Bytes between current position and the end of
|
||||
stream `- equivalent to GetSize() `- GetPos().&]
|
||||
[s3; &]
|
||||
[s4;%- &]
|
||||
[s5;:Stream`:`:SeekEnd`(int64`):%- [@(0.0.255) void]_[* SeekEnd]([_^int64^ int64]_[*@3 rel]_`=
|
||||
_[@3 0])&]
|
||||
|
|
@ -364,11 +365,11 @@ position. Same as Seek(GetPos() `+ rel).&]
|
|||
[s3; &]
|
||||
[s4;%- &]
|
||||
[s5;:Stream`:`:Term`(`):%- [@(0.0.255) int]_[* Term]()&]
|
||||
[s5;:Stream`:`:Peek`(`):%- [@(0.0.255) int]_[* Peek]()&]
|
||||
[s2; Peeks byte from input stream not advancing current position.
|
||||
If there are no more bytes in input stream or error occurred,
|
||||
negative value is returned.&]
|
||||
[s7; [*/ Return value]-|Byte at current position in the stream.&]
|
||||
[s3; &]
|
||||
[s3;%- &]
|
||||
[s4;%- &]
|
||||
[s5;:Stream`:`:Get`(`):%- [@(0.0.255) int]_[* Get]()&]
|
||||
[s2; Reads single byte from input stream, advancing current position.
|
||||
|
|
@ -377,8 +378,8 @@ negative value is returned.&]
|
|||
[s7; [*/ Return value]-|Byte read from input stream.&]
|
||||
[s3; &]
|
||||
[s4;%- &]
|
||||
[s5;:Stream`:`:Peek`(int`):%- [@(0.0.255) const]_[_^byte^ byte]_`*[* Peek]([@(0.0.255) int]_[*@3 s
|
||||
ize]_`=_[@3 1])&]
|
||||
[s5;:Stream`:`:PeekPtr`(int`):%- [@(0.0.255) const]_[_^byte^ byte]_`*[* PeekPtr]([@(0.0.255) i
|
||||
nt]_[*@3 size]_`=_[@3 1])&]
|
||||
[s2; This is a special optimization method; it might return a pointer
|
||||
to data of [%-*@3 size] bytes at current position in the stream,
|
||||
but it is allowed to return NULL `- in that case you need to
|
||||
|
|
@ -393,25 +394,20 @@ but it is allowed to return NULL `- in that case you need to
|
|||
output data using Put. Advances stream by [%-*@3 size].&]
|
||||
[s3; &]
|
||||
[s4;%- &]
|
||||
[s5;:Stream`:`:Put`(const void`*`,dword`):%- [@(0.0.255) void]_[* Put]([@(0.0.255) const]_[@(0.0.255) v
|
||||
oid]_`*[*@3 data], [_^dword^ dword]_[*@3 size])&]
|
||||
[s5;:Stream`:`:Put`(const void`*`,int`):%- [@(0.0.255) void]_[* Put]([@(0.0.255) const]_[@(0.0.255) v
|
||||
oid]_`*[*@3 data], [@(0.0.255) int]_[*@3 size])&]
|
||||
[s2; Writes a block of raw binary data to the output stream.&]
|
||||
[s7; [%-*C@3 data]-|Pointer to data.&]
|
||||
[s7; [%-*C@3 size]-|Number of bytes to write.&]
|
||||
[s3; &]
|
||||
[s4;%- &]
|
||||
[s5;:Stream`:`:Get`(void`*`,dword`):%- [_^dword^ dword]_[* Get]([@(0.0.255) void]_`*[*@3 data
|
||||
], [_^dword^ dword]_[*@3 size])&]
|
||||
[s2; Reads a block of raw binary data from the input stream.&]
|
||||
[s7; [%-*C@3 data]-|Pointer to buffer to receive the data.&]
|
||||
[s7; [%-*C@3 size]-|Number of bytes to read.&]
|
||||
[s7; [*/ Return value]-|Number of bytes actually read (lower or equal
|
||||
to the requested [*@3 size]).&]
|
||||
[s5;:Stream`:`:Get`(void`*`,int`):%- [@(0.0.255) int]_[* Get]([@(0.0.255) void]_`*[*@3 data],
|
||||
[@(0.0.255) int]_[*@3 size])&]
|
||||
[s2; Reads at most [%-*@3 size] bytes from the stream to [%-*@3 data].
|
||||
Returns the number of bytes actually read.&]
|
||||
[s3; &]
|
||||
[s4;%- &]
|
||||
[s5;:Stream`:`:Get`(dword`):%- [_^String^ String]_[* Get]([_^dword^ dword]_[*@3 size])&]
|
||||
[s2; Reads a block of raw binary data from the input stream. The
|
||||
number of bytes read is the length of String.&]
|
||||
[s5;:Stream`:`:Get`(int`):%- [_^String^ String]_[* Get]([@(0.0.255) int]_[*@3 size])&]
|
||||
[s2; Reads at most [%-*@3 size] bytes from the input stream and returns
|
||||
result as String.&]
|
||||
[s3; &]
|
||||
[s4;%- &]
|
||||
[s5;:Stream`:`:LoadThrowing`(`):%- [@(0.0.255) void]_[* LoadThrowing]()&]
|
||||
|
|
@ -677,8 +673,8 @@ the end is written.&]
|
|||
[s7; [*/ Return value]-|true if stream is in storing mode.&]
|
||||
[s3; &]
|
||||
[s4;%- &]
|
||||
[s5;:Stream`:`:SerializeRaw`(byte`*`,dword`):%- [@(0.0.255) void]_[* SerializeRaw]([_^byte^ b
|
||||
yte]_`*[*@3 data], [_^dword^ dword]_[*@3 count])&]
|
||||
[s5;:Stream`:`:SerializeRaw`(byte`*`,int`):%- [@(0.0.255) void]_[* SerializeRaw]([_^byte^ b
|
||||
yte]_`*[*@3 data], [@(0.0.255) int]_[*@3 count])&]
|
||||
[s2; Serializes raw 8`-bit data. Might invoke LoadError if there
|
||||
is not enough data to load.&]
|
||||
[s7; [%-*C@3 data]-|Pointer to data to store or buffer to receive loaded
|
||||
|
|
@ -686,8 +682,8 @@ data.&]
|
|||
[s7; [%-*C@3 count]-|Number of bytes to load/store.&]
|
||||
[s3; &]
|
||||
[s4;%- &]
|
||||
[s5;:Stream`:`:SerializeRaw`(word`*`,dword`):%- [@(0.0.255) void]_[* SerializeRaw]([_^word^ w
|
||||
ord]_`*[*@3 data], [_^dword^ dword]_[*@3 count])&]
|
||||
[s5;:Stream`:`:SerializeRaw`(word`*`,int`):%- [@(0.0.255) void]_[* SerializeRaw]([_^word^ w
|
||||
ord]_`*[*@3 data], [@(0.0.255) int]_[*@3 count])&]
|
||||
[s2; Serializes raw 16`-bit data. Might invoke LoadError if there
|
||||
is not enough data to load.&]
|
||||
[s7; [%-*C@3 data]-|Pointer to data to store or buffer to receive loaded
|
||||
|
|
@ -695,8 +691,8 @@ data.&]
|
|||
[s7; [%-*C@3 count]-|Number of values to load/store.&]
|
||||
[s3; &]
|
||||
[s4;%- &]
|
||||
[s5;:Stream`:`:SerializeRaw`(dword`*`,dword`):%- [@(0.0.255) void]_[* SerializeRaw]([_^dword^ d
|
||||
word]_`*[*@3 data], [_^dword^ dword]_[*@3 count])&]
|
||||
[s5;:Stream`:`:SerializeRaw`(dword`*`,int`):%- [@(0.0.255) void]_[* SerializeRaw]([_^dword^ d
|
||||
word]_`*[*@3 data], [@(0.0.255) int]_[*@3 count])&]
|
||||
[s2; Serializes raw 32`-bit data. Might invoke LoadError if there
|
||||
is not enough data to load.&]
|
||||
[s7; [%-*C@3 data]-|Pointer to data to store or buffer to receive loaded
|
||||
|
|
@ -704,8 +700,8 @@ data.&]
|
|||
[s7; [%-*C@3 count]-|Number of values to load/store.&]
|
||||
[s3; &]
|
||||
[s4;%- &]
|
||||
[s5;:Stream`:`:SerializeRaw`(uint64`*`,dword`):%- [@(0.0.255) void]_[* SerializeRaw]([_^uint64^ u
|
||||
int64]_`*[*@3 data], [_^dword^ dword]_[*@3 count])&]
|
||||
[s5;:Stream`:`:SerializeRaw`(uint64`*`,int`):%- [@(0.0.255) void]_[* SerializeRaw]([_^uint64^ u
|
||||
int64]_`*[*@3 data], [@(0.0.255) int]_[*@3 count])&]
|
||||
[s2; Serializes raw 64`-bit data. Might invoke LoadError if there
|
||||
is not enough data to load.&]
|
||||
[s7; [%-*C@3 data]-|Pointer to data to store or buffer to receive loaded
|
||||
|
|
@ -713,6 +709,11 @@ data.&]
|
|||
[s7; [%-*C@3 count]-|Number of values to load/store.&]
|
||||
[s3; &]
|
||||
[s4;%- &]
|
||||
[s5;:Stream`:`:SerializeRLE`(byte`*`,int`):%- [@(0.0.255) void]_[* SerializeRLE]([_^byte^ b
|
||||
yte]_`*[*@3 data], [@(0.0.255) int]_[*@3 count])&]
|
||||
[s2; Serializes raw data, using simple RLE compression.&]
|
||||
[s3; &]
|
||||
[s4;%- &]
|
||||
[s5;:Stream`:`:operator`%`(bool`&`):%- [_^Stream^ Stream][@(0.0.255) `&]_[* operator%]([@(0.0.255) b
|
||||
ool`&]_[*@3 d])&]
|
||||
[s2; Serializes bool variable [%-*@3 d]. Might invoke LoadError if
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue